def query_asa(device, query_cmd): '''Read information back from the given device @param device: dict a device dictionary @param query: str, a show command cli, like "show run access-list bla" @return tuple with: 1) response string from ASA; or None if cannot connect to the device 2) any error or exception string, otherwise None @attention: PLEASE do not use this API to make configuration change on the device ''' if not device: error = "query_asa: fails to read response for command '%s'. Error: %s" % (query_cmd, 'empty device dictionary') env.debug(error) return (None, error) if not query_cmd.strip().startswith('show'): error = "query_asa: '%s' is not a show command, discarded" % query_cmd env.debug(error) return (None, error) try: dispatcher = HttpDispatch(device) messenger = dispatcher.make_shows_messenger([query_cmd]) result = messenger.read() if result == 'Command failed\n': return None, None if '\nERROR: %' in result: return None,None return result, None except Exception as e: env.debug("query_asa: fails to read response for command '%s'. Error: %s" % (query_cmd, e)) return (None, str(e))
def query_asa(device, query_cmd): '''Read information back from the given device @param device: dict a device dictionary @param query: str, a show command cli, like "show run access-list bla" @return tuple with: 1) response string from ASA; or None if cannot connect to the device 2) any error or exception string, otherwise None @attention: PLEASE do not use this API to make configuration change on the device ''' if not device: error = "query_asa: fails to read response for command '%s'. Error: %s" % ( query_cmd, 'empty device dictionary') env.debug(error) return (None, error) if not query_cmd.strip().startswith('show'): error = "query_asa: '%s' is not a show command, discarded" % query_cmd env.debug(error) return (None, error) try: dispatcher = HttpDispatch(device) messenger = dispatcher.make_shows_messenger([query_cmd]) result = messenger.read() if result == 'Command failed\n': return None, None if '\nERROR: %' in result: return None, None return result, None except Exception as e: env.debug( "query_asa: fails to read response for command '%s'. Error: %s" % (query_cmd, e)) return (None, str(e))
def deliver_sts_table(device, sts, is_audit): ''' Send STS table to ASA device @param device: dict a device dictionary @param table; dict an STS dictionary @param is_audit: boolean True if this is an audit operation else False ''' table = sts.sts_table if not deliver_clis.enabled: env.debug("[STS table would be delivered]\n\n") return True if not table: return True dispatcher = HttpDispatch(device) if is_audit: messenger = dispatcher.make_sts_audit_write_messenger(sts) else: messenger = dispatcher.make_sts_write_messenger(sts) results = messenger.get_results() if results: faults = [] faults.append(('STS', 0, results)) raise ASACommandError(faults)
def read_clis(device, transformers=[convert_to_structured_commands, lambda x: x.split('\n')]): '''Read running-configuration from ASA device @param device: dict a device dictionary @param transformers: list of function that takes one argument and return an object the purpose of a transformer is to transform ASA configuration to a desired format. The order of the application of the transformer is the reverse given in the parameter, i.e. if the transformers is [a, b], the result will be a(b(config)). @return: list of CLI's ''' dispatcher = HttpDispatch(device) messenger = dispatcher.make_read_config_messenger() result = messenger.read() if result and transformers: for transformer in reversed(transformers): result = transformer(result) return result
def query_sts_audit_table(device, sts): ''' Query STS table from ASA device @param device: dict a device dictionary @param table; dict an STS dictionary ''' table = sts.sts_table if not device: error = "query_sts_table: fails to read response for quering sts table" env.debug(error) return (None, error) dispatcher = HttpDispatch(device) messenger = dispatcher.make_sts_audit_read_messenger(sts) results = messenger.get_results() if results: faults = [] faults.append(('STS', 0, results)) raise ASACommandError(faults)
def read_clis( device, transformers=[convert_to_structured_commands, lambda x: x.split('\n')]): '''Read running-configuration from ASA device @param device: dict a device dictionary @param transformers: list of function that takes one argument and return an object the purpose of a transformer is to transform ASA configuration to a desired format. The order of the application of the transformer is the reverse given in the parameter, i.e. if the transformers is [a, b], the result will be a(b(config)). @return: list of CLI's ''' dispatcher = HttpDispatch(device) messenger = dispatcher.make_read_config_messenger() result = messenger.read() if result and transformers: for transformer in reversed(transformers): result = transformer(result) return result
def deliver_clis(device, clis, transformers=[filter_out_sacred_commands], save_config=True): '''Deliver a list of CLI's to an ASA device @param device: dict a device dictionary @param clis: list of CLIIneraction's @param transformers: list of function that takes one argument and return an object the purpose of a transformer is to transform ASA configuration to a desired format before actually sending them down to the ASA device. The order of the application of the transformer is the reverse given in the parameter, i.e. if the transformers is [a, b], the result will be a(b(config)). a list of CLI objects. @param save_config: boolean indicate if the running-config should be saved to startup-config if the configuration is delivered successfully. @return: True if successful in delivery, or ASACommandError or ConnectionError exception will be raised. ''' if not deliver_clis.enabled: env.debug("[CLIs would be delivered]\n%s\n" % '\n'.join([str(cli) for cli in clis])) return True if not clis: return True if transformers: for transformer in reversed(transformers): clis = transformer(clis) dispatcher = HttpDispatch(device) def dispatch(clis): 'deliver a list of CLIInteraction, and return list errors if any' messenger = dispatcher.make_command_messenger(clis) results = messenger.get_results() errs = filter( lambda x: x != None and x.err_msg != None and len(x.err_msg.strip( )) > 0, results) return errs errs = dispatch(clis) if not errs: def is_cluster_config(clis): return any(str(cli).find('cluster group') >= 0 for cli in clis) if save_config and not is_cluster_config(clis): # 'wr mem' will fail during cluster setup so bypass now. Defer till cluster state is stable. write_mem = CLIInteraction("write mem", response_parser=lambda response: None if '[OK]' in response else response) errs = dispatch([write_mem]) if not errs: return True else: return True faults = [] for err in errs: faults.append((err.model_key, 0, err.err_msg)) raise ASACommandError(faults)
def serviceCounters(device, configuration): ''' This function is called periodically to report statistics associated with the service functions rendered on the device. @param device: a device dictionary @param configuration: dict It contains device configuration, group configuration for a particular graph instance and function configuration. The configuration dictionary follows the format described above. @return: dict The format of the dictionary is as follows { 'state': <state> 'counters': [(path, counters), ...] } path: Identifies the object to which the counter is associated. The path is a list identifying a specific instance of a connector. It includes device name, group name, etc. as shown below: path = [ vdev, vgrp, vfunc, conn ] vdev - Device Name. Passed in the configuration dictionary vgrp - Function Group name passed in the configuration dictionary vfunc - function name passed in configuration dictionary conn - connector name within the function counters: { 'rxpackets': <rxpackets>, 'rxerrors': <rxerrors>, 'rxdrops': <rxdrops>, 'txpackets': <txpackets>, 'txerrors': <txerrors>, 'txdrops': <txdrops> } ''' result = {'counters': []} asa = DeviceModel() ifc_cfg = massage_param_dict(asa, configuration) asa.populate_model(ifc_cfg.keys()[0], ifc_cfg.values()[0]) connectors = get_all_connectors(asa) if connectors: cli_holder = [] for connector in connectors: cli_holder.append( CLIInteraction('show interface ' + connector.get_nameif())) dispatcher = HttpDispatch(device) try: messenger = dispatcher.make_command_messenger(cli_holder) cli_results = messenger.get_results() except HTTPError as e: env.debug('serviceCounters: %s' % e) result['state'] = Status.TRANSIENT return result result['state'] = Status.SUCCESS for connector, cli_result in zip(connectors, cli_results): path = connector.get_config_path() counters = parse_connector_counters(cli_result.err_msg) result['counters'].append((path, counters)) else: # Check if there is connectivity to the device version = read_asa_version(device)[0] result['state'] = Status.SUCCESS if version else Status.TRANSIENT return result
def deviceCounters(device, interfaces, configuration): ''' This function is called periodically to report statistics associated with the physical interfaces of the device. @param device: a device dictionary @param interfaces: A list of the physical interfaces The format is: { (cifType, '', <interface name>) : { 'state': <state>, 'label': <label> }, ... } @param configuration: dict It contains device configuration. The configuration dictionary follows the format described above. @return: dict The format of the dictionary is as follows { 'state': <state> 'counters': [(path, counters), ...] } path: Identifies the object to which the counter is associated. counters: { 'rxpackets': <rxpackets>, 'rxerrors': <rxerrors>, 'rxdrops': <rxdrops>, 'txpackets': <txpackets>, 'txerrors': <txerrors>, 'txdrops': <txdrops> } ''' env.debug("[Interfaces argument]\n%s" % pretty_dict(interfaces)) result = {'counters': []} if interfaces: cli_holder = [] for interface in interfaces: cli_holder.append( CLIInteraction('show interface ' + interface[2].replace('_', '/'))) dispatcher = HttpDispatch(device) try: messenger = dispatcher.make_command_messenger(cli_holder) cli_results = messenger.get_results() except HTTPError as e: env.debug('deviceCounters: %s' % e) result['state'] = Status.TRANSIENT return result result['state'] = Status.SUCCESS for interface, cli_result in zip(interfaces, cli_results): if cli_result and cli_result.err_type == CLIResult.INFO: path = [(Type.CIF, '', interface[2])] counters = parse_interface_counters(cli_result.err_msg) result['counters'].append((path, counters)) else: # Check if there is connectivity to the device version = read_asa_version(device)[0] result['state'] = Status.SUCCESS if version else Status.TRANSIENT return result
def serviceCounters(device, configuration): ''' This function is called periodically to report statistics associated with the service functions rendered on the device. @param device: a device dictionary @param configuration: dict It contains device configuration, group configuration for a particular graph instance and function configuration. The configuration dictionary follows the format described above. @return: dict The format of the dictionary is as follows { 'state': <state> 'counters': [(path, counters), ...] } path: Identifies the object to which the counter is associated. The path is a list identifying a specific instance of a connector. It includes device name, group name, etc. as shown below: path = [ vdev, vgrp, vfunc, conn ] vdev - Device Name. Passed in the configuration dictionary vgrp - Function Group name passed in the configuration dictionary vfunc - function name passed in configuration dictionary conn - connector name within the function counters: { 'rxpackets': <rxpackets>, 'rxerrors': <rxerrors>, 'rxdrops': <rxdrops>, 'txpackets': <txpackets>, 'txerrors': <txerrors>, 'txdrops': <txdrops> } ''' result = {'counters': []} asa = DeviceModel() ifc_cfg = massage_param_dict(asa, configuration) asa.populate_model(ifc_cfg.keys()[0], ifc_cfg.values()[0]) connectors = get_all_connectors(asa) if connectors: cli_holder = [] for connector in connectors: cli_holder.append(CLIInteraction('show interface ' + connector.get_nameif())) dispatcher = HttpDispatch(device) try: messenger = dispatcher.make_command_messenger(cli_holder) cli_results = messenger.get_results() except HTTPError as e: env.debug('serviceCounters: %s' % e) result['state'] = Status.TRANSIENT return result result['state'] = Status.SUCCESS for connector, cli_result in zip(connectors, cli_results): path = connector.get_config_path() counters = parse_connector_counters(cli_result.err_msg) result['counters'].append((path, counters)) else: # Check if there is connectivity to the device version = read_asa_version(device)[0] result['state'] = Status.SUCCESS if version else Status.TRANSIENT return result
def deviceCounters(device, interfaces, configuration): ''' This function is called periodically to report statistics associated with the physical interfaces of the device. @param device: a device dictionary @param interfaces: A list of the physical interfaces The format is: { (cifType, '', <interface name>) : { 'state': <state>, 'label': <label> }, ... } @param configuration: dict It contains device configuration. The configuration dictionary follows the format described above. @return: dict The format of the dictionary is as follows { 'state': <state> 'counters': [(path, counters), ...] } path: Identifies the object to which the counter is associated. counters: { 'rxpackets': <rxpackets>, 'rxerrors': <rxerrors>, 'rxdrops': <rxdrops>, 'txpackets': <txpackets>, 'txerrors': <txerrors>, 'txdrops': <txdrops> } ''' env.debug("[Interfaces argument]\n%s" % pretty_dict(interfaces)) result = {'counters': []} if interfaces: cli_holder = [] for interface in interfaces: cli_holder.append(CLIInteraction('show interface ' + interface[2].replace('_', '/'))) dispatcher = HttpDispatch(device) try: messenger = dispatcher.make_command_messenger(cli_holder) cli_results = messenger.get_results() except HTTPError as e: env.debug('deviceCounters: %s' % e) result['state'] = Status.TRANSIENT return result result['state'] = Status.SUCCESS for interface, cli_result in zip(interfaces, cli_results): if cli_result and cli_result.err_type == CLIResult.INFO: path = [(Type.CIF, '', interface[2])] counters = parse_interface_counters(cli_result.err_msg) result['counters'].append((path, counters)) else: # Check if there is connectivity to the device version = read_asa_version(device)[0] result['state'] = Status.SUCCESS if version else Status.TRANSIENT return result