Exemple #1
0
def main(args):

    import_data = yaml.safe_load(args.input)
    groups = {k['group']['name']:k['group'] for k in import_data if 'group' in k}
    programs = {k['program']['name']:k['program'] for k in import_data if 'program' in k}

    for group in groups.values():
        group_dir = path.join(config.dirs.user_data_dir, 'groups')
        if not path.isdir(group_dir): os.makedirs(group_dir)

        group_path = path.join(group_dir, '%s.yaml' % group['name'])
        log.info("Writing group %s to %s" % (group['name'], group_path))
        with open(group_path, 'w') as gf:
            yaml.safe_dump(group, gf, default_flow_style=False)

    for defn in programs.values():
        if 'name' not in defn:
            raise errors.ChalmersError("Import definition requires a name field")

        prog = Program(defn['name'])
        if prog.exists():
            log.warn("Program '%s' already exists, not importing" % defn['name'])
            continue

        prog.raw_data.update(defn)
        prog.mk_data()
Exemple #2
0
def main(args):

    config.set_relative_dirs(path.abspath('.chalmers'))
    if not os.path.isfile(args.procfile):
        raise errors.ChalmersError("procfile '{}' does not exist".format(
            args.procfile))

    with open(args.procfile) as fd:
        procs = yaml.load(fd)
    print('procs', procs)
    programs = []
    for name, command in procs.items():
        definition = {
            'name': name,
            'command': split(command),
        }
        program = Program(name)
        pprint(definition)
        program.raw_data.update(definition)
        programs.append(program)

    pool = MultiPlexIOPool(stream=True, use_color=args.color)

    for prog in programs:
        pool.append(prog)

    pool.join()
Exemple #3
0
    def add(cls,
            name,
            command,
            paused=False,
            cwd=None,
            stdout=None,
            stderr=None,
            daemon_log=None,
            redirect_stderr=None,
            env=None):
        """
        Add a new program to run, 
        
        This will not start the program, to start it run prog.start()
        """

        program = cls(name)

        if program.exists():
            raise errors.ChalmersError(
                "Program with name '{name}' already exists.  \n"
                "Use the -n/--name option to change the name or \n"
                "Run 'chalmers remove {name}' to remove it \n"
                "or 'chalmers set' to update the parameters".format(name=name))

        state = {'paused': paused}
        definition = create_definition(name, command)

        program.raw_data.update(definition)
        program.state.update(state)
        # Updated the data attribute from the raw data
        program.mk_data()

        return program
    def __init__(self, target_user):

        if target_user is not False:  #
            raise errors.ChalmersError(
                "You can not install a local service into another users account. "
                "To do this use the 'runas' windows command with chalmers")

        self.target_user = target_user
Exemple #5
0
def get_crontab():
    try:
        output = sp.check_output(['crontab', '-l']).strip()
    except sp.CalledProcessError as err:
        if err.returncode != 1:
            raise errors.ChalmersError("Could not read crontab")
        return []

    return output.split('\n')
Exemple #6
0
    def check_output(self, command):
        if self.target_user:
            if os.getuid() != 0:
                raise errors.ChalmersError("Can not perform system install without root")

        log.info("Running command: %s" % ' '.join(command))
        try:
            output = sp.check_output(command, stderr=sp.STDOUT)
        except OSError as err:
            raise errors.ChalmersError("Could not access program 'launchctl' required for osx service install")
        except sp.CalledProcessError as err:
            if err.returncode == 1:
                if 'Socket is not connected' in err.output:
                    log.error(err.output)
                    raise errors.ChalmersError("The user '%s' must be logged in via the osx gui to perform this operation" % self.target_user)
            raise

        return output
Exemple #7
0
    def remove(self):
        """
        Remove this program definition
        """
        if self.is_running:
            raise errors.ChalmersError(
                "Can not remove running program (must be stopped)")

        self.state.delete()
        self.raw_data.delete()
Exemple #8
0
    def handle_signals(self):
        # Called before keep_alive

        new_mask = self.data.get('umask')
        if new_mask:
            log.warning("Config var 'umask' will be ignored on win32")

        user = self.data.get('user')

        if user:
            raise errors.ChalmersError(
                "Can not yet run as program as a user on win32")
Exemple #9
0
    def __init__(self, name, load=True, force=False):
        self._name = name

        EventDispatcher.__init__(self)
        self.finished_event = Event()

        defn_filename = path.join(config.dirs.user_data_dir, 'programs',
                                  '%s.yaml' % self.name)
        state_filename = path.join(config.dirs.user_data_dir, 'state',
                                   '%s.yaml' % self.name)

        try:
            self.state = PersistentDict(state_filename)
        except yaml.error.YAMLError:
            log.error("Yaml parser error. could not parse state file %s" %
                      state_filename)
            if force:
                log.warn("Removing state file and continuing")
                os.unlink(state_filename)
                self.state = PersistentDict(state_filename)
            else:
                msg = "Invalid state file. run `chalmers stop --force` to clear the state file"
                raise errors.ChalmersError(msg)

        try:
            self.raw_data = PersistentDict(defn_filename)
        except yaml.error.YAMLError:
            log.error("Yaml parser error. could not parse definition file %s" %
                      defn_filename)
            if force:
                self.raw_data = PersistentDict(defn_filename, load=False)
            else:
                msg = "Invalid definition file. Run `chalmers edit %s` to fix the definition file"
                raise errors.ChalmersError(msg % (defn_filename))

        self.data = {}
        self.mk_data()

        self._p0 = None
        self.pipe_output = False
Exemple #10
0
def main(args):

    service = LocalService(False)

    if args.action == 'status':
        service.status()
    elif args.action == 'enable':
        service.install()
    elif args.action == 'disable':
        service.uninstall()

    else:
        raise errors.ChalmersError("Invalid action %s" % args.action)
Exemple #11
0
    def install(self):
        if not self.is_admin:
            raise errors.ChalmersError(
                "System services requires admin privleges. "
                "run this command as an administrator")

        log.info(
            "Your password is required by the windows service manager to launch "
            "the chalmers service at startup")
        password = getpass.getpass("Password for {}: ".format(
            self.target_user))

        instart('.\\{}'.format(self.target_user), password)
Exemple #12
0
    def __init__(self, target_user):
        if target_user is not False:
            msg = ("Not implemented: chalmers can not detect "
                   "the init system for your unix machine "
                   "(upstart, systemd or sysv)")
            raise errors.ChalmersError(msg)
        self.target_user = target_user
        log = logging.getLogger('chalmers.cron_service')

        log.info('Platform: %s' % platform.linux_distribution()[0]
                 or 'Unknown')
        log.info('Using posix crond @reboot command')
        log.info('Chalmers service for current user (does not require root)')
Exemple #13
0
def main(args):

    if os.name == 'nt':
        from win32com.shell import shell
        if not shell.IsUserAnAdmin():
            raise errors.ChalmersError(
                'You must be an administrator to run this command')
    else:
        if os.getuid() != 0:
            raise errors.ChalmersError('You must be root to run this command')

    service = SystemService(args.target_user)

    if args.action == 'status':
        service.status()
    elif args.action == 'enable':
        service.install()
    elif args.action == 'disable':
        service.uninstall()

    else:
        raise errors.ChalmersError("Invalid action %s" % args.action)
Exemple #14
0
def main(args):

    EDITOR = os.environ.get('EDITOR', None)
    if EDITOR is None:
        raise errors.ChalmersError(
            "Environment variable 'EDITOR' needs to be set")

    prog = Program(args.name, force=True)

    if prog and not prog.exists():
        raise errors.ProgramNotFound("program '{}' not found".format(
            args.name))

    cmd = '%s %s' % (EDITOR, pipes.quote(prog.raw_data.filename))

    print(cmd)
    if subprocess.call(cmd, shell=True):
        raise errors.ChalmersError('Command "%s" exited with non zero status' %
                                   cmd)

    if prog.is_running:
        log.info("Changes to program %s will take effect on the next restart" %
                 prog.name)
Exemple #15
0
def main(args):

    if args.cmd and args.command:
        raise errors.ChalmersError('Unknow arguments %r' % args.command)
    elif not (args.cmd or args.command):
        raise errors.ChalmersError('Must specify a command to add')
    if args.cmd:
        args.command = args.cmd

    if not args.name:
        args.name = args.command[0]

    env = {}
    for env_var in args.save_env:
        if env_var in os.environ:
            env[env_var] = os.environ[env_var]
        else:
            log.warn(
                "Environment variable %s does not exist (from -e/--save-env)" %
                env_var)

    program = Program.add(args.name,
                          args.command,
                          paused=args.paused,
                          cwd=args.cwd,
                          stdout=args.stdout,
                          stderr=args.stderr,
                          daemon_log=args.daemon_log,
                          redirect_stderr=args.redirect_stderr,
                          env=env)

    log.info('Added program {args.name}'.format(args=args))

    if args.run_now:
        log.info('Running program {args.name}'.format(args=args))
        program.start(daemon=not args.wait)
Exemple #16
0
 def listener(self):
     "Return the multiprocessing Listener object"
     if self._listener is None:
         if self.FAMILY == 'AF_UNIX' and os.path.exists(self.addr):
             os.unlink(self.addr)
         try:
             log.debug("Listening to events from: %s" % self.addr)
             self._listener = Listener(self.addr, family=self.FAMILY)
         except socket.error as err:
             if err.errno == 48:
                 msg = "Unix socket '%s' appears to be in use. Please stop this program."
                 raise errors.ChalmersError(msg % self.addr)
             else:
                 raise
     return self._listener
Exemple #17
0
 def _mk_lockfile(self):
     'TODO: not implemented'
     lockfile = self._filename + '.lock'
     try:
         if self.exists():
             os.link(self._filename, lockfile)
         else:
             os.mkdir(lockfile)
     except OSError as err:
         if err.errno == 17:
             msg = ("The file '%s' is locked by another process.\n"
                    "If this process is not running, "
                    "you can manually remove the lockfile\n\trm '%s'" %
                    (self._filename, lockfile))
             raise errors.ChalmersError(msg)
         raise
Exemple #18
0
    def dispatch_terminate(self, timeout=None):
        'Action for event listener'
        children = self._stop()
        if not self.finished_event.wait(timeout):
            if self._p0:
                log.info('Process did not stop within %s seconds' % (timeout))
                log.info('Hard killing process %s' % (self._p0.pid))
                kill_tree(self._p0.pid)

            if not self.finished_event.wait(timeout):
                raise errors.ChalmersError(
                    "Timed out waiting for program %s to finish" % self.name)
        else:
            for child in children:
                if child.is_running():
                    child.kill()
Exemple #19
0
    def use_if_not_root(cls, subcls, target_user):
        if target_user is False:
            if py3:
                return object.__new__(cls)
            else:
                return object.__new__(cls, target_user)

        else:
            if os.getuid() != 0:
                raise errors.ChalmersError(
                    "You can not install a posix service for "
                    "user %s without root privileges. "
                    "Run this command again with sudo")
            if py3:
                return object.__new__(subcls)
            else:
                return object.__new__(subcls, target_user)
Exemple #20
0
    def uninstall(self):
        if not self.is_admin:
            raise errors.ChalmersError(
                "System services requires admin privileges. "
                "run this command as an administrator")

        if is_running(self.target_user):
            log.info("Service is running, stopping service {}".format(
                self.service_name))
            StopService(self.service_name)

        if is_installed(self.target_user):
            RemoveService(self.service_name)
            log.info("Uninstalled windows service '{}'".format(
                self.service_name))
        else:
            log.error("Windows service '{}' is not installed".format(
                self.service_name))
Exemple #21
0
def restart_main(args):

    programs = cli.select_programs(args, filter_paused=True)

    if not (args.all or args.names):
        raise errors.ChalmersError(
            "Must specify at least one program to restart")

    if len(programs):
        print("Restarting programs %s" % ', '.join([p.name for p in programs]))
        print("")
    else:
        log.warn("No programs to restart")
        return

    for prog in programs:

        sys.stdout.flush()

        if prog.is_running:
            print("Stop program %-25s ... " % (prog.name[:25]), end='')
            try:
                prog.stop()
            except errors.StateError:
                print_colors('[  {=ERROR!c:red}  ]')

            print_colors('[  {=OK!c:green}  ]')

    time.sleep(.5)

    for prog in programs:
        prog.start()

    for prog in programs:
        print("Checking status of program %-25s ... " % (prog.name[:25]),
              end='')
        sys.stdout.flush()
        err = prog.wait_for_start()
        if err:
            print_colors('[{=ERROR!c:red} ]')
        else:

            print_colors('[  {=OK!c:green}  ]')
Exemple #22
0
    def add_launchd(self):
        if self.target_user:
            username = '******' % self.target_user
        else:
            username = ''
        plist = self.template.format(python_exe=python_exe,
                                     chalmers=chalmers_script,
                                     label=self.label,
                                     username=username)

        with tempfile.NamedTemporaryFile('w', suffix='.plist', prefix='chalmers') as fd:

            fd.write(plist)
            fd.flush()
            try:
                command = ['launchctl', 'load', fd.name]
                self.check_output(command).strip()
            except sp.CalledProcessError as err:
                if err.returncode == 1:
                    raise errors.ChalmersError("Chalmers service is already installed")
                raise
Exemple #23
0
def main(args):

    proc = Program(args.name)

    if not proc.exists():
        raise errors.ProgramNotFound("program '{}' not found".format(
            args.name))

    if proc.is_running:
        log.warning(
            "Program is running: Updates will not be reflected until a restart is done"
        )
    with proc.raw_data.transaction():
        for key, value in args.items:
            if key == 'name':
                raise errors.ChalmersError("Can not set program name")

            set_nested_key(proc.raw_data, key, value)
            print("Set '%s' to %r for program %s" % (key, value, args.name))

    print("done")
Exemple #24
0
def send_action(name, action, *args, **kwargs):
    """
    Send an action to a listener
    the listener must have a 'dispatch_{action}' method
    or this will raise a ChalmersError
    """

    addr = get_addr(name)
    try:
        c = Client(addr, family=EventDispatcher.FAMILY)
    except (socket.error, WindowsError):
        raise errors.ConnectionError(
            "Could not connect to chalmers program %s" % name)

    try:
        c.send({'action': action, 'args': args, 'kwargs': kwargs})
        res = c.recv()

        if res.get('error'):
            raise errors.ChalmersError(res.get('message', 'Unknown error'))
        return res.get('result')
    finally:
        c.close()
Exemple #25
0
 def dispatch_bg(self):
     raise errors.ChalmersError(
         "Can not yet move a win32 process to the background")
Exemple #26
0
 def __init__(self, target_user=None):
     supported_dists = platform._supported_dists + system_dist
     linux = platform.linux_distribution(supported_dists=supported_dists)
     raise errors.ChalmersError(
         "Could not detect system service for platform %s (tried systemd, sysv init and upstart)"
         % linux[0])