def get_snmp(self, context, snmp_module_name, miboid): """ :param InitCommandContext context: this is the context passed by cloudshell automatically :param str snmp_module_name: MIB name :param str miboid: 'management information base object id' test two :return: """ session = CloudShellAPISession( host=context.connectivity.server_address, token_id=context.connectivity.admin_auth_token, domain=context.reservation.domain) reservation_id = context.reservation.reservation_id logger = get_qs_logger() address = context.resource.address snmp_read_community = session.DecryptPassword( context.resource.attributes['LinuxServerShell.SNMP Read Community'] ).Value snmp_v2_parameters = SNMPV2ReadParameters( ip=address, snmp_read_community=snmp_read_community) snmp_service = QualiSnmp(snmp_v2_parameters, logger) for index, info in snmp_service.get_table(snmp_module_name, miboid).items(): session.WriteMessageToReservationOutput(reservation_id, "[{0}]".format(index)) for key, value in info.items(): session.WriteMessageToReservationOutput( reservation_id, " {0}: {1}".format(key, value)) return "\nEnd of execution"
def __get_snmp_handler(self, host, logger): path = os.path.abspath( os.path.join(os.path.dirname(__file__), ".", "mibs")) logger.info(host) logger.info(self._snmp_write_community) if "3" in self._snmp_version: if not self._snmp_v3_user or not self._snmp_v3_password or not self._snmp_v3_private_key: raise Exception( self.__class__.__name__, "Cannot create SNMP Version 3, Check configuration") snmp_params = SNMPV3Parameters( ip=host, snmp_user=self._snmp_v3_user, snmp_password=self._snmp_v3_password, snmp_private_key=self._snmp_v3_private_key) logger.info("SNMP V3 Created") else: if not self._snmp_write_community: raise Exception( self.__class__.__name__, "Cannot create SNMP Version 2, Check configuration") snmp_params = SNMPV2Parameters( ip=host, snmp_community=self._snmp_write_community) logger.info("SNMP V2 Created") snmp_handler = QualiSnmp(snmp_params, logger) snmp_handler.update_mib_sources(path) return snmp_handler
def __init__(self, snmp_params, shell_name, shell_type, resource_name, logger): self.logger = logger self.snmp = QualiSnmp(snmp_parameters=snmp_params, logger=logger) self.resource_name = resource_name self.shell_name = shell_name self.shell_type = shell_type self.resource_model = networking_model self.resource = self.resource_model.GenericResource(shell_name=shell_name, shell_type=shell_type, name=resource_name, unique_id=resource_name) self._chassis = {} self.entity_table_black_list = [] self.chassis_list = [] self.module_dict = dict() self.module_num = 1 self.port_exclude_pattern = 'TEST' self.port_mapping = {} self.port_list = [] self.power_supply_list = []
def discover(self, ip, model, vendor, snmp_params): """ :param str ip: The device IP address :param str model: The device model in CloudShell :param str vendor: The device vendor :param SNMPParams snmp_params: The device vendor :return: The loaded resources and attributes :rtype: AutoLoadDetails """ logger = get_qs_logger() self.snmp = QualiSnmp(ip=ip, snmp_version=snmp_params.snmp_version, snmp_user=snmp_params.snmp_v3_user, snmp_password=snmp_params.snmp_v3_password, snmp_community=snmp_params.snmp_read_community, snmp_private_key=snmp_params.snmp_v3_privatekey, logger=logger) self.attributes=[] self.exclusion_list=[] self.chassis_list=[] self.port_exclude_pattern='TEST' self.port_mapping ={} self.port_list =[] self.power_supply_list=[] self.entity_table_black_list=[] self._excluded_models = [] self.relative_path = {} self.module_list = [] self.resources = [] self._get_device_details(model, vendor) self._load_snmp_tables() if(len(self.chassis_list)<1): print 'Empty Chasis List Found' exit(1) for chassis in self.chassis_list: if chassis not in self.exclusion_list: chassis_id = self._get_resource_id(chassis) if chassis_id == '-1': chassis_id = '0' self.relative_path[chassis] = chassis_id # to add custom MIBSs #snmp_handler.update_mib_sources() self._filter_lower_bay_containers() self.get_module_list() self.add_relative_paths() self._get_chassis_attributes(self.chassis_list) self._get_ports_attributes() self._get_module_attributes() result = AutoLoadDetails(resources=self.resources, attributes=self.attributes) print result #an Object you can play with it
def retrieving_snmp_table(self, ip): logger = get_qs_logger() snmp_service = QualiSnmp(ip=ip, snmp_version='2', snmp_community="Community String", logger=logger) if_table = snmp_service.get_table('IF-MIB', 'ifDescr')
def retrieving_snmp_properties(self, ip, community_string): logger = get_qs_logger() snmp_service = QualiSnmp(ip=ip, snmp_version='2', snmp_community=community_string, logger=logger) return snmp_service.get_property('SNMPv2-MIB', 'sysName', 0)
def get_inventory(self, context): """ Discovers the resource structure and attributes. :param AutoLoadCommandContext context: the context the command runs on :return Attribute and sub-resource information for the Shell resource you can return an AutoLoadDetails object :rtype: AutoLoadDetails """ # See below some example code demonstrating how to return the resource structure and attributes # In real life, this code will be preceded by SNMP/other calls to the resource details and will not be static # run 'shellfoundry generate' in order to create classes that represent your data model self._logger = self._get_logger(context) resource = LinuxServerShell.create_from_context(context) session = CloudShellAPISession( host=context.connectivity.server_address, token_id=context.connectivity.admin_auth_token, domain='Global') logger = get_qs_logger() address = context.resource.address snmp_read_community = session.DecryptPassword( context.resource.attributes['LinuxServerShell.SNMP Read Community'] ).Value snmp_v2_parameters = SNMPV2ReadParameters( ip=address, snmp_read_community=snmp_read_community) snmp_service = QualiSnmp(snmp_v2_parameters, logger) for if_table in snmp_service.get_table('IF-MIB', 'ifTable').values(): port = ResourcePort(if_table['ifDescr']) port.model_name = if_table['ifType'] port.mac_address = if_table['ifPhysAddress'] port.port_speed = if_table['ifSpeed'] for ip_table in snmp_service.get_table('IP-MIB', 'ipAddrTable').values(): if ip_table['ipAdEntIfIndex'] == if_table['ifIndex']: port.ipv4_address = ip_table['ipAdEntAddr'] resource.add_sub_resource(if_table['ifIndex'], port) autoload_details = resource.create_autoload_details() self._logger.info( 'autoload attributes: ' + ','.join([str(vars(x)) for x in autoload_details.attributes])) self._logger.info( 'autoload resources: ' + ','.join([str(vars(x)) for x in autoload_details.resources])) return autoload_details
def __enter__(self): """ Execute enable flow and create snmp service :return: :rtype: QualiSnmp """ if self._enable_flow: self._enable_flow.execute_flow(self._snmp_parameters) return QualiSnmp(self._snmp_parameters, self._logger)
def create_snmp_handler(self): kwargs = {} for key, value in QUALISNMP_INIT_PARAMS.iteritems(): if callable(value): kwargs[key] = value() else: kwargs[key] = value # snmp_instance = SaveCachedChanges(**kwargs) snmp_instance = QualiSnmp(**kwargs) return snmp_instance
def _handler(self, action): """ Sets up an SNMP handler with the current SNMPHandler state :rtype: QualiSnmp """ mib_path = os.path.abspath( os.path.join(os.path.dirname(__file__), 'mibs')) snmp_parameters = self._snmp_parameters(action) try: handler = QualiSnmp(snmp_parameters, self.logger) except Exception as e: if action.lower() == 'get': error = '''Unable to communicate via SNMP read to resource Please verify the SNMP read community and that the device is accessible''' elif action.lower() == 'set': error = '''Unable to communicate via SNMP write to resource Please verify the SNMP write community and that the device is accessible''' else: error = '''Unable to communicate via SNMP to resource Please verify the SNMP communities and that the device is accessible''' raise Exception(error + '\nDownstream error: ' + str(e)) handler.update_mib_sources(mib_path) handler.load_mib(['Sentry3-MIB']) return handler
def _get_handler(self, action): mib_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'mibs')) snmp_parameters = self._get_snmp_parameters(action) handler = QualiSnmp(snmp_parameters, self.logger) handler.update_mib_sources(mib_path) handler.load_mib(['Sentry3-MIB']) return handler
def do_geist_power(context, f, portstr): logger = get_logger(context) snmp_parameters = get_snmp_parameters_from_command_context(context, write=True) snmp = QualiSnmp(snmp_parameters, logger) path = os.path.abspath( os.path.join(os.path.dirname(__file__), '..', 'mibs')) snmp.update_mib_sources(path) snmp.load_mib(['GEIST-MIB-V3']) logger.info('geist power called with port "%s"' % portstr) f(snmp, portstr)
def _get_snmp_handler(self, device_ip, snmp_comunity_strings): """Get SNMP Handler and valid community string for the device :param str device_ip: :param list[str] snmp_comunity_strings: :return: tuple with QualiSnmp instance and valid SNMP community string :rtype: (QualiSnmp, str) """ for snmp_community in snmp_comunity_strings: self.logger.info( "Trying community string '{}' for device with IP {}".format( snmp_community, device_ip)) snmp_parameters = SNMPV2Parameters(ip=device_ip, snmp_community=snmp_community) try: return QualiSnmp(snmp_parameters, self.logger), snmp_community except Exception: self.logger.warning( "SNMP Community string '{}' is not valid for device with IP {}" .format(snmp_community, device_ip)) raise ReportableException("SNMP timeout - no resource detected")
def create_snmp_handler(): kwargs = {} for key, value in QUALISNMP_INIT_PARAMS.iteritems(): if callable(value): kwargs[key] = value() return QualiSnmp(**kwargs)
from cloudshell.snmp.quali_snmp import ObjectIdentity, ObjectType, QualiSnmp from cloudshell.core.logger import qs_logger from cloudshell.snmp.snmp_parameters import SNMPV2ReadParameters class SNMP_data(): def __init__(self, oid, type, value): self.oid = oid self.type = type self.value = value logger = qs_logger.get_qs_logger() qsnmp_params = SNMPV2ReadParameters(ip='192.168.105.4', snmp_read_community='publi') filename = r"C:\Users\yoav.e\AppData\Roaming\Quali\Recordings\192.168.105.4\192.168.105.4.snmp" with open(filename, "r") as f: all_lines = f.readlines() snmp_all_data = [] qsnmp_instance = QualiSnmp(snmp_parameters=qsnmp_params, logger=logger) for line in all_lines: split_line = line.split(',') snmp_all_data.append(SNMP_data(split_line[0], split_line[1], split_line[2])) for q in snmp_all_data: Otype = ObjectType(ObjectIdentity(q.oid), q.value) Otype.resolveWithMib(qsnmp_instance.mib_viewer) print Otype pass
def geist_autoload(context): logger = get_logger(context) snmp_parameters = get_snmp_parameters_from_command_context(context, write=False) snmp = QualiSnmp(snmp_parameters, logger) path = os.path.abspath( os.path.join(os.path.dirname(__file__), '..', 'mibs')) snmp.update_mib_sources(path) snmp.load_mib(['GEIST-MIB-V3']) def makeres(name, model, relative_address, unique_identifier): r = AutoLoadResource() r.name = name r.model = model r.relative_address = relative_address r.unique_identifier = unique_identifier return r def makeattr(relative_address, attribute_name, attribute_value): a = AutoLoadAttribute() a.relative_address = relative_address a.attribute_name = attribute_name a.attribute_value = attribute_value return a rv = AutoLoadDetails() rv.resources = [] rv.attributes = [] rv.attributes.append( makeattr('', 'Version', snmp.get_property('GEIST-MIB-V3', 'productVersion', 0))) rv.attributes.append( makeattr('', 'Location', snmp.get_property('SNMPv2-MIB', 'sysLocation', 0))) rv.attributes.append( makeattr('', 'Vendor', snmp.get_property('GEIST-MIB-V3', 'productHardware', 0))) rv.attributes.append( makeattr('', 'Model', snmp.get_property('GEIST-MIB-V3', 'productTitle', 0))) pduname = snmp.get_property('GEIST-MIB-V3', 'productFriendlyName', 0) outlet_table = snmp.get_table('GEIST-MIB-V3', 'ctrlOutletTable') for idx, record in outlet_table.iteritems(): addr = '%d' % idx rv.resources.append( makeres('Port %d' % idx, 'Generic Power Socket', addr, '%s.%d' % (pduname, idx))) rv.attributes.append( makeattr(addr, 'Port Description', record['ctrlOutletName'])) return rv
class GenericSNMPDiscovery: def discover(self, ip, model, vendor, snmp_params): """ :param str ip: The device IP address :param str model: The device model in CloudShell :param str vendor: The device vendor :param SNMPParams snmp_params: The device vendor :return: The loaded resources and attributes :rtype: AutoLoadDetails """ logger = get_qs_logger() self.snmp = QualiSnmp(ip=ip, snmp_version=snmp_params.snmp_version, snmp_user=snmp_params.snmp_v3_user, snmp_password=snmp_params.snmp_v3_password, snmp_community=snmp_params.snmp_read_community, snmp_private_key=snmp_params.snmp_v3_privatekey, logger=logger) self.attributes=[] self.exclusion_list=[] self.chassis_list=[] self.port_exclude_pattern='TEST' self.port_mapping ={} self.port_list =[] self.power_supply_list=[] self.entity_table_black_list=[] self._excluded_models = [] self.relative_path = {} self.module_list = [] self.resources = [] self._get_device_details(model, vendor) self._load_snmp_tables() if(len(self.chassis_list)<1): print 'Empty Chasis List Found' exit(1) for chassis in self.chassis_list: if chassis not in self.exclusion_list: chassis_id = self._get_resource_id(chassis) if chassis_id == '-1': chassis_id = '0' self.relative_path[chassis] = chassis_id # to add custom MIBSs #snmp_handler.update_mib_sources() self._filter_lower_bay_containers() self.get_module_list() self.add_relative_paths() self._get_chassis_attributes(self.chassis_list) self._get_ports_attributes() self._get_module_attributes() result = AutoLoadDetails(resources=self.resources, attributes=self.attributes) print result #an Object you can play with it def _get_device_details(self, model, vendor): """Get root element attributes :param ResourceCommandContext attributes_dictionary: """ result = {'system_name': self.snmp.get_property('SNMPv2-MIB', 'sysName', 0), 'vendor': vendor, 'model': model, 'location': self.snmp.get_property('SNMPv2-MIB', 'sysLocation', 0), 'contact': self.snmp.get_property('SNMPv2-MIB', 'sysContact', 0), 'version': ''} match_version = re.search(r'Version\s+(?P<software_version>\S+)\S*\s+', self.snmp.get_property('SNMPv2-MIB', 'sysDescr', 0)) if match_version: result['version'] = match_version.groupdict()['software_version'].replace(',', '') root = NetworkingStandardRootAttributes(**result) self.attributes.extend(root.get_autoload_resource_attributes()) def _load_snmp_tables(self): """ Load all required snmp tables :return: """ self.if_table = self.snmp.get_table('IF-MIB', 'ifDescr') self.entity_table = self._get_entity_table() if len(self.entity_table.keys()) < 1: raise Exception('Cannot load entPhysicalTable. Autoload cannot continue') self.lldp_local_table = self.snmp.get_table('LLDP-MIB', 'lldpLocPortDesc') self.lldp_remote_table = self.snmp.get_table('LLDP-MIB', 'lldpRemTable') self.duplex_table = self.snmp.get_table('EtherLike-MIB', 'dot3StatsIndex') self.ip_v4_table = self.snmp.get_table('IP-MIB', 'ipAddrTable') def _get_entity_table(self): """Read Entity-MIB and filter out device's structure and all it's elements, like ports, modules, chassis, etc. :rtype: QualiMibTable :return: structured and filtered EntityPhysical table. """ result_dict = QualiMibTable('entPhysicalTable') entity_table_critical_port_attr = {'entPhysicalContainedIn': 'str', 'entPhysicalClass': 'str', 'entPhysicalVendorType': 'str'} entity_table_optional_port_attr = {'entPhysicalDescr': 'str', 'entPhysicalName': 'str'} physical_indexes = self.snmp.get_table('ENTITY-MIB', 'entPhysicalParentRelPos') for index in physical_indexes.keys(): is_excluded = False if physical_indexes[index]['entPhysicalParentRelPos'] == '': self.exclusion_list.append(index) continue temp_entity_table = physical_indexes[index].copy() temp_entity_table.update(self.snmp.get_properties('ENTITY-MIB', index, entity_table_critical_port_attr) [index]) if temp_entity_table['entPhysicalContainedIn'] == '': is_excluded = True self.exclusion_list.append(index) for item in self.entity_table_black_list: if item in temp_entity_table['entPhysicalVendorType'].lower(): is_excluded = True break if is_excluded is True: continue temp_entity_table.update(self.snmp.get_properties('ENTITY-MIB', index, entity_table_optional_port_attr) [index]) if temp_entity_table['entPhysicalClass'] == '': vendor_type = self.snmp.get_property('ENTITY-MIB', 'entPhysicalVendorType', index) index_entity_class = None if vendor_type == '': continue if 'cevcontainer' in vendor_type.lower(): index_entity_class = 'container' elif 'cevchassis' in vendor_type.lower(): index_entity_class = 'chassis' elif 'cevmodule' in vendor_type.lower(): index_entity_class = 'module' elif 'cevport' in vendor_type.lower(): index_entity_class = 'port' elif 'cevpowersupply' in vendor_type.lower(): index_entity_class = 'powerSupply' if index_entity_class: temp_entity_table['entPhysicalClass'] = index_entity_class else: temp_entity_table['entPhysicalClass'] = temp_entity_table['entPhysicalClass'].replace("'", "") if re.search(r'stack|chassis|module|port|powerSupply|container|backplane', temp_entity_table['entPhysicalClass']): result_dict[index] = temp_entity_table if temp_entity_table['entPhysicalClass'] == 'chassis': self.chassis_list.append(index) elif temp_entity_table['entPhysicalClass'] == 'port': if not re.search(self.port_exclude_pattern, temp_entity_table['entPhysicalName'], re.IGNORECASE) \ and not re.search(self.port_exclude_pattern, temp_entity_table['entPhysicalDescr'], re.IGNORECASE): port_id = self._get_mapping(index, temp_entity_table['entPhysicalDescr']) if port_id and port_id in self.if_table and port_id not in self.port_mapping.values(): self.port_mapping[index] = port_id self.port_list.append(index) elif temp_entity_table['entPhysicalClass'] == 'powerSupply': self.power_supply_list.append(index) self._filter_entity_table(result_dict) return result_dict def _get_mapping(self, port_index, port_descr): """Get mapping from entPhysicalTable to ifTable. Build mapping based on ent_alias_mapping_table if exists else build manually based on entPhysicalDescr <-> ifDescr mapping. :return: simple mapping from entPhysicalTable index to ifTable index: | {entPhysicalTable index: ifTable index, ...} """ port_id = None try: ent_alias_mapping_identifier = self.snmp.get(('ENTITY-MIB', 'entAliasMappingIdentifier', port_index, 0)) port_id = int(ent_alias_mapping_identifier['entAliasMappingIdentifier'].split('.')[-1]) except Exception as e: if_table_re = "/".join(re.findall('\d+', port_descr)) for interface in self.if_table.values(): if re.search(if_table_re, interface['ifDescr']): port_id = int(interface['suffix']) break return port_id def _filter_entity_table(self, raw_entity_table): """Filters out all elements if their parents, doesn't exist, or listed in self.exclusion_list :param raw_entity_table: entity table with unfiltered elements """ elements = raw_entity_table.filter_by_column('ContainedIn').sort_by_column('ParentRelPos').keys() for element in reversed(elements): parent_id = int(self.entity_table[element]['entPhysicalContainedIn']) if parent_id not in raw_entity_table or parent_id in self.exclusion_list: self.exclusion_list.append(element) def _get_resource_id(self, item_id): parent_id = int(self.entity_table[item_id]['entPhysicalContainedIn']) if parent_id > 0 and parent_id in self.entity_table: if re.search(r'container|backplane', self.entity_table[parent_id]['entPhysicalClass']): result = self.entity_table[parent_id]['entPhysicalParentRelPos'] elif parent_id in self._excluded_models: result = self._get_resource_id(parent_id) else: result = self.entity_table[item_id]['entPhysicalParentRelPos'] else: result = self.entity_table[item_id]['entPhysicalParentRelPos'] return result def _filter_lower_bay_containers(self): upper_container = None lower_container = None containers = self.entity_table.filter_by_column('Class', "container").sort_by_column('ParentRelPos').keys() for container in containers: vendor_type = self.snmp.get_property('ENTITY-MIB', 'entPhysicalVendorType', container) if 'uppermodulebay' in vendor_type.lower(): upper_container = container if 'lowermodulebay' in vendor_type.lower(): lower_container = container if lower_container and upper_container: child_upper_items_len = len(self.entity_table.filter_by_column('ContainedIn', str(upper_container) ).sort_by_column('ParentRelPos').keys()) child_lower_items = self.entity_table.filter_by_column('ContainedIn', str(lower_container) ).sort_by_column('ParentRelPos').keys() for child in child_lower_items: self.entity_table[child]['entPhysicalContainedIn'] = upper_container self.entity_table[child]['entPhysicalParentRelPos'] = str(child_upper_items_len + int( self.entity_table[child]['entPhysicalParentRelPos'])) def get_module_list(self): """Set list of all modules from entity mib table for provided list of ports :return: """ for port in self.port_list: modules = [] modules.extend(self._get_module_parents(port)) for module in modules: if module in self.module_list: continue vendor_type = self.snmp.get_property('ENTITY-MIB', 'entPhysicalVendorType', module) if not re.search(self.module_exclude_pattern, vendor_type.lower()): if module not in self.exclusion_list and module not in self.module_list: self.module_list.append(module) else: self._excluded_models.append(module) def add_relative_paths(self): """Build dictionary of relative paths for each module and port :return: """ port_list = list(self.port_list) module_list = list(self.module_list) for module in module_list: if module not in self.exclusion_list: self.relative_path[module] = self.get_relative_path(module) + '/' + self._get_resource_id(module) else: self.module_list.remove(module) for port in port_list: if port not in self.exclusion_list: self.relative_path[port] = self._get_port_relative_path( self.get_relative_path(port) + '/' + self._get_resource_id(port)) else: self.port_list.remove(port) def get_relative_path(self, item_id): """Build relative path for received item :param item_id: :return: """ result = '' if item_id not in self.chassis_list: parent_id = int(self.entity_table[item_id]['entPhysicalContainedIn']) if parent_id not in self.relative_path.keys(): if parent_id in self.module_list: result = self._get_resource_id(parent_id) if result != '': result = self.get_relative_path(parent_id) + '/' + result else: result = self.get_relative_path(parent_id) else: result = self.relative_path[parent_id] else: result = self.relative_path[item_id] return result def _get_chassis_attributes(self, chassis_list): """Get Chassis element attributes :param chassis_list: list of chassis to load attributes for :return: """ for chassis in chassis_list: chassis_id = self.relative_path[chassis] chassis_details_map = { 'chassis_model': self.snmp.get_property('ENTITY-MIB', 'entPhysicalModelName', chassis), 'serial_number': self.snmp.get_property('ENTITY-MIB', 'entPhysicalSerialNum', chassis) } if chassis_details_map['chassis_model'] == '': chassis_details_map['chassis_model'] = self.entity_table[chassis]['entPhysicalDescr'] relative_path = '{0}'.format(chassis_id) chassis_object = Chassis(relative_path=relative_path, **chassis_details_map) self._add_resource(chassis_object) def _get_ports_attributes(self): """Get resource details and attributes for every port in self.port_list :return: """ for port in self.port_list: if_table_port_attr = {'ifType': 'str', 'ifPhysAddress': 'str', 'ifMtu': 'int', 'ifSpeed': 'int'} if_table = self.if_table[self.port_mapping[port]].copy() if_table.update(self.snmp.get_properties('IF-MIB', self.port_mapping[port], if_table_port_attr)) interface_name = self.if_table[self.port_mapping[port]]['ifDescr'].replace("'", '') if interface_name == '': interface_name = self.entity_table[port]['entPhysicalName'] if interface_name == '': continue interface_type = if_table[self.port_mapping[port]]['ifType'].replace('/', '').replace("'", '') attribute_map = {'l2_protocol_type': interface_type, 'mac': if_table[self.port_mapping[port]]['ifPhysAddress'], 'mtu': if_table[self.port_mapping[port]]['ifMtu'], 'bandwidth': if_table[self.port_mapping[port]]['ifSpeed'], 'description': self.snmp.get_property('IF-MIB', 'ifAlias', self.port_mapping[port]), 'adjacent': self._get_adjacent(self.port_mapping[port])} attribute_map.update(self._get_interface_details(self.port_mapping[port])) attribute_map.update(self._get_ip_interface_details(self.port_mapping[port])) port_object = Port(name=interface_name, relative_path=self.relative_path[port], **attribute_map) self._add_resource(port_object) def _get_module_attributes(self): """Set attributes for all discovered modules :return: """ for module in self.module_list: module_id = self.relative_path[module] module_index = self._get_resource_id(module) module_details_map = { 'module_model': self.entity_table[module]['entPhysicalDescr'], 'version': self.snmp.get_property('ENTITY-MIB', 'entPhysicalSoftwareRev', module), 'serial_number': self.snmp.get_property('ENTITY-MIB', 'entPhysicalSerialNum', module) } if '/' in module_id and len(module_id.split('/')) < 3: module_name = 'Module {0}'.format(module_index) model = 'Generic Module' else: module_name = 'Sub Module {0}'.format(module_index) model = 'Generic Sub Module' module_object = Module(name=module_name, model=model, relative_path=module_id, **module_details_map) self._add_resource(module_object) def _get_module_parents(self, module_id): result = [] parent_id = int(self.entity_table[module_id]['entPhysicalContainedIn']) if parent_id > 0 and parent_id in self.entity_table: if re.search(r'module', self.entity_table[parent_id]['entPhysicalClass']): result.append(parent_id) result.extend(self._get_module_parents(parent_id)) elif re.search(r'chassis', self.entity_table[parent_id]['entPhysicalClass']): return result else: result.extend(self._get_module_parents(parent_id)) return result def _get_port_relative_path(self, relative_id): if relative_id in self.relative_path.values(): if '/' in relative_id: ids = relative_id.split('/') ids[-1] = str(int(ids[-1]) + 1000) result = '/'.join(ids) else: result = str(int(relative_id.split()[-1]) + 1000) if relative_id in self.relative_path.values(): result = self._get_port_relative_path(result) else: result = relative_id return result def _add_resource(self, resource): """Add object data to resources and attributes lists :param resource: object which contains all required data for certain resource """ self.resources.append(resource.get_autoload_resource_details()) self.attributes.extend(resource.get_autoload_resource_attributes()) def _get_adjacent(self, interface_id): """Get connected device interface and device name to the specified port id, using lldp protocols :param interface_id: port id :return: device's name and port connected to port id :rtype string """ result = '' if self.lldp_remote_table: for key, value in self.lldp_local_table.iteritems(): interface_name = self.if_table[interface_id]['ifDescr'] if interface_name == '': break if 'lldpLocPortDesc' in value and interface_name in value['lldpLocPortDesc']: if 'lldpRemSysName' in self.lldp_remote_table and 'lldpRemPortDesc' in self.lldp_remote_table: result = '{0} through {1}'.format(self.lldp_remote_table[key]['lldpRemSysName'], self.lldp_remote_table[key]['lldpRemPortDesc']) return result def _get_interface_details(self, port_index): """Get interface attributes :param port_index: port index in ifTable :return interface_details: detected info for provided interface dict{'Auto Negotiation': '', 'Duplex': ''} """ interface_details = {'duplex': 'Full', 'auto_negotiation': 'False'} try: auto_negotiation = self.snmp.get(('MAU-MIB', 'ifMauAutoNegAdminStatus', port_index, 1)).values()[0] if 'enabled' in auto_negotiation.lower(): interface_details['auto_negotiation'] = 'True' except Exception as e: print('Failed to load auto negotiation property for interface {0}'.format(e.message)) for key, value in self.duplex_table.iteritems(): if 'dot3StatsIndex' in value.keys() and value['dot3StatsIndex'] == str(port_index): interface_duplex = self.snmp.get_property('EtherLike-MIB', 'dot3StatsDuplexStatus', key) if 'halfDuplex' in interface_duplex: interface_details['duplex'] = 'Half' return interface_details def _get_ip_interface_details(self, port_index): """Get IP address details for provided port :param port_index: port index in ifTable :return interface_details: detected info for provided interface dict{'IPv4 Address': '', 'IPv6 Address': ''} """ interface_details = {'ipv4_address': '', 'ipv6_address': ''} if self.ip_v4_table and len(self.ip_v4_table) > 1: for key, value in self.ip_v4_table.iteritems(): if 'ipAdEntIfIndex' in value and int(value['ipAdEntIfIndex']) == port_index: interface_details['ipv4_address'] = key break return interface_details
class SonicGenericSNMPDiscovery: def __init__(self, snmp_params, shell_name, shell_type, resource_name, logger): self.logger = logger self.snmp = QualiSnmp(snmp_parameters=snmp_params, logger=logger) self.resource_name = resource_name self.shell_name = shell_name self.shell_type = shell_type self.resource_model = networking_model self.resource = self.resource_model.GenericResource( shell_name=shell_name, shell_type=shell_type, name=resource_name, unique_id=resource_name) self._chassis = {} self.entity_table_black_list = [] self.chassis_list = [] self.port_exclude_pattern = 'TEST' self.port_mapping = {} self.port_list = [] self.power_supply_list = [] def discover(self): """ :param str ip: The device IP address :param str model: The device model in CloudShell :param str vendor: The device vendor :param SNMPV2ReadParameters snmp_params: The device vendor :return: The loaded resources and attributes :rtype: AutoLoadDetails """ self._get_device_details() self._load_snmp_tables() self._build_chassis() self._build_ports() autoload_details = AutoloadDetailsBuilder( self.resource).autoload_details() self._log_autoload_details(autoload_details) return autoload_details def _get_device_details(self): """Get root element attributes """ self.logger.info("Building Root") sysDescr = self.snmp.get_property('SNMPv2-MIB', 'sysDescr', '0') match_version = re.search( r'Version:\s+(?P<software_version>\S+)\S*\s+', sysDescr) if match_version: match_version = match_version.groupdict( )['software_version'].replace(',', '') match_vendor_model = re.search(r'HwSku:\s+(?P<vendor_model>\S+)\S*\s+', sysDescr) if match_vendor_model: match_vendor_model = match_vendor_model.groupdict( )['vendor_model'].replace(',', '') vendor, model = match_vendor_model.split('-', 1) else: vendor = model = None self.resource.contact_name = self.snmp.get_property( 'SNMPv2-MIB', 'sysContact', '0') self.resource.system_name = self.snmp.get_property( 'SNMPv2-MIB', 'sysName', '0') self.resource.location = self.snmp.get_property( 'SNMPv2-MIB', 'sysLocation', '0') self.resource.os_version = match_version self.resource.vendor = vendor self.resource.model = model def _log_autoload_details(self, autoload_details): """ Logging autoload details :param autoload_details: :return: """ self.logger.info( '-------------------- <RESOURCES> ----------------------') for resource in autoload_details.resources: self.logger.info('{0:15}, {1:20}, {2}'.format( resource.relative_address, resource.name, resource.unique_identifier)) self.logger.info( '-------------------- </RESOURCES> ----------------------') self.logger.info( '-------------------- <ATTRIBUTES> ---------------------') for attribute in autoload_details.attributes: self.logger.info('-- {0:15}, {1:60}, {2}'.format( attribute.relative_address, attribute.attribute_name, attribute.attribute_value)) self.logger.info( '-------------------- </ATTRIBUTES> ---------------------') def _load_snmp_tables(self): """ Load all required snmp tables :return: """ self.if_table = self.snmp.get_table('IF-MIB', 'ifDescr') self.entity_table = self._get_entity_table() #if len(self.entity_table.keys()) < 1: #raise Exception('Cannot load entPhysicalTable. Autoload cannot continue') self.lldp_local_table = self.snmp.get_table('LLDP-MIB', 'lldpLocPortDesc') self.lldp_remote_table = self.snmp.get_table('LLDP-MIB', 'lldpRemTable') self.duplex_table = self.snmp.get_table('EtherLike-MIB', 'dot3StatsIndex') self.ip_v4_table = self.snmp.get_table('IP-MIB', 'ipAddrTable') def _get_entity_table(self): """Read Entity-MIB and filter out device's structure and all it's elements, like ports, modules, chassis, etc. :rtype: QualiMibTable :return: structured and filtered EntityPhysical table. """ result_dict = QualiMibTable('entPhysicalTable') entity_table_critical_port_attr = { 'entPhysicalContainedIn': 'str', 'entPhysicalVendorType': 'str' } entity_table_optional_port_attr = { 'entPhysicalDescr': 'str', 'entPhysicalSerialNum': 'str' } physical_indexes = self.snmp.get_table('ENTITY-MIB', 'entPhysicalClass') for index in physical_indexes.keys(): is_excluded = False #if physical_indexes[index]['entPhysicalParentRelPos'] == '': # self.exclusion_list.append(index) # continue temp_entity_table = physical_indexes[index].copy() #temp_entity_table.update(self.snmp.get_properties('ENTITY-MIB', index, entity_table_critical_port_attr) # [index]) #if temp_entity_table['entPhysicalContainedIn'] == '': # is_excluded = True # self.exclusion_list.append(index) for item in self.entity_table_black_list: if item in temp_entity_table['entPhysicalVendorType'].lower(): is_excluded = True break if is_excluded is True: continue temp_entity_table.update( self.snmp.get_properties( 'ENTITY-MIB', index, entity_table_optional_port_attr)[index]) '''if temp_entity_table['entPhysicalClass'] == '': vendor_type = self.snmp.get_property('ENTITY-MIB', 'entPhysicalVendorType', index) index_entity_class = None if vendor_type == '': continue if 'cevcontainer' in vendor_type.lower(): index_entity_class = 'container' elif 'cevchassis' in vendor_type.lower(): index_entity_class = 'chassis' elif 'cevmodule' in vendor_type.lower(): index_entity_class = 'module' elif 'cevport' in vendor_type.lower(): index_entity_class = 'port' elif 'cevpowersupply' in vendor_type.lower(): index_entity_class = 'powerSupply' if index_entity_class: temp_entity_table['entPhysicalClass'] = index_entity_class else:''' temp_entity_table['entPhysicalClass'] = temp_entity_table[ 'entPhysicalClass'].replace("'", "") if re.search( r'stack|chassis|module|port|powerSupply|container|backplane', temp_entity_table['entPhysicalClass']): result_dict[index] = temp_entity_table if temp_entity_table['entPhysicalClass'] == 'chassis': self.chassis_list.append(index) break #elif temp_entity_table['entPhysicalClass'] == 'port': # if not re.search(self.port_exclude_pattern, temp_entity_table['entPhysicalName'], re.IGNORECASE) \ # and not re.search(self.port_exclude_pattern, temp_entity_table['entPhysicalDescr'], # re.IGNORECASE): # port_id = self._get_mapping(index, temp_entity_table['entPhysicalDescr']) # if port_id and port_id in self.if_table and port_id not in self.port_mapping.values(): # self.port_mapping[index] = port_id # self.port_list.append(index) #elif temp_entity_table['entPhysicalClass'] == 'powerSupply': # self.power_supply_list.append(index) #self._filter_entity_table(result_dict) return result_dict def _get_mapping(self, port_index, port_descr): """Get mapping from entPhysicalTable to ifTable. Build mapping based on ent_alias_mapping_table if exists else build manually based on entPhysicalDescr <-> ifDescr mapping. :return: simple mapping from entPhysicalTable index to ifTable index: | {entPhysicalTable index: ifTable index, ...} """ port_id = None try: ent_alias_mapping_identifier = self.snmp.get( ('ENTITY-MIB', 'entAliasMappingIdentifier', port_index, 0)) port_id = int( ent_alias_mapping_identifier['entAliasMappingIdentifier']. split('.')[-1]) except Exception as e: if_table_re = "/".join(re.findall('\d+', port_descr)) for interface in self.if_table.values(): if re.search(if_table_re, interface['ifDescr']): port_id = int(interface['suffix']) break return port_id def _build_chassis(self): """ Build Chassis resources and attributes :return: """ self.logger.debug('Building Chassis') for index in self.chassis_list: chassis = self.resource_model.GenericChassis( shell_name=self.shell_name, name="Chassis {}".format(index), unique_id="{0}.{1}.{2}".format(self.resource_name, "chassis", index)) chassis.serial_number = self.snmp.get_property( 'ENTITY-MIB', 'entPhysicalSerialNum', index) self.resource.add_sub_resource(index, chassis) self._chassis[index] = chassis if self.chassis_list == []: chassis = self.resource_model.GenericChassis( shell_name=self.shell_name, name="Chassis {}".format(1), unique_id="{0}.{1}.{2}".format(self.resource_name, "chassis", '1')) self.resource.add_sub_resource('1', chassis) self.chassis_list.append('1') self._chassis['1'] = chassis def _build_ports(self): if self.chassis_list == {}: chassis = self._chassis['1'] else: chassis = self._chassis[self.chassis_list[0]] interface_indexes = self.snmp.get_table('IF-MIB', 'ifDescr') for index in interface_indexes.keys(): interface_name = self.snmp.get_property('IF-MIB', 'ifDescr', index).replace( '/', '-').replace(':', '-') if interface_name != '' and 'Channel' not in interface_indexes.get( index).get('ifDescr'): interface = self.resource_model.GenericPort( shell_name=self.shell_name, name=interface_name, unique_id="{0}.{1}.{2}".format(self.resource_name, "port", index)) interface.l2_protocol_type = self.snmp.get_property( 'IF-MIB', 'ifType', index).strip('\'') interface.mac_address = self.snmp.get_property( 'IF-MIB', 'ifPhysAddress', index) interface.mtu = self.snmp.get_property('IF-MIB', 'ifMtu', index) interface.bandwidth = self.snmp.get_property( 'IF-MIB', 'ifHighSpeed', index) duplex = None snmp_result = self.snmp.get_property('EtherLike-MIB', 'dot3StatsDuplexStatus', index) if snmp_result: port_duplex = snmp_result.strip('\'') if re.search(r'[Ff]ull', port_duplex): duplex = 'Full' else: duplex = 'Half' interface.duplex = duplex interface.adjacent = None interface.auto_negotiation = False interface.port_description = interface_indexes.get(index).get( 'ifDescr') chassis.add_sub_resource(index, interface) '''if 'Channel' in interface_indexes.get(index).get('ifDescr'):