def get_interface_subjects(self): netdev = self._proc.open('net', 'dev') faces = [] subjects = {} type_map = {'ipv4': netifaces.AF_INET, 'ipv6': netifaces.AF_INET6, 'mac': netifaces.AF_LINK} for line in netdev: line = line.split() if line[0].count(":"): faces.append(line[0][:line[0].index(":")]) unis = UNISInstance(unis_url=self.unis_url) for face in faces: post_dict = {} try: capacity = ethtool.get_speed(face) except OSError: capacity = 0 # assume each port is a layer2 port for the main 'address' try: l2_addr = netifaces.ifaddresses(face)[type_map['mac']] if len(l2_addr): addr = {"type": "mac", "address": l2_addr[0]['addr']} post_dict['address'] = addr except: pass # add all the other address info we can find post_dict['properties'] = {} for t in type_map: try: addrs = netifaces.ifaddresses(face)[type_map[t]] for a in addrs: addr = {"type": t, "address": a['addr']} post_dict['properties'][t] = addr except: pass ### some sort of verification here that capacity is right post_dict['name'] = face post_dict['capacity'] = capacity # hack in a 'nodeRef' so we can find port from rspec post_dict['nodeRef'] = settings.URN_STRING[:-1] resp = unis.post_port(post_dict) if isinstance(resp, dict): subjects[face]=resp['selfRef'] return subjects
class Probe: """Get network statistics """ UNUSED_METRICS = ["errs_in", "errs_out", "drop_in", "drop_out", "fifo_in", "fifo_out", "frame_in", "compressed_in", "compressed_out", "multicast_in", "colls_out", "colls_in", "carrier_out", "carrier_in", "frame_out", "multicast_out"] def __init__(self, service, measurement): self.service = service self.measurement = measurement self.config = measurement["configuration"] logger.debug('Probe.__init__', config=self.config) self._proc = Proc(self.config.get("proc_dir", "/proc/")) self.node_subject=self.config.get( "subject", self.config.get("runningOn", {}).get('href', 'not found')) self.port_match_method=self.config.get( "port_match_method", "geni_utils.mac_match") self.port_match_method=blipp_import_method(self.port_match_method) self.unis = UNISInstance(service) logger.debug('Probe.__init__ ', subject=self.node_subject) self.subjects=self.get_interface_subjects() def get_data(self): netdev = self._proc.open('net', 'dev') netsnmp = self._proc.open('net', 'snmp') netdev.readline() data = self._get_dev_data(netdev.read()) sdata = self._get_snmp_data(netsnmp.read()) data[self.node_subject] = sdata data = full_event_types(data, EVENT_TYPES) return data def _get_dev_data(self, dev_string): headers_regex = re.compile( '[^|]*\|(?P<rxheaders>[^|]*)\|(?P<txheaders>.*)') dev_lines = dev_string.splitlines() matches = headers_regex.search(dev_lines.pop(0)).groupdict() txheaders = [ head + "_in" for head in matches['txheaders'].split() ] rxheaders = [ head + "_out" for head in matches['rxheaders'].split() ] headers = txheaders + rxheaders data = {} for line in dev_lines: if not line: continue line = line.replace(':', ' ') line = line.split() iface = line.pop(0) face_data = dict(zip(headers, line)) self._vals_to_int(face_data) errors = face_data.pop('errs_in') + face_data.pop('errs_out') drops = face_data.pop('drop_in') + face_data.pop('drop_out') face_data['errors'] = errors face_data['drops'] = drops for metric in self.UNUSED_METRICS: if metric in face_data: del face_data[metric] data[self.subjects[iface]] = face_data return data def _vals_to_int(self, adict): for k,v in adict.items(): adict[k] = int(v) return adict def _get_snmp_data(self, snmp_string): data = {} lines = snmp_string.splitlines() i = 0 while i < len(lines): line = lines[i].split() if line[0].lower()=="tcp:": i += 1 in_index = line.index("InSegs") out_index = line.index("OutSegs") retrans_index = line.index("RetransSegs") dataline = lines[i].split() data.update({"tcp_segments_in":dataline[in_index], "tcp_segments_out":dataline[out_index], "tcp_retrans":dataline[retrans_index]}) elif line[0].lower()=="udp:": i += 1 in_index = line.index("InDatagrams") out_index = line.index("OutDatagrams") dataline = lines[i].split() data.update({"datagrams_in":dataline[in_index], "datagrams_out":dataline[out_index]}) i += 1 return self._vals_to_int(data) def get_interface_subjects(self): subjects = {} unis_ports = self.get_interfaces_in_unis() for face in netifaces.interfaces(): local_port_dict = self._build_port_dict(face) portRef = self._find_or_post_port(unis_ports, local_port_dict, self.port_match_method) if isinstance(portRef, str) or isinstance(portRef, unicode): subjects[face]=portRef else: logger.warn('get_interface_subjects', msg="subject for face %s is of an unexpected type %s, portRef=%s"%(face, type(portRef), portRef)) subjects[face]="unexpected type" return subjects def _build_port_dict(self, port_name): type_map = {'ipv4': netifaces.AF_INET, 'ipv6': netifaces.AF_INET6, 'mac': netifaces.AF_LINK} post_dict = {} try: capacity = ethtool.get_speed(port_name) except OSError: capacity = 0 # assume each port is a layer2 port for the main 'address' try: l2_addr = netifaces.ifaddresses(port_name)[type_map['mac']] if len(l2_addr): addr = {"type": "mac", "address": l2_addr[0]['addr']} post_dict['address'] = addr.strip().replace(':', '').lower() except: pass # add all the other address info we can find post_dict['properties'] = {} for t in type_map: try: addrs = netifaces.ifaddresses(port_name)[type_map[t]] for a in addrs: addr = {"type": t, "address": a['addr']} post_dict['properties'][t] = addr except Exception as e: logger.exc('get_interface_subjects', e) # TODO some sort of verification here that capacity is right post_dict['name'] = port_name post_dict['capacity'] = capacity # hack in a 'nodeRef' so we can find port from rspec post_dict['nodeRef'] = settings.HOST_URN[:-1] return post_dict def get_interfaces_in_unis(self): node = self.unis.get(self.service["runningOn"]["href"]) port_list = node.get('ports', []) ports = [] for port in port_list: ports.append(self.unis.get(port['href'])) return ports def _find_or_post_port(self, ports, local_port, matching_method): for port in ports: if matching_method(port, local_port): return port["selfRef"] post = self.unis.post_port(local_port) if post: return post["selfRef"] else: logger.warn('_find_or_post_port', msg="post seems to have failed... subject for %s will be wrong" % local_port['name']) return "failed"