Пример #1
0
func runCommand(cmdStr ...string) error {
	cmd := exec.Command(cmdStr[0], cmdStr[1:]...)
	if output, err := cmd.CombinedOutput(); err != nil {
		return fmt.Errorf("cannot run %v: %s", cmdStr, osutil.OutputErr(output, err))
	}
	return nil
}
Пример #2
0
func removeMountUnit(baseDir string, meter progress.Meter) error {
	sysd := systemd.New(dirs.GlobalRootDir, meter)
	unit := systemd.MountUnitPath(dirs.StripRootDir(baseDir), "mount")
	if osutil.FileExists(unit) {
		// use umount -l (lazy) to ensure that even busy mount points
		// can be unmounted.
		// note that the long option --lazy is not supported on trusty.
		if output, err := exec.Command("umount", "-l", baseDir).CombinedOutput(); err != nil {
			return osutil.OutputErr(output, err)
		}

		if err := sysd.Stop(filepath.Base(unit), time.Duration(1*time.Second)); err != nil {
			return err
		}
		if err := sysd.Disable(filepath.Base(unit)); err != nil {
			return err
		}
		if err := os.Remove(unit); err != nil {
			return err
		}
		// daemon-reload to ensure that systemd actually really
		// forgets about this mount unit
		if err := sysd.DaemonReload(); err != nil {
			return err
		}
	}

	return nil
}
Пример #3
0
func (b Backend) DiscardSnapNamespace(snapName string) error {
	mntFile := mountNsPath(snapName)
	// If there's a .mnt file that was created by snap-confine we should ask
	// snap-confine to discard it appropriately.
	if osutil.FileExists(mntFile) {
		snapDiscardNs := filepath.Join(dirs.LibExecDir, "snap-discard-ns")
		cmd := exec.Command(snapDiscardNs, snapName)
		output, err := cmd.CombinedOutput()
		if err != nil {
			return fmt.Errorf("cannot discard preserved namespaces of snap %q: %s", snapName, osutil.OutputErr(output, err))
		}
	}
	return nil
}
Пример #4
0
func tryMount(deviceName string) (string, error) {
	tmpMountTarget, err := ioutil.TempDir("", "snapd-auto-import-mount-")
	if err != nil {
		err = fmt.Errorf("cannot create temporary mount point: %v", err)
		logger.Noticef("error: %v", err)
		return "", err
	}
	// udev does not provide much environment ;)
	if os.Getenv("PATH") == "" {
		os.Setenv("PATH", "/usr/sbin:/usr/bin:/sbin:/bin")
	}
	// not using syscall.Mount() because we don't know the fs type in advance
	cmd := exec.Command("mount", "-o", "ro", "--make-private", deviceName, tmpMountTarget)
	if output, err := cmd.CombinedOutput(); err != nil {
		os.Remove(tmpMountTarget)
		err = fmt.Errorf("cannot mount %s: %s", deviceName, osutil.OutputErr(output, err))
		logger.Noticef("error: %v", err)
		return "", err
	}

	return tmpMountTarget, nil
}
Пример #5
0
// Start the Daemon
func (d *Daemon) Start() {
	// die when asked to restart (systemd should get us back up!)
	d.overlord.SetRestartHandler(func(t state.RestartType) {
		switch t {
		case state.RestartDaemon:
			d.tomb.Kill(nil)
		case state.RestartSystem:
			cmd := exec.Command("shutdown", "+10", "-r", shutdownMsg)
			if out, err := cmd.CombinedOutput(); err != nil {
				logger.Noticef("%s", osutil.OutputErr(out, err))
			}
		default:
			logger.Noticef("internal error: restart handler called with unknown restart type: %v", t)
			d.tomb.Kill(nil)
		}
	})

	// the loop runs in its own goroutine
	d.overlord.Loop()

	d.tomb.Go(func() error {
		if d.snapListener != nil {
			d.tomb.Go(func() error {
				if err := http.Serve(d.snapListener, logit(d.router)); err != nil && d.tomb.Err() == tomb.ErrStillAlive {
					return err
				}

				return nil
			})
		}

		if err := http.Serve(d.snapdListener, logit(d.router)); err != nil && d.tomb.Err() == tomb.ErrStillAlive {
			return err
		}

		return nil
	})
}
Пример #6
0
// doRunHook actually runs the hook that was requested.
//
// Note that this method is synchronous, as the task is already running in a
// goroutine.
func (m *HookManager) doRunHook(task *state.Task, tomb *tomb.Tomb) error {
	task.State().Lock()
	setup := &HookSetup{}
	err := task.Get("hook-setup", setup)
	task.State().Unlock()

	if err != nil {
		return fmt.Errorf("cannot extract hook setup from task: %s", err)
	}

	context, err := NewContext(task, setup, nil)
	if err != nil {
		return err
	}

	// Obtain a handler for this hook. The repository returns a list since it's
	// possible for regular expressions to overlap, but multiple handlers is an
	// error (as is no handler).
	handlers := m.repository.generateHandlers(context)
	handlersCount := len(handlers)
	if handlersCount == 0 {
		return fmt.Errorf("no registered handlers for hook %q", setup.Hook)
	}
	if handlersCount > 1 {
		return fmt.Errorf("%d handlers registered for hook %q, expected 1", handlersCount, setup.Hook)
	}

	context.handler = handlers[0]

	contextID := context.ID()
	m.contextsMutex.Lock()
	m.contexts[contextID] = context
	m.contextsMutex.Unlock()

	defer func() {
		m.contextsMutex.Lock()
		delete(m.contexts, contextID)
		m.contextsMutex.Unlock()
	}()

	// About to run the hook-- notify the handler
	if err = context.Handler().Before(); err != nil {
		return err
	}

	// Actually run the hook
	output, err := runHookAndWait(setup.Snap, setup.Revision, setup.Hook, contextID, tomb)
	if err != nil {
		err = osutil.OutputErr(output, err)
		if handlerErr := context.Handler().Error(err); handlerErr != nil {
			return handlerErr
		}

		return err
	}

	// Assuming no error occurred, notify the handler that the hook has
	// finished.
	if err = context.Handler().Done(); err != nil {
		return err
	}

	// Let the context know we're finished with it.
	context.Lock()
	defer context.Unlock()
	if err = context.Done(); err != nil {
		return err
	}

	return nil
}
Пример #7
0
// doRunHook actually runs the hook that was requested.
//
// Note that this method is synchronous, as the task is already running in a
// goroutine.
func (m *HookManager) doRunHook(task *state.Task, tomb *tomb.Tomb) error {
	task.State().Lock()
	hooksup, snapst, err := hookSetup(task)
	task.State().Unlock()
	if err != nil {
		return err
	}

	info, err := snapst.CurrentInfo()
	if err != nil {
		return fmt.Errorf("cannot read %q snap details: %v", hooksup.Snap, err)
	}

	hookExists := info.Hooks[hooksup.Hook] != nil
	if !hookExists && !hooksup.Optional {
		return fmt.Errorf("snap %q has no %q hook", hooksup.Snap, hooksup.Hook)
	}

	context, err := NewContext(task, hooksup, nil)
	if err != nil {
		return err
	}

	// Obtain a handler for this hook. The repository returns a list since it's
	// possible for regular expressions to overlap, but multiple handlers is an
	// error (as is no handler).
	handlers := m.repository.generateHandlers(context)
	handlersCount := len(handlers)
	if handlersCount == 0 {
		return fmt.Errorf("internal error: no registered handlers for hook %q", hooksup.Hook)
	}
	if handlersCount > 1 {
		return fmt.Errorf("internal error: %d handlers registered for hook %q, expected 1", handlersCount, hooksup.Hook)
	}

	context.handler = handlers[0]

	contextID := context.ID()
	m.contextsMutex.Lock()
	m.contexts[contextID] = context
	m.contextsMutex.Unlock()

	defer func() {
		m.contextsMutex.Lock()
		delete(m.contexts, contextID)
		m.contextsMutex.Unlock()
	}()

	if err = context.Handler().Before(); err != nil {
		return err
	}

	if hookExists {
		output, err := runHook(context, tomb)
		if err != nil {
			err = osutil.OutputErr(output, err)
			if handlerErr := context.Handler().Error(err); handlerErr != nil {
				return handlerErr
			}

			return err
		}
	}

	if err = context.Handler().Done(); err != nil {
		return err
	}

	context.Lock()
	defer context.Unlock()
	if err = context.Done(); err != nil {
		return err
	}

	return nil
}
Пример #8
0
func LoadModule(module string) error {
	if output, err := exec.Command("modprobe", "--syslog", module).CombinedOutput(); err != nil {
		return fmt.Errorf("cannot load module %s: %s", module, osutil.OutputErr(output, err))
	}
	return nil
}