class CliFetchVserviceVnics(CliAccess): def __init__(self): super().__init__() self.inv = InventoryMgr() self.if_header = re.compile('^\d+: ([^:]+): (.+)') self.regexps = [{ 'name': 'mac_address', 're': '^.*\slink/ether\s(\S+)\s' }, { 'name': 'IP Address', 're': '^\s*inet ([0-9.]+)/' }, { 'name': 'netmask', 're': '^\s*inet [0-9.]+/([0-9]+)' }, { 'name': 'IPv6 Address', 're': '^\s*inet6 ([^/]+)/.* global ' }] def get(self, host_id): host = self.inv.get_by_id(self.get_env(), host_id) if not host: self.log.error("host not found: " + host_id) return [] if "host_type" not in host: self.log.error("host does not have host_type: " + host_id + ", host: " + str(host)) return [] if "Network" not in host["host_type"]: return [] lines = self.run_fetch_lines("ip netns list", host_id) ret = [] for l in [ l for l in lines if l.startswith("qdhcp") or l.startswith("qrouter") ]: service = l.strip() service = service if ' ' not in service \ else service[:service.index(' ')] ret.extend(self.handle_service(host_id, service)) return ret def handle_service(self, host, service, enable_cache=True): cmd = "ip netns exec " + service + " ip address show" lines = self.run_fetch_lines(cmd, host, enable_cache) interfaces = [] current = None for line in lines: matches = self.if_header.match(line) if matches: if current: self.set_interface_data(current) name = matches.group(1).strip(":") # ignore 'lo' interface if name == 'lo': current = None else: line_remainder = matches.group(2) master_parent_id = "{}-{}".format(host, service) current = { "id": host + "-" + name, "vnic_type": "vservice_vnic", "host": host, "name": name, "lines": [] } self.set_folder_parent(current, object_type="vnic", master_parent_type="vservice", master_parent_id=master_parent_id, parent_text="vNICs") interfaces.append(current) self.handle_line(current, line_remainder) else: if current: self.handle_line(current, line) if current: self.set_interface_data(current) return interfaces def handle_line(self, interface, line): self.find_matching_regexps(interface, line, self.regexps) interface["lines"].append(line.strip()) def set_interface_data(self, interface): if not interface or 'IP Address' not in interface or 'netmask' not in interface: return interface["data"] = "\n".join(interface.pop("lines", None)) interface["cidr"] = self.get_cidr_for_vnic(interface) network = self.inv.get_by_field(self.get_env(), "network", "cidrs", interface["cidr"], get_single=True) if not network: return interface["network"] = network["id"] # set network for the vservice, to check network on clique creation vservice = self.inv.get_by_id(self.get_env(), interface["master_parent_id"]) network_id = network["id"] if "network" not in vservice: vservice["network"] = list() if network_id not in vservice["network"]: vservice["network"].append(network_id) self.inv.set(vservice) # find CIDR string by IP address and netmask def get_cidr_for_vnic(self, vnic): if "IP Address" not in vnic: vnic["IP Address"] = "No IP Address" return "No IP Address" ipaddr = vnic["IP Address"].split('.') vnic['netmask'] = self.convert_netmask(vnic['netmask']) netmask = vnic["netmask"].split('.') # calculate network start net_start = [] for pos in range(0, 4): net_start.append(str(int(ipaddr[pos]) & int(netmask[pos]))) cidr_string = '.'.join(net_start) + '/' cidr_string = cidr_string + self.get_net_size(netmask) return cidr_string def get_net_size(self, netmask): binary_str = '' for octet in netmask: binary_str += bin(int(octet))[2:].zfill(8) return str(len(binary_str.rstrip('0'))) @staticmethod def convert_netmask(cidr): netmask_conversion = { '32': '255.255.255.255', '31': '255.255.255.254', '30': '255.255.255.252', '29': '255.255.255.248', '28': '255.255.255.240', '27': '255.255.255.224', '26': '255.255.255.192', '25': '255.255.255.128', '24': '255.255.255.0', '23': '255.255.254.0', '22': '255.255.252.0', '21': '255.255.248.0', '20': '255.255.240.0', '19': '255.255.224.0', '18': '255.255.192.0', '17': '255.255.128.0', '16': '255.255.0.0', '15': '255.254.0.0', '14': '255.252.0.0', '13': '255.248.0.0', '12': '255.240.0.0', '11': '255.224.0.0', '10': '255.192.0.0', '9': '255.128.0.0', '8': '255.0.0.0', '7': '254.0.0.0', '6': '252.0.0.0', '5': '248.0.0.0', '4': '240.0.0.0', '3': '224.0.0.0', '2': '192.0.0.0', '1': '128.0.0.0', '0': '0.0.0.0' } if cidr not in netmask_conversion: raise ValueError('can' 't convert to netmask: {}'.format(cidr)) return netmask_conversion.get(cidr)
class ApiFetchNetworks(ApiAccess): def __init__(self): super(ApiFetchNetworks, self).__init__() self.inv = InventoryMgr() def get(self, project_id=None): # use project admin credentials, to be able to fetch all networks token = self.v2_auth_pwd(self.admin_project) if not token: return [] ret = [] for region in self.regions: ret.extend(self.get_networks(region, token)) return ret def get_networks(self, region, token): endpoint = self.get_region_url_nover(region, "neutron") req_url = endpoint + "/v2.0/networks" headers = { "X-Auth-Project-Id": self.admin_project, "X-Auth-Token": token["id"] } response = self.get_url(req_url, headers) if "networks" not in response: return [] networks = response["networks"] req_url = endpoint + "/v2.0/subnets" response = self.get_url(req_url, headers) subnets_hash = {} if "subnets" in response: # create a hash subnets, to allow easy locating of subnets subnets = response["subnets"] for s in subnets: subnets_hash[s["id"]] = s for doc in networks: project_id = doc["tenant_id"] if not project_id: # find project ID of admin project project = self.inv.get_by_field(self.get_env(), "project", "name", self.admin_project, get_single=True) if not project: self.log.error("failed to find admin project in DB") project_id = project["id"] self.set_folder_parent(doc, object_type='network', master_parent_id=project_id, master_parent_type='project') # set the 'network' attribute for network objects to the name of # network, to allow setting constraint on network when creating # network clique doc['network'] = doc["id"] # get the project name project = self.inv.get_by_id(self.get_env(), project_id) if project: doc["project"] = project["name"] subnets_details = {} cidrs = [] subnet_ids = [] for s in doc["subnets"]: try: subnet = subnets_hash[s] cidrs.append(subnet["cidr"]) subnet_ids.append(subnet["id"]) subnets_details[subnet["name"]] = subnet except KeyError: pass doc["subnets"] = subnets_details doc["cidrs"] = cidrs doc["subnet_ids"] = subnet_ids return networks