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))
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)
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()
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))
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')
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()
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)
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')
def start(self): ''' Start broker. ''' self.prepare() if check_user(self.config['user']): self.broker.start()
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 )
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()
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')
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)
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()
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()
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()
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()
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()
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()
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()
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()
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)
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()
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()
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()
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()
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()
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()
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()
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()
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')
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)
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()
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')
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()
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()
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')
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))
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()
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')
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))
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()
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))
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))
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)
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)
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')
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)
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)
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)
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)
def test_user(self): self.assertTrue(check_user(getpass.getuser()))
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)
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')
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
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)