Пример #1
0
 def _queued_stop(self, slist, names, disable):
     try:
         for s in slist:
             yield from s.stop()
             if disable:
                 s.enabled = False
     except Exception as ex:
         error("queued stop (for {0}) failed: {1}", names, ex)
Пример #2
0
 def _queued_stop(self, slist, names, disable):
     try:
         for s in slist:
             yield from s.stop()
             if disable:
                 s.enabled = False
     except Exception as ex:
         error("queued stop (for {0}) failed: {1}", names, ex)
Пример #3
0
    def _backtick_expand(self, cmd):
        """
        Performs rudimentary backtick expansion after all other environment variables have been
        expanded.   Because these are cached, the user should not expect results to differ
        for different environment contexts, nor should the environment itself be relied upon.
        """

        # Accepts either a string or match object
        if not isinstance(cmd, str):
            cmd = cmd.group(1)

        if not self._cls_backtick:
            return "`" + cmd + "`"

        key = '{0}:{1}:{2}'.format(self.uid, self.gid, cmd)

        result = self._cls_btcache.get(key)

        if result is None:
            if self.uid:
                try:
                    pwrec = lookup_user(self.uid, self.gid)
                except ChNotFoundError as ex:
                    ex.annotate(
                        '(required for backtick expansion `{0}`)'.format(cmd))
                    raise ex
            else:
                pwrec = None

            def _proc_setup():
                if pwrec:
                    os.setgid(pwrec.pw_gid)
                    os.setuid(pwrec.pw_uid)

            try:
                result = subprocess.check_output(cmd,
                                                 shell=True,
                                                 stderr=subprocess.STDOUT,
                                                 preexec_fn=_proc_setup)
                result = result.decode()
            except Exception as ex:
                error(ex, "Backtick expansion returned error: " + str(ex))
                result = ""

            result = result.strip().replace("\n", " ")
            if self._cls_use_btcache:
                self._cls_btcache[key] = result

        return result
Пример #4
0
    def _backtick_expand(self, cmd):
        """
        Performs rudimentary backtick expansion after all other environment variables have been
        expanded.   Because these are cached, the user should not expect results to differ
        for different environment contexts, nor should the environment itself be relied upon.
        """

        # Accepts either a string or match object
        if not isinstance(cmd, str):
            cmd = cmd.group(1)

        if not self._cls_backtick:
            return "`" + cmd + "`"

        key = '{0}:{1}:{2}'.format(self.uid, self.gid, cmd)

        result = self._cls_btcache.get(key)

        if result is None:
            if self.uid:
                try:
                    pwrec = lookup_user(self.uid, self.gid)
                except ChNotFoundError as ex:
                    ex.annotate('(required for backtick expansion `{0}`)'.format(cmd))
                    raise ex
            else:
                pwrec = None

            def _proc_setup():
                if pwrec:
                    os.setgid(pwrec.pw_gid)
                    os.setuid(pwrec.pw_uid)

            try:
                result = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT,
                                                 preexec_fn=_proc_setup)
                result = result.decode()
            except Exception as ex:
                error(ex, "Backtick expansion returned error: " + str(ex))
                result = ""

            result = result.strip().replace("\n", " ")
            if self._cls_use_btcache:
                self._cls_btcache[key] = result

        return result
Пример #5
0
def main_entry():

   # parse these first since we may disable the environment check
   options = docopt(__doc__, options_first=True, version=VERSION_MESSAGE)

   if options['--task']:
      options['--disable-services'] = True
      options['--no-console-log'] = not options['--debug']
      options['--exitkills'] = True
      os.environ[ENV_TASK_MODE] = '1'

   if not options['--no-defaults']:
      envopts = os.environ.get(ENV_CHAP_OPTIONS)
      if envopts:
         try:
            defaults = docopt(__doc__, argv=(shlex.split(envopts)), options_first=True)
         except SystemExit as ex:
            print("Error occurred in {0} environment variable: {1}".format(ENV_CHAP_OPTIONS, envopts))
            raise
         # Replace any "false" command option with the default version.
         options.update({k:defaults[k] for k in options.keys() if not options[k]})

   if options['--config'] is None:
      options['--config'] = '/etc/chaperone.d'

   if options['--debug']:
      options['--log-level'] = "DEBUG"
      print('COMMAND OPTIONS', options)

   force = options['--force']

   if not force and os.getpid() != 1:
      print(MSG_PID1)
      exit(1)

   tty = sys.stdin.isatty()
   os.environ[ENV_INTERACTIVE] = "1" if tty else "0"

   kill_switch = options['--exitkills'] or (False if options['--no-exitkills'] else tty)

   cmd = options['<command>']

   if options['--task'] and not cmd:
      error("--task can only be used if a shell command is specified as an argument")
      exit(1)

   # It's possible that BOTH --create-user and --user exist due to the way _CHAP_OPTIONS is overlaid
   # with command line options.  So, in such a case, note that we ignore --user.

   create = options['--create-user']

   if create is None:
      user = options['--user']
   else:
     match = RE_CREATEUSER.match(create)
     if not match:
        print("Invalid format for --create-user argument: {0}".format(create))
        exit(1)
     udata = match.groupdict()
     try:
        maybe_create_user(udata['user'], udata['uid'] or None, udata['gid'] or None, 
                          udata['file'] and udata['file'].replace(r'\:', ':'),
                          options['--default-home'])
     except Exception as ex:
        print("--create-user failure: {0}".format(ex))
        exit(1)
     user = udata['user']

   extras = None
   if options['--ignore-failures']:
      extras = {'ignore_failures': True}
      
   try:
      config = Configuration.configFromCommandSpec(options['--config'], user=user, extra_settings=extras,
                                                   disable_console_log=options['--no-console-log'])
      services = config.get_services()
   except Exception as ex:
      error(ex, "Configuration Error: {0}", ex)
      exit(1)

   if not (services or cmd):
      print(MSG_NOTHING_TO_DO)
      exit(1)

   if options['--show-dependencies']:
      dg = services.get_dependency_graph()
      print("\n".join(dg))
      exit(0)

   if not cmd and options['--disable-services']:
      error("--disable-services not valid without specifying a command to run")
      exit(1)

   # Now, create the tlp and proceed

   tlp = TopLevelProcess(config)

   if options['--log-level']:
      tlp.force_log_level(options['--log-level'])

   if tlp.debug:
      config.dump()

   # Set proctitle and go

   proctitle = "[" + os.path.basename(sys.argv[0]) + "]"
   if cmd:
      proctitle += " " + cmd

   try:
      from setproctitle import setproctitle
      setproctitle(proctitle)
   except ImportError:
      pass

   # Define here so we can share scope

   @asyncio.coroutine
   def startup_done():

      if options['--ignore-failures']:
         warn("ignoring failures on all service startups due to --ignore-failures")

      if options['--disable-services'] and services:
         warn("services will not be configured due to --disable-services")

      extra_services = None
      if cmd:
         cmdsvc = ServiceConfig.createConfig(config=config,
                                             name="CONSOLE",
                                             exec_args=[cmd] + options['<args>'],
                                             uid=user,
                                             kill_signal=("SIGHUP" if tty else None),
                                             setpgrp=not tty,
                                             exit_kills=kill_switch,
                                             service_groups="IDLE",
                                             ignore_failures=not options['--task'],
                                             stderr='inherit', stdout='inherit')
         extra_services = [cmdsvc]

      yield from tlp.run_services(extra_services, disable_others = options['--disable-services'])

      tlp.signal_ready()

   tlp.run_event_loop(startup_done())
Пример #6
0
def main_entry():

   # parse these first since we may disable the environment check
   options = docopt(__doc__, options_first=True, version=VERSION_MESSAGE)

   if options['--task']:
      options['--disable-services'] = True
      options['--no-console-log'] = not options['--debug']
      options['--exitkills'] = True
      os.environ[ENV_TASK_MODE] = '1'

   if not options['--no-defaults']:
      envopts = os.environ.get(ENV_CHAP_OPTIONS)
      if envopts:
         try:
            defaults = docopt(__doc__, argv=(shlex.split(envopts)), options_first=True)
         except SystemExit as ex:
            print("Error occurred in {0} environment variable: {1}".format(ENV_CHAP_OPTIONS, envopts))
            raise
         # Replace any "false" command option with the default version.
         options.update({k:defaults[k] for k in options.keys() if not options[k]})

   if options['--config'] is None:
      options['--config'] = '/etc/chaperone.d'

   if options['--debug']:
      options['--log-level'] = "DEBUG"
      print('COMMAND OPTIONS', options)

   force = options['--force']

   if not force and os.getpid() != 1:
      print(MSG_PID1)
      exit(1)

   tty = sys.stdin.isatty()
   os.environ[ENV_INTERACTIVE] = "1" if tty else "0"

   kill_switch = options['--exitkills'] or (False if options['--no-exitkills'] else tty)

   cmd = options['<command>']

   if options['--task'] and not cmd:
      error("--task can only be used if a shell command is specified as an argument")
      exit(1)

   # It's possible that BOTH --create-user and --user exist due to the way _CHAP_OPTIONS is overlaid
   # with command line options.  So, in such a case, note that we ignore --user.

   create = options['--create-user']

   if create is None:
      user = options['--user']
   else:
     match = RE_CREATEUSER.match(create)
     if not match:
        print("Invalid format for --create-user argument: {0}".format(create))
        exit(1)
     udata = match.groupdict()
     try:
        maybe_create_user(udata['user'], udata['uid'] or None, udata['gid'] or None, 
                          udata['file'] and udata['file'].replace(r'\:', ':'),
                          options['--default-home'])
     except Exception as ex:
        print("--create-user failure: {0}".format(ex))
        exit(1)
     user = udata['user']

   extras = dict()
   if options['--ignore-failures']:
      extras['ignore_failures'] =  True
   if options['--no-syslog']:
      extras['enable_syslog'] = False
      
   try:
      config = Configuration.configFromCommandSpec(options['--config'], user=user, extra_settings=extras,
                                                   disable_console_log=options['--no-console-log'])
      services = config.get_services()
   except Exception as ex:
      error(ex, "Configuration Error: {0}", ex)
      exit(1)

   if not (services or cmd):
      print(MSG_NOTHING_TO_DO)
      exit(1)

   if options['--show-dependencies']:
      dg = services.get_dependency_graph()
      print("\n".join(dg))
      exit(0)

   if not cmd and options['--disable-services']:
      error("--disable-services not valid without specifying a command to run")
      exit(1)

   # Now, create the tlp and proceed

   tlp = TopLevelProcess(config)

   if options['--log-level']:
      tlp.force_log_level(options['--log-level'])

   if tlp.debug:
      config.dump()

   # Define here so we can share scope

   @asyncio.coroutine
   def startup_done():

      if options['--ignore-failures']:
         warn("ignoring failures on all service startups due to --ignore-failures")

      if options['--disable-services'] and services:
         warn("services will not be configured due to --disable-services")

      extra_services = None
      if cmd:
         cmdsvc = ServiceConfig.createConfig(config=config,
                                             name="CONSOLE",
                                             exec_args=[cmd] + options['<args>'],
                                             uid=user,
                                             kill_signal=("SIGHUP" if tty else None),
                                             setpgrp=not tty,
                                             exit_kills=kill_switch,
                                             service_groups="IDLE",
                                             ignore_failures=not options['--task'],
                                             stderr='inherit', stdout='inherit')
         extra_services = [cmdsvc]

      yield from tlp.run_services(extra_services, disable_others = options['--disable-services'])

      tlp.signal_ready()

   tlp.run_event_loop(startup_done())
Пример #7
0
 def _system_coro_check(self, f):
     if f.exception():
         error("system startup cancelled due to error: {0}".format(f.exception()))
         self.kill_system(get_errno_from_exception(f.exception()))
Пример #8
0
 def _queued_start(self, slist, names):
     try:
         yield from self.run(slist)
     except Exception as ex:
         error("queued start (for {0}) failed: {1}", names, ex)
Пример #9
0
 def logerror(self, *args, **kwargs):
     self.error_count += 1
     error(*args, facility=self.syslog_facility, **kwargs)
Пример #10
0
 def _queued_reset(self, slist, names):
     try:
         for s in slist:
             yield from s.reset(restarts_ok=True)
     except Exception as ex:
         error("queued reset (for {0}) failed: {1}", names, ex)
Пример #11
0
 def _queued_reset(self, slist, names):
     try:
         for s in slist:
             yield from s.reset(restarts_ok = True)
     except Exception as ex:
         error("queued reset (for {0}) failed: {1}", names, ex)
Пример #12
0
 def _queued_start(self, slist, names):
     try:
         yield from self.run(slist)
     except Exception as ex:
         error("queued start (for {0}) failed: {1}", names, ex)
Пример #13
0
 def logerror(self, *args, **kwargs):
     self.error_count += 1
     error(*args, facility=self.syslog_facility, **kwargs)
Пример #14
0
 def _system_coro_check(self, f):
     if f.exception():
         error("system startup cancelled due to error: {0}".format(
             f.exception()))
         self.kill_system(get_errno_from_exception(f.exception()))