def ifc2asa(self, no_asa_cfg_stack, asa_cfg_list): ''' Translate IFC config to ASA config ''' if not self.has_ifc_delta_cfg(): return self.rate_type = self.get_parent().rate_type self.asa_key = 'threat-detection rate ' + self.rate_type state = self.delta_ifc_cfg_value['state'] self.extra_cli = None if state != State.NOCHANGE: config = util.normalize_param_dict(self.delta_ifc_cfg_value['value']) config['rate'] = self.rate_type if not config.get('rate_status'): config['rate_status'] = 'enable' cli = self.create_cli(config, state) if not cli: return if self.extra_cli: no_asa_cfg_stack.append(CLIInteraction(self.extra_cli, response_parser=self.ignore_response_parser)) asa_cfg_list.append(CLIInteraction(cli)) else: if cli.startswith('no '): no_cli_cur = None if len(no_asa_cfg_stack): no_cli_cur = no_asa_cfg_stack[len(no_asa_cfg_stack) - 1].command if cli != no_cli_cur: no_asa_cfg_stack.append(CLIInteraction(cli, response_parser=self.ignore_response_parser)) else: asa_cfg_list.append(CLIInteraction(cli))
def process_collectors(self, no_asa_cfg_stack, asa_cfg_list, translator, value): ''' Process collectors ''' state = value.get('state', State.CREATE) if len(translator.children.values()) > 0: child = translator.children.values()[0] if self.interface: child.interface = self.interface cli = child.create_cli(value, state) else: return else: return if state != State.DESTROY: key = NetFlowCollectors.get_collector_info(value) if key in self.parent.collectors and value.get( 'status', 'enable') == 'enable': return asa_cfg_list.append( CLIInteraction( cli, response_parser=self.ignore_msg_response_parser)) else: no_asa_cfg_stack.append( CLIInteraction( cli, response_parser=self.ignore_msg_response_parser))
def ifc2asa(self, no_asa_cfg_stack, asa_cfg_list): ''' Translate IFC config to ASA config ''' if not self.has_ifc_delta_cfg(): return state = self.delta_ifc_cfg_value['state'] if state != State.NOCHANGE: config = util.normalize_param_dict( self.delta_ifc_cfg_value['value']) cli = self.create_cli(config, state) if not len(cli): return if self.extra_cli: no_asa_cfg_stack.append( CLIInteraction(self.extra_cli, response_parser=ScanningThreatDetection. ignore_msg_response_parser)) asa_cfg_list.append( CLIInteraction(cli, response_parser=ScanningThreatDetection. ignore_msg_response_parser)) else: if cli.startswith('no '): no_asa_cfg_stack.append( CLIInteraction(cli, response_parser=ScanningThreatDetection. ignore_msg_response_parser)) else: asa_cfg_list.append( CLIInteraction(cli, response_parser=ScanningThreatDetection. ignore_msg_response_parser))
def generate_single_cli(self, enabled): ''' Generate a CLI ''' if enabled: return CLIInteraction(self.get_asa_key() + ' ' + self.destination, mode_command=self.mode_command, response_parser=TemplateAndCollectors. ignore_msg_response_parser) else: return CLIInteraction('no ' + self.get_asa_key() + ' ' + self.destination, mode_command=self.mode_command, response_parser=TemplateAndCollectors. ignore_msg_response_parser)
def ifc2asa(self, no_asa_cfg_stack, asa_cfg_list): ''' Translate IFC config to ASA config ''' self.get_parent().query_collectors() self.interface = None for (ifc_key, ifc_name), value in self.config.iteritems(): if not value: continue translator = self.get_child(ifc_key) state = value['state'] if isinstance(translator, DMList): if not self.interface: child = translator.children.values()[0] self.interface = child.get_top().get_utility_nameif() self.process_collectors(no_asa_cfg_stack, asa_cfg_list, translator, value) else: clia = CLIInteraction( translator.create_cli(value, state), response_parser=self.ignore_msg_response_parser) if state == State.CREATE or state == State.MODIFY: asa_cfg_list.append(clia) elif state == State.DESTROY: no_asa_cfg_stack.append(clia) self.config[ifc_key, ifc_name] = None
def ifc2asa(self, no_asa_cfg_stack, asa_cfg_list, interfaces = None): '''Generate ASA configuration from IFC configuration delta. @see DMObject.ifc2asa for parameter details ''' if not self.has_ifc_delta_cfg(): return action = self.get_action() if action == State.NOCHANGE: return if action == State.DESTROY and self.is_removable: self.generate_cli(no_asa_cfg_stack, 'no ' + self.get_cli()) else: self.generate_cli(asa_cfg_list, self.get_cli()) # apply the pool to the management interface value = normalize_param_dict(self.delta_ifc_cfg_value['value']) intf = self.get_top().get_mgmt_interface() if not intf: # default management interface: m0/0 intf = 'm0/0' attr = self.get_mgmt_intf_attributes(intf) if attr == None: return clii = CLIInteraction(mode_command='interface ' + util.normalize_interface_name(intf), command='ip address ' + attr['ip'] + ' ' + attr['mask'] + ' cluster-pool ' + value['pool_name'], response_parser=cluster_response_parser) asa_cfg_list.append(clii) SimpleType.ifc2asa(self, no_asa_cfg_stack, asa_cfg_list)
def ifc2asa(self, no_asa_cfg_stack, asa_cfg_list): ''' Translate IFC config to ASA config ''' if not self.has_ifc_delta_cfg(): return config = self.delta_ifc_cfg_value['value'] mode = self.mode_command if hasattr( self, 'mode_command') and self.mode_command else None no_len = len(no_asa_cfg_stack) for (ifc_type, ifc_key, inst), values in config.iteritems(): inspect = self.get_child(ifc_key) inspect.mode_command = mode state = values.get('state', State.NOCHANGE) enable = values.get('value', None) if enable == 'disable' and state == State.MODIFY: values['state'] = State.DESTROY inspect.ifc2asa(no_asa_cfg_stack, asa_cfg_list) if len(no_asa_cfg_stack) > no_len: no_asa_cfg_stack.append( CLIInteraction(self.MATCH_DEFAULT_INSPECT_CLI)) no_asa_cfg_stack.append(CLIInteraction(self.CLASS_MAP_INSPECT_CLI))
def get_cli(self): ''' Normalize the interface name before filling the template. ''' assert self.has_ifc_delta_cfg() intf = util.normalize_param_dict(self.get_top().get_mgmt_interface()) if not intf: return value = util.normalize_param_dict(self.delta_ifc_cfg_value['value']) command = ' '.join((self.asa_gen_template % value).split()) mode_command = 'interface ' + intf return CLIInteraction(command=command, mode_command=mode_command, response_parser=failover_response_parser)
def ifc2asa(self, no_asa_cfg_stack, asa_cfg_list): '''Generate ASA configuration from IFC configuration delta. @see DMObject.ifc2asa for parameter details ''' CompositeType.ifc2asa(self, no_asa_cfg_stack, asa_cfg_list) if not self.has_ifc_delta_cfg(): return action = self.get_action() if action == State.NOCHANGE: return if action == State.DESTROY and self.is_removable: # when removing cluster group, disable the cluster first no_asa_cfg_stack.append(CLIInteraction('no enable', mode_command=self.get_cli()))
def ifc2asa(self, no_asa_cfg_stack, asa_cfg_list): '''Generate ASA configuration from IFC configuration delta. @see DMObject.ifc2asa for parameter details ''' if not self.has_ifc_delta_cfg(): return action = self.get_action() if action == State.NOCHANGE: return if action in (State.CREATE, State.MODIFY): self.generate_cli(asa_cfg_list, self.get_cli()) # 'no shutdown' the cluster control link interface intf = util.normalize_interface_name(self.get_top().get_ClusterControLink_interface()) if intf: clii = CLIInteraction(mode_command='interface ' + intf, command='no shutdown') asa_cfg_list.append(clii)
def ifc2asa(self, no_asa_cfg_stack, asa_cfg_list): '''Generate ASA configuration from IFC configuration delta. ''' if not self.has_ifc_delta_cfg(): return action = self.delta_ifc_cfg_value['state'] if action == State.NOCHANGE: return if self.is_cli_mode: if action in (State.CREATE, State.MODIFY): self.generate_cli(asa_cfg_list, self.get_cli()) intf = util.normalize_param_dict( self.get_top().get_failover_link_interface()) if intf: mode_cmd = 'interface ' + intf asa_cfg_list.append( CLIInteraction(command='no shutdown', mode_command=mode_cmd)) elif action == State.DESTROY and self.is_removable: self.generate_cli(asa_cfg_list, 'no ' + self.get_cli())
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 generate_clear_xlate(self): cli = 'clear xlate interface ' + self.parent.get_interface_name( 'internal') return CLIInteraction(cli, model_key=self.get_config_path())
def ifc2asa(self, no_asa_cfg_stack, asa_cfg_list): cli = self.get_cli() if cli: asa_cfg_list.append(CLIInteraction(command=cli, response_parser=cluster_response_parser))