def cb_action(self, uinfo, name, kp, input, output): self.log.info('Action: {}'.format(name)) action_set_timeout(uinfo, 240) try: service_call = service_handler( input.service_name, ServiceArgs(input.service_name, input.operation_id), self.log) result = service_call(uinfo) except Exception as e: self.log.error('Error in {}: {}'.format(name, e)) output.failure = "An error occurred: {}".format(e) else: action_output = ["Service call completed successfully"] if result is not None: action_output.append(":\n{}".format(result)) output.success = "".join(action_output)
def cb_action(self, uinfo, name, kp, input, output): self.log.info("Action {}".format(name)) action_set_timeout(uinfo, 240) try: # Run assessment results = None with ncs.maapi.single_read_trans(uinfo.username, "system") as read_t: root = ncs.maagic.get_root(read_t) # kp sample: /ncs:services/snap:health-samples/device{IOS-0} kp_node = ncs.maagic.cd(root, kp) assessment_name = kp_node.snap__lightweight_assessment if assessment_name is None: raise AssessmentError( "No lightweight assessment defined for {}".format( kp_node.snap__name)) results = run_assessment( root.devices.device[kp_node.snap__name], root.ncs__services.snap__health_samples.snap__setup. snap__stop_on_error, root.ncs__services. snap__health_samples.snap__assessment[assessment_name], self.log) # Figure out the outcome assessment_outcome = all(map(attrgetter('passed'), results)) if assessment_outcome: output.success = "Assessment completed without errors" else: failed_cmds = ', '.join([ str(seq) for seq, result, passed in results if not passed ]) output.failure = "Assessment completed with errors. Commands that failed: {}".format( failed_cmds) except AssessmentError as e: output.failure = "Assessment error: {}".format(e) self.log.info("Lightweight assessment error: {}".format(e))
def cb_action(self, uinfo, name, kp, input, output): self.log.info("Action {}".format(name)) action_set_timeout(uinfo, 240) try: # Run assessment with ncs.maapi.single_read_trans(uinfo.username, "system") as read_t: root = ncs.maagic.get_root(read_t) # kp sample: /ncs:services/snap:health-samples/device{IOS-0} kp_node = ncs.maagic.cd(root, kp) assessment_name = kp_node.snap__assessment results = run_assessment( root.devices.device[kp_node.snap__name], root.ncs__services.snap__health_samples.snap__setup. snap__stop_on_error, root.ncs__services. snap__health_samples.snap__assessment[assessment_name], self.log) # Save assessment sample with ncs.maapi.single_write_trans(uinfo.username, "system", db=ncs.OPERATIONAL) as write_t: root = ncs.maagic.get_root(write_t) kp_node = ncs.maagic.cd(root, kp) # Create a new sample timestamp = int(time()) new_sample = kp_node.snap__sample.create(timestamp) for seq, result, passed in results: new_cmd = new_sample.snap__command.create(seq) new_cmd.snap__output = result new_cmd.snap__passed = passed # Trim old samples key_list = [ sample_entry.timestamp for sample_entry in kp_node.snap__sample ] items_to_trim = len( key_list ) - root.ncs__services.snap__health_samples.snap__setup.snap__max_samples if items_to_trim > 0: for old_key in islice(sorted(key_list), items_to_trim): del kp_node.snap__sample[old_key] self.log.info('Trimmed {} sample(s)'.format(items_to_trim)) write_t.apply() self.log.info("Saved assessment: {}, timestamp: {}".format( kp_node.snap__name, timestamp)) # Figure out the outcome assessment_outcome = all(map(attrgetter('passed'), results)) if assessment_outcome: output.success = "Assessment completed without errors" else: failed_cmds = ', '.join([ str(seq) for seq, result, passed in results if not passed ]) output.failure = "Assessment completed with errors. Commands that failed: {}".format( failed_cmds) except AssessmentError as e: output.failure = "Assessment error: {}".format(e) self.log.info("Assessment error: {}".format(e))
def cb_action(self, uinfo, name, kp, input, output): def sample_cmds(sample_node): """ Return commands in a sample as a generator :param sample_node: maagic node representing a sample instance :return: list of (seq, output, passed) tuples """ return ( (cmd.seq, cmd.output, cmd.passed) for cmd in sorted(sample_node.command, key=attrgetter('seq'))) self.log.info("Action {}".format(name)) action_set_timeout(uinfo, 240) with ncs.maapi.single_read_trans(uinfo.username, "system") as read_t: root = ncs.maagic.get_root(read_t) # kp: /ncs:services/snap:health-samples/device{IOS-0} kp_node = ncs.maagic.cd(root, kp) ts_list = sorted([ sample_entry.timestamp for sample_entry in kp_node.snap__sample ]) try: if len(ts_list) < 2: raise DiffFailed("Not enough samples to complete") assessment = root.ncs__services.snap__health_samples.snap__assessment[ kp_node.snap__assessment] parse_dict = { cmd.seq: cmd.parse for cmd in assessment.snap__command } last_ts, prev_ts = ts_list[-1], ts_list[-2] self.log.info("{}: comparing {} and {} samples".format( kp_node.snap__name, last_ts, prev_ts)) # Iterate over commands from the last 2 samples zipped_cmds = zip(sample_cmds(kp_node.snap__sample[last_ts]), sample_cmds(kp_node.snap__sample[prev_ts])) for (last_seq, last_output, last_passed), (prev_seq, prev_output, prev_passed) in zipped_cmds: if last_seq != prev_seq: raise DiffFailed( "Command sequence number mismatch: last: {}, prev: {}" .format(last_seq, prev_seq)) if not last_passed: raise DiffFailed( "Last assessment failed: {}".format(last_ts)) if not prev_passed: raise DiffFailed( "Previous assessment failed: {}".format(prev_ts)) cmd_run = assessment.snap__command[last_seq].snap__run self.log.info("Comparing '{}' ({}) output".format( cmd_run, last_seq)) last_tokens = cmd_parse(last_output, parse_dict[last_seq]) prev_tokens = cmd_parse(prev_output, parse_dict[prev_seq]) if len(last_tokens) != len(prev_tokens): raise DiffFailed( "Different number of matches across samples from '{}' ({})" .format(cmd_run, last_seq)) token_match = [(token_last == token_prev) for token_last, token_prev in zip( last_tokens, prev_tokens)] if not all(token_match): raise DiffFailed( "Output from '{}' ({}) changed".format( cmd_run, last_seq)) output.success = "Diff passed" self.log.info("Diff assessment passed") except DiffFailed as e: output.failure = "Diff failed: {}".format(e) self.log.info("Diff assessment failed: {}".format(e))
def extend_timeout(self, timeout_extension): dp.action_set_timeout(self.uinfo, timeout_extension)
def extend_timeout(self) -> None: '''Tell NSO to wait a bit longer. See also `TIMEOUT_MARGIN`. ''' extension = self.device_timeout + 2 * TIMEOUT_MARGIN dp.action_set_timeout(self.uinfo, extension)