예제 #1
0
파일: run.py 프로젝트: HowardMei/saltstack
    def run(self):
        '''
        Execute salt-run
        '''
        import salt.runner
        self.parse_args()

        # Setup file logging!
        self.setup_logfile_logger()
        verify_log(self.config)
        profiling_enabled = self.options.profiling_enabled

        runner = salt.runner.Runner(self.config)
        if self.options.doc:
            runner.print_docs()
            self.exit(salt.defaults.exitcodes.EX_OK)

        # Run this here so SystemExit isn't raised anywhere else when
        # someone tries to use the runners via the python API
        try:
            if check_user(self.config['user']):
                pr = activate_profile(profiling_enabled)
                try:
                    ret = runner.run()
                    if isinstance(ret, dict) and 'retcode' in ret:
                        self.exit(ret['retcode'])
                finally:
                    output_profile(
                        pr,
                        stats_path=self.options.profiling_path,
                        stop=True)

        except SaltClientError as exc:
            raise SystemExit(str(exc))
예제 #2
0
파일: daemons.py 프로젝트: bryson/salt
    def start(self):
        '''
        Start the actual proxy minion.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        '''
        super(ProxyMinion, self).start()
        try:
            if check_user(self.config['user']):
                self.action_log_info('The Proxy Minion is starting up')
                self.verify_hash_type()
                self.minion.tune_in()
                if self.minion.restart:
                    raise SaltClientError('Proxy Minion could not connect to Master')
        except (KeyboardInterrupt, SaltSystemExit) as exc:
            self.action_log_info('Proxy Minion Stopping')
            if isinstance(exc, KeyboardInterrupt):
                log.warning('Exiting on Ctrl-c')
                self.shutdown()
            else:
                log.error(str(exc))
                self.shutdown(exc.code)
예제 #3
0
    def start(self):
        '''
        Start the actual minion.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        '''
        reconnect = True
        while reconnect:
            reconnect = False
            try:
                self.prepare()
                if check_user(self.config['user']):
                    self.minion.tune_in()
            except (KeyboardInterrupt, SaltSystemExit) as exc:
                logger.warn('Stopping the Salt Minion')
                if isinstance(exc, KeyboardInterrupt):
                    logger.warn('Exiting on Ctrl-c')
                else:
                    logger.error(str(exc))
            except SaltClientError as exc:
                logger.error(exc)
                if self.config.get('restart_on_error'):
                    logger.warn('** Restarting minion **')
                    s = randint(0, self.config.get('random_reauth_delay', 10))
                    logger.info('Sleeping random_reauth_delay of {0} seconds'.format(s))
                    time.sleep(s)
                    reconnect = True
            finally:
                self.shutdown()
예제 #4
0
    def run(self):
        """
        Execute salt-run
        """
        self.parse_args()

        if self.config["verify_env"]:
            verify_env(
                [self.config["pki_dir"], self.config["cachedir"]],
                self.config["user"],
                permissive=self.config["permissive_pki_access"],
                pki_dir=self.config["pki_dir"],
            )
            if not self.config["log_file"].startswith(("tcp://", "udp://", "file://")):
                # Logfile is not using Syslog, verify
                verify_files([self.config["log_file"]], self.config["user"])

        # Setup file logging!
        self.setup_logfile_logger()

        runner = salt.runner.Runner(self.config)
        if self.options.doc:
            runner._print_docs()
            self.exit(salt.exitcodes.EX_OK)

        # Run this here so SystemExit isn't raised anywhere else when
        # someone tries to use the runners via the python API
        try:
            if check_user(self.config["user"]):
                runner.run()
        except SaltClientError as exc:
            raise SystemExit(str(exc))
예제 #5
0
파일: __init__.py 프로젝트: Adapptor/salt
    def start(self):
        '''
        Execute this method to start up a syndic.
        '''
        verify_env([self.opts['pki_dir'], self.opts['cachedir'],
                os.path.dirname(self.opts['log_file']),
                ],
                self.opts['user'])
        import salt.log
        salt.log.setup_logfile_logger(
            self.opts['log_file'], self.opts['log_level']
        )
        for name, level in self.opts['log_granular_levels'].items():
            salt.log.set_logger_level(name, level)

        import logging

        # Late import so logging works correctly
        import salt.minion
        log = logging.getLogger(__name__)
        if self.cli['daemon']:
            # Late import so logging works correctly
            import salt.utils
            salt.utils.daemonize()
        set_pidfile(self.cli['pidfile'])
        if check_user(self.opts['user'], log):
            try:
                syndic = salt.minion.Syndic(self.opts)
                syndic.tune_in()
            except KeyboardInterrupt:
                log.warn('Stopping the Salt Syndic Minion')
                raise SystemExit('\nExiting on Ctrl-c')
예제 #6
0
파일: __init__.py 프로젝트: Adapptor/salt
 def start(self):
     '''
     Run the sequence to start a salt master server
     '''
     verify_env([self.opts['pki_dir'],
                 os.path.join(self.opts['pki_dir'], 'minions'),
                 os.path.join(self.opts['pki_dir'], 'minions_pre'),
                 os.path.join(self.opts['pki_dir'], 'minions_rejected'),
                 self.opts['cachedir'],
                 os.path.join(self.opts['cachedir'], 'jobs'),
                 os.path.dirname(self.opts['log_file']),
                 self.opts['sock_dir'],
                 ],
                 self.opts['user'])
     import salt.log
     salt.log.setup_logfile_logger(
         self.opts['log_file'], self.opts['log_level']
     )
     for name, level in self.opts['log_granular_levels'].items():
         salt.log.set_logger_level(name, level)
     import logging
     log = logging.getLogger(__name__)
     # Late import so logging works correctly
     import salt.master
     master = salt.master.Master(self.opts)
     if self.cli['daemon']:
         # Late import so logging works correctly
         import salt.utils
         salt.utils.daemonize()
     set_pidfile(self.opts['pidfile'])
     if check_user(self.opts['user'], log):
         try:
             master.start()
         except salt.master.MasterExit:
             sys.exit()
예제 #7
0
    def call(self, cleanup_protecteds):
        '''
        Start the actual minion as a caller minion.

        cleanup_protecteds is list of yard host addresses that should not be
        cleaned up this is to fix race condition when salt-caller minion starts up

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        '''
        try:
            self.prepare()
            if check_user(self.config['user']):
                self.minion.opts['__role'] = kinds.APPL_KIND_NAMES[kinds.applKinds.caller]
                self.minion.opts['raet_cleanup_protecteds'] = cleanup_protecteds
                self.minion.call_in()
        except (KeyboardInterrupt, SaltSystemExit) as exc:
            log.warn('Stopping the Salt Minion')
            if isinstance(exc, KeyboardInterrupt):
                log.warn('Exiting on Ctrl-c')
                self.shutdown()
            else:
                log.error(str(exc))
                self.shutdown(exc.code)
예제 #8
0
파일: __init__.py 프로젝트: LinuxJedi/salt
 def start(self):
     '''
     Execute this method to start up a minion.
     '''
     verify_env([self.opts['pki_dir'],
         self.opts['cachedir'],
         self.opts['extension_modules'],
         os.path.dirname(self.opts['log_file']),
             ])
     import salt.log
     salt.log.setup_logfile_logger(
         self.opts['log_file'], self.opts['log_level']
     )
     for name, level in self.opts['log_granular_levels'].iteritems():
         salt.log.set_logger_level(name, level)
     import logging
     # Late import so logging works correctly
     import salt.minion
     log = logging.getLogger(__name__)
     if self.cli['daemon']:
         # Late import so logging works correctly
         import salt.utils
         # If the minion key has not been accepted, then Salt enters a loop
         # waiting for it, if we daemonize later then the minion cound halt
         # the boot process waiting for a key to be accepted on the master.
         # This is the latest safe place to daemonize
         salt.utils.daemonize()
     minion = salt.minion.Minion(self.opts)
     set_pidfile(self.cli['pidfile'])
     if check_user(self.opts['user'], log):
         try:
             minion.tune_in()
         except KeyboardInterrupt:
             log.warn('Stopping the Salt Minion')
             raise SystemExit('\nExiting on Ctrl-c')
예제 #9
0
 def start(self):
     '''
     Start broker.
     '''
     self.prepare()
     if check_user(self.config['user']):
         self.broker.start()
예제 #10
0
파일: setup.py 프로젝트: bryson/salt
def __process_multiprocessing_logging_queue(opts, queue):
    import salt.utils
    salt.utils.appendproctitle('MultiprocessingLoggingQueue')

    # Assign UID/GID of user to proc if set
    from salt.utils.verify import check_user
    user = opts.get('user')
    if user:
        check_user(user)

    if salt.utils.is_windows():
        # On Windows, creating a new process doesn't fork (copy the parent
        # process image). Due to this, we need to setup all of our logging
        # inside this process.
        setup_temp_logger()
        setup_console_logger(
            log_level=opts.get('log_level'),
            log_format=opts.get('log_fmt_console'),
            date_format=opts.get('log_datefmt_console')
        )
        setup_logfile_logger(
            opts.get('log_file'),
            log_level=opts.get('log_level_logfile'),
            log_format=opts.get('log_fmt_logfile'),
            date_format=opts.get('log_datefmt_logfile'),
            max_bytes=opts.get('log_rotate_max_bytes', 0),
            backup_count=opts.get('log_rotate_backup_count', 0)
        )
        setup_extended_logging(opts)
    while True:
        try:
            record = queue.get()
            if record is None:
                # A sentinel to stop processing the queue
                break
            # Just log everything, filtering will happen on the main process
            # logging handlers
            logger = logging.getLogger(record.name)
            logger.handle(record)
        except (EOFError, KeyboardInterrupt, SystemExit):
            break
        except Exception as exc:  # pylint: disable=broad-except
            logging.getLogger(__name__).warning(
                'An exception occurred in the multiprocessing logging '
                'queue thread: {0}'.format(exc),
                exc_info_on_loglevel=logging.DEBUG
            )
예제 #11
0
    def start(self):
        '''
        Start the actual master.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        '''
        self.prepare()
        if check_user(self.config['user']):
            self.master.start()
예제 #12
0
class Minion(parsers.MinionOptionParser):
    '''
    Create a minion server
    '''

    def start(self):
        '''
        Execute this method to start up a minion.
        '''
        self.parse_args()

        try:
            if self.config['verify_env']:
                verify_env([
                    self.config['pki_dir'],
                    self.config['cachedir'],
                    self.config['sock_dir'],
                    self.config['extension_modules'],
                    os.path.dirname(self.config['log_file']),
                ],
                self.config['user'],
                permissive=self.config['permissive_pki_access'],
                pki_dir=self.config['pki_dir'],
                )
        except OSError, err:
            sys.exit(err.errno)

        self.setup_logfile_logger()
        log = logging.getLogger(__name__)
        log.warn(
            'Setting up the Salt Minion "{0}"'.format(
                self.config['id']
            )
        )

        # Late import so logging works correctly
        import salt.minion
        # If the minion key has not been accepted, then Salt enters a loop
        # waiting for it, if we daemonize later then the minion could halt
        # the boot process waiting for a key to be accepted on the master.
        # This is the latest safe place to daemonize
        self.daemonize_if_required()
        try:
            minion = salt.minion.Minion(self.config)
            self.set_pidfile()
            if check_user(self.config['user']):
                minion.tune_in()
        except KeyboardInterrupt:
            log.warn('Stopping the Salt Minion')
            raise SystemExit('\nExiting on Ctrl-c')
예제 #13
0
    def test_no_user(self):
        # Catch sys.stderr here since no logging is configured and
        # check_user WILL write to sys.stderr
        class FakeWriter(object):
            def __init__(self):
                self.output = ""

            def write(self, data):
                self.output += data

        stderr = sys.stderr
        writer = FakeWriter()
        sys.stderr = writer
        # Now run the test
        if sys.platform.startswith('win'):
            self.assertTrue(check_user('nouser'))
        else:
            self.assertFalse(check_user('nouser'))
        # Restore sys.stderr
        sys.stderr = stderr
        if writer.output != 'CRITICAL: User not found: "nouser"\n':
            # If there's a different error catch, write it to sys.stderr
            sys.stderr.write(writer.output)
예제 #14
0
    def start(self):
        '''
        Start the actual master.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        '''
        super(Master, self).start()
        if check_user(self.config['user']):
            log.info('The salt master is starting up')
            self.master.start()
예제 #15
0
파일: api.py 프로젝트: nicholasmhughes/salt
    def start(self):
        """
        Start the actual master.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        """
        super().start()
        if check_user(self.config["user"]):
            log.info("The salt-api is starting up")
            self.api.run()
예제 #16
0
파일: key.py 프로젝트: fake-name/salt
    def run(self):
        """
        Execute salt-key
        """
        import salt.key

        self.parse_args()

        self.setup_logfile_logger()
        verify_log(self.config)

        key = salt.key.KeyCLI(self.config)
        if check_user(self.config['user']):
            key.run()
예제 #17
0
파일: daemons.py 프로젝트: saltyus/salt
    def start(self):
        '''
        Start the actual master.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        '''
        self.prepare()
        if check_user(self.config['user']):
            logger.info('The salt master is starting up')
            self.master.start()
예제 #18
0
파일: api.py 프로젝트: bryson/salt
    def start(self):
        """
        Start the actual master.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        """
        super(SaltAPI, self).start()
        if check_user(self.config["user"]):
            log.info("The salt-api is starting up")
            self.api.run()
예제 #19
0
class Master(parsers.MasterOptionParser):
    '''
    Creates a master server
    '''

    def start(self):
        '''
        Run the sequence to start a salt master server
        '''
        self.parse_args()

        try:
            if self.config['verify_env']:
                verify_env([
                    self.config['pki_dir'],
                    os.path.join(self.config['pki_dir'], 'minions'),
                    os.path.join(self.config['pki_dir'], 'minions_pre'),
                    os.path.join(self.config['pki_dir'], 'minions_rejected'),
                    self.config['cachedir'],
                    os.path.join(self.config['cachedir'], 'jobs'),
                    os.path.dirname(self.config['log_file']),
                    self.config['sock_dir'],
                    self.config['token_dir'],
                ],
                self.config['user'],
                permissive=self.config['permissive_pki_access'],
                pki_dir=self.config['pki_dir'],
                )
        except OSError, err:
            sys.exit(err.errno)

        self.setup_logfile_logger()
        logging.getLogger(__name__).warn('Setting up the Salt Master')

        # Late import so logging works correctly
        if not verify_socket(self.config['interface'],
                             self.config['publish_port'],
                             self.config['ret_port']):
            self.exit(4, 'The ports are not available to bind\n')

        import salt.master
        master = salt.master.Master(self.config)
        self.daemonize_if_required()
        self.set_pidfile()
        if check_user(self.config['user']):
            try:
                master.start()
            except salt.master.MasterExit:
                sys.exit()
예제 #20
0
파일: daemons.py 프로젝트: fake-name/salt
    def start(self):
        """
        Start the actual master.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        """
        super(Master, self).start()
        if check_user(self.config["user"]):
            self.action_log_info("Starting up")
            self.verify_hash_type()
            self.master.start()
예제 #21
0
    def start(self):
        '''
        Start the actual master.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        '''
        self.prepare()
        if check_user(self.config['user']):
            self.verify_hash_type()
            self.start_log_info()
            self.master.start()
예제 #22
0
파일: daemons.py 프로젝트: fake-name/salt
 def _real_start(self):
     try:
         if check_user(self.config["user"]):
             self.action_log_info("Starting up")
             self.verify_hash_type()
             self.minion.tune_in()
             if self.minion.restart:
                 raise SaltClientError("Minion could not connect to Master")
     except (KeyboardInterrupt, SaltSystemExit) as error:
         self.action_log_info("Stopping")
         if isinstance(error, KeyboardInterrupt):
             log.warning("Exiting on Ctrl-c")
             self.shutdown()
         else:
             log.error(error)
             self.shutdown(error.code)
예제 #23
0
파일: __init__.py 프로젝트: 1mentat/salt
    def start(self):
        '''
        Start the actual syndic.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        '''
        self.prepare()
        if check_user(self.config['user']):
            try:
                self.syndic.tune_in()
            except KeyboardInterrupt:
                logger.warn('Stopping the Salt Syndic Minion')
                self.shutdown()
예제 #24
0
파일: __init__.py 프로젝트: vicever/salt
    def start(self):
        '''
        Start the actual syndic.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        '''
        self.prepare()
        if check_user(self.config['user']):
            try:
                self.syndic.tune_in()
            except KeyboardInterrupt:
                logger.warn('Stopping the Salt Syndic Minion')
                self.shutdown()
예제 #25
0
    def run(self):
        '''
        Execute salt-key
        '''

        import salt.key
        self.parse_args()

        if self.config['verify_env']:
            verify_env_dirs = []
            if not self.config['gen_keys']:
                if self.config['transport'] == 'raet':
                    verify_env_dirs.extend([
                        self.config['pki_dir'],
                        os.path.join(self.config['pki_dir'], 'accepted'),
                        os.path.join(self.config['pki_dir'], 'pending'),
                        os.path.join(self.config['pki_dir'], 'rejected'),
                    ])
                elif self.config['transport'] == 'zeromq':
                    verify_env_dirs.extend([
                        self.config['pki_dir'],
                        os.path.join(self.config['pki_dir'], 'minions'),
                        os.path.join(self.config['pki_dir'], 'minions_pre'),
                        os.path.join(self.config['pki_dir'], 'minions_rejected'),
                    ])

            verify_env(
                verify_env_dirs,
                self.config['user'],
                permissive=self.config['permissive_pki_access'],
                pki_dir=self.config['pki_dir'],
            )
            if not self.config['log_file'].startswith(('tcp://',
                                                       'udp://',
                                                       'file://')):
                # Logfile is not using Syslog, verify
                verify_files(
                    [self.config['key_logfile']],
                    self.config['user']
                )

        self.setup_logfile_logger()

        key = salt.key.KeyCLI(self.config)
        if check_user(self.config['user']):
            key.run()
예제 #26
0
파일: __init__.py 프로젝트: gspradeep/salt
    def start(self):
        '''
        Run the sequence to start a salt master server
        '''
        self.parse_args()

        try:
            if self.config['verify_env']:
                verify_env([
                    self.config['pki_dir'],
                    os.path.join(self.config['pki_dir'], 'minions'),
                    os.path.join(self.config['pki_dir'], 'minions_pre'),
                    os.path.join(self.config['pki_dir'], 'minions_rejected'),
                    self.config['cachedir'],
                    os.path.join(self.config['cachedir'], 'jobs'),
                    os.path.join(self.config['cachedir'], 'proc'),
                    os.path.dirname(self.config['log_file']),
                    self.config['sock_dir'],
                    self.config['token_dir'],
                ],
                self.config['user'],
                permissive=self.config['permissive_pki_access'],
                pki_dir=self.config['pki_dir'],
                )
        except OSError as err:
            sys.exit(err.errno)

        self.setup_logfile_logger()
        logging.getLogger(__name__).warn('Setting up the Salt Master')

        # Late import so logging works correctly
        if not verify_socket(self.config['interface'],
                             self.config['publish_port'],
                             self.config['ret_port']):
            self.exit(4, 'The ports are not available to bind\n')
        migrations.migrate_paths(self.config)
        import salt.master
        master = salt.master.Master(self.config)
        self.daemonize_if_required()
        self.set_pidfile()
        if check_user(self.config['user']):
            try:
                master.start()
            except salt.master.MasterExit:
                sys.exit()
예제 #27
0
파일: __init__.py 프로젝트: vicever/salt
    def start(self):
        '''
        Start the actual master.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        '''
        self.prepare()
        if check_user(self.config['user']):
            try:
                self.master.start()
            except MasterExit:
                self.shutdown()
            finally:
                sys.exit()
예제 #28
0
파일: key.py 프로젝트: DaveQB/salt
    def run(self):
        '''
        Execute salt-key
        '''
        import salt.key
        self.parse_args()
        multi = False
        if self.config.get('zmq_behavior') and self.config.get('transport') == 'raet':
            multi = True

        self.setup_logfile_logger()

        if multi:
            key = salt.key.MultiKeyCLI(self.config)
        else:
            key = salt.key.KeyCLI(self.config)
        if check_user(self.config['user']):
            key.run()
예제 #29
0
    def run(self):
        '''
        Execute salt-key
        '''
        self.parse_args()

        if self.config['verify_env']:
            verify_env_dirs = []
            if not self.config['gen_keys']:
                if self.config['transport'] == 'raet':
                    verify_env_dirs.extend([
                        self.config['pki_dir'],
                        os.path.join(self.config['pki_dir'], 'accepted'),
                        os.path.join(self.config['pki_dir'], 'pending'),
                        os.path.join(self.config['pki_dir'], 'rejected'),
                    ])
                elif self.config['transport'] == 'zeromq':
                    verify_env_dirs.extend([
                        self.config['pki_dir'],
                        os.path.join(self.config['pki_dir'], 'minions'),
                        os.path.join(self.config['pki_dir'], 'minions_pre'),
                        os.path.join(self.config['pki_dir'], 'minions_rejected'),
                    ])

            verify_env(
                verify_env_dirs,
                self.config['user'],
                permissive=self.config['permissive_pki_access'],
                pki_dir=self.config['pki_dir'],
            )
            if not self.config['log_file'].startswith(('tcp://',
                                                       'udp://',
                                                       'file://')):
                # Logfile is not using Syslog, verify
                verify_files(
                    [self.config['key_logfile']],
                    self.config['user']
                )

        self.setup_logfile_logger()

        key = salt.key.KeyCLI(self.config)
        if check_user(self.config['user']):
            key.run()
예제 #30
0
파일: daemons.py 프로젝트: bryson/salt
    def start(self):
        '''
        Start the actual syndic.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        '''
        super(Syndic, self).start()
        if check_user(self.config['user']):
            self.action_log_info('Starting up')
            self.verify_hash_type()
            try:
                self.syndic.tune_in()
            except KeyboardInterrupt:
                self.action_log_info('Stopping')
                self.shutdown()
예제 #31
0
파일: daemons.py 프로젝트: fake-name/salt
    def start(self):
        """
        Start the actual syndic.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        """
        super(Syndic, self).start()
        if check_user(self.config["user"]):
            self.action_log_info("Starting up")
            self.verify_hash_type()
            try:
                self.syndic.tune_in()
            except KeyboardInterrupt:
                self.action_log_info("Stopping")
                self.shutdown()
예제 #32
0
class Syndic(parsers.SyndicOptionParser):
    '''
    Create a syndic server
    '''

    def start(self):
        '''
        Execute this method to start up a syndic.
        '''
        self.parse_args()
        try:
            if self.config['verify_env']:
                verify_env([
                        self.config['pki_dir'], self.config['cachedir'],
                        os.path.dirname(self.config['log_file']),
                    ],
                    self.config['user'],
                    permissive=self.config['permissive_pki_access'],
                    pki_dir=self.config['pki_dir'],
                )
        except OSError, err:
            sys.exit(err.errno)

        self.setup_logfile_logger()
        log = logging.getLogger(__name__)
        log.warn(
            'Setting up the Salt Syndic Minion "{0}"'.format(
                self.config['id']
            )
        )

        # Late import so logging works correctly
        import salt.minion
        self.daemonize_if_required()
        self.set_pidfile()

        if check_user(self.config['user']):
            try:
                syndic = salt.minion.Syndic(self.config)
                syndic.tune_in()
            except KeyboardInterrupt:
                log.warn('Stopping the Salt Syndic Minion')
                raise SystemExit('\nExiting on Ctrl-c')
예제 #33
0
파일: verify_test.py 프로젝트: herlo/salt
    def test_no_user(self):
        # Catch sys.stderr here since no logging is configured and
        # check_user WILL write to sys.stderr
        class FakeWriter(object):
            def __init__(self):
                self.output = ""

            def write(self, data):
                self.output += data
        stderr = sys.stderr
        writer = FakeWriter()
        sys.stderr = writer
        # Now run the test
        self.assertFalse(check_user('nouser'))
        # Restore sys.stderr
        sys.stderr = stderr
        if writer.output != 'CRITICAL: User not found: "nouser"\n':
            # If there's a different error catch, write it to sys.stderr
            sys.stderr.write(writer.output)
예제 #34
0
파일: daemons.py 프로젝트: waterdrops/salt
    def start(self):
        '''
        Start the actual master.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        '''
        self.prepare()
        if check_user(self.config['user']):
            logger.info('The salt master is starting up')
            try:
                self.master.start()
            except KeyboardInterrupt:
                logger.warn('The salt master is shutting down')
            finally:
                self.shutdown()
예제 #35
0
파일: __init__.py 프로젝트: gspradeep/salt
    def start(self):
        '''
        Execute this method to start up a minion.
        '''
        self.parse_args()

        try:
            if self.config['verify_env']:
                verify_env([
                    self.config['pki_dir'],
                    self.config['cachedir'],
                    self.config['sock_dir'],
                    self.config['extension_modules'],
                    os.path.dirname(self.config['log_file']),
                ],
                self.config['user'],
                permissive=self.config['permissive_pki_access'],
                pki_dir=self.config['pki_dir'],
                )
        except OSError as err:
            sys.exit(err.errno)

        self.setup_logfile_logger()
        log = logging.getLogger(__name__)
        log.warn(
            'Setting up the Salt Minion "{0}"'.format( self.config['id'])
        )
        migrations.migrate_paths(self.config)
        # Late import so logging works correctly
        import salt.minion
        # If the minion key has not been accepted, then Salt enters a loop
        # waiting for it, if we daemonize later then the minion could halt
        # the boot process waiting for a key to be accepted on the master.
        # This is the latest safe place to daemonize
        self.daemonize_if_required()
        try:
            minion = salt.minion.Minion(self.config)
            self.set_pidfile()
            if check_user(self.config['user']):
                minion.tune_in()
        except KeyboardInterrupt:
            log.warn('Stopping the Salt Minion')
            raise SystemExit('\nExiting on Ctrl-c')
예제 #36
0
파일: key.py 프로젝트: mjura/salt-1
    def run(self):
        '''
        Execute salt-key
        '''
        import salt.key
        self.parse_args()
        multi = False
        if self.config.get('zmq_behavior') and self.config.get(
                'transport') == 'raet':
            multi = True

        self.setup_logfile_logger()

        if multi:
            key = salt.key.MultiKeyCLI(self.config)
        else:
            key = salt.key.KeyCLI(self.config)
        if check_user(self.config['user']):
            key.run()
예제 #37
0
    def run(self):
        """
        Execute salt-key
        """
        self.parse_args()

        if self.config["verify_env"]:
            verify_env_dirs = []
            if not self.config["gen_keys"]:
                if self.config["transport"] == "raet":
                    verify_env_dirs.extend(
                        [
                            self.config["pki_dir"],
                            os.path.join(self.config["pki_dir"], "accepted"),
                            os.path.join(self.config["pki_dir"], "pending"),
                            os.path.join(self.config["pki_dir"], "rejected"),
                        ]
                    )
                elif self.config["transport"] == "zeromq":
                    verify_env_dirs.extend(
                        [
                            self.config["pki_dir"],
                            os.path.join(self.config["pki_dir"], "minions"),
                            os.path.join(self.config["pki_dir"], "minions_pre"),
                            os.path.join(self.config["pki_dir"], "minions_rejected"),
                        ]
                    )

            verify_env(
                verify_env_dirs,
                self.config["user"],
                permissive=self.config["permissive_pki_access"],
                pki_dir=self.config["pki_dir"],
            )
            if not self.config["log_file"].startswith(("tcp://", "udp://", "file://")):
                # Logfile is not using Syslog, verify
                verify_files([self.config["key_logfile"]], self.config["user"])

        self.setup_logfile_logger()

        key = salt.key.KeyCLI(self.config)
        if check_user(self.config["user"]):
            key.run()
예제 #38
0
    def start(self):
        '''
        Start the actual minion.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        '''
        self.prepare()
        try:
            if check_user(self.config['user']):
                self.minion.tune_in()
        except KeyboardInterrupt:
            logger.warn('Stopping the Salt Minion')
            self.shutdown()
        finally:
            raise SystemExit('\nExiting on Ctrl-c')
예제 #39
0
    def run(self):
        """
        Execute salt-run
        """
        import salt.runner

        self.parse_args()

        # Setup file logging!
        self.setup_logfile_logger()
        verify_log(self.config)
        profiling_enabled = self.options.profiling_enabled

        runner = salt.runner.Runner(self.config)
        if self.options.doc:
            runner.print_docs()
            self.exit(salt.defaults.exitcodes.EX_OK)

        # Run this here so SystemExit isn't raised anywhere else when
        # someone tries to use the runners via the python API
        try:
            if check_user(self.config["user"]):
                pr = salt.utils.profile.activate_profile(profiling_enabled)
                try:
                    ret = runner.run()
                    # In older versions ret['data']['retcode'] was used
                    # for signaling the return code. This has been
                    # changed for the orchestrate runner, but external
                    # runners might still use it. For this reason, we
                    # also check ret['data']['retcode'] if
                    # ret['retcode'] is not available.
                    if isinstance(ret, dict) and "retcode" in ret:
                        self.exit(ret["retcode"])
                    elif isinstance(ret, dict) and "retcode" in ret.get("data", {}):
                        self.exit(ret["data"]["retcode"])
                finally:
                    salt.utils.profile.output_profile(
                        pr, stats_path=self.options.profiling_path, stop=True
                    )

        except SaltClientError as exc:
            raise SystemExit(str(exc))
예제 #40
0
파일: daemons.py 프로젝트: vpsfreecz/salt
    def start(self):
        '''
        Start the actual minion.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        '''
        try:
            self.prepare()
            if check_user(self.config['user']):
                self.verify_hash_type()
                self.start_log_info()
                self.minion.tune_in()
                if self.minion.restart:
                    raise SaltClientError('Minion could not connect to Master')
        finally:
            self.shutdown()
예제 #41
0
    def start(self):
        '''
        Execute this method to start up a syndic.
        '''
        self.parse_args()
        try:
            if self.config['verify_env']:
                verify_env([
                    self.config['pki_dir'],
                    self.config['cachedir'],
                    self.config['sock_dir'],
                    self.config['extension_modules'],
                    os.path.dirname(self.config['log_file']),
                ],
                self.config['user'],
                permissive=self.config['permissive_pki_access'],
                pki_dir=self.config['pki_dir'],
                )
        except OSError as err:
            sys.exit(err.errno)

        self.setup_logfile_logger()
        log = logging.getLogger(__name__)
        log.warn(
            'Setting up the Salt Syndic Minion "{0}"'.format(
                self.config['id']
            )
        )

        # Late import so logging works correctly
        import salt.minion
        self.daemonize_if_required()
        self.set_pidfile()

        if check_user(self.config['user']):
            try:
                syndic = salt.minion.Syndic(self.config)
                syndic.tune_in()
            except KeyboardInterrupt:
                log.warn('Stopping the Salt Syndic Minion')
                raise SystemExit('\nExiting on Ctrl-c')
예제 #42
0
    def run(self):
        '''
        Execute salt-run
        '''
        import salt.runner
        self.parse_args()

        if self.config['verify_env']:
            verify_env([
                    self.config['pki_dir'],
                    self.config['cachedir'],
                ],
                self.config['user'],
                permissive=self.config['permissive_pki_access'],
                pki_dir=self.config['pki_dir'],
            )
            if not self.config['log_file'].startswith(('tcp://',
                                                       'udp://',
                                                       'file://')):
                # Logfile is not using Syslog, verify
                verify_files(
                    [self.config['log_file']],
                    self.config['user']
                )

        # Setup file logging!
        self.setup_logfile_logger()

        runner = salt.runner.Runner(self.config)
        if self.options.doc:
            runner.print_docs()
            self.exit(os.EX_OK)

        # Run this here so SystemExit isn't raised anywhere else when
        # someone tries to use the runners via the python API
        try:
            if check_user(self.config['user']):
                runner.run()
        except SaltClientError as exc:
            raise SystemExit(str(exc))
예제 #43
0
파일: __init__.py 프로젝트: 1mentat/salt
    def start(self):
        '''
        Start the actual minion.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        '''
        self.prepare()
        try:
            if check_user(self.config['user']):
                self.minion.tune_in()
        except (KeyboardInterrupt, SaltSystemExit) as exc:
            logger.warn('Stopping the Salt Minion')
            if isinstance(exc, KeyboardInterrupt):
                logger.warn('Exiting on Ctrl-c')
            else:
                logger.error(str(exc))
        finally:
            self.shutdown()
예제 #44
0
파일: run.py 프로젝트: zsjohny/salt
    def run(self):
        '''
        Execute salt-run
        '''
        import salt.runner
        self.parse_args()

        # Setup file logging!
        self.setup_logfile_logger()

        runner = salt.runner.Runner(self.config)
        if self.options.doc:
            runner.print_docs()
            self.exit(os.EX_OK)

        # Run this here so SystemExit isn't raised anywhere else when
        # someone tries to use the runners via the python API
        try:
            if check_user(self.config['user']):
                runner.run()
        except SaltClientError as exc:
            raise SystemExit(str(exc))
예제 #45
0
    def run(self):
        '''
        Execute salt-run
        '''
        self.parse_args()

        if self.config['verify_env']:
            verify_env([
                    self.config['pki_dir'],
                    self.config['cachedir'],
                ],
                self.config['user'],
                permissive=self.config['permissive_pki_access'],
                pki_dir=self.config['pki_dir'],
            )
            if (not self.config['log_file'].startswith('tcp://') or
                not self.config['log_file'].startswith('udp://') or
                not self.config['log_file'].startswith('file://')):
                # Logfile is not using Syslog, verify
                verify_files(
                    [self.config['log_file']],
                    self.config['user']
                )

        # Setup file logging!
        self.setup_logfile_logger()

        runner = salt.runner.Runner(self.config)
        if self.options.doc:
            runner._print_docs()
            self.exit(0)

        # Run this here so SystemExit isn't raised anywhere else when
        # someone tries to use the runners via the python API
        try:
            if check_user(self.config['user']):
                runner.run()
        except SaltClientError as exc:
            raise SystemExit(str(exc))
예제 #46
0
파일: __init__.py 프로젝트: vicever/salt
    def start(self):
        '''
        Start the actual minion.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        '''
        self.prepare()
        try:
            if check_user(self.config['user']):
                self.minion.tune_in()
        except (KeyboardInterrupt, SaltSystemExit) as exc:
            logger.warn('Stopping the Salt Minion')
            if isinstance(exc, KeyboardInterrupt):
                logger.warn('Exiting on Ctrl-c')
            else:
                logger.error(str(exc))
        finally:
            self.shutdown()
예제 #47
0
    def start(self):
        '''
        Start the actual proxy minion.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        '''
        super(ProxyMinion, self).start()
        try:
            if check_user(self.config['user']):
                log.info('The proxy minion is starting up')
                self.minion.tune_in()
        except (KeyboardInterrupt, SaltSystemExit) as exc:
            log.warn('Stopping the Salt Proxy Minion')
            if isinstance(exc, KeyboardInterrupt):
                log.warn('Exiting on Ctrl-c')
                self.shutdown()
            else:
                log.error(str(exc))
                self.shutdown(exc.code)
예제 #48
0
    def start(self):
        '''
        Start the actual minion.

        If sub-classed, don't **ever** forget to run:

            super(YourSubClass, self).start()

        NOTE: Run any required code before calling `super()`.
        '''
        super(Minion, self).start()
        try:
            if check_user(self.config['user']):
                self.action_log_info('Starting up')
                self.verify_hash_type()
                self.minion.tune_in()
        except (KeyboardInterrupt, SaltSystemExit) as error:
            self.action_log_info('Stopping')
            if isinstance(error, KeyboardInterrupt):
                log.warning('Exiting on Ctrl-c')
                self.shutdown()
            else:
                log.error(str(error))
                self.shutdown(error.code)
예제 #49
0
파일: cli.py 프로젝트: 1mentat/salt
    def run(self):
        '''
        Execute the salt-cloud command line
        '''
        if HAS_LIBCLOUD is False:
            self.error('salt-cloud requires >= libcloud 0.11.4')

        libcloud_version()

        # Parse shell arguments
        self.parse_args()

        salt_master_user = self.config.get('user', getpass.getuser())
        if salt_master_user is not None and not check_user(salt_master_user):
            self.error(
                'salt-cloud needs to run as the same user as salt-master, '
                '{0!r}, but was unable to switch credentials. Please run '
                'salt-cloud as root or as {0!r}'.format(salt_master_user)
            )

        try:
            if self.config['verify_env']:
                verify_env(
                    [os.path.dirname(self.config['conf_file'])],
                    salt_master_user
                )
                logfile = self.config['log_file']
                if logfile is not None and not logfile.startswith('tcp://') \
                        and not logfile.startswith('udp://') \
                        and not logfile.startswith('file://'):
                    # Logfile is not using Syslog, verify
                    verify_files([logfile], salt_master_user)
        except (IOError, OSError) as err:
            log.error('Error while verifying the environment: {0}'.format(err))
            sys.exit(err.errno)

        # Setup log file logging
        self.setup_logfile_logger()

        if self.options.update_bootstrap:
            import urllib2
            url = 'http://bootstrap.saltstack.org'
            req = urllib2.urlopen(url)
            if req.getcode() != 200:
                self.error(
                    'Failed to download the latest stable version of the '
                    'bootstrap-salt.sh script from {0}. HTTP error: '
                    '{1}'.format(
                        url, req.getcode()
                    )
                )

            for entry in self.config.get('deploy_scripts_search_path'):
                deploy_path = os.path.join(entry, 'bootstrap-salt.sh')
                try:
                    print(
                        'Updating bootstrap-salt.sh.'
                        '\n\tSource:      {0}'
                        '\n\tDestination: {1}'.format(
                            url,
                            deploy_path
                        )
                    )
                    with salt.utils.fopen(deploy_path, 'w') as fp_:
                        fp_.write(req.read())
                    # We were able to update, no need to continue trying to
                    # write up the search path
                    self.exit(0)
                except (OSError, IOError), err:
                    log.debug(
                        'Failed to write the updated script: {0}'.format(err)
                    )
                    continue
            self.error('Failed to update the bootstrap script')
예제 #50
0
파일: cli.py 프로젝트: HowardMei/saltstack
    def run(self):
        '''
        Execute the salt-cloud command line
        '''
        # Parse shell arguments
        self.parse_args()

        salt_master_user = self.config.get('user')
        if salt_master_user is None:
            salt_master_user = salt.utils.get_user()

        if not check_user(salt_master_user):
            self.error(
                'If salt-cloud is running on a master machine, salt-cloud '
                'needs to run as the same user as the salt-master, \'{0}\'. '
                'If salt-cloud is not running on a salt-master, the '
                'appropriate write permissions must be granted to \'{1}\'. '
                'Please run salt-cloud as root, \'{0}\', or change '
                'permissions for \'{1}\'.'.format(
                    salt_master_user,
                    syspaths.CONFIG_DIR
                )
            )

        try:
            if self.config['verify_env']:
                verify_env(
                    [os.path.dirname(self.config['conf_file'])],
                    salt_master_user
                )
                logfile = self.config['log_file']
                if logfile is not None and not logfile.startswith('tcp://') \
                        and not logfile.startswith('udp://') \
                        and not logfile.startswith('file://'):
                    # Logfile is not using Syslog, verify
                    verify_files([logfile], salt_master_user)
        except (IOError, OSError) as err:
            log.error('Error while verifying the environment: {0}'.format(err))
            sys.exit(err.errno)

        # Setup log file logging
        self.setup_logfile_logger()
        verify_log(self.config)

        if self.options.update_bootstrap:
            ret = salt.utils.cloud.update_bootstrap(self.config)
            salt.output.display_output(ret,
                                       self.options.output,
                                       opts=self.config)
            self.exit(salt.defaults.exitcodes.EX_OK)

        log.info('salt-cloud starting')
        try:
            mapper = salt.cloud.Map(self.config)
        except SaltCloudSystemExit as exc:
            self.handle_exception(exc.args, exc)
        except SaltCloudException as exc:
            msg = 'There was an error generating the mapper.'
            self.handle_exception(msg, exc)

        names = self.config.get('names', None)
        if names is not None:
            filtered_rendered_map = {}
            for map_profile in mapper.rendered_map:
                filtered_map_profile = {}
                for name in mapper.rendered_map[map_profile]:
                    if name in names:
                        filtered_map_profile[name] = mapper.rendered_map[map_profile][name]
                if filtered_map_profile:
                    filtered_rendered_map[map_profile] = filtered_map_profile
            mapper.rendered_map = filtered_rendered_map

        ret = {}

        if self.selected_query_option is not None:
            if self.selected_query_option == 'list_providers':
                try:
                    ret = mapper.provider_list()
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error listing providers: {0}'
                    self.handle_exception(msg, exc)

            elif self.selected_query_option == 'list_profiles':
                provider = self.options.list_profiles
                try:
                    ret = mapper.profile_list(provider)
                except(SaltCloudException, Exception) as exc:
                    msg = 'There was an error listing profiles: {0}'
                    self.handle_exception(msg, exc)

            elif self.config.get('map', None):
                log.info(
                    'Applying map from \'{0}\'.'.format(self.config['map'])
                )
                try:
                    ret = mapper.interpolated_map(
                        query=self.selected_query_option
                    )
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error with a custom map: {0}'
                    self.handle_exception(msg, exc)
            else:
                try:
                    ret = mapper.map_providers_parallel(
                        query=self.selected_query_option
                    )
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error with a map: {0}'
                    self.handle_exception(msg, exc)

        elif self.options.list_locations is not None:
            try:
                ret = mapper.location_list(
                    self.options.list_locations
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error listing locations: {0}'
                self.handle_exception(msg, exc)

        elif self.options.list_images is not None:
            try:
                ret = mapper.image_list(
                    self.options.list_images
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error listing images: {0}'
                self.handle_exception(msg, exc)

        elif self.options.list_sizes is not None:
            try:
                ret = mapper.size_list(
                    self.options.list_sizes
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error listing sizes: {0}'
                self.handle_exception(msg, exc)

        elif self.options.destroy and (self.config.get('names', None) or
                                       self.config.get('map', None)):
            map_file = self.config.get('map', None)
            names = self.config.get('names', ())
            if map_file is not None:
                if names != ():
                    msg = 'Supplying a mapfile, \'{0}\', in addition to instance names {1} ' \
                          'with the \'--destroy\' or \'-d\' function is not supported. ' \
                          'Please choose to delete either the entire map file or individual ' \
                          'instances.'.format(map_file, names)
                    self.handle_exception(msg, SaltCloudSystemExit)

                log.info('Applying map from \'{0}\'.'.format(map_file))
                matching = mapper.delete_map(query='list_nodes')
            else:
                matching = mapper.get_running_by_names(
                    names,
                    profile=self.options.profile
                )

            if not matching:
                print('No machines were found to be destroyed')
                self.exit(salt.defaults.exitcodes.EX_OK)

            msg = 'The following virtual machines are set to be destroyed:\n'
            names = set()
            for alias, drivers in six.iteritems(matching):
                msg += '  {0}:\n'.format(alias)
                for driver, vms in six.iteritems(drivers):
                    msg += '    {0}:\n'.format(driver)
                    for name in vms:
                        msg += '      {0}\n'.format(name)
                        names.add(name)
            try:
                if self.print_confirm(msg):
                    ret = mapper.destroy(names, cached=True)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error destroying machines: {0}'
                self.handle_exception(msg, exc)

        elif self.options.action and (self.config.get('names', None) or
                                      self.config.get('map', None)):
            if self.config.get('map', None):
                log.info(
                    'Applying map from \'{0}\'.'.format(self.config['map'])
                )
                try:
                    names = mapper.get_vmnames_by_action(self.options.action)
                except SaltCloudException as exc:
                    msg = 'There was an error actioning virtual machines.'
                    self.handle_exception(msg, exc)
            else:
                names = self.config.get('names', None)

            kwargs = {}
            machines = []
            msg = (
                'The following virtual machines are set to be actioned with '
                '"{0}":\n'.format(
                    self.options.action
                )
            )
            for name in names:
                if '=' in name:
                    # This is obviously not a machine name, treat it as a kwarg
                    key, value = name.split('=', 1)
                    kwargs[key] = value
                else:
                    msg += '  {0}\n'.format(name)
                    machines.append(name)
            names = machines

            try:
                if self.print_confirm(msg):
                    ret = mapper.do_action(names, kwargs)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error actioning machines: {0}'
                self.handle_exception(msg, exc)

        elif self.options.function:
            kwargs = {}
            args = self.args[:]
            for arg in args[:]:
                if '=' in arg:
                    key, value = arg.split('=', 1)
                    kwargs[key] = value
                    args.remove(arg)

            if args:
                self.error(
                    'Any arguments passed to --function need to be passed '
                    'as kwargs. Ex: image=ami-54cf5c3d. Remaining '
                    'arguments: {0}'.format(args)
                )
            try:
                ret = mapper.do_function(
                    self.function_provider, self.function_name, kwargs
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error running the function: {0}'
                self.handle_exception(msg, exc)

        elif self.options.profile and self.config.get('names', False):
            try:
                ret = mapper.run_profile(
                    self.options.profile,
                    self.config.get('names')
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was a profile error: {0}'
                self.handle_exception(msg, exc)

        elif self.options.set_password:
            username = self.credential_username
            provider_name = "salt.cloud.provider.{0}".format(self.credential_provider)
            # TODO: check if provider is configured
            # set the password
            salt.utils.cloud.store_password_in_keyring(provider_name, username)
        elif self.config.get('map', None) and \
                self.selected_query_option is None:
            if len(mapper.rendered_map) == 0:
                sys.stderr.write('No nodes defined in this map')
                self.exit(salt.defaults.exitcodes.EX_GENERIC)
            try:
                ret = {}
                run_map = True

                log.info(
                    'Applying map from \'{0}\'.'.format(self.config['map'])
                )
                dmap = mapper.map_data()

                msg = ''
                if 'errors' in dmap:
                    # display profile errors
                    msg += 'Found the following errors:\n'
                    for profile_name, error in six.iteritems(dmap['errors']):
                        msg += '  {0}: {1}\n'.format(profile_name, error)
                    sys.stderr.write(msg)
                    sys.stderr.flush()

                msg = ''
                if 'existing' in dmap:
                    msg += ('The following virtual machines already exist:\n')
                    for name in dmap['existing']:
                        msg += '  {0}\n'.format(name)

                if dmap['create']:
                    msg += ('The following virtual machines are set to be '
                            'created:\n')
                    for name in dmap['create']:
                        msg += '  {0}\n'.format(name)

                if 'destroy' in dmap:
                    msg += ('The following virtual machines are set to be '
                            'destroyed:\n')
                    for name in dmap['destroy']:
                        msg += '  {0}\n'.format(name)

                if not dmap['create'] and not dmap.get('destroy', None):
                    if not dmap.get('existing', None):
                        # nothing to create or destroy & nothing exists
                        print(msg)
                        self.exit(1)
                    else:
                        # nothing to create or destroy, print existing
                        run_map = False

                if run_map:
                    if self.print_confirm(msg):
                        ret = mapper.run_map(dmap)

                    if self.config.get('parallel', False) is False:
                        log.info('Complete')

                if dmap.get('existing', None):
                    for name in dmap['existing']:
                        if 'ec2' in dmap['existing'][name]['provider']:
                            msg = 'Instance already exists, or is terminated and has the same name.'
                        else:
                            msg = 'Already running.'
                        ret[name] = {'Message': msg}

            except (SaltCloudException, Exception) as exc:
                msg = 'There was a query error: {0}'
                self.handle_exception(msg, exc)

        elif self.options.bootstrap:
            host = self.options.bootstrap
            if len(self.args) > 0:
                if '=' not in self.args[0]:
                    minion_id = self.args.pop(0)
                else:
                    minion_id = host
            else:
                minion_id = host

            vm_ = {
                'driver': '',
                'ssh_host': host,
                'name': minion_id,
            }
            args = self.args[:]
            for arg in args[:]:
                if '=' in arg:
                    key, value = arg.split('=', 1)
                    vm_[key] = value
                    args.remove(arg)

            if args:
                self.error(
                    'Any arguments passed to --bootstrap need to be passed as '
                    'kwargs. Ex: ssh_username=larry. Remaining arguments: {0}'.format(args)
                )

            try:
                ret = salt.utils.cloud.bootstrap(vm_, self.config)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error bootstrapping the minion: {0}'
                self.handle_exception(msg, exc)

        else:
            self.error('Nothing was done. Using the proper arguments?')

        salt.output.display_output(ret,
                                   self.options.output,
                                   opts=self.config)
        self.exit(salt.defaults.exitcodes.EX_OK)
예제 #51
0
파일: cli.py 프로젝트: Anbcorp/salt
    def run(self):
        '''
        Execute the salt-cloud command line
        '''
        if HAS_LIBCLOUD is False:
            self.error('salt-cloud requires >= libcloud 0.11.4')

        libcloud_version()

        # Parse shell arguments
        self.parse_args()

        salt_master_user = self.config.get('user', salt.utils.get_user())
        if salt_master_user is not None and not check_user(salt_master_user):
            self.error(
                'salt-cloud needs to run as the same user as salt-master, '
                '{0!r}, but was unable to switch credentials. Please run '
                'salt-cloud as root or as {0!r}'.format(salt_master_user)
            )

        try:
            if self.config['verify_env']:
                verify_env(
                    [os.path.dirname(self.config['conf_file'])],
                    salt_master_user
                )
                logfile = self.config['log_file']
                if logfile is not None and not logfile.startswith('tcp://') \
                        and not logfile.startswith('udp://') \
                        and not logfile.startswith('file://'):
                    # Logfile is not using Syslog, verify
                    verify_files([logfile], salt_master_user)
        except (IOError, OSError) as err:
            log.error('Error while verifying the environment: {0}'.format(err))
            sys.exit(err.errno)

        # Setup log file logging
        self.setup_logfile_logger()

        if self.options.update_bootstrap:
            log.debug('Updating the bootstrap-salt.sh script to latest stable')
            import urllib2
            url = 'http://bootstrap.saltstack.org'
            req = urllib2.urlopen(url)
            if req.getcode() != 200:
                self.error(
                    'Failed to download the latest stable version of the '
                    'bootstrap-salt.sh script from {0}. HTTP error: '
                    '{1}'.format(
                        url, req.getcode()
                    )
                )

            # Get the path to the built-in deploy scripts directory
            builtin_deploy_dir = os.path.join(
                os.path.dirname(__file__),
                'deploy'
            )

            # Compute the search path from the current loaded opts conf_file
            # value
            deploy_d_from_conf_file = os.path.join(
                os.path.dirname(self.config['conf_file']),
                'cloud.deploy.d'
            )

            # Compute the search path using the install time defined
            # syspaths.CONF_DIR
            deploy_d_from_syspaths = os.path.join(
                syspaths.CONFIG_DIR,
                'cloud.deploy.d'
            )

            # Get a copy of any defined search paths, flagging them not to
            # create parent
            deploy_scripts_search_paths = []
            for entry in self.config.get('deploy_scripts_search_path', []):
                if entry.startswith(builtin_deploy_dir):
                    # We won't write the updated script to the built-in deploy
                    # directory
                    continue

                if entry in (deploy_d_from_conf_file, deploy_d_from_syspaths):
                    # Allow parent directories to be made
                    deploy_scripts_search_paths.append((entry, True))
                else:
                    deploy_scripts_search_paths.append((entry, False))

            # In case the user is not using defaults and the computed
            # 'cloud.deploy.d' from conf_file and syspaths is not included, add
            # them
            if deploy_d_from_conf_file not in deploy_scripts_search_paths:
                deploy_scripts_search_paths.append(
                    (deploy_d_from_conf_file, True)
                )
            if deploy_d_from_syspaths not in deploy_scripts_search_paths:
                deploy_scripts_search_paths.append(
                    (deploy_d_from_syspaths, True)
                )

            for entry, makedirs in deploy_scripts_search_paths:
                if makedirs and not os.path.isdir(entry):
                    try:
                        os.makedirs(entry)
                    except (OSError, IOError) as err:
                        log.info(
                            'Failed to create directory {0!r}'.format(entry)
                        )
                        continue

                if not is_writeable(entry):
                    log.debug(
                        'The {0!r} is not writeable. Continuing...'.format(
                            entry
                        )
                    )
                    continue

                deploy_path = os.path.join(entry, 'bootstrap-salt.sh')
                try:
                    print(
                        '\nUpdating \'bootstrap-salt.sh\':'
                        '\n\tSource:      {0}'
                        '\n\tDestination: {1}'.format(
                            url,
                            deploy_path
                        )
                    )
                    with salt.utils.fopen(deploy_path, 'w') as fp_:
                        fp_.write(req.read())
                    # We were able to update, no need to continue trying to
                    # write up the search path
                    self.exit(0)
                except (OSError, IOError) as err:
                    log.debug(
                        'Failed to write the updated script: {0}'.format(err)
                    )
                    continue

            self.error('Failed to update the bootstrap script')

        log.info('salt-cloud starting')
        mapper = salt.cloud.Map(self.config)

        ret = {}

        if self.selected_query_option is not None:
            if self.selected_query_option == 'list_providers':
                try:
                    ret = mapper.provider_list()
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error listing providers: {0}'
                    self.handle_exception(msg, exc)

            elif self.config.get('map', None):
                log.info('Applying map from {0!r}.'.format(self.config['map']))
                try:
                    ret = mapper.interpolated_map(
                        query=self.selected_query_option
                    )
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error with a custom map: {0}'
                    self.handle_exception(msg, exc)
            else:
                try:
                    ret = mapper.map_providers_parallel(
                        query=self.selected_query_option
                    )
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error with a map: {0}'
                    self.handle_exception(msg, exc)

        elif self.options.list_locations is not None:
            try:
                ret = mapper.location_list(
                    self.options.list_locations
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error listing locations: {0}'
                self.handle_exception(msg, exc)

        elif self.options.list_images is not None:
            try:
                ret = mapper.image_list(
                    self.options.list_images
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error listing images: {0}'
                self.handle_exception(msg, exc)

        elif self.options.list_sizes is not None:
            try:
                ret = mapper.size_list(
                    self.options.list_sizes
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error listing sizes: {0}'
                self.handle_exception(msg, exc)

        elif self.options.destroy and (self.config.get('names', None) or
                                       self.config.get('map', None)):
            if self.config.get('map', None):
                log.info('Applying map from {0!r}.'.format(self.config['map']))
                matching = mapper.delete_map(query='list_nodes')
            else:
                matching = mapper.get_running_by_names(
                    self.config.get('names', ())
                )

            if not matching:
                print('No machines were found to be destroyed')
                self.exit()

            msg = 'The following virtual machines are set to be destroyed:\n'
            names = set()
            for alias, drivers in matching.iteritems():
                msg += '  {0}:\n'.format(alias)
                for driver, vms in drivers.iteritems():
                    msg += '    {0}:\n'.format(driver)
                    for name in vms:
                        msg += '      {0}\n'.format(name)
                        names.add(name)
            try:
                if self.print_confirm(msg):
                    ret = mapper.destroy(names, cached=True)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error destroying machines: {0}'
                self.handle_exception(msg, exc)

        elif self.options.action and (self.config.get('names', None) or
                                      self.config.get('map', None)):
            if self.config.get('map', None):
                log.info('Applying map from {0!r}.'.format(self.config['map']))
                names = mapper.get_vmnames_by_action(self.options.action)
            else:
                names = self.config.get('names', None)

            kwargs = {}
            machines = []
            msg = (
                'The following virtual machines are set to be actioned with '
                '"{0}":\n'.format(
                    self.options.action
                )
            )
            for name in names:
                if '=' in name:
                    # This is obviously not a machine name, treat it as a kwarg
                    comps = name.split('=')
                    kwargs[comps[0]] = comps[1]
                else:
                    msg += '  {0}\n'.format(name)
                    machines.append(name)
            names = machines

            try:
                if self.print_confirm(msg):
                    ret = mapper.do_action(names, kwargs)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error actioning machines: {0}'
                self.handle_exception(msg, exc)

        elif self.options.function:
            kwargs = {}
            args = self.args[:]
            for arg in args[:]:
                if '=' in arg:
                    key, value = arg.split('=')
                    kwargs[key] = value
                    args.remove(arg)

            if args:
                self.error(
                    'Any arguments passed to --function need to be passed '
                    'as kwargs. Ex: image=ami-54cf5c3d. Remaining '
                    'arguments: {0}'.format(args)
                )
            try:
                ret = mapper.do_function(
                    self.function_provider, self.function_name, kwargs
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error running the function: {0}'
                self.handle_exception(msg, exc)

        elif self.options.profile and self.config.get('names', False):
            try:
                ret = mapper.run_profile(
                    self.options.profile,
                    self.config.get('names')
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was a profile error: {0}'
                self.handle_exception(msg, exc)

        elif self.config.get('map', None) and \
                self.selected_query_option is None:
            if len(mapper.rendered_map) == 0:
                sys.stderr.write('No nodes defined in this map')
                self.exit(1)
            try:
                ret = {}
                run_map = True

                log.info('Applying map from {0!r}.'.format(self.config['map']))
                dmap = mapper.map_data()

                msg = ''
                if 'errors' in dmap:
                    # display profile errors
                    msg += 'Found the following errors:\n'
                    for profile_name, error in dmap['errors'].iteritems():
                        msg += '  {0}: {1}\n'.format(profile_name, error)
                    sys.stderr.write(msg)
                    sys.stderr.flush()

                msg = ''
                if 'existing' in dmap:
                    msg += ('The following virtual machines were found '
                            'already running:\n')
                    for name in dmap['existing']:
                        msg += '  {0}\n'.format(name)

                if dmap['create']:
                    msg += ('The following virtual machines are set to be '
                            'created:\n')
                    for name in dmap['create']:
                        msg += '  {0}\n'.format(name)

                if 'destroy' in dmap:
                    msg += ('The following virtual machines are set to be '
                            'destroyed:\n')
                    for name in dmap['destroy']:
                        msg += '  {0}\n'.format(name)

                if not dmap['create'] and not dmap.get('destroy', None):
                    if not dmap.get('existing', None):
                        # nothing to create or destroy & nothing exists
                        print(msg)
                        self.exit(1)
                    else:
                        # nothing to create or destroy, print existing
                        run_map = False

                if run_map:
                    if self.print_confirm(msg):
                        ret = mapper.run_map(dmap)

                    if self.config.get('parallel', False) is False:
                        log.info('Complete')

                if dmap.get('existing', None):
                    for name in dmap['existing'].keys():
                        ret[name] = {'Message': 'Already running'}

            except (SaltCloudException, Exception) as exc:
                msg = 'There was a query error: {0}'
                self.handle_exception(msg, exc)

        else:
            self.error('Nothing was done. Using the proper arguments?')

        display_output = salt.output.get_printout(
            self.options.output, self.config
        )
        # display output using salt's outputter system
        print(display_output(ret))
        self.exit(0)
예제 #52
0
파일: cli.py 프로젝트: mzdaniel/salt
    def run(self):
        '''
        Execute the salt-cloud command line
        '''
        # Parse shell arguments
        self.parse_args()

        salt_master_user = self.config.get('user', salt.utils.get_user())
        if salt_master_user is not None and not check_user(salt_master_user):
            self.error(
                'If salt-cloud is running on a master machine, salt-cloud '
                'needs to run as the same user as the salt-master, {0!r}. If '
                'salt-cloud is not running on a salt-master, the appropriate '
                'write permissions must be granted to /etc/salt/. Please run '
                'salt-cloud as root, {0!r}, or change permissions for '
                '/etc/salt/.'.format(salt_master_user))

        try:
            if self.config['verify_env']:
                verify_env([os.path.dirname(self.config['conf_file'])],
                           salt_master_user)
                logfile = self.config['log_file']
                if logfile is not None and not logfile.startswith('tcp://') \
                        and not logfile.startswith('udp://') \
                        and not logfile.startswith('file://'):
                    # Logfile is not using Syslog, verify
                    verify_files([logfile], salt_master_user)
        except (IOError, OSError) as err:
            log.error('Error while verifying the environment: {0}'.format(err))
            sys.exit(err.errno)

        # Setup log file logging
        self.setup_logfile_logger()

        if self.options.update_bootstrap:
            ret = salt.utils.cloud.update_bootstrap(self.config)
            display_output = salt.output.get_printout(self.options.output,
                                                      self.config)
            print(display_output(ret))
            self.exit(os.EX_OK)

        log.info('salt-cloud starting')
        mapper = salt.cloud.Map(self.config)

        ret = {}

        if self.selected_query_option is not None:
            if self.selected_query_option == 'list_providers':
                try:
                    ret = mapper.provider_list()
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error listing providers: {0}'
                    self.handle_exception(msg, exc)

            elif self.config.get('map', None):
                log.info('Applying map from {0!r}.'.format(self.config['map']))
                try:
                    ret = mapper.interpolated_map(
                        query=self.selected_query_option)
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error with a custom map: {0}'
                    self.handle_exception(msg, exc)
            else:
                try:
                    ret = mapper.map_providers_parallel(
                        query=self.selected_query_option)
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error with a map: {0}'
                    self.handle_exception(msg, exc)

        elif self.options.list_locations is not None:
            try:
                ret = mapper.location_list(self.options.list_locations)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error listing locations: {0}'
                self.handle_exception(msg, exc)

        elif self.options.list_images is not None:
            try:
                ret = mapper.image_list(self.options.list_images)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error listing images: {0}'
                self.handle_exception(msg, exc)

        elif self.options.list_sizes is not None:
            try:
                ret = mapper.size_list(self.options.list_sizes)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error listing sizes: {0}'
                self.handle_exception(msg, exc)

        elif self.options.destroy and (self.config.get('names', None)
                                       or self.config.get('map', None)):
            if self.config.get('map', None):
                log.info('Applying map from {0!r}.'.format(self.config['map']))
                matching = mapper.delete_map(query='list_nodes')
            else:
                matching = mapper.get_running_by_names(
                    self.config.get('names', ()), profile=self.options.profile)

            if not matching:
                print('No machines were found to be destroyed')
                self.exit(os.EX_OK)

            msg = 'The following virtual machines are set to be destroyed:\n'
            names = set()
            for alias, drivers in matching.iteritems():
                msg += '  {0}:\n'.format(alias)
                for driver, vms in drivers.iteritems():
                    msg += '    {0}:\n'.format(driver)
                    for name in vms:
                        msg += '      {0}\n'.format(name)
                        names.add(name)
            try:
                if self.print_confirm(msg):
                    ret = mapper.destroy(names, cached=True)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error destroying machines: {0}'
                self.handle_exception(msg, exc)

        elif self.options.action and (self.config.get('names', None)
                                      or self.config.get('map', None)):
            if self.config.get('map', None):
                log.info('Applying map from {0!r}.'.format(self.config['map']))
                names = mapper.get_vmnames_by_action(self.options.action)
            else:
                names = self.config.get('names', None)

            kwargs = {}
            machines = []
            msg = (
                'The following virtual machines are set to be actioned with '
                '"{0}":\n'.format(self.options.action))
            for name in names:
                if '=' in name:
                    # This is obviously not a machine name, treat it as a kwarg
                    comps = name.split('=')
                    kwargs[comps[0]] = comps[1]
                else:
                    msg += '  {0}\n'.format(name)
                    machines.append(name)
            names = machines

            try:
                if self.print_confirm(msg):
                    ret = mapper.do_action(names, kwargs)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error actioning machines: {0}'
                self.handle_exception(msg, exc)

        elif self.options.function:
            kwargs = {}
            args = self.args[:]
            for arg in args[:]:
                if '=' in arg:
                    key, value = arg.split('=')
                    kwargs[key] = value
                    args.remove(arg)

            if args:
                self.error(
                    'Any arguments passed to --function need to be passed '
                    'as kwargs. Ex: image=ami-54cf5c3d. Remaining '
                    'arguments: {0}'.format(args))
            try:
                ret = mapper.do_function(self.function_provider,
                                         self.function_name, kwargs)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error running the function: {0}'
                self.handle_exception(msg, exc)

        elif self.options.profile and self.config.get('names', False):
            try:
                ret = mapper.run_profile(self.options.profile,
                                         self.config.get('names'))
            except (SaltCloudException, Exception) as exc:
                msg = 'There was a profile error: {0}'
                self.handle_exception(msg, exc)

        elif self.options.set_password:
            username = self.credential_username
            provider_name = "salt.cloud.provider.{0}".format(
                self.credential_provider)
            # TODO: check if provider is configured
            # set the password
            salt.utils.cloud.store_password_in_keyring(provider_name, username)
        elif self.config.get('map', None) and \
                self.selected_query_option is None:
            if len(mapper.rendered_map) == 0:
                sys.stderr.write('No nodes defined in this map')
                self.exit(salt.exitcodes.EX_GENERIC)
            try:
                ret = {}
                run_map = True

                log.info('Applying map from {0!r}.'.format(self.config['map']))
                dmap = mapper.map_data()

                msg = ''
                if 'errors' in dmap:
                    # display profile errors
                    msg += 'Found the following errors:\n'
                    for profile_name, error in dmap['errors'].iteritems():
                        msg += '  {0}: {1}\n'.format(profile_name, error)
                    sys.stderr.write(msg)
                    sys.stderr.flush()

                msg = ''
                if 'existing' in dmap:
                    msg += ('The following virtual machines already exist:\n')
                    for name in dmap['existing']:
                        msg += '  {0}\n'.format(name)

                if dmap['create']:
                    msg += ('The following virtual machines are set to be '
                            'created:\n')
                    for name in dmap['create']:
                        msg += '  {0}\n'.format(name)

                if 'destroy' in dmap:
                    msg += ('The following virtual machines are set to be '
                            'destroyed:\n')
                    for name in dmap['destroy']:
                        msg += '  {0}\n'.format(name)

                if not dmap['create'] and not dmap.get('destroy', None):
                    if not dmap.get('existing', None):
                        # nothing to create or destroy & nothing exists
                        print(msg)
                        self.exit(1)
                    else:
                        # nothing to create or destroy, print existing
                        run_map = False

                if run_map:
                    if self.print_confirm(msg):
                        ret = mapper.run_map(dmap)

                    if self.config.get('parallel', False) is False:
                        log.info('Complete')

                if dmap.get('existing', None):
                    for name in dmap['existing'].keys():
                        ret[name] = {'Message': 'Already running'}

            except (SaltCloudException, Exception) as exc:
                msg = 'There was a query error: {0}'
                self.handle_exception(msg, exc)

        else:
            self.error('Nothing was done. Using the proper arguments?')

        display_output = salt.output.get_printout(self.options.output,
                                                  self.config)
        # display output using salt's outputter system
        print(display_output(ret))
        self.exit(os.EX_OK)
예제 #53
0
    def run(self):
        """
        Execute the salt-cloud command line
        """
        # Parse shell arguments
        self.parse_args()

        salt_master_user = self.config.get("user")
        if salt_master_user is None:
            salt_master_user = salt.utils.user.get_user()

        if not check_user(salt_master_user):
            self.error(
                "If salt-cloud is running on a master machine, salt-cloud "
                "needs to run as the same user as the salt-master, '{0}'. "
                "If salt-cloud is not running on a salt-master, the "
                "appropriate write permissions must be granted to '{1}'. "
                "Please run salt-cloud as root, '{0}', or change "
                "permissions for '{1}'.".format(salt_master_user,
                                                syspaths.CONFIG_DIR))

        try:
            if self.config["verify_env"]:
                verify_env(
                    [os.path.dirname(self.config["conf_file"])],
                    salt_master_user,
                    root_dir=self.config["root_dir"],
                )
                logfile = self.config["log_file"]
                if logfile is not None:
                    # Logfile is not using Syslog, verify
                    verify_log_files([logfile], salt_master_user)
        except (IOError, OSError) as err:
            log.error("Error while verifying the environment: %s", err)
            sys.exit(err.errno)

        # Setup log file logging
        self.setup_logfile_logger()
        verify_log(self.config)

        if self.options.update_bootstrap:
            ret = salt.utils.cloud.update_bootstrap(self.config)
            salt.output.display_output(ret,
                                       self.options.output,
                                       opts=self.config)
            self.exit(salt.defaults.exitcodes.EX_OK)

        log.info("salt-cloud starting")
        try:
            mapper = salt.cloud.Map(self.config)
        except SaltCloudSystemExit as exc:
            self.handle_exception(exc.args, exc)
        except SaltCloudException as exc:
            msg = "There was an error generating the mapper."
            self.handle_exception(msg, exc)

        names = self.config.get("names", None)
        if names is not None:
            filtered_rendered_map = {}
            for map_profile in mapper.rendered_map:
                filtered_map_profile = {}
                for name in mapper.rendered_map[map_profile]:
                    if name in names:
                        filtered_map_profile[name] = mapper.rendered_map[
                            map_profile][name]
                if filtered_map_profile:
                    filtered_rendered_map[map_profile] = filtered_map_profile
            mapper.rendered_map = filtered_rendered_map

        ret = {}

        if self.selected_query_option is not None:
            if self.selected_query_option == "list_providers":
                # pylint: disable=broad-except
                try:
                    ret = mapper.provider_list()
                except (
                        SaltCloudException,
                        Exception,
                ) as exc:
                    msg = "There was an error listing providers: {0}"
                    self.handle_exception(msg, exc)
                # pylint: enable=broad-except

            elif self.selected_query_option == "list_profiles":
                provider = self.options.list_profiles
                # pylint: disable=broad-except
                try:
                    ret = mapper.profile_list(provider)
                except (
                        SaltCloudException,
                        Exception,
                ) as exc:
                    msg = "There was an error listing profiles: {0}"
                    self.handle_exception(msg, exc)
                # pylint: enable=broad-except

            elif self.config.get("map", None):
                log.info("Applying map from '%s'.", self.config["map"])
                # pylint: disable=broad-except
                try:
                    ret = mapper.interpolated_map(
                        query=self.selected_query_option)
                except (
                        SaltCloudException,
                        Exception,
                ) as exc:
                    msg = "There was an error with a custom map: {0}"
                    self.handle_exception(msg, exc)
                # pylint: enable=broad-except
            else:
                # pylint: disable=broad-except
                try:
                    ret = mapper.map_providers_parallel(
                        query=self.selected_query_option)
                except (
                        SaltCloudException,
                        Exception,
                ) as exc:
                    msg = "There was an error with a map: {0}"
                    self.handle_exception(msg, exc)
                # pylint: enable=broad-except

        elif self.options.list_locations is not None:
            # pylint: disable=broad-except
            try:
                ret = mapper.location_list(self.options.list_locations)
            except (
                    SaltCloudException,
                    Exception,
            ) as exc:
                msg = "There was an error listing locations: {0}"
                self.handle_exception(msg, exc)
            # pylint: enable=broad-except

        elif self.options.list_images is not None:
            # pylint: disable=broad-except
            try:
                ret = mapper.image_list(self.options.list_images)
            except (
                    SaltCloudException,
                    Exception,
            ) as exc:
                msg = "There was an error listing images: {0}"
                self.handle_exception(msg, exc)
            # pylint: enable=broad-except

        elif self.options.list_sizes is not None:
            # pylint: disable=broad-except
            try:
                ret = mapper.size_list(self.options.list_sizes)
            except (
                    SaltCloudException,
                    Exception,
            ) as exc:
                msg = "There was an error listing sizes: {0}"
                self.handle_exception(msg, exc)
            # pylint: enable=broad-except

        elif self.options.destroy and (self.config.get("names", None)
                                       or self.config.get("map", None)):
            map_file = self.config.get("map", None)
            names = self.config.get("names", ())
            if map_file is not None:
                if names != ():
                    msg = (
                        "Supplying a mapfile, '{0}', in addition to instance names {1} "
                        "with the '--destroy' or '-d' function is not supported. "
                        "Please choose to delete either the entire map file or individual "
                        "instances.".format(map_file, names))
                    self.handle_exception(msg, SaltCloudSystemExit)

                log.info("Applying map from '%s'.", map_file)
                matching = mapper.delete_map(query="list_nodes")
            else:
                matching = mapper.get_running_by_names(
                    names, profile=self.options.profile)

            if not matching:
                print("No machines were found to be destroyed")
                self.exit(salt.defaults.exitcodes.EX_OK)

            msg = "The following virtual machines are set to be destroyed:\n"
            names = set()
            for alias, drivers in six.iteritems(matching):
                msg += "  {0}:\n".format(alias)
                for driver, vms in six.iteritems(drivers):
                    msg += "    {0}:\n".format(driver)
                    for name in vms:
                        msg += "      {0}\n".format(name)
                        names.add(name)
            # pylint: disable=broad-except
            try:
                if self.print_confirm(msg):
                    ret = mapper.destroy(names, cached=True)
            except (
                    SaltCloudException,
                    Exception,
            ) as exc:
                msg = "There was an error destroying machines: {0}"
                self.handle_exception(msg, exc)
            # pylint: enable=broad-except

        elif self.options.action and (self.config.get("names", None)
                                      or self.config.get("map", None)):
            if self.config.get("map", None):
                log.info("Applying map from '%s'.", self.config["map"])
                try:
                    names = mapper.get_vmnames_by_action(self.options.action)
                except SaltCloudException as exc:
                    msg = "There was an error actioning virtual machines."
                    self.handle_exception(msg, exc)
            else:
                names = self.config.get("names", None)

            kwargs = {}
            machines = []
            msg = (
                "The following virtual machines are set to be actioned with "
                '"{0}":\n'.format(self.options.action))
            for name in names:
                if "=" in name:
                    # This is obviously not a machine name, treat it as a kwarg
                    key, value = name.split("=", 1)
                    kwargs[key] = value
                else:
                    msg += "  {0}\n".format(name)
                    machines.append(name)
            names = machines

            # pylint: disable=broad-except
            try:
                if self.print_confirm(msg):
                    ret = mapper.do_action(names, kwargs)
            except (
                    SaltCloudException,
                    Exception,
            ) as exc:
                msg = "There was an error actioning machines: {0}"
                self.handle_exception(msg, exc)
            # pylint: enable=broad-except

        elif self.options.function:
            kwargs = {}
            args = self.args[:]
            for arg in args[:]:
                if "=" in arg:
                    key, value = arg.split("=", 1)
                    kwargs[key] = value
                    args.remove(arg)

            if args:
                self.error(
                    "Any arguments passed to --function need to be passed "
                    "as kwargs. Ex: image=ami-54cf5c3d. Remaining "
                    "arguments: {0}".format(args))
            # pylint: disable=broad-except
            try:
                ret = mapper.do_function(self.function_provider,
                                         self.function_name, kwargs)
            except (
                    SaltCloudException,
                    Exception,
            ) as exc:
                msg = "There was an error running the function: {0}"
                self.handle_exception(msg, exc)
            # pylint: enable=broad-except

        elif self.options.profile and self.config.get("names", False):
            # pylint: disable=broad-except
            try:
                ret = mapper.run_profile(self.options.profile,
                                         self.config.get("names"))
            except (
                    SaltCloudException,
                    Exception,
            ) as exc:
                msg = "There was a profile error: {0}"
                self.handle_exception(msg, exc)
            # pylint: enable=broad-except

        elif self.options.set_password:
            username = self.credential_username
            provider_name = "salt.cloud.provider.{0}".format(
                self.credential_provider)
            # TODO: check if provider is configured
            # set the password
            salt.utils.cloud.store_password_in_keyring(provider_name, username)
        elif self.config.get("map",
                             None) and self.selected_query_option is None:
            if not mapper.rendered_map:
                sys.stderr.write("No nodes defined in this map")
                self.exit(salt.defaults.exitcodes.EX_GENERIC)
            # pylint: disable=broad-except
            try:
                ret = {}
                run_map = True

                log.info("Applying map from '%s'.", self.config["map"])
                dmap = mapper.map_data()

                msg = ""
                if "errors" in dmap:
                    # display profile errors
                    msg += "Found the following errors:\n"
                    for profile_name, error in six.iteritems(dmap["errors"]):
                        msg += "  {0}: {1}\n".format(profile_name, error)
                    sys.stderr.write(msg)
                    sys.stderr.flush()

                msg = ""
                if "existing" in dmap:
                    msg += "The following virtual machines already exist:\n"
                    for name in dmap["existing"]:
                        msg += "  {0}\n".format(name)

                if dmap["create"]:
                    msg += "The following virtual machines are set to be " "created:\n"
                    for name in dmap["create"]:
                        msg += "  {0}\n".format(name)

                if "destroy" in dmap:
                    msg += ("The following virtual machines are set to be "
                            "destroyed:\n")
                    for name in dmap["destroy"]:
                        msg += "  {0}\n".format(name)

                if not dmap["create"] and not dmap.get("destroy", None):
                    if not dmap.get("existing", None):
                        # nothing to create or destroy & nothing exists
                        print(msg)
                        self.exit(1)
                    else:
                        # nothing to create or destroy, print existing
                        run_map = False

                if run_map:
                    if self.print_confirm(msg):
                        ret = mapper.run_map(dmap)

                    if self.config.get("parallel", False) is False:
                        log.info("Complete")

                if dmap.get("existing", None):
                    for name in dmap["existing"]:
                        if "ec2" in dmap["existing"][name]["provider"]:
                            msg = "Instance already exists, or is terminated and has the same name."
                        else:
                            msg = "Already running."
                        ret[name] = {"Message": msg}

            except (
                    SaltCloudException,
                    Exception,
            ) as exc:
                msg = "There was a query error: {0}"
                self.handle_exception(msg, exc)
            # pylint: enable=broad-except

        elif self.options.bootstrap:
            host = self.options.bootstrap
            if self.args and "=" not in self.args[0]:
                minion_id = self.args.pop(0)
            else:
                minion_id = host

            vm_ = {
                "driver": "",
                "ssh_host": host,
                "name": minion_id,
            }
            args = self.args[:]
            for arg in args[:]:
                if "=" in arg:
                    key, value = arg.split("=", 1)
                    vm_[key] = value
                    args.remove(arg)

            if args:
                self.error(
                    "Any arguments passed to --bootstrap need to be passed as "
                    "kwargs. Ex: ssh_username=larry. Remaining arguments: {0}".
                    format(args))

            # pylint: disable=broad-except
            try:
                ret = salt.utils.cloud.bootstrap(vm_, self.config)
            except (
                    SaltCloudException,
                    Exception,
            ) as exc:
                msg = "There was an error bootstrapping the minion: {0}"
                self.handle_exception(msg, exc)
            # pylint: enable=broad-except

        else:
            self.error("Nothing was done. Using the proper arguments?")

        salt.output.display_output(ret, self.options.output, opts=self.config)
        self.exit(salt.defaults.exitcodes.EX_OK)
예제 #54
0
파일: verify_test.py 프로젝트: herlo/salt
 def test_user(self):
     self.assertTrue(check_user(getpass.getuser()))
예제 #55
0
    def run(self):
        '''
        Execute the salt-cloud command line
        '''
        # Parse shell arguments
        self.parse_args()

        salt_master_user = self.config.get('user')
        if salt_master_user is None:
            salt_master_user = salt.utils.get_user()

        if not check_user(salt_master_user):
            self.error(
                'If salt-cloud is running on a master machine, salt-cloud '
                'needs to run as the same user as the salt-master, \'{0}\'. '
                'If salt-cloud is not running on a salt-master, the '
                'appropriate write permissions must be granted to \'{1}\'. '
                'Please run salt-cloud as root, \'{0}\', or change '
                'permissions for \'{1}\'.'.format(salt_master_user,
                                                  syspaths.CONFIG_DIR))

        try:
            if self.config['verify_env']:
                verify_env([os.path.dirname(self.config['conf_file'])],
                           salt_master_user)
                logfile = self.config['log_file']
                if logfile is not None and not logfile.startswith('tcp://') \
                        and not logfile.startswith('udp://') \
                        and not logfile.startswith('file://'):
                    # Logfile is not using Syslog, verify
                    verify_files([logfile], salt_master_user)
        except (IOError, OSError) as err:
            log.error('Error while verifying the environment: {0}'.format(err))
            sys.exit(err.errno)

        # Setup log file logging
        self.setup_logfile_logger()
        verify_log(self.config)

        if self.options.update_bootstrap:
            ret = salt.utils.cloud.update_bootstrap(self.config)
            display_output = salt.output.get_printout(self.options.output,
                                                      self.config)
            print(display_output(ret))
            self.exit(salt.defaults.exitcodes.EX_OK)

        log.info('salt-cloud starting')
        try:
            mapper = salt.cloud.Map(self.config)
        except SaltCloudException as exc:
            msg = 'There was an error generating the mapper.'
            self.handle_exception(msg, exc)

        names = self.config.get('names', None)
        if names is not None:
            filtered_rendered_map = {}
            for map_profile in mapper.rendered_map:
                filtered_map_profile = {}
                for name in mapper.rendered_map[map_profile]:
                    if name in names:
                        filtered_map_profile[name] = mapper.rendered_map[
                            map_profile][name]
                if filtered_map_profile:
                    filtered_rendered_map[map_profile] = filtered_map_profile
            mapper.rendered_map = filtered_rendered_map

        ret = {}

        if self.selected_query_option is not None:
            if self.selected_query_option == 'list_providers':
                try:
                    ret = mapper.provider_list()
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error listing providers: {0}'
                    self.handle_exception(msg, exc)

            elif self.selected_query_option == 'list_profiles':
                provider = self.options.list_profiles
                try:
                    ret = mapper.profile_list(provider)
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error listing profiles: {0}'
                    self.handle_exception(msg, exc)

            elif self.config.get('map', None):
                log.info('Applying map from \'{0}\'.'.format(
                    self.config['map']))
                try:
                    ret = mapper.interpolated_map(
                        query=self.selected_query_option)
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error with a custom map: {0}'
                    self.handle_exception(msg, exc)
            else:
                try:
                    ret = mapper.map_providers_parallel(
                        query=self.selected_query_option)
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error with a map: {0}'
                    self.handle_exception(msg, exc)

        elif self.options.list_locations is not None:
            try:
                ret = mapper.location_list(self.options.list_locations)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error listing locations: {0}'
                self.handle_exception(msg, exc)

        elif self.options.list_images is not None:
            try:
                ret = mapper.image_list(self.options.list_images)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error listing images: {0}'
                self.handle_exception(msg, exc)

        elif self.options.list_sizes is not None:
            try:
                ret = mapper.size_list(self.options.list_sizes)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error listing sizes: {0}'
                self.handle_exception(msg, exc)

        elif self.options.destroy and (self.config.get('names', None)
                                       or self.config.get('map', None)):
            map_file = self.config.get('map', None)
            names = self.config.get('names', ())
            if map_file is not None:
                if names != ():
                    msg = 'Supplying a mapfile, \'{0}\', in addition to instance names {1} ' \
                          'with the \'--destroy\' or \'-d\' function is not supported. ' \
                          'Please choose to delete either the entire map file or individual ' \
                          'instances.'.format(map_file, names)
                    self.handle_exception(msg, SaltCloudSystemExit)

                log.info('Applying map from \'{0}\'.'.format(map_file))
                matching = mapper.delete_map(query='list_nodes')
            else:
                matching = mapper.get_running_by_names(
                    names, profile=self.options.profile)

            if not matching:
                print('No machines were found to be destroyed')
                self.exit(salt.defaults.exitcodes.EX_OK)

            msg = 'The following virtual machines are set to be destroyed:\n'
            names = set()
            for alias, drivers in six.iteritems(matching):
                msg += '  {0}:\n'.format(alias)
                for driver, vms in six.iteritems(drivers):
                    msg += '    {0}:\n'.format(driver)
                    for name in vms:
                        msg += '      {0}\n'.format(name)
                        names.add(name)
            try:
                if self.print_confirm(msg):
                    ret = mapper.destroy(names, cached=True)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error destroying machines: {0}'
                self.handle_exception(msg, exc)

        elif self.options.action and (self.config.get('names', None)
                                      or self.config.get('map', None)):
            if self.config.get('map', None):
                log.info('Applying map from \'{0}\'.'.format(
                    self.config['map']))
                try:
                    names = mapper.get_vmnames_by_action(self.options.action)
                except SaltCloudException as exc:
                    msg = 'There was an error actioning virtual machines.'
                    self.handle_exception(msg, exc)
            else:
                names = self.config.get('names', None)

            kwargs = {}
            machines = []
            msg = (
                'The following virtual machines are set to be actioned with '
                '"{0}":\n'.format(self.options.action))
            for name in names:
                if '=' in name:
                    # This is obviously not a machine name, treat it as a kwarg
                    key, value = name.split('=', 1)
                    kwargs[key] = value
                else:
                    msg += '  {0}\n'.format(name)
                    machines.append(name)
            names = machines

            try:
                if self.print_confirm(msg):
                    ret = mapper.do_action(names, kwargs)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error actioning machines: {0}'
                self.handle_exception(msg, exc)

        elif self.options.function:
            kwargs = {}
            args = self.args[:]
            for arg in args[:]:
                if '=' in arg:
                    key, value = arg.split('=', 1)
                    kwargs[key] = value
                    args.remove(arg)

            if args:
                self.error(
                    'Any arguments passed to --function need to be passed '
                    'as kwargs. Ex: image=ami-54cf5c3d. Remaining '
                    'arguments: {0}'.format(args))
            try:
                ret = mapper.do_function(self.function_provider,
                                         self.function_name, kwargs)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error running the function: {0}'
                self.handle_exception(msg, exc)

        elif self.options.profile and self.config.get('names', False):
            try:
                ret = mapper.run_profile(self.options.profile,
                                         self.config.get('names'))
            except (SaltCloudException, Exception) as exc:
                msg = 'There was a profile error: {0}'
                self.handle_exception(msg, exc)

        elif self.options.set_password:
            username = self.credential_username
            provider_name = "salt.cloud.provider.{0}".format(
                self.credential_provider)
            # TODO: check if provider is configured
            # set the password
            salt.utils.cloud.store_password_in_keyring(provider_name, username)
        elif self.config.get('map', None) and \
                self.selected_query_option is None:
            if len(mapper.rendered_map) == 0:
                sys.stderr.write('No nodes defined in this map')
                self.exit(salt.defaults.exitcodes.EX_GENERIC)
            try:
                ret = {}
                run_map = True

                log.info('Applying map from \'{0}\'.'.format(
                    self.config['map']))
                dmap = mapper.map_data()

                msg = ''
                if 'errors' in dmap:
                    # display profile errors
                    msg += 'Found the following errors:\n'
                    for profile_name, error in six.iteritems(dmap['errors']):
                        msg += '  {0}: {1}\n'.format(profile_name, error)
                    sys.stderr.write(msg)
                    sys.stderr.flush()

                msg = ''
                if 'existing' in dmap:
                    msg += ('The following virtual machines already exist:\n')
                    for name in dmap['existing']:
                        msg += '  {0}\n'.format(name)

                if dmap['create']:
                    msg += ('The following virtual machines are set to be '
                            'created:\n')
                    for name in dmap['create']:
                        msg += '  {0}\n'.format(name)

                if 'destroy' in dmap:
                    msg += ('The following virtual machines are set to be '
                            'destroyed:\n')
                    for name in dmap['destroy']:
                        msg += '  {0}\n'.format(name)

                if not dmap['create'] and not dmap.get('destroy', None):
                    if not dmap.get('existing', None):
                        # nothing to create or destroy & nothing exists
                        print(msg)
                        self.exit(1)
                    else:
                        # nothing to create or destroy, print existing
                        run_map = False

                if run_map:
                    if self.print_confirm(msg):
                        ret = mapper.run_map(dmap)

                    if self.config.get('parallel', False) is False:
                        log.info('Complete')

                if dmap.get('existing', None):
                    for name in dmap['existing']:
                        if 'ec2' in dmap['existing'][name]['provider']:
                            msg = 'Instance already exists, or is terminated and has the same name.'
                        else:
                            msg = 'Already running.'
                        ret[name] = {'Message': msg}

            except (SaltCloudException, Exception) as exc:
                msg = 'There was a query error: {0}'
                self.handle_exception(msg, exc)

        elif self.options.bootstrap:
            host = self.options.bootstrap
            if len(self.args) > 0:
                if '=' not in self.args[0]:
                    minion_id = self.args.pop(0)
                else:
                    minion_id = host
            else:
                minion_id = host

            vm_ = {
                'driver': '',
                'ssh_host': host,
                'name': minion_id,
            }
            args = self.args[:]
            for arg in args[:]:
                if '=' in arg:
                    key, value = arg.split('=', 1)
                    vm_[key] = value
                    args.remove(arg)

            if args:
                self.error(
                    'Any arguments passed to --bootstrap need to be passed as '
                    'kwargs. Ex: ssh_username=larry. Remaining arguments: {0}'.
                    format(args))

            try:
                ret = salt.utils.cloud.bootstrap(vm_, self.config)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error bootstrapping the minion: {0}'
                self.handle_exception(msg, exc)

        else:
            self.error('Nothing was done. Using the proper arguments?')

        display_output = salt.output.get_printout(self.options.output,
                                                  self.config)
        # display output using salt's outputter system
        print(display_output(ret))
        self.exit(salt.defaults.exitcodes.EX_OK)
예제 #56
0
 def test_user(self):
     self.assertTrue(check_user(getpass.getuser()))
예제 #57
0
class Syndic(object):
    '''
    Create a syndic server
    '''
    def __init__(self):
        self.cli = self.__parse_cli()
        # command line overrides config
        if self.cli['user']:
            self.opts['user'] = self.cli['user']

    def __prep_opts(self, cli):
        '''
        Generate the opts used by the syndic
        '''
        opts = salt.config.master_config(cli['master_config'])
        opts['_minion_conf_file'] = opts['conf_file']
        opts.update(salt.config.minion_config(cli['minion_config']))
        if 'syndic_master' in opts:
            # Some of the opts need to be changed to match the needed opts
            # in the minion class.
            opts['master'] = opts['syndic_master']
            opts['master_ip'] = salt.utils.dns_check(opts['master'])

            opts['master_uri'] = ('tcp://' + opts['master_ip'] + ':' +
                                  str(opts['master_port']))
            opts['_master_conf_file'] = opts['conf_file']
            opts.pop('conf_file')
            return opts
        err = ('The syndic_master needs to be configured in the salt master '
               'config, EXITING!\n')
        sys.stderr.write(err)
        sys.exit(2)

    def __parse_cli(self):
        '''
        Parse the cli for options passed to a syndic daemon
        '''
        import salt.log
        parser = optparse.OptionParser(version="%%prog %s" % __version__)
        parser.add_option('-d',
                          '--daemon',
                          dest='daemon',
                          default=False,
                          action='store_true',
                          help='Run the syndic as a daemon')
        parser.add_option(
            '--master-config',
            dest='master_config',
            default='/etc/salt/master',
            help='Pass in an alternative master configuration file')
        parser.add_option(
            '--minion-config',
            dest='minion_config',
            default='/etc/salt/minion',
            help='Pass in an alternative minion configuration file')
        parser.add_option('-u',
                          '--user',
                          dest='user',
                          help='Specify user to run syndic')
        parser.add_option('--pid-file',
                          dest='pidfile',
                          default='/var/run/salt-syndic.pid',
                          help=('Specify the location of the pidfile. Default'
                                ' %default'))
        parser.add_option(
            '-l',
            '--log-level',
            dest='log_level',
            choices=list(salt.log.LOG_LEVELS),
            help='Console log level. One of %s. For the logfile settings '
            'see the config file. Default: \'warning\'.' %
            ', '.join([repr(l) for l in salt.log.LOG_LEVELS]))

        options, args = parser.parse_args()

        cli = {
            'daemon': options.daemon,
            'minion_config': options.minion_config,
            'master_config': options.master_config,
            'pidfile': options.pidfile,
            'user': options.user
        }

        self.opts = self.__prep_opts(cli)

        if not options.log_level:
            options.log_level = self.opts['log_level']

        salt.log.setup_console_logger(options.log_level,
                                      log_format=self.opts['log_fmt_console'],
                                      date_format=self.opts['log_datefmt'])

        return cli

    def start(self):
        '''
        Execute this method to start up a syndic.
        '''
        try:
            verify_env([
                self.opts['pki_dir'],
                self.opts['cachedir'],
                os.path.dirname(self.opts['log_file']),
            ],
                       self.opts['user'],
                       permissive=self.opts['permissive_pki_access'])
        except OSError, err:
            sys.exit(err.errno)
        import salt.log
        salt.log.setup_logfile_logger(self.opts['log_file'],
                                      self.opts['log_level'])
        for name, level in self.opts['log_granular_levels'].items():
            salt.log.set_logger_level(name, level)

        import logging

        # Late import so logging works correctly
        import salt.minion
        log = logging.getLogger(__name__)
        if self.cli['daemon']:
            # Late import so logging works correctly
            import salt.utils
            salt.utils.daemonize()
        set_pidfile(self.cli['pidfile'])
        if check_user(self.opts['user'], log):
            try:
                syndic = salt.minion.Syndic(self.opts)
                syndic.tune_in()
            except KeyboardInterrupt:
                log.warn('Stopping the Salt Syndic Minion')
                raise SystemExit('\nExiting on Ctrl-c')
예제 #58
0
    def run(self):
        '''
        Execute salt-run
        '''
        self.parse_args()

        if self.config.get('config_dump'):
            sys.stdout.write(safe_dump(self.config, default_flow_style=False))
            return self.config

        # Setup file logging!
        self.setup_logfile_logger()
        verify_log(self.config)
        profiling_enabled = self.options.profiling_enabled
        curpath = os.path.dirname(os.path.realpath(__file__))
        saltenv = self.config.get('saltenv_cli', self.config.get('saltenv'))
        if not saltenv:
            saltenv = 'base'
        self.config['saltenv'] = saltenv
        if self.config.get('pillar_root'):
            log.info(
                'Setting and using %s as the Pillar root', self.config['pillar_root']
            )
            self.config['pillar_roots'] = {saltenv: self.config['pillar_root']}
        if self.config.get('file_root'):
            log.info(
                'Setting and using %s as the Salt file root', self.config['file_root']
            )
            self.config['file_root'] = {saltenv: self.config['file_root']}
        if self.config.get('installation_path'):
            salt.utils.stringutils.print_cli(curpath)
            return
        if self.config.get('display_file_roots'):
            salt.utils.stringutils.print_cli(
                'salt-sproxy is installed at: {}'.format(curpath)
            )
            salt.utils.stringutils.print_cli(
                '\nYou can configure the file_roots on the Master, e.g.,\n'
            )
            salt.utils.stringutils.print_cli(
                'file_roots:\n  {0}:\n    - {1}'.format(saltenv, curpath)
            )
            salt.utils.stringutils.print_cli('\n\nOr only for the Runners:\n')
            salt.utils.stringutils.print_cli(
                'runner_dirs:\n  - {}/_runners'.format(curpath)
            )
            return
        if self.config.get('save_file_roots'):
            updated = False
            with fopen(self.config['conf_file'], 'r+') as master_fp:
                master_cfg = safe_load(master_fp)
                if not master_cfg:
                    master_cfg = {}
                file_roots = master_cfg.get('file_roots', {saltenv: []}).get(
                    saltenv, []
                )
                runner_dirs = master_cfg.get('runner_dirs', [])
                sproxy_runners = os.path.join(curpath, '_runners')
                if curpath not in file_roots:
                    file_roots.append(curpath)
                    master_cfg['file_roots'] = {saltenv: file_roots}
                    updated = True
                    salt.utils.stringutils.print_cli(
                        '{} added to the file_roots:\n'.format(curpath)
                    )
                    salt.utils.stringutils.print_cli(
                        'file_roots:\n  {0}\n    - {1}\n'.format(
                            saltenv, '\n    -'.join(file_roots)
                        )
                    )
                if sproxy_runners not in runner_dirs:
                    runner_dirs.append(sproxy_runners)
                    master_cfg['runner_dirs'] = runner_dirs
                    updated = True
                    salt.utils.stringutils.print_cli(
                        '{} added to runner_dirs:\n'.format(sproxy_runners)
                    )
                    salt.utils.stringutils.print_cli(
                        'runner_dirs:\n  - {0}'.format('\n  - '.join(runner_dirs))
                    )
                if updated:
                    master_fp.seek(0)
                    safe_dump(master_cfg, master_fp, default_flow_style=False)
                    log.debug('Syncing Runners on the Master')
                    runner_client = salt.runner.RunnerClient(self.config)
                    sync_runners = runner_client.cmd(
                        'saltutil.sync_all',
                        kwarg={'saltenv': saltenv},
                        print_event=False,
                    )
                    log.debug('saltutil.sync_all output:')
                    log.debug(sync_runners)
                else:
                    salt.utils.stringutils.print_cli(
                        'The {} path is already included into the file_roots and runner_dirs'.format(
                            curpath
                        )
                    )
                salt.utils.stringutils.print_cli(
                    '\nNow you can start using salt-sproxy for '
                    'event-driven automation, and the Salt REST API.\n'
                    'See https://salt-sproxy.readthedocs.io/en/latest/salt_api.html'
                    '\nand https://salt-sproxy.readthedocs.io/en/latest/events.html '
                    'for more details.'
                )
            return
        # The code below executes the Runner sequence, but it swaps the function
        # to be invoked, and instead call ``napalm.execute``, passing the
        # function requested by the user from the CLI, as an argument.
        # The same goes with the CLI options that are sent as kwargs to the
        # proxy Runner.
        tgt = self.config['tgt']
        fun = self.config['fun']
        args = self.config['arg']
        kwargs = {}
        if 'output' not in self.config and fun in (
            'state.sls',
            'state.apply',
            'state.highstate',
        ):
            self.config['output'] = 'highstate'
        kwargs['progress'] = self.config.pop('progress', False)
        # To be able to reuse the proxy Runner (which is not yet available
        # natively in Salt), we can override the ``runner_dirs`` configuration
        # option to tell Salt to load that Runner too. This way, we can also
        # load other types of modules that may be required or we provide fixes
        # or backports - for example the Ansible Roster which doesn't work fine
        # pre Salt 2018.3 (in case anyone would like to use it).
        file_roots = self.config.get('file_roots', {saltenv: []})
        if saltenv not in file_roots:
            file_roots[saltenv] = []
        file_roots[saltenv].append(curpath)
        self.config['file_roots'] = file_roots
        runner_dirs = self.config.get('runner_dirs', [])
        runner_path = os.path.join(curpath, '_runners')
        runner_dirs.append(runner_path)
        self.config['runner_dirs'] = runner_dirs
        runner_client = None
        sync_all = self.config.get('sync_all', False)
        sync_grains = self.config.get('sync_grains', True)
        sync_modules = self.config.get('sync_modules', True)
        sync_roster = self.config.get('sync_roster', True)
        sync_proxy = self.config.get('sync_proxy', False)
        sync_executors = self.config.get('sync_executors', False)
        kwargs.update(
            {
                'sync_all': sync_all,
                'sync_roster': sync_roster,
                'sync_modules': sync_modules,
            }
        )
        if any(
            [
                sync_all,
                sync_grains,
                sync_modules,
                sync_roster,
                sync_proxy,
                sync_executors,
            ]
        ):
            runner_client = salt.runner.RunnerClient(self.config)
        if sync_all:
            log.debug('Sync all')
            sync_all_ret = runner_client.cmd(
                'saltutil.sync_all', kwarg={'saltenv': saltenv}, print_event=False
            )
            log.debug(sync_all_ret)
        if sync_grains and not sync_all:
            log.debug('Syncing grains')
            sync_grains_ret = runner_client.cmd(
                'saltutil.sync_grains',
                kwarg={
                    'saltenv': saltenv,
                    'extmod_whitelist': ','.join(
                        self.config.get('whitelist_grains', [])
                    ),
                    'extmod_blacklist': ','.join(self.config.get('disable_grains', [])),
                },
                print_event=False,
            )
            log.debug(sync_grains_ret)
        if self.config.get('module_dirs_cli'):
            log.debug(
                'Loading execution modules from the dirs provided via --module-dirs'
            )
            module_dirs = self.config.get('module_dirs', [])
            module_dirs.extend(self.config['module_dirs_cli'])
            self.config['module_dirs'] = module_dirs
        if sync_modules and not sync_all:
            # Don't sync modules by default
            log.debug('Syncing modules')
            module_dirs = self.config.get('module_dirs', [])
            module_path = os.path.join(curpath, '_modules')
            module_dirs.append(module_path)
            self.config['module_dirs'] = module_dirs
            # No need to explicitly load the modules here, as during runtime,
            # Salt is anyway going to load the modules on the fly.
            sync_modules_ret = runner_client.cmd(
                'saltutil.sync_modules',
                kwarg={
                    'saltenv': saltenv,
                    'extmod_whitelist': ','.join(
                        self.config.get('whitelist_modules', [])
                    ),
                    'extmod_blacklist': ','.join(
                        self.config.get('disable_modules', [])
                    ),
                },
                print_event=False,
            )
            log.debug(sync_modules_ret)
        # Resync Roster module to load the ones we have here in the library, and
        # potentially others provided by the user in their environment
        if sync_roster and not sync_all and self.config.get('roster'):
            # Sync Rosters by default
            log.debug('Syncing roster')
            roster_dirs = self.config.get('roster_dirs', [])
            roster_path = os.path.join(curpath, '_roster')
            roster_dirs.append(roster_path)
            self.config['roster_dirs'] = roster_dirs
            sync_roster_ret = runner_client.cmd(
                'saltutil.sync_roster',
                kwarg={'saltenv': saltenv, 'extmod_whitelist': self.config['roster']},
                print_event=False,
            )
            log.debug(sync_roster_ret)
        if sync_proxy and not sync_all:
            log.debug('Syncing Proxy modules')
            proxy_dirs = self.config.get('proxy_dirs', [])
            proxy_path = os.path.join(curpath, '_proxy')
            proxy_dirs.append(proxy_path)
            self.config['proxy_dirs'] = proxy_dirs
            sync_proxy_ret = runner_client.cmd(
                'saltutil.sync_proxymodules',
                kwarg={
                    'saltenv': saltenv,
                    'extmod_whitelist': ','.join(
                        self.config.get('whitelist_proxys', [])
                    ),
                    'extmod_blacklist': ','.join(self.config.get('disable_proxys', [])),
                },
                print_event=False,
            )
            log.debug(sync_proxy_ret)
        if sync_executors and not sync_all:
            log.debug('Syncing Executors modules')
            executor_dirs = self.config.get('executor_dirs', [])
            executor_path = os.path.join(curpath, '_executors')
            executor_dirs.append(executor_path)
            self.config['executor_dirs'] = executor_dirs
            sync_executors_ret = runner_client.cmd(
                'saltutil.sync_executors',
                kwarg={
                    'saltenv': saltenv,
                    'extmod_whitelist': ','.join(
                        self.config.get('whitelist_executors', [])
                    ),
                    'extmod_blacklist': ','.join(
                        self.config.get('disable_executors', [])
                    ),
                },
                print_event=False,
            )
            log.debug(sync_executors_ret)
        if self.config.get('states_dir'):
            states_dirs = self.config.get('states_dirs', [])
            states_dirs.append(self.config['states_dir'])
            self.config['states_dirs'] = states_dirs
        self.config['fun'] = 'proxy.execute'
        tmp_args = args[:]
        for index, arg in enumerate(tmp_args):
            if isinstance(arg, dict) and '__kwarg__' in arg:
                args.pop(index)
                kwargs = arg
        kwargs['__kwarg__'] = True
        tgt_types = (
            'compound',
            'list',
            'grain',
            'pcre',
            'grain_pcre',
            'pillar_pcre',
            'pillar_target',
            'nodegroup',
        )
        kwargs['tgt_type'] = 'glob'
        for tgt_type in tgt_types:
            if hasattr(self.options, tgt_type) and getattr(self.options, tgt_type):
                kwargs['tgt_type'] = tgt_type
        kwargs_opts = (
            'preview_target',
            'batch_size',
            'batch_wait',
            'roster',
            'timeout',
            'static',
            'no_connect',
            'failhard',
            'summary',
            'verbose',
            'show_jid',
            'hide_timeout',
            'progress',
            'returner',
            'target_cache',
            'returner_config',
            'returner_kwargs',
        )
        for kwargs_opt in kwargs_opts:
            if getattr(self.options, kwargs_opt) is not None:
                kwargs[kwargs_opt] = getattr(self.options, kwargs_opt)
        reverse_opts = {
            # option_name: runner_kwarg
            'no_cached_grains': 'use_cached_grains',
            'no_cached_pillar': 'use_cached_pillar',
            'no_grains': 'with_grains',
            'no_pillar': 'with_pillar',
            'dont_cache_grains': 'cache_grains',
            'dont_cache_pillar': 'cache_pillar',
        }
        for opt, kwarg in six.iteritems(reverse_opts):
            if getattr(self.options, opt):
                kwargs[kwarg] = False
        kwargs['events'] = self.config.get('events', False)
        kwargs['use_existing_proxy'] = self.config.get('use_existing_proxy', False)
        kwargs['test_ping'] = self.config.get('test_ping', False)
        kwargs['target_cache_timeout'] = self.config.get(
            'target_cache_timeout', 60
        )  # seconds
        kwargs['args'] = args
        kwargs['default_grains'] = self.config.get(
            'sproxy_grains',
            self.config.get('default_grains', self.config.get('grains')),
        )
        kwargs['default_pillar'] = self.config.get(
            'sproxy_pillar',
            self.config.get('default_pillar', self.config.get('pillar')),
        )
        kwargs['preload_targeting'] = self.config.get('preload_targeting', False)
        kwargs['invasive_targeting'] = self.config.get('invasive_targeting', False)
        kwargs['failhard'] = self.config.get('failhard', False)
        self.config['arg'] = [tgt, fun, kwargs]
        runner = salt.runner.Runner(self.config)

        if self.config.get('doc', True):
            # late import as salt.loader adds up some execution time, and we
            # don't want that, but only when displaying docs.
            from salt.loader import utils, grains, minion_mods

            runner.opts['fun'] = fun
            runner.opts['grains'] = grains(runner.opts)
            runner._functions = minion_mods(runner.opts, utils=utils(runner.opts))

        # Run this here so SystemExit isn't raised anywhere else when
        # someone tries to use the runners via the python API
        try:
            if check_user(self.config['user']):
                pr = activate_profile(profiling_enabled)
                try:
                    ret = runner.run()
                    # In older versions ret['data']['retcode'] was used
                    # for signaling the return code. This has been
                    # changed for the orchestrate runner, but external
                    # runners might still use it. For this reason, we
                    # also check ret['data']['retcode'] if
                    # ret['retcode'] is not available.
                    if 'retcode' in runner.context:
                        self.exit(runner.context['retcode'])
                    if isinstance(ret, dict) and 'retcode' in ret:
                        self.exit(ret['retcode'])
                    elif isinstance(ret, dict) and 'retcode' in ret.get('data', {}):
                        self.exit(ret['data']['retcode'])
                finally:
                    output_profile(
                        pr, stats_path=self.options.profiling_path, stop=True
                    )

        except SaltClientError as exc:
            raise SystemExit from exc
예제 #59
0
    def run(self):
        '''
        Execute the salt-cloud command line
        '''
        # Parse shell arguments
        self.parse_args()

        salt_master_user = self.config.get('user', salt.utils.get_user())
        if salt_master_user is not None and not check_user(salt_master_user):
            self.error(
                'If salt-cloud is running on a master machine, salt-cloud '
                'needs to run as the same user as the salt-master, {0!r}. If '
                'salt-cloud is not running on a salt-master, the appropriate '
                'write permissions must be granted to /etc/salt/. Please run '
                'salt-cloud as root, {0!r}, or change permissions for '
                '/etc/salt/.'.format(salt_master_user)
            )

        try:
            if self.config['verify_env']:
                verify_env(
                    [os.path.dirname(self.config['conf_file'])],
                    salt_master_user
                )
                logfile = self.config['log_file']
                if logfile is not None and not logfile.startswith('tcp://') \
                        and not logfile.startswith('udp://') \
                        and not logfile.startswith('file://'):
                    # Logfile is not using Syslog, verify
                    verify_files([logfile], salt_master_user)
        except (IOError, OSError) as err:
            log.error('Error while verifying the environment: {0}'.format(err))
            sys.exit(err.errno)

        # Setup log file logging
        self.setup_logfile_logger()

        if self.options.update_bootstrap:
            ret = salt.utils.cloud.update_bootstrap(self.config)
            display_output = salt.output.get_printout(
                self.options.output, self.config
            )
            print(display_output(ret))
            self.exit(salt.defaults.exitcodes.EX_OK)

        log.info('salt-cloud starting')
        mapper = salt.cloud.Map(self.config)

        names = self.config.get('names', None)
        if names is not None:
            filtered_rendered_map = {}
            for map_profile in mapper.rendered_map:
                filtered_map_profile = {}
                for name in mapper.rendered_map[map_profile]:
                    if name in names:
                        filtered_map_profile[name] = mapper.rendered_map[map_profile][name]
                if filtered_map_profile:
                    filtered_rendered_map[map_profile] = filtered_map_profile
            mapper.rendered_map = filtered_rendered_map

        ret = {}

        if self.selected_query_option is not None:
            if self.selected_query_option == 'list_providers':
                try:
                    ret = mapper.provider_list()
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error listing providers: {0}'
                    self.handle_exception(msg, exc)

            elif self.selected_query_option == 'list_profiles':
                provider = self.options.list_profiles
                try:
                    ret = mapper.profile_list(provider)
                except(SaltCloudException, Exception) as exc:
                    msg = 'There was an error listing profiles: {0}'
                    self.handle_exception(msg, exc)

            elif self.config.get('map', None):
                log.info('Applying map from {0!r}.'.format(self.config['map']))
                try:
                    ret = mapper.interpolated_map(
                        query=self.selected_query_option
                    )
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error with a custom map: {0}'
                    self.handle_exception(msg, exc)
            else:
                try:
                    ret = mapper.map_providers_parallel(
                        query=self.selected_query_option
                    )
                except (SaltCloudException, Exception) as exc:
                    msg = 'There was an error with a map: {0}'
                    self.handle_exception(msg, exc)

        elif self.options.list_locations is not None:
            try:
                ret = mapper.location_list(
                    self.options.list_locations
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error listing locations: {0}'
                self.handle_exception(msg, exc)

        elif self.options.list_images is not None:
            try:
                ret = mapper.image_list(
                    self.options.list_images
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error listing images: {0}'
                self.handle_exception(msg, exc)

        elif self.options.list_sizes is not None:
            try:
                ret = mapper.size_list(
                    self.options.list_sizes
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error listing sizes: {0}'
                self.handle_exception(msg, exc)

        elif self.options.destroy and (self.config.get('names', None) or
                                       self.config.get('map', None)):
            if self.config.get('map', None):
                log.info('Applying map from {0!r}.'.format(self.config['map']))
                matching = mapper.delete_map(query='list_nodes')
            else:
                matching = mapper.get_running_by_names(
                    self.config.get('names', ()),
                    profile=self.options.profile
                )

            if not matching:
                print('No machines were found to be destroyed')
                self.exit(salt.defaults.exitcodes.EX_OK)

            msg = 'The following virtual machines are set to be destroyed:\n'
            names = set()
            for alias, drivers in six.iteritems(matching):
                msg += '  {0}:\n'.format(alias)
                for driver, vms in six.iteritems(drivers):
                    msg += '    {0}:\n'.format(driver)
                    for name in vms:
                        msg += '      {0}\n'.format(name)
                        names.add(name)
            try:
                if self.print_confirm(msg):
                    ret = mapper.destroy(names, cached=True)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error destroying machines: {0}'
                self.handle_exception(msg, exc)

        elif self.options.action and (self.config.get('names', None) or
                                      self.config.get('map', None)):
            if self.config.get('map', None):
                log.info('Applying map from {0!r}.'.format(self.config['map']))
                names = mapper.get_vmnames_by_action(self.options.action)
            else:
                names = self.config.get('names', None)

            kwargs = {}
            machines = []
            msg = (
                'The following virtual machines are set to be actioned with '
                '"{0}":\n'.format(
                    self.options.action
                )
            )
            for name in names:
                if '=' in name:
                    # This is obviously not a machine name, treat it as a kwarg
                    comps = name.split('=')
                    kwargs[comps[0]] = comps[1]
                else:
                    msg += '  {0}\n'.format(name)
                    machines.append(name)
            names = machines

            try:
                if self.print_confirm(msg):
                    ret = mapper.do_action(names, kwargs)
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error actioning machines: {0}'
                self.handle_exception(msg, exc)

        elif self.options.function:
            kwargs = {}
            args = self.args[:]
            for arg in args[:]:
                if '=' in arg:
                    key, value = arg.split('=')
                    kwargs[key] = value
                    args.remove(arg)

            if args:
                self.error(
                    'Any arguments passed to --function need to be passed '
                    'as kwargs. Ex: image=ami-54cf5c3d. Remaining '
                    'arguments: {0}'.format(args)
                )
            try:
                ret = mapper.do_function(
                    self.function_provider, self.function_name, kwargs
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was an error running the function: {0}'
                self.handle_exception(msg, exc)

        elif self.options.profile and self.config.get('names', False):
            try:
                ret = mapper.run_profile(
                    self.options.profile,
                    self.config.get('names')
                )
            except (SaltCloudException, Exception) as exc:
                msg = 'There was a profile error: {0}'
                self.handle_exception(msg, exc)

        elif self.options.set_password:
            username = self.credential_username
            provider_name = "salt.cloud.provider.{0}".format(self.credential_provider)
            # TODO: check if provider is configured
            # set the password
            salt.utils.cloud.store_password_in_keyring(provider_name, username)
        elif self.config.get('map', None) and \
                self.selected_query_option is None:
            if len(mapper.rendered_map) == 0:
                sys.stderr.write('No nodes defined in this map')
                self.exit(salt.defaults.exitcodes.EX_GENERIC)
            try:
                ret = {}
                run_map = True

                log.info('Applying map from {0!r}.'.format(self.config['map']))
                dmap = mapper.map_data()

                msg = ''
                if 'errors' in dmap:
                    # display profile errors
                    msg += 'Found the following errors:\n'
                    for profile_name, error in six.iteritems(dmap['errors']):
                        msg += '  {0}: {1}\n'.format(profile_name, error)
                    sys.stderr.write(msg)
                    sys.stderr.flush()

                msg = ''
                if 'existing' in dmap:
                    msg += ('The following virtual machines already exist:\n')
                    for name in dmap['existing']:
                        msg += '  {0}\n'.format(name)

                if dmap['create']:
                    msg += ('The following virtual machines are set to be '
                            'created:\n')
                    for name in dmap['create']:
                        msg += '  {0}\n'.format(name)

                if 'destroy' in dmap:
                    msg += ('The following virtual machines are set to be '
                            'destroyed:\n')
                    for name in dmap['destroy']:
                        msg += '  {0}\n'.format(name)

                if not dmap['create'] and not dmap.get('destroy', None):
                    if not dmap.get('existing', None):
                        # nothing to create or destroy & nothing exists
                        print(msg)
                        self.exit(1)
                    else:
                        # nothing to create or destroy, print existing
                        run_map = False

                if run_map:
                    if self.print_confirm(msg):
                        ret = mapper.run_map(dmap)

                    if self.config.get('parallel', False) is False:
                        log.info('Complete')

                if dmap.get('existing', None):
                    for name in dmap['existing']:
                        ret[name] = {'Message': 'Already running'}

            except (SaltCloudException, Exception) as exc:
                msg = 'There was a query error: {0}'
                self.handle_exception(msg, exc)

        else:
            self.error('Nothing was done. Using the proper arguments?')

        display_output = salt.output.get_printout(
            self.options.output, self.config
        )
        # display output using salt's outputter system
        print(display_output(ret))
        self.exit(salt.defaults.exitcodes.EX_OK)