From bb5e085ffde9fcbb670dc2f00708b8a5b962a677 Mon Sep 17 00:00:00 2001 From: Atul Moghe Date: Thu, 20 Oct 2016 13:34:37 -0700 Subject: [PATCH] Changes in ip_alloc, ip_free and ip_count APIs to use subnet_uuid instead of subnet_name. ip_free will not use either subnet_name or subnet_uuid device-manager changes to reflect api chagnes. changes in UT for ip_alloc, ip_free and ip_count Closes-Bug:#1635414 Change-Id: I61e5ee267a0cfa8f63cad4c05d9bfa4f09f9a768 --- src/api-lib/vnc_api.py | 11 ++-- src/config/api-server/tests/test_ip_alloc.py | 20 ++++---- src/config/api-server/vnc_addr_mgmt.py | 19 ++++++- src/config/api-server/vnc_cfg_api_server.py | 3 +- src/config/api-server/vnc_cfg_types.py | 50 ++----------------- .../device-manager/device_manager/db.py | 22 ++++---- .../device-manager/device_manager/dm_utils.py | 3 +- 7 files changed, 51 insertions(+), 77 deletions(-) diff --git a/src/api-lib/vnc_api.py b/src/api-lib/vnc_api.py index d21d37b2dba..370abe72bdd 100644 --- a/src/api-lib/vnc_api.py +++ b/src/api-lib/vnc_api.py @@ -1063,7 +1063,7 @@ def kv_delete(self, key): #end kv_delete # reserve block of IP address from a VN - # expected format {"subnet" : "2.1.1.0/24", "count" : 4} + # expected format {"subnet" : "subnet_uuid", "count" : 4} @check_homepage def virtual_network_ip_alloc(self, vnobj, count=1, subnet=None, family=None): json_body = json.dumps({'count': count, 'subnet': subnet, 'family':family}) @@ -1073,18 +1073,17 @@ def virtual_network_ip_alloc(self, vnobj, count=1, subnet=None, family=None): #end virtual_network_ip_alloc # free previously reserved block of IP address from a VN - # Expected format "subnet" : "2.1.1.0/24", - # "ip_addr" : ["2.1.1.239", "2.1.1.238"] + # Expected format "ip_addr" : ["2.1.1.239", "2.1.1.238"] @check_homepage - def virtual_network_ip_free(self, vnobj, ip_list, subnet=None): - json_body = json.dumps({'ip_addr': ip_list, 'subnet': subnet}) + def virtual_network_ip_free(self, vnobj, ip_list): + json_body = json.dumps({'ip_addr': ip_list}) uri = self._action_uri['virtual-network-ip-free'] % vnobj.uuid rv = self._request_server(rest.OP_POST, uri, data=json_body) return rv #end virtual_network_ip_free # return no of ip instances from a given VN/Subnet - # Expected format "subne_list" : ["2.1.1.0/24", "2.2.2.0/24"] + # Expected format "subne_list" : ["subnet_uuid1", "subnet_uuid2"] @check_homepage def virtual_network_subnet_ip_count(self, vnobj, subnet_list): json_body = json.dumps({'subnet_list': subnet_list}) diff --git a/src/config/api-server/tests/test_ip_alloc.py b/src/config/api-server/tests/test_ip_alloc.py index 09cae393b3c..9a938cc2d3f 100644 --- a/src/config/api-server/tests/test_ip_alloc.py +++ b/src/config/api-server/tests/test_ip_alloc.py @@ -1682,8 +1682,9 @@ def test_bulk_ip_alloc_free(self): logger.debug('Created Virtual Network object %s', vn.uuid) net_obj = self._vnc_lib.virtual_network_read(id = vn.uuid) + subnet_uuid = net_obj.network_ipam_refs[0]['attr'].ipam_subnets[0].subnet_uuid # request to allocate 10 ip address using bulk allocation api - data = {"subnet" : "11.1.1.0/24", "count" : 10} + data = {"subnet" : subnet_uuid, "count" : 10} url = '/virtual-network/%s/ip-alloc' %(vn.uuid) rv_json = self._vnc_lib._request_server(rest.OP_POST, url, json.dumps(data)) @@ -1700,9 +1701,9 @@ def test_bulk_ip_alloc_free(self): logger.debug('Verify bulk ip address allocation') # Find out number of allocated ips from given VN/subnet - # We should not get 13 ip allocated from this subnet + # We should get 13 ip allocated from this subnet # 10 user request + 3 reserved ips (first, last and gw). - data = {"subnet_list" : ["11.1.1.0/24"]} + data = {"subnet_list" : [subnet_uuid]} url = '/virtual-network/%s/subnet-ip-count' %(vn.uuid) rv_json = self._vnc_lib._request_server(rest.OP_POST, url, json.dumps(data)) @@ -1711,15 +1712,14 @@ def test_bulk_ip_alloc_free(self): self.assertEqual(allocated_ip, 10) #free 5 allocated ip addresses from vn - data = {"subnet" : "11.1.1.0/24", - "ip_addr" : ['11.1.1.252', '11.1.1.251', '11.1.1.250', + data = {"ip_addr" : ['11.1.1.252', '11.1.1.251', '11.1.1.250', '11.1.1.249', '11.1.1.248']} url = '/virtual-network/%s/ip-free' %(vn.uuid) self._vnc_lib._request_server(rest.OP_POST, url, json.dumps(data)) # Find out number of allocated ips from given VN/subnet # We should get 5+3 ip allocated from this subnet - data = {"subnet_list" : ["11.1.1.0/24"]} + data = {"subnet_list" : [subnet_uuid]} url = '/virtual-network/%s/subnet-ip-count' %(vn.uuid) rv_json = self._vnc_lib._request_server(rest.OP_POST, url, json.dumps(data)) @@ -1728,13 +1728,12 @@ def test_bulk_ip_alloc_free(self): self.assertEqual(allocated_ip, 5) #free remaining 5 allocated ip addresses from vn - data = {"subnet" : "11.1.1.0/24", - "ip_addr": ['11.1.1.247', '11.1.1.246', '11.1.1.245', + data = {"ip_addr": ['11.1.1.247', '11.1.1.246', '11.1.1.245', '11.1.1.244', '11.1.1.243']} url = '/virtual-network/%s/ip-free' %(vn.uuid) self._vnc_lib._request_server(rest.OP_POST, url, json.dumps(data)) - data = {"subnet_list" : ["11.1.1.0/24"]} + data = {"subnet_list" : [subnet_uuid]} url = '/virtual-network/%s/subnet-ip-count' %(vn.uuid) rv_json = self._vnc_lib._request_server(rest.OP_POST, url, json.dumps(data)) @@ -1844,7 +1843,8 @@ def test_v4_ip_allocation_exhaust(self): # Find out number of allocated ips from given VN/subnet to test # vn_subnet_ip_count_http_post() - data = {"subnet_list" : ["11.1.1.0/24"]} + subnet_uuid = net_obj.network_ipam_refs[0]['attr'].ipam_subnets[0].subnet_uuid + data = {"subnet_list" : [subnet_uuid]} url = '/virtual-network/%s/subnet-ip-count' %(vn.uuid) rv_json = self._vnc_lib._request_server(rest.OP_POST, url, json.dumps(data)) ret_ip_count = json.loads(rv_json)['ip_count_list'][0] diff --git a/src/config/api-server/vnc_addr_mgmt.py b/src/config/api-server/vnc_addr_mgmt.py index fb591adcbab..d71e0ec7d7e 100644 --- a/src/config/api-server/vnc_addr_mgmt.py +++ b/src/config/api-server/vnc_addr_mgmt.py @@ -1162,10 +1162,25 @@ def net_check_subnet_delete(self, db_vn_dict, req_vn_dict): # return number of ip address currently allocated for a subnet # count will also include reserved ips - def ip_count_req(self, vn_fq_name, subnet_name=None): + def ip_count_req(self, vn_fq_name, subnet_uuid): + if subnet_uuid is None: + return 0 + db_conn = self._get_db_conn() vn_uuid = db_conn.fq_name_to_uuid('virtual_network', vn_fq_name) - subnet_obj = self._subnet_objs[vn_uuid][subnet_name] + subnet_dicts = self._get_net_subnet_dicts(vn_uuid) + req_subnet_name = None + for subnet_name, subnet_dict in subnet_dicts.items(): + if subnet_uuid == subnet_dict.get('subnet_uuid'): + req_subnet_name = subnet_name + break + + if req_subnet_name is None: + # subnet is not on this network, return zero to reflect no ip addr + # is allocated from requested subnet_uuid + return 0 + + subnet_obj = self._subnet_objs[vn_uuid][req_subnet_name] return subnet_obj.ip_count() # end ip_count_req diff --git a/src/config/api-server/vnc_cfg_api_server.py b/src/config/api-server/vnc_cfg_api_server.py index f044145524b..45b37f03c0e 100644 --- a/src/config/api-server/vnc_cfg_api_server.py +++ b/src/config/api-server/vnc_cfg_api_server.py @@ -3463,9 +3463,8 @@ def vn_ip_free_http_post(self, id): req_dict = get_request().json ip_list = req_dict['ip_addr'] if 'ip_addr' in req_dict else [] - subnet = req_dict['subnet'] if 'subnet' in req_dict else None result = vnc_cfg_types.VirtualNetworkServer.ip_free( - vn_fq_name, subnet, ip_list) + vn_fq_name, ip_list) return result # end vn_ip_free_http_post diff --git a/src/config/api-server/vnc_cfg_types.py b/src/config/api-server/vnc_cfg_types.py index 351dd482825..c4d4db7cb0a 100644 --- a/src/config/api-server/vnc_cfg_types.py +++ b/src/config/api-server/vnc_cfg_types.py @@ -1308,68 +1308,28 @@ def drop_ref(obj_uuid): @classmethod - def ip_alloc(cls, vn_fq_name, subnet_name, count, family=None): + def ip_alloc(cls, vn_fq_name, subnet_uuid=None, count=1, family=None): if family: ip_version = 6 if family == 'v6' else 4 else: ip_version = None - subnet_uuid = None - if subnet_name: - vn_uuid = cls.addr_mgmt._db_conn.fq_name_to_uuid('virtual_network', - vn_fq_name) - (ok, result) = cls.addr_mgmt._db_conn.dbe_read( - obj_type='virtual_network', - obj_ids={'uuid': vn_uuid}, - obj_fields=['network_ipam_refs']) - - if not ok: - raise cfgm_common.exceptions.VncError(result) - vn_dict = result - - ipam_refs = vn_dict.get('network_ipam_refs') or [] - for ipam in ipam_refs: - # Currently ip_alloc api is not supported for flat-ipam - # only to user-defined-ipam, we need to skip - # any flat ipam - vnsn_data = ipam['attr'] - ipam_subnets = vnsn_data.get('ipam_subnets') or [] - if len(ipam_subnets) is 0: - continue - first_ipam_subnet = ipam_subnets[0] - subnet = first_ipam_subnet.get('subnet') or {} - if ('ip_prefix' not in subnet): - continue - - ipam_subnets = ipam['attr'].get('ipam_subnets') or [] - for ipam_subnet in ipam_subnets: - subnet = ipam_subnet.get('subnet') or {} - if 'ip_prefix' in subnet: - ipam_subnet_name = subnet['ip_prefix'] + '/' +\ - str(subnet['ip_prefix_len']) - if ipam_subnet_name == subnet_name: - subnet_uuid = ipam_subnet.get('subnet_uuid') - break - - if subnet_uuid is None: - return {'ip_addr' : []} ip_list = [cls.addr_mgmt.ip_alloc_req(vn_fq_name, sub=subnet_uuid, asked_ip_version=ip_version, alloc_id=str(uuid.uuid4())) for i in range(count)] msg = 'AddrMgmt: reserve %d IP for vn=%s, subnet=%s - %s' \ - % (count, vn_fq_name, subnet_name if subnet_name else '', ip_list) + % (count, vn_fq_name, subnet_uuid or '', ip_list) cls.addr_mgmt.config_log(msg, level=SandeshLevel.SYS_DEBUG) return {'ip_addr': ip_list} # end ip_alloc @classmethod - def ip_free(cls, vn_fq_name, subnet_name, ip_list): - msg = 'AddrMgmt: release IP %s for vn=%s, subnet=%s' \ - % (ip_list, vn_fq_name, subnet_name if subnet_name else '') + def ip_free(cls, vn_fq_name, ip_list): + msg = 'AddrMgmt: release IP %s for vn=%s' % (ip_list, vn_fq_name) cls.addr_mgmt.config_log(msg, level=SandeshLevel.SYS_DEBUG) for ip_addr in ip_list: - cls.addr_mgmt.ip_free_req(ip_addr, vn_fq_name, subnet_name) + cls.addr_mgmt.ip_free_req(ip_addr, vn_fq_name) # end ip_free @classmethod diff --git a/src/config/device-manager/device_manager/db.py b/src/config/device-manager/device_manager/db.py index c7d02ed5202..c5c7467bd11 100644 --- a/src/config/device-manager/device_manager/db.py +++ b/src/config/device-manager/device_manager/db.py @@ -211,13 +211,13 @@ def init_cs_state(self): self.vn_ip_map[vn_subnet] = ip['ip_address'] # end init_cs_state - def reserve_ip(self, vn_uuid, subnet_prefix): + def reserve_ip(self, vn_uuid, subnet_uuid): try: vn = VirtualNetwork() vn.set_uuid(vn_uuid) ip_addr = self._manager._vnc_lib.virtual_network_ip_alloc( vn, - subnet=subnet_prefix) + subnet_uuid=subnet_uuid) if ip_addr: return ip_addr[0] # ip_alloc default ip count is 1 except Exception as e: @@ -225,14 +225,12 @@ def reserve_ip(self, vn_uuid, subnet_prefix): return None # end - def free_ip(self, vn_uuid, subnet_prefix, ip_addr): + def free_ip(self, vn_uuid, ip_addr): try: vn = VirtualNetwork() vn.set_uuid(vn_uuid) self._manager._vnc_lib.virtual_network_ip_free( - vn, - [ip_addr], - subnet=subnet_prefix) + vn, [ip_addr]) return True except Exception as e: self._logger.error("Exception: %s" % (str(e))) @@ -246,7 +244,9 @@ def get_vn_irb_ip_map(self): vn = VirtualNetworkDM.get(vn_uuid) if vn_uuid not in irb_ips: irb_ips[vn_uuid] = set() - irb_ips[vn_uuid].add((ip_addr, vn.gateways[subnet_prefix])) + irb_ips[vn_uuid].add( + (ip_addr, + vn.gateways[subnet_prefix].get('default_gateway'))) return irb_ips # end get_vn_irb_ip_map @@ -265,8 +265,7 @@ def evaluate_vn_irb_ip_map(self, vn_set): create_set = new_vn_ip_set.difference(old_set) for vn_subnet in delete_set: (vn_uuid, subnet_prefix) = vn_subnet.split(':', 1) - ret = self.free_ip( - vn_uuid, subnet_prefix, self.vn_ip_map[vn_subnet]) + ret = self.free_ip(vn_uuid, self.vn_ip_map[vn_subnet]) if ret == False: self._logger.error("Unable to free ip for vn/subnet/pr \ (%s/%s/%s)" % ( @@ -288,8 +287,9 @@ def evaluate_vn_irb_ip_map(self, vn_set): for vn_subnet in create_set: (vn_uuid, subnet_prefix) = vn_subnet.split(':', 1) + subnet_uuid = vn.gateways[subnet_prefix].get('subnet_uuid') (sub, length) = subnet_prefix.split('/') - ip_addr = self.reserve_ip(vn_uuid, subnet_prefix) + ip_addr = self.reserve_ip(vn_uuid, subnet_uuid) if ip_addr is None: self._logger.error("Unable to allocate ip for vn/subnet/pr \ (%s/%s/%s)" % ( @@ -307,7 +307,7 @@ def evaluate_vn_irb_ip_map(self, vn_set): self.uuid, subnet_prefix, self.uuid)) - if self.free_ip(vn_uuid, subnet_prefix, ip_addr) == False: + if self.free_ip(vn_uuid, ip_addr) == False: self._logger.error("Unable to free ip for vn/subnet/pr \ (%s/%s/%s)" % ( self.uuid, diff --git a/src/config/device-manager/device_manager/dm_utils.py b/src/config/device-manager/device_manager/dm_utils.py index 7cb2602d381..a28a15a28db 100644 --- a/src/config/device-manager/device_manager/dm_utils.py +++ b/src/config/device-manager/device_manager/dm_utils.py @@ -39,7 +39,8 @@ def get_network_gateways(ipam_refs=[]): prefix = subnet['subnet']['ip_prefix'] prefix_len = subnet['subnet']['ip_prefix_len'] gateways[prefix + '/' + str(prefix_len)] = \ - subnet.get('default_gateway', '') + {"default_gateway": subnet.get('default_gateway', ''), + "subnet_uuid": subnet.get('subnet_uuid')} return gateways # end get_network_gateways