// RemoveSnapServices disables and removes service units for the applications from the snap which are services. func RemoveSnapServices(s *snap.Info, inter interacter) error { sysd := systemd.New(dirs.GlobalRootDir, inter) nservices := 0 for _, app := range s.Apps { if app.Daemon == "" { continue } nservices++ serviceName := filepath.Base(app.ServiceFile()) if err := sysd.Disable(serviceName); err != nil { return err } if err := os.Remove(app.ServiceFile()); err != nil && !os.IsNotExist(err) { logger.Noticef("Failed to remove service file for %q: %v", serviceName, err) } if err := os.Remove(app.ServiceSocketFile()); err != nil && !os.IsNotExist(err) { logger.Noticef("Failed to remove socket file for %q: %v", serviceName, err) } } // only reload if we actually had services if nservices > 0 { if err := sysd.DaemonReload(); err != nil { return err } } return nil }
// StartSnapServices starts service units for the applications from the snap which are services. func StartSnapServices(s *snap.Info, inter interacter) error { for _, app := range s.Apps { if app.Daemon == "" { continue } // daemon-reload and enable plus start serviceName := filepath.Base(app.ServiceFile()) sysd := systemd.New(dirs.GlobalRootDir, inter) if err := sysd.DaemonReload(); err != nil { return err } if err := sysd.Enable(serviceName); err != nil { return err } if err := sysd.Start(serviceName); err != nil { return err } if app.Socket { socketName := filepath.Base(app.ServiceSocketFile()) // enable the socket if err := sysd.Enable(socketName); err != nil { return err } if err := sysd.Start(socketName); err != nil { return err } } } return nil }
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 }
// StopSnapServices stops service units for the applications from the snap which are services. func StopSnapServices(s *snap.Info, inter interacter) error { sysd := systemd.New(dirs.GlobalRootDir, inter) nservices := 0 for _, app := range s.Apps { if app.Daemon == "" { continue } nservices++ serviceName := filepath.Base(app.ServiceFile()) tout := serviceStopTimeout(app) if err := sysd.Stop(serviceName, tout); err != nil { if !systemd.IsTimeout(err) { return err } inter.Notify(fmt.Sprintf("%s refused to stop, killing.", serviceName)) // ignore errors for kill; nothing we'd do differently at this point sysd.Kill(serviceName, "TERM") time.Sleep(killWait) sysd.Kill(serviceName, "KILL") } } return nil }
// StopSnapServices stops service units for the applications from the snap which are services. func StopSnapServices(s *snap.Info, inter interacter) error { sysd := systemd.New(dirs.GlobalRootDir, inter) for _, app := range s.Apps { // Handle the case where service file doesn't exist and don't try to stop it as it will fail. // This can happen with snap try when snap.yaml is modified on the fly and a daemon line is added. if app.Daemon == "" || !osutil.FileExists(app.ServiceFile()) { continue } serviceName := filepath.Base(app.ServiceFile()) tout := serviceStopTimeout(app) if err := sysd.Stop(serviceName, tout); err != nil { if !systemd.IsTimeout(err) { return err } inter.Notify(fmt.Sprintf("%s refused to stop, killing.", serviceName)) // ignore errors for kill; nothing we'd do differently at this point sysd.Kill(serviceName, "TERM") time.Sleep(killWait) sysd.Kill(serviceName, "KILL") } } return nil }
func (b *Backend) Setup(snapInfo *snap.Info, confinement interfaces.ConfinementOptions, repo *interfaces.Repository) error { snapName := snapInfo.Name() rawSnippets, err := repo.SecuritySnippetsForSnap(snapInfo.Name(), interfaces.SecuritySystemd) if err != nil { return fmt.Errorf("cannot obtain systemd security snippets for snap %q: %s", snapName, err) } snippets, err := unmarshalRawSnippetMap(rawSnippets) if err != nil { return fmt.Errorf("cannot unmarshal systemd snippets for snap %q: %s", snapName, err) } snippet, err := mergeSnippetMap(snippets) if err != nil { return fmt.Errorf("cannot merge systemd snippets for snap %q: %s", snapName, err) } content, err := renderSnippet(snippet) if err != nil { return fmt.Errorf("cannot render systemd snippets for snap %q: %s", snapName, err) } dir := dirs.SnapServicesDir if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("cannot create directory for systemd services %q: %s", dir, err) } glob := interfaces.InterfaceServiceName(snapName, "*") systemd := sysd.New(dirs.GlobalRootDir, &dummyReporter{}) // We need to be carefully here and stop all removed service units before // we remove their files as otherwise systemd is not able to disable/stop // them anymore. if err := disableRemovedServices(systemd, dir, glob, content); err != nil { logger.Noticef("cannot stop removed services: %s", err) } changed, removed, errEnsure := osutil.EnsureDirState(dir, glob, content) // Reload systemd whenever something is added or removed if len(changed) > 0 || len(removed) > 0 { err := systemd.DaemonReload() if err != nil { logger.Noticef("cannot reload systemd state: %s", err) } } // Ensure the service is running right now and on reboots for _, service := range changed { if err := systemd.Enable(service); err != nil { logger.Noticef("cannot enable service %q: %s", service, err) } // If we have a new service here which isn't started yet the restart // operation will start it. if err := systemd.Restart(service, 10*time.Second); err != nil { logger.Noticef("cannot restart service %q: %s", service, err) } } return errEnsure }
func (b *Backend) Setup(snapInfo *snap.Info, devMode bool, repo *interfaces.Repository) error { snapName := snapInfo.Name() rawSnippets, err := repo.SecuritySnippetsForSnap(snapInfo.Name(), interfaces.SecuritySystemd) if err != nil { return fmt.Errorf("cannot obtain systemd security snippets for snap %q: %s", snapName, err) } snippets, err := unmarshalRawSnippetMap(rawSnippets) if err != nil { return fmt.Errorf("cannot unmarshal systemd snippets for snap %q: %s", snapName, err) } snippet, err := mergeSnippetMap(snippets) if err != nil { return fmt.Errorf("cannot merge systemd snippets for snap %q: %s", snapName, err) } content, err := renderSnippet(snippet) if err != nil { return fmt.Errorf("cannot render systemd snippets for snap %q: %s", snapName, err) } dir := dirs.SnapServicesDir if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("cannot create directory for systemd services %q: %s", dir, err) } glob := interfaces.InterfaceServiceName(snapName, "*") changed, removed, errEnsure := osutil.EnsureDirState(dir, glob, content) systemd := sysd.New(dirs.GlobalRootDir, &dummyReporter{}) // Reload systemd whenever something is added or removed if len(changed) > 0 || len(removed) > 0 { err := systemd.DaemonReload() if err != nil { logger.Noticef("cannot reload systemd state: %s", err) } } // Start any new services for _, service := range changed { err := systemd.Start(service) if err != nil { logger.Noticef("cannot start service %q: %s", service, err) } } // Stop any removed services for _, service := range removed { err := systemd.Stop(service, 10*time.Second) if err != nil { logger.Noticef("cannot stop service %q: %s", service, err) } } return errEnsure }
func (b *Backend) Remove(snapName string) error { systemd := sysd.New(dirs.GlobalRootDir, &dummyReporter{}) // Remove all the files matching snap glob glob := interfaces.InterfaceServiceName(snapName, "*") _, removed, errEnsure := osutil.EnsureDirState(dirs.SnapServicesDir, glob, nil) for _, service := range removed { if err := systemd.DisableNow(service); err != nil { logger.Noticef("cannot disable service %q: %s", service, err) } } // Reload systemd whenever something is removed if len(removed) > 0 { err := systemd.DaemonReload() if err != nil { logger.Noticef("cannot reload systemd state: %s", err) } } return errEnsure }
func addMountUnit(s *snap.Info, meter progress.Meter) error { squashfsPath := dirs.StripRootDir(s.MountFile()) whereDir := dirs.StripRootDir(s.MountDir()) sysd := systemd.New(dirs.GlobalRootDir, meter) mountUnitName, err := sysd.WriteMountUnitFile(s.Name(), squashfsPath, whereDir, "squashfs") if err != nil { return err } // we need to do a daemon-reload here to ensure that systemd really // knows about this new mount unit file if err := sysd.DaemonReload(); err != nil { return err } if err := sysd.Enable(mountUnitName); err != nil { return err } return sysd.Start(mountUnitName) }