def migrate(name, target=''): ''' Migrate a vm from one hypervisor to another. This routine will just start the migration and display information on how to look up the progress ''' client = salt.client.LocalClient(__opts__['conf_file']) data = query(quiet=True) origin_data = _find_vm(name, data, quiet=True) try: origin_hyper = origin_data.keys()[0] except IndexError: print('Named vm {0} was not found to migrate'.format(name)) return '' disks = origin_data[origin_hyper][name]['disks'] if not origin_data: print('Named vm {0} was not found to migrate'.format(name)) return '' if not target: target = _determine_hyper(data, origin_hyper) if target not in data: print('Target hypervisor {0} not found'.format(origin_data)) return '' client.cmd(target, 'virt.seed_non_shared_migrate', [disks, True]) print client.cmd_async(origin_hyper, 'virt.migrate_non_shared', [name, target])
def migrate(name, target=''): ''' Migrate a vm from one hypervisor to another. This routine will just start the migration and display information on how to look up the progress ''' client = salt.client.LocalClient(__opts__['conf_file']) data = query(quiet=True) origin_data = _find_vm(name, data, quiet=True) try: origin_hyper = origin_data.keys()[0] except IndexError: print('Named vm {0} was not found to migrate'.format(name)) return '' disks = origin_data[origin_hyper][name]['disks'] if not origin_data: print('Named vm {0} was not found to migrate'.format(name)) return '' if not target: target = _determine_hyper(data, origin_hyper) if target not in data: print('Target hypervisor {0} not found'.format(origin_data)) return '' client.cmd(target, 'virt.seed_non_shared_migrate', [disks, True]) print client.cmd_async(origin_hyper, 'virt.migrate_non_shared', [name, target])
def ping_all_connected_minions(opts): client = salt.client.LocalClient() if opts['minion_data_cache']: tgt = list(salt.utils.minions.CkMinions(opts).connected_ids()) form = 'list' else: tgt = '*' form = 'glob' client.cmd_async(tgt, 'test.ping', tgt_type=form)
def ping_all_connected_minions(opts): client = salt.client.LocalClient() if opts["minion_data_cache"]: tgt = list(salt.utils.minions.CkMinions(opts).connected_ids()) form = "list" else: tgt = "*" form = "glob" client.cmd_async(tgt, "test.ping", tgt_type=form)
def delete_key(self, match=None, match_dict=None, preserve_minions=None, revoke_auth=False): """ Delete public keys. If "match" is passed, it is evaluated as a glob. Pre-gathered matches can also be passed via "match_dict". To preserve the master caches of minions who are matched, set preserve_minions """ if match is not None: matches = self.name_match(match) elif match_dict is not None and isinstance(match_dict, dict): matches = match_dict else: matches = {} with salt.client.get_local_client(mopts=self.opts) as client: for status, keys in matches.items(): for key in keys: try: if revoke_auth: if self.opts.get("rotate_aes_key") is False: print( "Immediate auth revocation specified but AES key" " rotation not allowed. Minion will not be" " disconnected until the master AES key is rotated." ) else: try: client.cmd_async(key, "saltutil.revoke_auth") except salt.exceptions.SaltClientError: print( "Cannot contact Salt master. " "Connection for {} will remain up until " "master AES key is rotated or auth is revoked " "with 'saltutil.revoke_auth'.".format( key)) os.remove( os.path.join(self.opts["pki_dir"], status, key)) eload = {"result": True, "act": "delete", "id": key} self.event.fire_event( eload, salt.utils.event.tagify(prefix="key")) except OSError: pass if self.opts.get("preserve_minions") is True: self.check_minion_cache( preserve_minions=matches.get("minions", [])) else: self.check_minion_cache() if self.opts.get("rotate_aes_key"): salt.crypt.dropfile(self.opts["cachedir"], self.opts["user"]) return self.name_match( match) if match is not None else self.dict_match(matches)
def highstate_accepted_minion(name, database_location=DEFAULT_DATABASE_LOCATION, registry_script=DEFAULT_REGISTRY_SCRIPT): """ Highstate a previously accepted minion. Highstating is done asynchronously to not block the reactor. """ registry_call = _registry_call(database_location, registry_script) if _key_submitted_and_autoscaled(registry_call, name): client = salt.client.LocalClient(__opts__['conf_file']) client.cmd_async(name, 'state.highstate')
def delete_key(self, match=None, match_dict=None, preserve_minions=None, revoke_auth=False): ''' Delete public keys. If "match" is passed, it is evaluated as a glob. Pre-gathered matches can also be passed via "match_dict". To preserve the master caches of minions who are matched, set preserve_minions ''' if match is not None: matches = self.name_match(match) elif match_dict is not None and isinstance(match_dict, dict): matches = match_dict else: matches = {} for status, keys in six.iteritems(matches): for key in keys: try: if revoke_auth: if self.opts.get('rotate_aes_key') is False: print( 'Immediate auth revocation specified but AES key rotation not allowed. ' 'Minion will not be disconnected until the master AES key is rotated.' ) else: try: client = salt.client.get_local_client( mopts=self.opts) client.cmd_async(key, 'saltutil.revoke_auth') except salt.exceptions.SaltClientError: print( 'Cannot contact Salt master. ' 'Connection for {0} will remain up until ' 'master AES key is rotated or auth is revoked ' 'with \'saltutil.revoke_auth\'.'.format( key)) os.remove(os.path.join(self.opts['pki_dir'], status, key)) eload = {'result': True, 'act': 'delete', 'id': key} self.event.fire_event( eload, salt.utils.event.tagify(prefix='key')) except (OSError, IOError): pass if self.opts.get('preserve_minions') is True: self.check_minion_cache( preserve_minions=matches.get('minions', [])) else: self.check_minion_cache() if self.opts.get('rotate_aes_key'): salt.crypt.dropfile(self.opts['cachedir'], self.opts['user']) return (self.name_match(match) if match is not None else self.dict_match(matches))
def submit_job(target, action, params, audit_params=None, **kwargs): """ Submit an async Salt Job and return the job ID and the client instance Arguments: target -- the Salt target hosts pattern action -- the Salt module.function to call as string params -- a list of parameters to pass to the module.function audit_params -- the parameters cleaned for logging purposes **kwargs -- additional parameter for the Salt cmd_async function """ # Checking multiple Job results in non-blocking mode is not supported # within the same client client = salt.client.LocalClient() # Returns int 0 if fails, str with Job ID on success jid = client.cmd_async(target, action, params, **kwargs) if jid == 0: logger.warning(("Unable to submit job to run '{action}' on target " "'{target}'").format(action=action, target=target)) else: if audit_params is None: audit_params = params logger.info( ("Submitted job '{jid}' on target '{target}' with action " "'{action}' and params '{params}'").format(jid=jid, target=target, action=action, params=audit_params)) return (jid, client)
def migrate(name, target=''): ''' Migrate a vm from one hypervisor to another. This routine will just start the migration and display information on how to look up the progress. ''' client = salt.client.get_local_client(__opts__['conf_file']) data = query(quiet=True) origin_data = _find_vm(name, data, quiet=True) try: origin_hyper = origin_data.iterkeys().next() except StopIteration: print('Named vm {0} was not found to migrate'.format(name)) return '' disks = origin_data[origin_hyper][name]['disks'] if not origin_data: print('Named vm {0} was not found to migrate'.format(name)) return '' if not target: target = _determine_hyper(data, origin_hyper) if target not in data: print('Target hypervisor {0} not found'.format(origin_data)) return '' client.cmd(target, 'virt.seed_non_shared_migrate', [disks, True]) jid = client.cmd_async(origin_hyper, 'virt.migrate_non_shared', [name, target]) msg = ('The migration of virtual machine {0} to hypervisor {1} has begun, ' 'and can be tracked via jid {2}. The ``salt-run virt.query`` ' 'runner can also be used, the target vm will be shown as paused ' 'until the migration is complete.').format(name, target, jid) print(msg)
def _async(fun, arg=[], tgt=None): """ Helper method for asynchronous Salt calls """ if not tgt: tgt = "master" client = salt.client.LocalClient() client.cmd_async( tgt=tgt, fun=fun, arg=arg, username=app.config["SALT_CLOUD_USERNAME"], password=app.config["SALT_CLOUD_PASSWORD"], eauth="pam", )
def migrate(name, target=""): """ Migrate a vm from one hypervisor to another. This routine will just start the migration and display information on how to look up the progress. """ client = salt.client.get_local_client(__opts__["conf_file"]) data = query(quiet=True) origin_data = _find_vm(name, data, quiet=True) try: origin_hyper = origin_data.iterkeys().next() except StopIteration: print("Named vm {0} was not found to migrate".format(name)) return "" disks = origin_data[origin_hyper][name]["disks"] if not origin_data: print("Named vm {0} was not found to migrate".format(name)) return "" if not target: target = _determine_hyper(data, origin_hyper) if target not in data: print("Target hypervisor {0} not found".format(origin_data)) return "" client.cmd(target, "virt.seed_non_shared_migrate", [disks, True]) jid = client.cmd_async(origin_hyper, "virt.migrate_non_shared", [name, target]) msg = ( "The migration of virtual machine {0} to hypervisor {1} has begun, " "and can be tracked via jid {2}. The ``salt-run virt.query`` " "runner can also be used, the target vm will be shown as paused " "until the migration is complete." ).format(name, target, jid) print(msg)
def migrate(name, target=''): ''' Migrate a vm from one hypervisor to another. This routine will just start the migration and display information on how to look up the progress. ''' client = salt.client.get_local_client(__opts__['conf_file']) data = query(quiet=True) origin_data = _find_vm(name, data, quiet=True) try: origin_hyper = list(origin_data.keys())[0] except IndexError: __jid_event__.fire_event({'error': 'Named vm {0} was not found to migrate'.format(name)}, 'progress') return '' disks = origin_data[origin_hyper][name]['disks'] if not origin_data: __jid_event__.fire_event({'error': 'Named vm {0} was not found to migrate'.format(name)}, 'progress') return '' if not target: target = _determine_hyper(data, origin_hyper) if target not in data: __jid_event__.fire_event({'error': 'Target hypervisor {0} not found'.format(origin_data)}, 'progress') return '' try: client.cmd(target, 'virt.seed_non_shared_migrate', [disks, True]) jid = client.cmd_async(origin_hyper, 'virt.migrate_non_shared', [name, target]) except SaltClientError as client_error: return 'Virtual machine {0} could not be migrated: {1}'.format(name, client_error) msg = ('The migration of virtual machine {0} to hypervisor {1} has begun, ' 'and can be tracked via jid {2}. The ``salt-run virt.query`` ' 'runner can also be used, the target vm will be shown as paused ' 'until the migration is complete.').format(name, target, jid) __jid_event__.fire_event({'message': msg}, 'progress')
def deploy(tgt_selector='haproxy', backend_selector='nodes', beta_backend_selector='beta_nodes', enable='webB(\d+)', disable=None): """ """ client = salt.client.LocalClient(__opts__['conf_file']) backends = client.cmd(tgt_selector, 'haproxy.list_servers', [backend_selector], kwarg={'objectify': True}) if not backends: logger.warn('No backends could be selected: {} {}'.format( tgt_selector, backend_selector)) for backend in sorted(backends.get('haproxy')): # set to drain in LB logger.info('Starting HAPROXY deploy on %s' % backend) server_line = server_list_pattern.search(backend).groupdict() name = server_line.get('name') if bool(re.search(enable, name)): # enable logger.info('Enable %s on %s' % (name, backend)) client.cmd_async(tgt_selector, 'haproxy.set_state', [name, backend_selector, 'ready']) elif disable is not None and bool(re.search(disable, name)) or disable is None: # disable logger.info('Disable %s on %s' % (name, backend)) client.cmd_async(tgt_selector, 'haproxy.set_state', [name, backend_selector, 'drain']) backends = client.cmd(tgt_selector, 'haproxy.list_servers', [backend_selector], kwarg={'objectify': True}) backends = client.cmd(tgt_selector, 'haproxy.list_servers', [beta_backend_selector], kwarg={'objectify': True}) pp.pprint(backends) return True
def call_highstate(minion_id): '''execute an async salt call to a minion to run state.highstate asynchronously''' client = salt.client.LocalClient() minions = client.cmd_async(tgt=minion_id, fun='state.highstate', arg=[], timeout=1, expr_form='compound') return
def saltcmdrun(ip,command,args): ''' command 是命令脚本,调用远程服务器脚本(带绝对路径) ''' #ip = ['172.17.62.43','172.17.62.42'] client = salt.client.LocalClient() #res = client.cmd(ip, 'cmd.run',[command],timeout=86400,expr_form='list') #res = client.cmd(ip, 'cmd.script',[command],kwarg=args,timeout=86400,expr_form='list') res = client.cmd_async(ip, 'cmd.script',[command],timeout=86400,expr_form='list') return res
def pollpush(): ''' Run the monitoring command and return to carbon ''' client = salt.client.LocalClient(__opts__['conf_file']) cmds = ('ps.physical_memory_usage', 'ps.cpu_percent') nodes = '*' for cmd in cmds: jid = client.cmd_async(nodes, cmd, ret='carbon', timeout=__opts__['timeout'])
def run_async(self): client = salt.client.LocalClient() task_id = client.cmd_async( self.salt_target, self.salt_function, [a.value for a in self.saltarg_set.all()] ) if self.hipchat_notification_msg: rendered_msg = self.hipchat_notification_msg.format(cmd=self, id=task_id) msg = '{msg} View state log on {saltobserver_url}/jobs/{id} after state has finished.'.format( saltobserver_url=settings.SALTOBSERVER_URL, msg=rendered_msg, id=task_id) notify_hipchat(msg) return task_id
def cmd(name, tgt, func, arg=(), tgt_type="glob", ret="", kwarg=None, **kwargs): """ Execute a remote execution command USAGE: .. code-block:: yaml run_remote_ex: local.cmd: - tgt: '*' - func: test.ping run_remote_ex: local.cmd: - tgt: '*' - func: test.sleep - arg: - 30 run_remote_ex: local.cmd: - tgt: '*' - func: test.sleep - kwarg: length: 30 """ ret = {"name": name, "changes": {}, "comment": "", "result": True} with salt.client.get_local_client(mopts=__opts__) as client: jid = client.cmd_async(tgt, func, arg, tgt_type=tgt_type, ret=ret, kwarg=kwarg, **kwargs) ret["changes"]["jid"] = jid return ret
def migrate(name, target=""): """ Migrate a VM from one host to another. This routine will just start the migration and display information on how to look up the progress. """ with salt.client.get_local_client(__opts__["conf_file"]) as client: data = query(quiet=True) origin_data = _find_vm(name, data, quiet=True) try: origin_host = next(iter(origin_data)) except StopIteration: __jid_event__.fire_event( {"error": "Named VM {} was not found to migrate".format(name)}, "progress", ) return "" disks = origin_data[origin_host][name]["disks"] if not origin_data: __jid_event__.fire_event( {"error": "Named VM {} was not found to migrate".format(name)}, "progress", ) return "" if not target: target = _determine_host(data, origin_host) if target not in data: __jid_event__.fire_event( {"error": "Target host {} not found".format(origin_data)}, "progress") return "" try: client.cmd(target, "virt.seed_non_shared_migrate", [disks, True]) jid = client.cmd_async(origin_host, "virt.migrate_non_shared", [name, target]) except SaltClientError as client_error: return "Virtual machine {} could not be migrated: {}".format( name, client_error) msg = ( "The migration of virtual machine {} to host {} has begun, " "and can be tracked via jid {}. The ``salt-run virt.query`` " "runner can also be used, the target VM will be shown as paused " "until the migration is complete.".format(name, target, jid)) __jid_event__.fire_event({"message": msg}, "progress")
def execute(**kwargs): return client.cmd_async(**kwargs)
def rerun(): inflight = {} # a dictionary for jobs with pending returned results repeat_count = 0 m = None client = salt.client.LocalClient('/etc/salt/minion') for data in event.iter_events(tag='rerun', full=True): # this is the inner event loop... # print 'data =', (data) target = data['data']['id'] fun = data['data']['data']['fun'] fun_args = data['data']['data']['fun_args'] RERUN_IT = True REDUCER_CALLBACK = True if fun == 'test.arg': # Interactive commands for controlling the mapper enter here... # We repurpose the existing salt test.arg command # # >>> salt "test.arg <command> <args> <kwargs> --return=rerun" # # to control the runner # RERUN_IT = False # ...don't rerun control commands REDUCER_CALLBACK = False # don't callback results from control commands command = fun_args[0].lower() if command == 'abort': print "\"abort\" received, now terminating runner..." return False elif command == 'reset': print "\"reset\" received, now restarting..." return True elif command == 'run': print "run" RERUN_IT = True elif command == 'stop': print "stop" elif command == 'pause': print "pause" elif command == 'stats': print "repeat_count = ", (repeat_count) print "results = ", (m.statit()) elif command == 'mapit': print "mapit" if not m: # run this only once... try: module_name = fun_args[1].split('.')[0] # from module_name import _mapper mod = __import__(module_name) mod = getattr(mod, '_mapper') # this module has a "_mapper" class so use it... m = mod(fun_args[1]) repeat = m.partializer(fun_args[2:]) except: # not a map-reduce style module, so use base mapper class m = mapper(fun_args[1]) repeat = m.partializer(fun_args[2:]) # RERUN_IT = True # # ...causes the initial "partializer" command to be run if REDUCER_CALLBACK: # only callback the reducer if we got "real" results from a salt # execution module if inflight[data['data']['data']['jid']]: # TODO: This should not happen. Investigate why and prevent it m.reducer(data['data']['data']['return']) inflight.pop(data['data']['data']['jid']) try: mod except: RERUN_IT = False # This is NOT a MR enabled salt execution module so don't rerun it else: RERUN_IT = False # ...ignore this spurious event if RERUN_IT: try: my_fun = m.module_name my_fun_args = repeat.next() print "my_fun_args = ", (my_fun_args) minions = client.cmd_async(target, my_fun, my_fun_args, ret='rerun') inflight[minions] = True print "sending...", (my_fun), (my_fun_args), (minions) repeat_count += 1 print 'repeat =', (repeat_count) except StopIteration: print "done." if len(inflight) == 0: # all the results in, ok to terminate exit([m.statit()])
def call_highstate(minion_id): '''execute an async salt call to a minion to run state.highstate asynchronously''' client = salt.client.LocalClient() minions = client.cmd_async(tgt=minion_id, fun='state.highstate', arg=[], timeout=1, expr_form='compound') return
def execute(**kwargs): return client.cmd_async(**kwargs)
def run(self, params, args): hosts = self.getHostnames(args, managed_only=True) (function, name, sls, test, timeout) = self.fillParams([('function', None), ('name', None), ('sls', None), ('test', None), ('timeout', 30)]) test = self.str2bool(test) self.beginOutput() client = salt.client.LocalClient() if sls: job = client.cmd_async(hosts, fun='state.sls', arg=[sls], expr_form='list') elif function or name: if not (function and name): raise ParamRequired(self, ('function', 'name')) job = client.cmd_async( hosts, fun='state.single', arg=[function, 'name=%s' % name, 'test=%s' % test], expr_form='list') else: job = client.cmd_async(hosts, fun='state.highstate', arg=['test=%s' % test], expr_form='list') if job: while timeout: result = client.get_cache_returns(job) if result and len(result.keys()) == len(hosts): break time.sleep(1) timeout -= 1 for host in hosts: if result.has_key(host): if result[host].has_key('ret'): ret = result[host]['ret'] if ret: for key in ret.keys(): list = key.split('_|-') function = '%s.%s' % (list[0], list[3]) id = list[1] name = None if ret[key].has_key('name'): name = ret[key]['name'] self.addOutput(host, [ name, function, ret[key]['result'], ret[key]['comment'] ]) else: self.addOutput(host, [None, None, False, 'Command not run']) self.endOutput( header=['host', 'name', 'function', 'result', 'comment'], trimOwner=False)
def rerun(): inflight = {} # a dictionary for jobs with pending returned results repeat_count = 0 m = None client = salt.client.LocalClient('/etc/salt/minion') for data in event.iter_events(tag='rerun', full=True): # this is the inner event loop... # print 'data =', (data) target = data['data']['id'] fun = data['data']['data']['fun'] fun_args = data['data']['data']['fun_args'] RERUN_IT = True REDUCER_CALLBACK = True if fun == 'test.arg': # Interactive commands for controlling the mapper enter here... # We repurpose the existing salt test.arg command # # >>> salt "test.arg <command> <args> <kwargs> --return=rerun" # # to control the runner # RERUN_IT = False # ...don't rerun control commands REDUCER_CALLBACK = False # don't callback results from control commands command = fun_args[0].lower() if command == 'abort': print "\"abort\" received, now terminating runner..." return False elif command == 'reset': print "\"reset\" received, now restarting..." return True elif command == 'run': print "run" RERUN_IT = True elif command == 'stop': print "stop" elif command == 'pause': print "pause" elif command == 'stats': print "repeat_count = ", (repeat_count) print "results = ", (m.statit()) elif command == 'mapit': print "mapit" if not m: # run this only once... try: module_name = fun_args[1].split('.')[0] # from module_name import _mapper mod = __import__(module_name) mod = getattr(mod, '_mapper') # this module has a "_mapper" class so use it... m = mod(fun_args[1]) repeat = m.partializer(fun_args[2:]) except: # not a map-reduce style module, so use base mapper class m = mapper(fun_args[1]) repeat = m.partializer(fun_args[2:]) # RERUN_IT = True # # ...causes the initial "partializer" command to be run if REDUCER_CALLBACK: # only callback the reducer if we got "real" results from a salt # execution module if inflight[data['data']['data']['jid']]: # TODO: This should not happen. Investigate why and prevent it m.reducer(data['data']['data']['return']) inflight.pop(data['data']['data']['jid']) try: mod except: RERUN_IT = False # This is NOT a MR enabled salt execution module so don't rerun it else: RERUN_IT = False # ...ignore this spurious event if RERUN_IT: try: my_fun = m.module_name my_fun_args = repeat.next() print "my_fun_args = ", (my_fun_args) minions = client.cmd_async(target, my_fun, my_fun_args, ret='rerun') inflight[minions] = True print "sending...", (my_fun), (my_fun_args), (minions) repeat_count += 1 print 'repeat =', (repeat_count) except StopIteration: print "done." if len(inflight) == 0: # all the results in, ok to terminate exit([m.statit()])