def task_generator(action, selector): log.debug("call task_generator: %s", action) try: service = Prototype.objects.get(bundle=action.prototype.bundle, type='service', name='ZOOKEEPER', version='1.2') except Prototype.DoesNotExist: raise AdcmEx('TASK_GENERATOR_ERROR', 'service ZOOKEEPER not found') try: stop = Action.objects.get(prototype=service, name='stop') except Prototype.DoesNotExist: raise AdcmEx('TASK_GENERATOR_ERROR', 'action stop of service ZOOKEEPER not found') try: start = Action.objects.get(prototype=service, name='start') except Prototype.DoesNotExist: raise AdcmEx('TASK_GENERATOR_ERROR', 'action start of service ZOOKEEPER not found') return ( { 'action': stop, 'selector': selector }, { 'action': start, 'selector': selector }, )
def run(self, tmp=None, task_vars=None): super().run(tmp, task_vars) job_id = None if task_vars is not None and 'job' in task_vars or 'id' in task_vars[ 'job']: job_id = task_vars['job']['id'] old_optional_condition = 'msg' in self._task.args new_optional_condition = 'fail_msg' in self._task.args and 'success_msg' in self._task.args optional_condition = old_optional_condition or new_optional_condition required_condition = ('title' in self._task.args and 'result' in self._task.args and optional_condition) if not required_condition: return { "failed": True, "msg": ("title, result and msg, fail_msg or success" "_msg are mandatory args of adcm_check") } title = self._task.args['title'] result = self._task.args['result'] msg = self._task.args.get('msg', '') fail_msg = self._task.args.get('fail_msg', '') success_msg = self._task.args.get('success_msg', '') group_title = self._task.args.get('group_title', '') group_fail_msg = self._task.args.get('group_fail_msg', '') group_success_msg = self._task.args.get('group_success_msg', '') if result: msg = success_msg if success_msg else msg else: msg = fail_msg if fail_msg else msg group = { 'title': group_title, 'success_msg': group_success_msg, 'fail_msg': group_fail_msg } check = { 'title': title, 'result': result, 'message': msg, } log.debug('ansible adcm_check: %s, %s', ', '.join([f'{k}: {v}' for k, v in group.items() if v]), ', '.join([f'{k}: {v}' for k, v in check.items() if v])) try: cm.job.log_check(job_id, group, check) except AdcmEx as e: return {"failed": True, "msg": e.code + ":" + e.msg} return {"failed": False, "changed": False}
def encrypt_passwords(apps, schema_editor): ConfigLog = apps.get_model('cm', 'ConfigLog') PrototypeConfig = apps.get_model('cm', 'PrototypeConfig') for model_name in 'Cluster', 'ClusterObject', 'HostProvider', 'Host', 'ADCM': log.debug('QQ model %s', model_name) Model = apps.get_model('cm', model_name) for obj in Model.objects.filter(config__isnull=False): log.debug('QQ model %s, obj %s', model_name, obj) process_objects(obj, ConfigLog, PrototypeConfig)
def lock_obj(obj, event): stack = obj.stack if not stack: stack = [obj.state] elif stack[-1] != obj.state: stack.append(obj.state) log.debug('lock %s, stack: %s', obj_ref(obj), stack) obj.stack = stack api.set_object_state(obj, config.Job.LOCKED, event)
def run_job(task_id, job_id, err_file): log.debug("run job #%s of task #%s", job_id, task_id) try: proc = subprocess.Popen([ os.path.join(config.CODE_DIR, 'job_runner.py'), str(job_id) ], stderr=err_file) res = proc.wait() return res except: log.error("exception runnung job %s", job_id) return 1
def run_task(task_id, args=None): log.debug("task_runner.py called as: %s", sys.argv) try: task = TaskLog.objects.get(id=task_id) except ObjectDoesNotExist: log.error("no task %s", task_id) return jobs = JobLog.objects.filter(task_id=task.id).order_by('id') if not jobs: log.error("no jobs for task %s", task.id) cm.job.finish_task(task, None, config.Job.FAILED) return err_file = open(os.path.join(config.LOG_DIR, 'job_runner.err'), 'a+', encoding='utf_8') log.info("run task #%s", task_id) job = None count = 0 res = 0 for job in jobs: if args == 'restart' and job.status == config.Job.SUCCESS: log.info('skip job #%s status "%s" of task #%s', job.id, job.status, task_id) continue cm.job.re_prepare_job(task, job) job.start_date = timezone.now() job.save() res = run_job(task.id, job.id, err_file) set_body_ansible(job) # For multi jobs task object state and/or config can be changed by adcm plugins if task.task_object is not None: try: task.task_object.refresh_from_db() except ObjectDoesNotExist: task.object_id = 0 task.object_type = None count += 1 if res != 0: break if res == 0: cm.job.finish_task(task, job, config.Job.SUCCESS) else: cm.job.finish_task(task, job, config.Job.FAILED) err_file.close() log.info("finish task #%s, ret %s", task_id, res)
def post_event(event, obj_type, obj_id, det_type=None, det_val=None): details = {'type': det_type, 'value': det_val} if det_type and not det_val: details = det_type data = { 'event': event, 'object': { 'type': obj_type, 'id': int(obj_id), 'details': details, }, } log.debug('post_event %s', data) return api_post('/event/', data)
def unlock_obj(obj, event): if obj.stack: stack = obj.stack else: log.warning('no stack in %s for unlock', obj_ref(obj)) return try: state = stack.pop() except IndexError: log.warning('empty stack in %s for unlock', obj_ref(obj)) return log.debug('unlock %s, stack: %s', obj_ref(obj), stack) obj.stack = stack api.set_object_state(obj, state, event)
def fix_task(apps, schema_editor): TaskLog = apps.get_model('cm', 'TaskLog') Action = apps.get_model('cm', 'Action') for task in TaskLog.objects.all(): try: action = Action.objects.get(id=task.action_id) except Action.DoesNotExist: continue selector = task.selector if action.prototype.type == 'service': if 'service' not in selector: selector['service'] = task.object_id log.debug('update task #%s new selector: %s', task.id, selector) task.selector = selector task.save()
def run_ansible(job_id): log.debug("job_runner.py called as: %s", sys.argv) conf = read_config(job_id) playbook = conf['job']['playbook'] out_file = open_file(config.RUN_DIR, 'ansible-stdout', job_id) err_file = open_file(config.RUN_DIR, 'ansible-stderr', job_id) post_log(job_id, 'stdout', 'ansible') post_log(job_id, 'stderr', 'ansible') event = Event() os.chdir(conf['env']['stack_dir']) cmd = [ '/adcm/python/job_venv_wrapper.sh', get_venv(int(job_id)), 'ansible-playbook', '--vault-password-file', f'{config.CODE_DIR}/ansible_secret.py', '-e', f'@{config.RUN_DIR}/{job_id}/config.json', '-i', f'{config.RUN_DIR}/{job_id}/inventory.json', playbook, ] if 'params' in conf['job']: if 'ansible_tags' in conf['job']['params']: cmd.append('--tags=' + conf['job']['params']['ansible_tags']) if 'verbose' in conf['job'] and conf['job']['verbose']: cmd.append('-vvvv') log.info("job run cmd: %s", ' '.join(cmd)) proc = subprocess.Popen(cmd, env=env_configuration(conf), stdout=out_file, stderr=err_file) cm.job.set_job_status(job_id, config.Job.RUNNING, event, proc.pid) event.send_state() log.info("run ansible job #%s, pid %s, playbook %s", job_id, proc.pid, playbook) ret = proc.wait() finish_check(job_id) ret = set_job_status(job_id, ret, proc.pid, event) event.send_state() out_file.close() err_file.close() log.info("finish ansible job #%s, pid %s, ret %s", job_id, proc.pid, ret) sys.exit(ret)
def run_job(task_id, job_id, err_file): log.debug("task run job #%s of task #%s", job_id, task_id) cmd = [ '/adcm/python/job_venv_wrapper.sh', TaskLog.objects.get(id=task_id).action.venv, os.path.join(config.CODE_DIR, 'job_runner.py'), str(job_id), ] log.info("task run job cmd: %s", ' '.join(cmd)) try: proc = subprocess.Popen(cmd, stderr=err_file) res = proc.wait() return res except: log.error("exception runnung job %s", job_id) return 1
def task_get(action, selector): log.debug("call task: %s", action) try: service = Prototype.objects.get(type='service', name='Simple_service') except Prototype.DoesNotExist: raise AdcmEx('TASK_GET_ERR', 'my error description') from None try: stop = Action.object.get(context='service', context_id=service.id, name='stop') except Prototype.DoesNotExist: raise AdcmEx( 'TASK_GENERATOR_ERROR', 'action stop in service Simple_service not found') from None return {'action': stop, 'selector': selector}
def fix_job(apps, schema_editor): JobLog = apps.get_model('cm', 'JobLog') TaskLog = apps.get_model('cm', 'TaskLog') Action = apps.get_model('cm', 'Action') for job in JobLog.objects.all(): try: action = Action.objects.get(id=job.action_id) except Action.DoesNotExist: continue task = TaskLog.objects.get(id=job.task_id) selector = job.selector if action.prototype.type == 'service': if 'service' not in selector: selector['service'] = task.object_id log.debug('update job #%s new selector: %s', job.id, selector) job.selector = selector job.save()
def process_adcm(): sp = StagePrototype.objects.get(type='adcm') adcm = ADCM.objects.filter() if adcm: old_proto = adcm[0].prototype new_proto = sp if old_proto.version == new_proto.version: log.debug('adcm vesrion %s, skip upgrade', old_proto.version) elif rpm.compare_versions(old_proto.version, new_proto.version) < 0: bundle = copy_stage('adcm', sp) upgrade_adcm(adcm[0], bundle) else: msg = 'Current adcm version {} is more than or equal to upgrade version {}' err('UPGRADE_ERROR', msg.format(old_proto.version, new_proto.version)) else: bundle = copy_stage('adcm', sp) init_adcm(bundle)
def get_job_data(self): env = os.environ ansible_config = env.get('ANSIBLE_CONFIG') if not ansible_config: return job_id = Path(ansible_config).parent.name try: self.job = models.JobLog.objects.select_related('task', 'task__lock').get( id=int(job_id) ) except (ValueError, models.ObjectDoesNotExist): return self.task = getattr(self.job, 'task', None) self.lock = getattr(self.task, 'lock', None) msg = f'API context was initialized with {self.job}, {self.task}, {self.lock}' log.debug(msg)
def run(self, terms, variables=None, **kwargs): # pylint: disable=too-many-branches log.debug('run %s %s', terms, kwargs) ret = [] if len(terms) < 3: msg = 'not enough arguments to set config ({} of 3)' raise AnsibleError(msg.format(len(terms))) if terms[0] == 'service': if 'cluster' not in variables: raise AnsibleError('there is no cluster in hostvars') cluster = variables['cluster'] if 'service_name' in kwargs: res = set_service_config_by_name(cluster['id'], kwargs['service_name'], terms[1], terms[2]) elif 'job' in variables and 'service_id' in variables['job']: res = set_service_config(cluster['id'], variables['job']['service_id'], terms[1], terms[2]) else: msg = 'no service_id in job or service_name and service_version in params' raise AnsibleError(msg) elif terms[0] == 'cluster': if 'cluster' not in variables: raise AnsibleError('there is no cluster in hostvars') cluster = variables['cluster'] res = set_cluster_config(cluster['id'], terms[1], terms[2]) elif terms[0] == 'provider': if 'provider' not in variables: raise AnsibleError('there is no host provider in hostvars') provider = variables['provider'] res = set_provider_config(provider['id'], terms[1], terms[2]) elif terms[0] == 'host': if 'adcm_hostid' not in variables: raise AnsibleError('there is no adcm_hostid in hostvars') res = set_host_config(variables['adcm_hostid'], terms[1], terms[2]) else: raise AnsibleError(f'unknown object type: {terms[0]}') ret.append(res) return ret
def load_service_map(): comps = {} hosts = {} hc_map = {} services = {} passive = {} for c in ServiceComponent.objects.filter(prototype__monitoring='passive'): passive[c.id] = True for hc in HostComponent.objects.all(): if hc.component.id in passive: continue key = '{}.{}'.format(hc.host.id, hc.component.id) hc_map[key] = {'cluster': hc.cluster.id, 'service': hc.service.id} if str(hc.cluster.id) not in comps: comps[str(hc.cluster.id)] = {} if str(hc.service.id) not in comps[str(hc.cluster.id)]: comps[str(hc.cluster.id)][str(hc.service.id)] = [] comps[str(hc.cluster.id)][str(hc.service.id)].append(key) for host in Host.objects.filter(prototype__monitoring='active'): if host.cluster: cluster_id = host.cluster.id else: cluster_id = 0 if cluster_id not in hosts: hosts[cluster_id] = [] hosts[cluster_id].append(host.id) for co in ClusterObject.objects.filter(prototype__monitoring='active'): if co.cluster.id not in services: services[co.cluster.id] = [] services[co.cluster.id].append(co.id) m = { 'hostservice': hc_map, 'component': comps, 'service': services, 'host': hosts, } log.debug("service map: %s", m) return api_post('/servicemap/', m)
def run(self, terms, variables=None, **kwargs): # pylint: disable=too-many-branches log.debug('run %s %s', terms, kwargs) ret = [] event = Event() if len(terms) < 2: msg = 'not enough arguments to set state ({} of 2)' raise AnsibleError(msg.format(len(terms))) if terms[0] == 'service': if 'cluster' not in variables: raise AnsibleError('there is no cluster in hostvars') cluster = variables['cluster'] if 'service_name' in kwargs: res = cm.api.set_service_state(cluster['id'], kwargs['service_name'], terms[1]) elif 'job' in variables and 'service_id' in variables['job']: res = cm.api.set_service_state_by_id( cluster['id'], variables['job']['service_id'], terms[1]) else: msg = 'no service_id in job or service_name in params' raise AnsibleError(msg) elif terms[0] == 'cluster': if 'cluster' not in variables: raise AnsibleError('there is no cluster in hostvars') cluster = variables['cluster'] res = cm.api.set_cluster_state(cluster['id'], terms[1]) elif terms[0] == 'provider': if 'provider' not in variables: raise AnsibleError('there is no provider in hostvars') provider = variables['provider'] res = cm.api.set_provider_state(provider['id'], terms[1], event) elif terms[0] == 'host': if 'adcm_hostid' not in variables: raise AnsibleError('there is no adcm_hostid in hostvars') res = cm.api.set_host_state(variables['adcm_hostid'], terms[1]) else: raise AnsibleError('unknown object type: %s' % terms[0]) event.send_state() ret.append(res) return ret
def run(self, tmp=None, task_vars=None): super().run(tmp, task_vars) if task_vars is not None and 'job' in task_vars or 'id' in task_vars['job']: job_id = task_vars['job']['id'] name = self._task.args.get('name') log_format = self._task.args.get('format') path = self._task.args.get('path') content = self._task.args.get('content') if not name and log_format and (path or content): return { "failed": True, "msg": "name, format and path or content are mandatory args of adcm_custom_log", } try: if path is None: log.debug( 'ansible adcm_custom_log: %s, %s, %s, %s', job_id, name, log_format, content ) log_custom(job_id, name, log_format, content) else: log.debug('ansible adcm_custom_log: %s, %s, %s, %s', job_id, name, log_format, path) slurp_return = self._execute_module( module_name='slurp', module_args={'src': path}, task_vars=task_vars, tmp=tmp ) try: body = base64.standard_b64decode(slurp_return['content']).decode() except Error as error: raise AdcmEx('UNKNOWN_ERROR', msg='Error b64decode for slurp module') from error except UnicodeDecodeError as error: raise AdcmEx( 'UNKNOWN_ERROR', msg='Error UnicodeDecodeError for slurp module' ) from error log_custom(job_id, name, log_format, body) except AdcmEx as e: return {"failed": True, "msg": f"{e.code}: {e.msg}"} return {"failed": False, "changed": False}
def task_generator(action, selector): log.debug("call task_generator: %s", action) try: service = Prototype.objects.get(type='service', name='Simple_service', version='new_version') except Prototype.DoesNotExist: raise AdcmEx('TASK_GENERATOR_ERROR', 'service Simple_service not found') from None try: stop = Action.objects.get(context='service', context_id=service.id, name='stop') except Prototype.DoesNotExist: raise AdcmEx('TASK_GENERATOR_ERROR', 'action stop of service ZOOKEEPER not found') from None try: start = Action.objects.get(context='service', context_id=service.id, name='start') except Prototype.DoesNotExist: raise AdcmEx('TASK_GENERATOR_ERROR', 'action start of service ZOOKEEPER not found') from None return ( { 'action': stop, 'selector': selector }, { 'action': start, 'selector': selector }, )
def cook_delta( # pylint: disable=too-many-branches cluster: Cluster, new_hc: List[Tuple[ClusterObject, Host, ServiceComponent]], action_hc: List[dict], old: dict = None, ) -> dict: def add_delta(delta, action, key, fqdn, host): service, comp = key.split('.') if not check_action_hc(action_hc, service, comp, action): msg = (f'no permission to "{action}" component "{comp}" of ' f'service "{service}" to/from hostcomponentmap') err('WRONG_ACTION_HC', msg) add_to_dict(delta[action], key, fqdn, host) new = {} for service, host, comp in new_hc: key = cook_comp_key(service.prototype.name, comp.prototype.name) add_to_dict(new, key, host.fqdn, host) if not old: old = {} for hc in HostComponent.objects.filter(cluster=cluster): key = cook_comp_key(hc.service.prototype.name, hc.component.prototype.name) add_to_dict(old, key, hc.host.fqdn, hc.host) delta = {'add': {}, 'remove': {}} for key, value in new.items(): if key in old: for host in value: if host not in old[key]: add_delta(delta, 'add', key, host, value[host]) for host in old[key]: if host not in value: add_delta(delta, 'remove', key, host, old[key][host]) else: for host in value: add_delta(delta, 'add', key, host, value[host]) for key, value in old.items(): if key not in new: for host in value: add_delta(delta, 'remove', key, host, value[host]) log.debug('OLD: %s', old) log.debug('NEW: %s', new) log.debug('DELTA: %s', delta) return delta
def cook_delta(cluster, new_hc, action_hc, old=None): def add_delta(delta, action, key, fqdn, host): service, comp = key.split('.') if not check_action_hc(action_hc, service, comp, action): msg = (f'no permission to "{action}" component "{comp}" of ' f'service "{service}" to/from hostcomponentmap') err('WRONG_ACTION_HC', msg) add_to_dict(delta[action], key, fqdn, host) new = {} for service, host, comp in new_hc: key = cook_comp_key(service.prototype.name, comp.prototype.name) add_to_dict(new, key, host.fqdn, host) if not old: old = {} for hc in HostComponent.objects.filter(cluster=cluster): key = cook_comp_key(hc.service.prototype.name, hc.component.prototype.name) add_to_dict(old, key, hc.host.fqdn, hc.host) delta = {'add': {}, 'remove': {}} for key in new: if key in old: for host in new[key]: if host not in old[key]: add_delta(delta, 'add', key, host, new[key][host]) for host in old[key]: if host not in new[key]: add_delta(delta, 'remove', key, host, old[key][host]) else: for host in new[key]: add_delta(delta, 'add', key, host, new[key][host]) for key in old: if key not in new: for host in old[key]: add_delta(delta, 'remove', key, host, old[key][host]) log.debug('OLD: %s', old) log.debug('NEW: %s', new) log.debug('DELTA: %s', delta) return delta
def task_generator(action): log.debug("call task_generator: %s", action) return {'action'}