def _init_index_allocators(): bgpaas_port_start = self._args.bgpaas_port_start bgpaas_port_end = self._args.bgpaas_port_end gsc_fq_name = ['default-global-system-config'] gsc_uuid = self._object_db.fq_name_to_uuid( obj_type='global_system_config', fq_name=gsc_fq_name) _, cfg = self._object_db.object_read('global_system_config', [gsc_uuid]) cfg_bgpaas_ports = cfg[0].get('bgpaas_parameters') if cfg_bgpaas_ports: bgpaas_port_start = cfg_bgpaas_ports['port_start'] bgpaas_port_end = cfg_bgpaas_ports['port_end'] self._bgpaas_port_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, bgpaas_port_end - bgpaas_port_start, bgpaas_port_start) self._rt_allocator = IndexAllocator( zkclient, self._zk_path_pfx + common.BGP_RTGT_ALLOC_PATH_TYPE0, common._BGP_RTGT_MAX_ID_TYPE0, common._BGP_RTGT_MIN_ID_TYPE0) self._rt_allocator_4 = IndexAllocator( zkclient, self._zk_path_pfx + common.BGP_RTGT_ALLOC_PATH_TYPE1_2, common._BGP_RTGT_MAX_ID_TYPE1_2, common._BGP_RTGT_MIN_ID_TYPE1_2)
def __init__(self, manager, zkclient): self._zkclient = zkclient self._manager = manager self._args = manager._args keyspaces = { self._KEYSPACE: {self._PR_VN_IP_CF: {}, self._PNF_RESOURCE_CF: {}}} cass_server_list = self._args.cassandra_server_list cred = None if (self._args.cassandra_user is not None and self._args.cassandra_password is not None): cred = {'username': self._args.cassandra_user, 'password': self._args.cassandra_password} super(DMCassandraDB, self).__init__( cass_server_list, self._args.cluster_id, keyspaces, None, manager.logger.log, credential=cred) self.pr_vn_ip_map = {} self.init_pr_map() self.pnf_vlan_allocator_map = {} self.pnf_unit_allocator_map = {} self.pnf_network_allocator = IndexAllocator( zkclient, self._zk_path_pfx+self._PNF_NETWORK_ALLOC_PATH, self._PNF_MAX_NETWORK_ID) self.pnf_cf = self.get_cf(self._PNF_RESOURCE_CF) self.pnf_resources_map = dict( self.pnf_cf.get_range(column_count=0, filter_empty=True))
def __init__(self, manager, zkclient): self._manager = manager self._args = manager._args self._zkclient = zkclient if self._args.cluster_id: self._zk_path_pfx = self._args.cluster_id + '/' else: self._zk_path_pfx = '' keyspaces = { self._KEYSPACE: {self._RT_CF: {}, self._SC_IP_CF: {}, self._SERVICE_CHAIN_CF: {}, self._SERVICE_CHAIN_UUID_CF: {}}} cass_server_list = self._args.cassandra_server_list cred = None if (self._args.cassandra_user is not None and self._args.cassandra_password is not None): cred={'username':self._args.cassandra_user, 'password':self._args.cassandra_password} super(SchemaTransformerDB, self).__init__( cass_server_list, self._args.cluster_id, keyspaces, None, manager.config_log, reset_config=self._args.reset_config, credential=cred) SchemaTransformerDB._rt_cf = self._cf_dict[self._RT_CF] SchemaTransformerDB._sc_ip_cf = self._cf_dict[self._SC_IP_CF] SchemaTransformerDB._service_chain_cf = self._cf_dict[ self._SERVICE_CHAIN_CF] SchemaTransformerDB._service_chain_uuid_cf = self._cf_dict[ self._SERVICE_CHAIN_UUID_CF] # reset zookeeper config if self._args.reset_config: zkclient.delete_node(self._zk_path_pfx + "/id", True) self._sg_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx+self._SECURITY_GROUP_ID_ALLOC_PATH, self._SECURITY_GROUP_MAX_ID) # 0 is not a valid sg id any more. So, if it was previously allocated, # delete it and reserve it if self._sg_id_allocator.read(0) != '__reserved__': self._sg_id_allocator.delete(0) self._sg_id_allocator.reserve(0, '__reserved__') self._rt_allocator = IndexAllocator( zkclient, self._zk_path_pfx+self._BGP_RTGT_ALLOC_PATH, self._BGP_RTGT_MAX_ID, common.BGP_RTGT_MIN_ID) self._bgpaas_port_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, self._args.bgpaas_port_end - self._args.bgpaas_port_start, self._args.bgpaas_port_start) self._sc_vlan_allocator_dict = {} self._upgrade_vlan_alloc_path()
def __init__(self, manager, zkclient): self._manager = manager self._args = manager._args self._zkclient = zkclient if self._args.cluster_id: self._keyspace = '%s_%s' % (self._args.cluster_id, self._KEYSPACE) self._zk_path_pfx = self._args.cluster_id + '/' else: self._keyspace = self._KEYSPACE self._zk_path_pfx = '' keyspaces = { self._keyspace: [(self._RT_CF, None), (self._SC_IP_CF, None), (self._SERVICE_CHAIN_CF, None), (self._SERVICE_CHAIN_UUID_CF, None)]} cass_server_list = self._args.cassandra_server_list if self._args.reset_config: cass_reset_config = [self._keyspace] else: cass_reset_config = [] super(SchemaTransformerDB, self).__init__( cass_server_list, self._args.cluster_id, keyspaces, manager.config_log, reset_config=cass_reset_config) SchemaTransformerDB._rt_cf = self._cf_dict[self._RT_CF] SchemaTransformerDB._sc_ip_cf = self._cf_dict[self._SC_IP_CF] SchemaTransformerDB._service_chain_cf = self._cf_dict[ self._SERVICE_CHAIN_CF] SchemaTransformerDB._service_chain_uuid_cf = self._cf_dict[ self._SERVICE_CHAIN_UUID_CF] # reset zookeeper config if self._args.reset_config: zkclient.delete_node(self._zk_path_pfx + "/id", True) self._vn_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx+self._VN_ID_ALLOC_PATH, self._VN_MAX_ID) self._sg_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx+self._SECURITY_GROUP_ID_ALLOC_PATH, self._SECURITY_GROUP_MAX_ID) # 0 is not a valid sg id any more. So, if it was previously allocated, # delete it and reserve it if self._sg_id_allocator.read(0) != '__reserved__': self._sg_id_allocator.delete(0) self._sg_id_allocator.reserve(0, '__reserved__') self._rt_allocator = IndexAllocator( zkclient, self._zk_path_pfx+self._BGP_RTGT_ALLOC_PATH, self._BGP_RTGT_MAX_ID, common.BGP_RTGT_MIN_ID) self._sc_vlan_allocator_dict = {} self._upgrade_vlan_alloc_path()
def __init__(self, manager, zkclient): self._manager = manager self._args = manager._args self._zkclient = zkclient if self._args.cluster_id: self._zk_path_pfx = self._args.cluster_id + '/' else: self._zk_path_pfx = '' keyspaces = { self._KEYSPACE: [(self._RT_CF, None), (self._SC_IP_CF, None), (self._SERVICE_CHAIN_CF, None), (self._SERVICE_CHAIN_UUID_CF, None)] } cass_server_list = self._args.cassandra_server_list super(SchemaTransformerDB, self).__init__(cass_server_list, self._args.cluster_id, keyspaces, None, manager.config_log, reset_config=self._args.reset_config) SchemaTransformerDB._rt_cf = self._cf_dict[self._RT_CF] SchemaTransformerDB._sc_ip_cf = self._cf_dict[self._SC_IP_CF] SchemaTransformerDB._service_chain_cf = self._cf_dict[ self._SERVICE_CHAIN_CF] SchemaTransformerDB._service_chain_uuid_cf = self._cf_dict[ self._SERVICE_CHAIN_UUID_CF] # reset zookeeper config if self._args.reset_config: zkclient.delete_node(self._zk_path_pfx + "/id", True) self._vn_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._VN_ID_ALLOC_PATH, self._VN_MAX_ID) self._sg_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._SECURITY_GROUP_ID_ALLOC_PATH, self._SECURITY_GROUP_MAX_ID) # 0 is not a valid sg id any more. So, if it was previously allocated, # delete it and reserve it if self._sg_id_allocator.read(0) != '__reserved__': self._sg_id_allocator.delete(0) self._sg_id_allocator.reserve(0, '__reserved__') self._rt_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGP_RTGT_ALLOC_PATH, self._BGP_RTGT_MAX_ID, common.BGP_RTGT_MIN_ID) self._bgpaas_port_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, self._args.bgpaas_port_end - self._args.bgpaas_port_start, self._args.bgpaas_port_start) self._sc_vlan_allocator_dict = {} self._upgrade_vlan_alloc_path()
def allocate_service_chain_vlan(self, service_vm, service_chain): alloc_new = False if service_vm not in self._sc_vlan_allocator_dict: self._sc_vlan_allocator_dict[service_vm] = IndexAllocator( self._zkclient, (self._zk_path_prefix + self._SERVICE_CHAIN_VLAN_ALLOC_PATH + service_vm + '/'), self._SERVICE_CHAIN_MAX_VLAN) vlan_ia = self._sc_vlan_allocator_dict[service_vm] try: vlan = int(self.get_one_col(self._SERVICE_CHAIN_CF, service_vm, service_chain)) db_sc = vlan_ia.read(vlan) if (db_sc is None) or (db_sc != service_chain): alloc_new = True except (KeyError, VncError, NoIdError): # TODO(ethuleau): VncError is raised if more than one row was # fetched from db with get_one_col method. # Probably need to be cleaned alloc_new = True if alloc_new: vlan = vlan_ia.alloc(service_chain) self._service_chain_cf.insert(service_vm, {service_chain: str(vlan)}) # Since vlan tag 0 is not valid, increment before returning return vlan + 1
def allocate_service_chain_vlan(self, service_vm, service_chain): alloc_new = False if service_vm not in self._sc_vlan_allocator_dict: self._sc_vlan_allocator_dict[service_vm] = IndexAllocator( self._zkclient, (self._zk_path_prefix + self._SERVICE_CHAIN_VLAN_ALLOC_PATH + service_vm), self._SERVICE_CHAIN_MAX_VLAN) vlan_ia = self._sc_vlan_allocator_dict[service_vm] try: vlan = int(self._service_chain_cf.get(service_vm)[service_chain]) db_sc = vlan_ia.read(vlan) if (db_sc is None) or (db_sc != service_chain): alloc_new = True except (KeyError, NotFoundException): alloc_new = True if alloc_new: vlan = vlan_ia.alloc(service_chain) self._service_chain_cf.insert(service_vm, {service_chain: str(vlan)}) # Since vlan tag 0 is not valid, increment before returning return vlan + 1
def get_pnf_unit_allocator(self, pi_id): return self.pnf_unit_allocator_map.setdefault( pi_id, IndexAllocator( self._zkclient, self._zk_path_pfx + self._PNF_UNIT_ALLOC_PATH + pi_id + '/', self._PNF_MAX_UNIT))
def get_pnf_vlan_allocator(self, pr_id): return self.pnf_vlan_allocator_map.setdefault( pr_id, IndexAllocator( self._zkclient, self._zk_path_pfx + self._PNF_VLAN_ALLOC_PATH + pr_id + '/', self._PNF_MAX_VLAN))
def _init_bgpaas_ports_index_allocator(): bgpaas_port_start = self._args.bgpaas_port_start bgpaas_port_end = self._args.bgpaas_port_end gsc_fq_name = ['default-global-system-config'] gsc_uuid = self.fq_name_to_uuid(obj_type='global_system_config', fq_name=gsc_fq_name) _, cfg = self.object_read('global_system_config', [gsc_uuid]) cfg_bgpaas_ports = cfg[0].get('bgpaas_parameters') if cfg_bgpaas_ports: bgpaas_port_start = cfg_bgpaas_ports['port_start'] bgpaas_port_end = cfg_bgpaas_ports['port_end'] self._bgpaas_port_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, bgpaas_port_end - bgpaas_port_start, bgpaas_port_start)
def _init_bgpaas_ports_index_allocator(): bgpaas_port_start = self._args.bgpaas_port_start bgpaas_port_end = self._args.bgpaas_port_end gsc_fq_name = ['default-global-system-config'] gsc_uuid = self._object_db.fq_name_to_uuid(obj_type='global_system_config', fq_name=gsc_fq_name) _, cfg = self._object_db.object_read('global_system_config', [gsc_uuid]) cfg_bgpaas_ports = cfg[0].get('bgpaas_parameters') if cfg_bgpaas_ports: bgpaas_port_start = cfg_bgpaas_ports['port_start'] bgpaas_port_end = cfg_bgpaas_ports['port_end'] self._bgpaas_port_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, bgpaas_port_end - bgpaas_port_start, bgpaas_port_start)
class SchemaTransformerDB(VncCassandraClient): _KEYSPACE = SCHEMA_KEYSPACE_NAME _RT_CF = 'route_target_table' _SC_IP_CF = 'service_chain_ip_address_table' _SERVICE_CHAIN_CF = 'service_chain_table' _SERVICE_CHAIN_UUID_CF = 'service_chain_uuid_table' _zk_path_prefix = '' _BGP_RTGT_MAX_ID = 1 << 24 _BGP_RTGT_ALLOC_PATH = "/id/bgp/route-targets/" _VN_MAX_ID = 1 << 24 _VN_ID_ALLOC_PATH = "/id/virtual-networks/" _SECURITY_GROUP_MAX_ID = 1 << 32 _SECURITY_GROUP_ID_ALLOC_PATH = "/id/security-groups/id/" _SERVICE_CHAIN_MAX_VLAN = 4093 _SERVICE_CHAIN_VLAN_ALLOC_PATH = "/id/service-chain/vlan/" @classmethod def get_db_info(cls): db_info = [(cls._KEYSPACE, [ cls._RT_CF, cls._SC_IP_CF, cls._SERVICE_CHAIN_CF, cls._SERVICE_CHAIN_UUID_CF ])] return db_info # end get_db_info def __init__(self, manager, zkclient): self._manager = manager self._args = manager._args self._zkclient = zkclient if self._args.cluster_id: self._keyspace = '%s_%s' % (self._args.cluster_id, self._KEYSPACE) self._zk_path_pfx = self._args.cluster_id + '/' else: self._keyspace = self._KEYSPACE self._zk_path_pfx = '' keyspaces = { self._keyspace: [(self._RT_CF, None), (self._SC_IP_CF, None), (self._SERVICE_CHAIN_CF, None), (self._SERVICE_CHAIN_UUID_CF, None)] } cass_server_list = self._args.cassandra_server_list if self._args.reset_config: cass_reset_config = [self._keyspace] else: cass_reset_config = [] super(SchemaTransformerDB, self).__init__(cass_server_list, self._args.cluster_id, keyspaces, manager.config_log, reset_config=cass_reset_config) SchemaTransformerDB._rt_cf = self._cf_dict[self._RT_CF] SchemaTransformerDB._sc_ip_cf = self._cf_dict[self._SC_IP_CF] SchemaTransformerDB._service_chain_cf = self._cf_dict[ self._SERVICE_CHAIN_CF] SchemaTransformerDB._service_chain_uuid_cf = self._cf_dict[ self._SERVICE_CHAIN_UUID_CF] # reset zookeeper config if self._args.reset_config: zkclient.delete_node(self._zk_path_pfx + "/id", True) self._vn_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._VN_ID_ALLOC_PATH, self._VN_MAX_ID) self._sg_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._SECURITY_GROUP_ID_ALLOC_PATH, self._SECURITY_GROUP_MAX_ID) # 0 is not a valid sg id any more. So, if it was previously allocated, # delete it and reserve it if self._sg_id_allocator.read(0) != '__reserved__': self._sg_id_allocator.delete(0) self._sg_id_allocator.reserve(0, '__reserved__') self._rt_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGP_RTGT_ALLOC_PATH, self._BGP_RTGT_MAX_ID, common.BGP_RTGT_MIN_ID) self._sc_vlan_allocator_dict = {} # end __init__ def allocate_service_chain_vlan(self, service_vm, service_chain): alloc_new = False if service_vm not in self._sc_vlan_allocator_dict: self._sc_vlan_allocator_dict[service_vm] = IndexAllocator( self._zkclient, (self._zk_path_prefix + self._SERVICE_CHAIN_VLAN_ALLOC_PATH + service_vm), self._SERVICE_CHAIN_MAX_VLAN) vlan_ia = self._sc_vlan_allocator_dict[service_vm] try: vlan = int(self._service_chain_cf.get(service_vm)[service_chain]) db_sc = vlan_ia.read(vlan) if (db_sc is None) or (db_sc != service_chain): alloc_new = True except (KeyError, NotFoundException): alloc_new = True if alloc_new: vlan = vlan_ia.alloc(service_chain) self._service_chain_cf.insert(service_vm, {service_chain: str(vlan)}) # Since vlan tag 0 is not valid, increment before returning return vlan + 1 # end allocate_service_chain_vlan def free_service_chain_vlan(self, service_vm, service_chain): try: vlan_ia = self._sc_vlan_allocator_dict[service_vm] vlan = int(self._service_chain_cf.get(service_vm)[service_chain]) self._service_chain_cf.remove(service_vm, [service_chain]) vlan_ia.delete(vlan) if vlan_ia.empty(): del self._sc_vlan_allocator_dict[service_vm] except (KeyError, NotFoundException): pass # end free_service_chain_vlan def get_route_target(self, ri_fq_name): try: return int(self._rt_cf.get(ri_fq_name)['rtgt_num']) except NotFoundException: return 0 def alloc_route_target(self, ri_fq_name, zk_only=False): alloc_new = False if zk_only: alloc_new = True else: rtgt_num = self.get_route_target(ri_fq_name) if rtgt_num < common.BGP_RTGT_MIN_ID: alloc_new = True else: rtgt_ri_fq_name_str = self._rt_allocator.read(rtgt_num) if (rtgt_ri_fq_name_str != ri_fq_name): alloc_new = True if (alloc_new): rtgt_num = self._rt_allocator.alloc(ri_fq_name) self._rt_cf.insert(ri_fq_name, {'rtgt_num': str(rtgt_num)}) return rtgt_num # end alloc_route_target def free_route_target_by_number(self, rtgt): self._rt_allocator.delete(rtgt) def free_route_target(self, ri_fq_name): try: rtgt = self.get_route_target(ri_fq_name) self._rt_cf.remove(ri_fq_name) except NotFoundException: pass self._rt_allocator.delete(rtgt) # end free_route_target def get_service_chain_ip(self, sc_name): try: return self._sc_ip_cf.get(sc_name)['ip_address'] except NotFoundException: return None def add_service_chain_ip(self, sc_name, ip): self._sc_ip_cf.insert(sc_name, {'ip_address': ip}) def remove_service_chain_ip(self, sc_name): try: self._sc_ip_cf.remove(sc_name) except NotFoundException: pass def list_service_chain_uuid(self): try: return self._service_chain_uuid_cf.get_range() except NotFoundException: return [] def add_service_chain_uuid(self, name, value): self._service_chain_uuid_cf.insert(name, {'value': value}) def remove_service_chain_uuid(self, name): try: self._service_chain_uuid_cf.remove(name) except NotFoundException: pass def get_sg_from_id(self, sg_id): return self._sg_id_allocator.read(sg_id) def alloc_sg_id(self, name): return self._sg_id_allocator.alloc(name) def free_sg_id(self, sg_id): self._sg_id_allocator.delete(sg_id) def get_vn_from_id(self, vn_id): return self._vn_id_allocator.read(vn_id) def alloc_vn_id(self, name): return self._vn_id_allocator.alloc(name) def free_vn_id(self, vn_id): self._vn_id_allocator.delete(vn_id)
def __init__(self, manager, zkclient): self._manager = manager self._args = manager._args self._zkclient = zkclient if self._args.cluster_id: self._zk_path_pfx = self._args.cluster_id else: self._zk_path_pfx = '' keyspaces = { self._KEYSPACE: {self._RT_CF: {}, self._SC_IP_CF: {}, self._SERVICE_CHAIN_CF: {}, self._SERVICE_CHAIN_UUID_CF: {}}} cass_server_list = self._args.cassandra_server_list cred = None if (self._args.cassandra_user is not None and self._args.cassandra_password is not None): cred={'username':self._args.cassandra_user, 'password':self._args.cassandra_password} super(SchemaTransformerDB, self).__init__( cass_server_list, self._args.cluster_id, keyspaces, None, manager.logger.log, reset_config=self._args.reset_config, credential=cred, ssl_enabled=self._args.cassandra_use_ssl, ca_certs=self._args.cassandra_ca_certs) SchemaTransformerDB._rt_cf = self._cf_dict[self._RT_CF] SchemaTransformerDB._sc_ip_cf = self._cf_dict[self._SC_IP_CF] SchemaTransformerDB._service_chain_cf = self._cf_dict[ self._SERVICE_CHAIN_CF] SchemaTransformerDB._service_chain_uuid_cf = self._cf_dict[ self._SERVICE_CHAIN_UUID_CF] # reset zookeeper config if self._args.reset_config: zkclient.delete_node( self._zk_path_pfx + self._BGP_RTGT_ALLOC_PATH, True) zkclient.delete_node( self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, True) zkclient.delete_node( self._zk_path_pfx + self._SERVICE_CHAIN_VLAN_ALLOC_PATH, True) self._rt_allocator = IndexAllocator( zkclient, self._zk_path_pfx+self._BGP_RTGT_ALLOC_PATH, self._BGP_RTGT_MAX_ID, common.BGP_RTGT_MIN_ID) def _init_bgpaas_ports_index_allocator(): bgpaas_port_start = self._args.bgpaas_port_start bgpaas_port_end = self._args.bgpaas_port_end gsc_fq_name = ['default-global-system-config'] gsc_uuid = self._object_db.fq_name_to_uuid(obj_type='global_system_config', fq_name=gsc_fq_name) _, cfg = self._object_db.object_read('global_system_config', [gsc_uuid]) cfg_bgpaas_ports = cfg[0].get('bgpaas_parameters') if cfg_bgpaas_ports: bgpaas_port_start = cfg_bgpaas_ports['port_start'] bgpaas_port_end = cfg_bgpaas_ports['port_end'] self._bgpaas_port_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, bgpaas_port_end - bgpaas_port_start, bgpaas_port_start) _init_bgpaas_ports_index_allocator() self._sc_vlan_allocator_dict = {} self._upgrade_vlan_alloc_path()
class SchemaTransformerDB(VncObjectDBClient): _KEYSPACE = SCHEMA_KEYSPACE_NAME _RT_CF = 'route_target_table' _SC_IP_CF = 'service_chain_ip_address_table' _SERVICE_CHAIN_CF = 'service_chain_table' _SERVICE_CHAIN_UUID_CF = 'service_chain_uuid_table' _zk_path_prefix = '' _BGP_RTGT_MAX_ID = 1 << 24 _BGP_RTGT_ALLOC_PATH = "/id/bgp/route-targets/" _SERVICE_CHAIN_MAX_VLAN = 4093 _SERVICE_CHAIN_VLAN_ALLOC_PATH = "/id/service-chain/vlan/" _BGPAAS_PORT_ALLOC_PATH = "/id/bgpaas/port/" @classmethod def get_db_info(cls): db_info = [(cls._KEYSPACE, [cls._RT_CF, cls._SC_IP_CF, cls._SERVICE_CHAIN_CF, cls._SERVICE_CHAIN_UUID_CF])] return db_info # end get_db_info def __init__(self, manager, zkclient): self._manager = manager self._args = manager._args self._zkclient = zkclient if self._args.cluster_id: self._zk_path_pfx = self._args.cluster_id else: self._zk_path_pfx = '' keyspaces = { self._KEYSPACE: {self._RT_CF: {}, self._SC_IP_CF: {}, self._SERVICE_CHAIN_CF: {}, self._SERVICE_CHAIN_UUID_CF: {}}} cass_server_list = self._args.cassandra_server_list cred = None if (self._args.cassandra_user is not None and self._args.cassandra_password is not None): cred={'username':self._args.cassandra_user, 'password':self._args.cassandra_password} super(SchemaTransformerDB, self).__init__( cass_server_list, self._args.cluster_id, keyspaces, None, manager.logger.log, reset_config=self._args.reset_config, credential=cred, ssl_enabled=self._args.cassandra_use_ssl, ca_certs=self._args.cassandra_ca_certs) SchemaTransformerDB._rt_cf = self._cf_dict[self._RT_CF] SchemaTransformerDB._sc_ip_cf = self._cf_dict[self._SC_IP_CF] SchemaTransformerDB._service_chain_cf = self._cf_dict[ self._SERVICE_CHAIN_CF] SchemaTransformerDB._service_chain_uuid_cf = self._cf_dict[ self._SERVICE_CHAIN_UUID_CF] # reset zookeeper config if self._args.reset_config: zkclient.delete_node( self._zk_path_pfx + self._BGP_RTGT_ALLOC_PATH, True) zkclient.delete_node( self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, True) zkclient.delete_node( self._zk_path_pfx + self._SERVICE_CHAIN_VLAN_ALLOC_PATH, True) self._rt_allocator = IndexAllocator( zkclient, self._zk_path_pfx+self._BGP_RTGT_ALLOC_PATH, self._BGP_RTGT_MAX_ID, common.BGP_RTGT_MIN_ID) def _init_bgpaas_ports_index_allocator(): bgpaas_port_start = self._args.bgpaas_port_start bgpaas_port_end = self._args.bgpaas_port_end gsc_fq_name = ['default-global-system-config'] gsc_uuid = self._object_db.fq_name_to_uuid(obj_type='global_system_config', fq_name=gsc_fq_name) _, cfg = self._object_db.object_read('global_system_config', [gsc_uuid]) cfg_bgpaas_ports = cfg[0].get('bgpaas_parameters') if cfg_bgpaas_ports: bgpaas_port_start = cfg_bgpaas_ports['port_start'] bgpaas_port_end = cfg_bgpaas_ports['port_end'] self._bgpaas_port_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, bgpaas_port_end - bgpaas_port_start, bgpaas_port_start) _init_bgpaas_ports_index_allocator() self._sc_vlan_allocator_dict = {} self._upgrade_vlan_alloc_path() # end __init__ def _upgrade_vlan_alloc_path(self): # In earlier releases, allocation path for vlans did not end with '/'. # This caused the allocated numbers to be just appended to the vm id # instead of being created as a child of it. That caused the vlan ids # to be leaked when process restarted. With that being fixed, we need # to change any vlan ids that were allocated in prior releases to the # new format. vlan_alloc_path = (self._zk_path_prefix + self._SERVICE_CHAIN_VLAN_ALLOC_PATH) for item in self._zkclient.get_children(vlan_alloc_path): try: # in the old format, item was vm id followed by 10 digit vlan # id allocated. Try to parse it to determine if it is still in # old format vm_id = uuid.UUID(item[:-10]) vlan_id = int(item[-10:]) except ValueError: continue sc_id = self._zkclient.read_node(vlan_alloc_path+item) self._zkclient.delete_node(vlan_alloc_path+item) self._zkclient.create_node( vlan_alloc_path+item[:-10]+'/'+item[-10:], sc_id) # end for item def allocate_service_chain_vlan(self, service_vm, service_chain): alloc_new = False if service_vm not in self._sc_vlan_allocator_dict: self._sc_vlan_allocator_dict[service_vm] = IndexAllocator( self._zkclient, (self._zk_path_prefix + self._SERVICE_CHAIN_VLAN_ALLOC_PATH + service_vm + '/'), self._SERVICE_CHAIN_MAX_VLAN) vlan_ia = self._sc_vlan_allocator_dict[service_vm] try: vlan = int(self.get_one_col(self._SERVICE_CHAIN_CF, service_vm, service_chain)) db_sc = vlan_ia.read(vlan) if (db_sc is None) or (db_sc != service_chain): alloc_new = True except (KeyError, VncError, NoIdError): # TODO(ethuleau): VncError is raised if more than one row was # fetched from db with get_one_col method. # Probably need to be cleaned alloc_new = True if alloc_new: vlan = vlan_ia.alloc(service_chain) self._service_chain_cf.insert(service_vm, {service_chain: str(vlan)}) # Since vlan tag 0 is not valid, increment before returning return vlan + 1 # end allocate_service_chain_vlan def free_service_chain_vlan(self, service_vm, service_chain): try: vlan_ia = self._sc_vlan_allocator_dict[service_vm] vlan = int(self.get_one_col(self._SERVICE_CHAIN_CF, service_vm, service_chain)) self._service_chain_cf.remove(service_vm, [service_chain]) vlan_ia.delete(vlan) if vlan_ia.empty(): del self._sc_vlan_allocator_dict[service_vm] except (KeyError, VncError, NoIdError): # TODO(ethuleau): VncError is raised if more than one row was # fetched from db with get_one_col method. # Probably need to be cleaned pass # end free_service_chain_vlan def get_route_target(self, ri_fq_name): try: return int(self.get_one_col(self._RT_CF, ri_fq_name, 'rtgt_num')) except (VncError, NoIdError): # TODO(ethuleau): VncError is raised if more than one row was # fetched from db with get_one_col method. # Probably need to be cleaned return 0 def alloc_route_target(self, ri_fq_name, zk_only=False): alloc_new = False if zk_only: alloc_new = True else: rtgt_num = self.get_route_target(ri_fq_name) if rtgt_num < common.BGP_RTGT_MIN_ID: alloc_new = True else: rtgt_ri_fq_name_str = self._rt_allocator.read(rtgt_num) if (rtgt_ri_fq_name_str != ri_fq_name): alloc_new = True if (alloc_new): rtgt_num = self._rt_allocator.alloc(ri_fq_name) self._rt_cf.insert(ri_fq_name, {'rtgt_num': str(rtgt_num)}) return rtgt_num # end alloc_route_target def free_route_target(self, ri_fq_name): try: rtgt = self.get_route_target(ri_fq_name) self._rt_cf.remove(ri_fq_name) except NotFoundException: pass self._rt_allocator.delete(rtgt) # end free_route_target def get_service_chain_ip(self, sc_name): return self.get(self._SC_IP_CF, sc_name) def add_service_chain_ip(self, sc_name, ip_dict): self._sc_ip_cf.insert(sc_name, ip_dict) def remove_service_chain_ip(self, sc_name): try: self._sc_ip_cf.remove(sc_name) except NotFoundException: pass def list_service_chain_uuid(self): try: return self._service_chain_uuid_cf.get_range() except NotFoundException: return [] def add_service_chain_uuid(self, name, value): self._service_chain_uuid_cf.insert(name, {'value': value}) def remove_service_chain_uuid(self, name): try: self._service_chain_uuid_cf.remove(name) except NotFoundException: pass def get_bgpaas_port(self, port): return self._bgpaas_allocator.read(port) def alloc_bgpaas_port(self, name): return self._bgpaas_port_allocator.alloc(name) def free_bgpaas_port(self, port): self._bgpaas_port_allocator.delete(port)
def __init__(self, manager, zkclient): self._manager = manager self._args = manager._args self._zkclient = zkclient if self._args.cluster_id: self._zk_path_pfx = self._args.cluster_id + "/" else: self._zk_path_pfx = "" keyspaces = { self._KEYSPACE: { self._RT_CF: {}, self._SC_IP_CF: {}, self._SERVICE_CHAIN_CF: {}, self._SERVICE_CHAIN_UUID_CF: {}, } } cass_server_list = self._args.cassandra_server_list cred = None if self._args.cassandra_user is not None and self._args.cassandra_password is not None: cred = {"username": self._args.cassandra_user, "password": self._args.cassandra_password} super(SchemaTransformerDB, self).__init__( cass_server_list, self._args.cluster_id, keyspaces, None, manager.logger.log, reset_config=self._args.reset_config, credential=cred, ) SchemaTransformerDB._rt_cf = self._cf_dict[self._RT_CF] SchemaTransformerDB._sc_ip_cf = self._cf_dict[self._SC_IP_CF] SchemaTransformerDB._service_chain_cf = self._cf_dict[self._SERVICE_CHAIN_CF] SchemaTransformerDB._service_chain_uuid_cf = self._cf_dict[self._SERVICE_CHAIN_UUID_CF] # reset zookeeper config if self._args.reset_config: zkclient.delete_node(self._zk_path_pfx + self._BGP_RTGT_ALLOC_PATH, True) zkclient.delete_node(self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, True) zkclient.delete_node(self._zk_path_pfx + self._SERVICE_CHAIN_VLAN_ALLOC_PATH, True) # TODO(ethuleau): We keep the virtual network and security group ID # allocation in schema and in the vnc API for one # release overlap to prevent any upgrade issue. So the # following code need to be remove in release (3.2 + 1) self._vn_id_allocator = IndexAllocator(zkclient, self._zk_path_pfx + self._VN_ID_ALLOC_PATH, self._VN_MAX_ID) self._sg_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._SECURITY_GROUP_ID_ALLOC_PATH, self._SECURITY_GROUP_MAX_ID ) # 0 is not a valid sg id any more. So, if it was previously allocated, # delete it and reserve it if self._sg_id_allocator.read(0) != "__reserved__": self._sg_id_allocator.delete(0) self._sg_id_allocator.reserve(0, "__reserved__") self._rt_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGP_RTGT_ALLOC_PATH, self._BGP_RTGT_MAX_ID, common.BGP_RTGT_MIN_ID ) self._bgpaas_port_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, self._args.bgpaas_port_end - self._args.bgpaas_port_start, self._args.bgpaas_port_start, ) self._sc_vlan_allocator_dict = {} self._upgrade_vlan_alloc_path()
class DMCassandraDB(VncObjectDBClient): _KEYSPACE = DEVICE_MANAGER_KEYSPACE_NAME _PR_VN_IP_CF = 'dm_pr_vn_ip_table' # PNF table _PNF_RESOURCE_CF = 'dm_pnf_resource_table' _zk_path_pfx = '' _PNF_MAX_NETWORK_ID = 4294967292 _PNF_NETWORK_ALLOC_PATH = "/id/pnf/network_id" _PNF_MAX_VLAN = 4093 _PNF_VLAN_ALLOC_PATH = "/id/pnf/vlan_id" _PNF_MAX_UNIT = 16385 _PNF_UNIT_ALLOC_PATH = "/id/pnf/unit_id" dm_object_db_instance = None @classmethod def get_instance(cls, manager=None, zkclient=None): if cls.dm_object_db_instance == None: cls.dm_object_db_instance = DMCassandraDB(manager, zkclient) return cls.dm_object_db_instance # end @classmethod def clear_instance(cls): cls.dm_object_db_instance = None # end def __init__(self, manager, zkclient): self._zkclient = zkclient self._manager = manager self._args = manager._args keyspaces = { self._KEYSPACE: { self._PR_VN_IP_CF: {}, self._PNF_RESOURCE_CF: {} } } cass_server_list = self._args.cassandra_server_list cred = None if (self._args.cassandra_user is not None and self._args.cassandra_password is not None): cred = { 'username': self._args.cassandra_user, 'password': self._args.cassandra_password } super(DMCassandraDB, self).__init__(cass_server_list, self._args.cluster_id, keyspaces, None, manager.logger.log, credential=cred) self.pr_vn_ip_map = {} self.init_pr_map() self.pnf_vlan_allocator_map = {} self.pnf_unit_allocator_map = {} self.pnf_network_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._PNF_NETWORK_ALLOC_PATH, self._PNF_MAX_NETWORK_ID) self.pnf_cf = self.get_cf(self._PNF_RESOURCE_CF) self.pnf_resources_map = dict( self.pnf_cf.get_range(column_count=0, filter_empty=True)) # end def get_si_pr_set(self, si_id): si_obj = ServiceInstanceDM.get(si_id) pr_set = set() for pt_uuid in si_obj.port_tuples: pt_obj = PortTupleDM.get(pt_uuid) for vmi_uuid in pt_obj.virtual_machine_interfaces: vmi_obj = VirtualMachineInterfaceDM.get(vmi_uuid) pi_obj = PhysicalInterfaceDM.get(vmi_obj.physical_interface) pr_set.add(pi_obj.physical_router) return pr_set def get_pnf_vlan_allocator(self, pr_id): return self.pnf_vlan_allocator_map.setdefault( pr_id, IndexAllocator( self._zkclient, self._zk_path_pfx + self._PNF_VLAN_ALLOC_PATH + pr_id + '/', self._PNF_MAX_VLAN)) def get_pnf_unit_allocator(self, pi_id): return self.pnf_unit_allocator_map.setdefault( pi_id, IndexAllocator( self._zkclient, self._zk_path_pfx + self._PNF_UNIT_ALLOC_PATH + pi_id + '/', self._PNF_MAX_UNIT)) def get_pnf_resources(self, vmi_obj, pr_id): si_id = vmi_obj.service_instance pi_id = vmi_obj.physical_interface if not si_id or not pi_id: return None if si_id in self.pnf_resources_map: return self.pnf_resources_map[si_id] network_id = self.pnf_network_allocator.alloc(si_id) vlan_alloc = self.get_pnf_vlan_allocator(pr_id) vlan_alloc.reserve(0) vlan_id = vlan_alloc.alloc(si_id) pr_set = self.get_si_pr_set(si_id) for other_pr_uuid in pr_set: if other_pr_uuid != pr_id: self.get_pnf_vlan_allocator(other_pr_uuid).reserve(vlan_id) unit_alloc = self.get_pnf_unit_allocator(pi_id) unit_alloc.reserve(0) unit_id = unit_alloc.alloc(si_id) pnf_resources = { "network_id": str(network_id), "vlan_id": str(vlan_id), "unit_id": str(unit_id) } self.pnf_resources_map[si_id] = pnf_resources self.pnf_cf.insert(si_id, pnf_resources) return pnf_resources # end def delete_pnf_resources(self, si_id): pnf_resources = self.pnf_resources_map.get(si_id, None) if not pnf_resources: return self.pnf_network_allocator.delete(int(pnf_resources['network_id'])) pr_set = self.get_si_pr_set(si_id) for pr_uuid in pr_set: if pr_uuid in self.pnf_vlan_allocator_map: self.get_pnf_vlan_allocator(pr_uuid).delete( int(pnf_resources['vlan_id'])) si_obj = ServiceInstanceDM.get(si_id) for pt_uuid in si_obj.port_tuples: pt_obj = PortTupleDM.get(pt_uuid) for vmi_uuid in pt_obj.virtual_machine_interfaces: vmi_obj = VirtualMachineInterfaceDM.get(vmi_uuid) if vmi_obj.physical_interface: self.get_pnf_unit_allocator( vmi_obj.physical_interface).delete( int(pnf_resources['unit_id'])) del self.pnf_resources_map[si_id] self.pnf_cf.remove(si_id) # end def handle_pnf_resource_deletes(self, si_id_list): for si_id in self.pnf_resources_map: if si_id not in si_id_list: self.delete_pnf_resources(si_id) # end def init_pr_map(self): cf = self.get_cf(self._PR_VN_IP_CF) pr_entries = dict(cf.get_range(column_count=0, filter_empty=False)) for key in pr_entries.keys(): key_data = key.split(':', 1) cols = pr_entries[key] or {} for col in cols.keys(): ip_used_for = DMUtils.get_ip_used_for_str(col) (pr_uuid, vn_subnet_uuid) = (key_data[0], key_data[1]) self.add_to_pr_map(pr_uuid, vn_subnet_uuid, ip_used_for) # end def get_ip(self, key, ip_used_for): return self.get_one_col(self._PR_VN_IP_CF, key, DMUtils.get_ip_cs_column_name(ip_used_for)) # end def add_ip(self, key, ip_used_for, ip): self.add(self._PR_VN_IP_CF, key, {DMUtils.get_ip_cs_column_name(ip_used_for): ip}) # end def delete_ip(self, key, ip_used_for): self.delete(self._PR_VN_IP_CF, key, [DMUtils.get_ip_cs_column_name(ip_used_for)]) # end def add_to_pr_map(self, pr_uuid, vn_subnet, ip_used_for): if pr_uuid in self.pr_vn_ip_map: self.pr_vn_ip_map[pr_uuid].add((vn_subnet, ip_used_for)) else: self.pr_vn_ip_map[pr_uuid] = set() self.pr_vn_ip_map[pr_uuid].add((vn_subnet, ip_used_for)) # end def delete_from_pr_map(self, pr_uuid, vn_subnet, ip_used_for): if pr_uuid in self.pr_vn_ip_map: self.pr_vn_ip_map[pr_uuid].remove((vn_subnet, ip_used_for)) if not self.pr_vn_ip_map[pr_uuid]: del self.pr_vn_ip_map[pr_uuid] # end def delete_pr(self, pr_uuid): vn_subnet_set = self.pr_vn_ip_map.get(pr_uuid, set()) for vn_subnet_ip_used_for in vn_subnet_set: vn_subnet = vn_subnet_ip_used_for[0] ip_used_for = vn_subnet_ip_used_for[1] ret = self.delete(self._PR_VN_IP_CF, pr_uuid + ':' + vn_subnet, [DMUtils.get_ip_cs_column_name(ip_used_for)]) if ret == False: self._logger.error( "Unable to free ip from db for vn/pr/subnet/ip_used_for " "(%s/%s/%s)" % (pr_uuid, vn_subnet, ip_used_for)) # end def handle_pr_deletes(self, current_pr_set): cs_pr_set = set(self.pr_vn_ip_map.keys()) delete_set = cs_pr_set.difference(current_pr_set) for pr_uuid in delete_set: self.delete_pr(pr_uuid) # end def get_pr_vn_set(self, pr_uuid): return self.pr_vn_ip_map.get(pr_uuid, set()) # end @classmethod def get_db_info(cls): db_info = [(cls._KEYSPACE, [cls._PR_VN_IP_CF])] return db_info
class SchemaTransformerDB(VncObjectDBClient): _KEYSPACE = SCHEMA_KEYSPACE_NAME _RT_CF = 'route_target_table' _SC_IP_CF = 'service_chain_ip_address_table' _SERVICE_CHAIN_CF = 'service_chain_table' _SERVICE_CHAIN_UUID_CF = 'service_chain_uuid_table' _zk_path_prefix = '' _BGP_RTGT_MAX_ID_TYPE0 = 1 << 24 # We don't left shift by 16 below to reserve certain target # values if required for future use _BGP_RTGT_MAX_ID_TYPE1_2 = 1 << 15 _SERVICE_CHAIN_MAX_VLAN = 4093 _SERVICE_CHAIN_VLAN_ALLOC_PATH = "/id/service-chain/vlan/" _BGPAAS_PORT_ALLOC_PATH = "/id/bgpaas/port/" @classmethod def get_db_info(cls): db_info = [(cls._KEYSPACE, [cls._RT_CF, cls._SC_IP_CF, cls._SERVICE_CHAIN_CF, cls._SERVICE_CHAIN_UUID_CF])] return db_info # end get_db_info def __init__(self, manager, zkclient): self._manager = manager self._args = manager._args self._zkclient = zkclient if self._args.cluster_id: self._zk_path_pfx = self._args.cluster_id else: self._zk_path_pfx = '' keyspaces = { self._KEYSPACE: {self._RT_CF: {}, self._SC_IP_CF: {}, self._SERVICE_CHAIN_CF: {}, self._SERVICE_CHAIN_UUID_CF: {}}} cass_server_list = self._args.cassandra_server_list cred = None if (self._args.cassandra_user is not None and self._args.cassandra_password is not None): cred = {'username': self._args.cassandra_user, 'password': self._args.cassandra_password} super(SchemaTransformerDB, self).__init__( cass_server_list, self._args.cluster_id, keyspaces, None, manager.logger.log, reset_config=self._args.reset_config, credential=cred, ssl_enabled=self._args.cassandra_use_ssl, ca_certs=self._args.cassandra_ca_certs) SchemaTransformerDB._rt_cf = self._cf_dict[self._RT_CF] SchemaTransformerDB._sc_ip_cf = self._cf_dict[self._SC_IP_CF] SchemaTransformerDB._service_chain_cf = self._cf_dict[ self._SERVICE_CHAIN_CF] SchemaTransformerDB._service_chain_uuid_cf = self._cf_dict[ self._SERVICE_CHAIN_UUID_CF] # reset zookeeper config if self._args.reset_config: zkclient.delete_node( self._zk_path_pfx + common.BGP_RTGT_ALLOC_PATH_TYPE0, True) zkclient.delete_node( self._zk_path_pfx + common.BGP_RTGT_ALLOC_PATH_TYPE1_2, True) zkclient.delete_node( self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, True) zkclient.delete_node( self._zk_path_pfx + self._SERVICE_CHAIN_VLAN_ALLOC_PATH, True) def _init_index_allocators(): bgpaas_port_start = self._args.bgpaas_port_start bgpaas_port_end = self._args.bgpaas_port_end gsc_fq_name = ['default-global-system-config'] gsc_uuid = self._object_db.fq_name_to_uuid( obj_type='global_system_config', fq_name=gsc_fq_name) _, cfg = self._object_db.object_read('global_system_config', [gsc_uuid]) cfg_bgpaas_ports = cfg[0].get('bgpaas_parameters') if cfg_bgpaas_ports: bgpaas_port_start = cfg_bgpaas_ports['port_start'] bgpaas_port_end = cfg_bgpaas_ports['port_end'] self._bgpaas_port_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, bgpaas_port_end - bgpaas_port_start, bgpaas_port_start) self._rt_allocator = IndexAllocator( zkclient, self._zk_path_pfx + common.BGP_RTGT_ALLOC_PATH_TYPE0, common._BGP_RTGT_MAX_ID_TYPE0, common._BGP_RTGT_MIN_ID_TYPE0) self._rt_allocator_4 = IndexAllocator( zkclient, self._zk_path_pfx + common.BGP_RTGT_ALLOC_PATH_TYPE1_2, common._BGP_RTGT_MAX_ID_TYPE1_2, common._BGP_RTGT_MIN_ID_TYPE1_2) _init_index_allocators() self._sc_vlan_allocator_dict = {} self._upgrade_vlan_alloc_path() # end __init__ def _upgrade_vlan_alloc_path(self): # In earlier releases, allocation path for vlans did not end with '/'. # This caused the allocated numbers to be just appended to the vm id # instead of being created as a child of it. That caused the vlan ids # to be leaked when process restarted. With that being fixed, we need # to change any vlan ids that were allocated in prior releases to the # new format. vlan_alloc_path = (self._zk_path_prefix + self._SERVICE_CHAIN_VLAN_ALLOC_PATH) for item in self._zkclient.get_children(vlan_alloc_path): try: # in the old format, item was vm id followed by 10 digit vlan # id allocated. Try to parse it to determine if it is still in # old format uuid.UUID(item[:-10]) int(item[-10:]) except ValueError: continue sc_id = self._zkclient.read_node(vlan_alloc_path + item) self._zkclient.delete_node(vlan_alloc_path + item) self._zkclient.create_node( vlan_alloc_path + item[:-10] + '/' + item[-10:], sc_id) # end for item def allocate_service_chain_vlan(self, service_vm, service_chain): alloc_new = False if service_vm not in self._sc_vlan_allocator_dict: self._sc_vlan_allocator_dict[service_vm] = IndexAllocator( self._zkclient, (self._zk_path_prefix + self._SERVICE_CHAIN_VLAN_ALLOC_PATH + service_vm + '/'), self._SERVICE_CHAIN_MAX_VLAN) vlan_ia = self._sc_vlan_allocator_dict[service_vm] try: vlan = int(self.get_one_col(self._SERVICE_CHAIN_CF, service_vm, service_chain)) db_sc = vlan_ia.read(vlan) if (db_sc is None) or (db_sc != service_chain): alloc_new = True except (KeyError, VncError, NoIdError): # TODO(ethuleau): VncError is raised if more than one row was # fetched from db with get_one_col method. # Probably need to be cleaned alloc_new = True if alloc_new: vlan = vlan_ia.alloc(service_chain) self._service_chain_cf.insert(service_vm, {service_chain: str(vlan)}) # Since vlan tag 0 is not valid, increment before returning return vlan + 1 # end allocate_service_chain_vlan def free_service_chain_vlan(self, service_vm, service_chain): try: vlan_ia = self._sc_vlan_allocator_dict[service_vm] vlan = int(self.get_one_col(self._SERVICE_CHAIN_CF, service_vm, service_chain)) self._service_chain_cf.remove(service_vm, [service_chain]) vlan_ia.delete(vlan) if vlan_ia.empty(): del self._sc_vlan_allocator_dict[service_vm] except (KeyError, VncError, NoIdError): # TODO(ethuleau): VncError is raised if more than one row was # fetched from db with get_one_col method. # Probably need to be cleaned pass # end free_service_chain_vlan def get_route_target(self, ri_fq_name): try: return int(self.get_one_col(self._RT_CF, ri_fq_name, 'rtgt_num')) except (VncError, NoIdError): # TODO(ethuleau): VncError is raised if more than one row was # fetched from db with get_one_col method. # Probably need to be cleaned return 0 def get_zk_route_target_allocator(self, asn): if int(asn) > 0xFFFF: return self._rt_allocator_4 else: return self._rt_allocator def alloc_route_target(self, ri_fq_name, asn, zk_only=False): alloc_new = False self.current_rt_allocator = self.get_zk_route_target_allocator(asn) if zk_only: alloc_new = True else: rtgt_num = self.get_route_target(ri_fq_name) if rtgt_num < common.get_bgp_rtgt_min_id(asn): alloc_new = True else: rtgt_ri_fq_name_str = self.current_rt_allocator.read(rtgt_num) if (rtgt_ri_fq_name_str != ri_fq_name): alloc_new = True if (alloc_new): rtgt_num = self.current_rt_allocator.alloc(ri_fq_name) self._rt_cf.insert(ri_fq_name, {'rtgt_num': str(rtgt_num)}) return rtgt_num # end alloc_route_target def free_route_target(self, ri_fq_name, asn): if ri_fq_name is None or ri_fq_name == '': return rtgt = self.get_route_target(ri_fq_name) self.delete(self._RT_CF, ri_fq_name) self.current_rt_allocator = self.get_zk_route_target_allocator(asn) self.current_rt_allocator.delete(rtgt) # end free_route_target def get_ri_from_route_target(self, rtgt_num, asn): self.current_rt_allocator = self.get_zk_route_target_allocator(asn) return self.current_rt_allocator.read(rtgt_num) def delete_route_target_directory(self, path): for zk_node in self._zkclient.get_children(path): if 'type0' in zk_node or 'type1_2' in zk_node: continue # The return value of read_node will be an list # where 0th element is fq_name and 1st element is node stat for # the Zookeeper node znode = self._zkclient.read_node( '%s/%s/%s' % (self._zk_path_pfx, path, zk_node), include_timestamp=True) # Delete all the zk nodes that are not sub-directories if znode is not None and znode[1].numChildren == 0: self._zkclient.delete_node('%s/%s/%s' % (self._zk_path_pfx, path, zk_node)) def populate_route_target_directory(self, old_path, asn): self.current_rt_allocator = self.get_zk_route_target_allocator(asn) for zk_node in self._zkclient.get_children(old_path): if 'type0' in zk_node or 'type1_2' in zk_node: continue znode = self._zkclient.read_node( '%s/%s/%s' % (self._zk_path_pfx, old_path, zk_node), include_timestamp=True) # For all the zk nodes that are not sub-directories, # create the node again in new path. if znode and len(znode) == 2 and znode[1].numChildren == 0: self.current_rt_allocator.reserve(int(zk_node), znode[0]) def get_service_chain_ip(self, sc_name): return self.get(self._SC_IP_CF, sc_name) def add_service_chain_ip(self, sc_name, ip_dict): self._sc_ip_cf.insert(sc_name, ip_dict) def remove_service_chain_ip(self, sc_name): self.delete(self._SC_IP_CF, sc_name) def list_service_chain_uuid(self): return self.get_range(self._SERVICE_CHAIN_UUID_CF) or [] def add_service_chain_uuid(self, name, value): self._service_chain_uuid_cf.insert(name, {'value': value}) def remove_service_chain_uuid(self, name): self.delete(self._SERVICE_CHAIN_UUID_CF, name) def get_bgpaas_port(self, port): return self._bgpaas_allocator.read(port) def alloc_bgpaas_port(self, name): return self._bgpaas_port_allocator.alloc(name) def free_bgpaas_port(self, port): self._bgpaas_port_allocator.delete(port)
def __init__(self, manager, zkclient): self._manager = manager self._args = manager._args self._zkclient = zkclient if self._args.cluster_id: self._zk_path_pfx = self._args.cluster_id else: self._zk_path_pfx = '' keyspaces = { self._KEYSPACE: {self._RT_CF: {}, self._SC_IP_CF: {}, self._SERVICE_CHAIN_CF: {}, self._SERVICE_CHAIN_UUID_CF: {}}} cass_server_list = self._args.cassandra_server_list cred = None if (self._args.cassandra_user is not None and self._args.cassandra_password is not None): cred={'username':self._args.cassandra_user, 'password':self._args.cassandra_password} super(SchemaTransformerDB, self).__init__( cass_server_list, self._args.cluster_id, keyspaces, None, manager.logger.log, reset_config=self._args.reset_config, credential=cred) SchemaTransformerDB._rt_cf = self._cf_dict[self._RT_CF] SchemaTransformerDB._sc_ip_cf = self._cf_dict[self._SC_IP_CF] SchemaTransformerDB._service_chain_cf = self._cf_dict[ self._SERVICE_CHAIN_CF] SchemaTransformerDB._service_chain_uuid_cf = self._cf_dict[ self._SERVICE_CHAIN_UUID_CF] # reset zookeeper config if self._args.reset_config: zkclient.delete_node( self._zk_path_pfx + self._BGP_RTGT_ALLOC_PATH, True) zkclient.delete_node( self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, True) zkclient.delete_node( self._zk_path_pfx + self._SERVICE_CHAIN_VLAN_ALLOC_PATH, True) self._rt_allocator = IndexAllocator( zkclient, self._zk_path_pfx+self._BGP_RTGT_ALLOC_PATH, self._BGP_RTGT_MAX_ID, common.BGP_RTGT_MIN_ID) def _init_bgpaas_ports_index_allocator(): bgpaas_port_start = self._args.bgpaas_port_start bgpaas_port_end = self._args.bgpaas_port_end gsc_fq_name = ['default-global-system-config'] gsc_uuid = self._object_db.fq_name_to_uuid(obj_type='global_system_config', fq_name=gsc_fq_name) _, cfg = self._object_db.object_read('global_system_config', [gsc_uuid]) cfg_bgpaas_ports = cfg[0].get('bgpaas_parameters') if cfg_bgpaas_ports: bgpaas_port_start = cfg_bgpaas_ports['port_start'] bgpaas_port_end = cfg_bgpaas_ports['port_end'] self._bgpaas_port_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, bgpaas_port_end - bgpaas_port_start, bgpaas_port_start) _init_bgpaas_ports_index_allocator() self._sc_vlan_allocator_dict = {} self._upgrade_vlan_alloc_path()
class SchemaTransformerDB(VncCassandraClient): _KEYSPACE = SCHEMA_KEYSPACE_NAME _RT_CF = 'route_target_table' _SC_IP_CF = 'service_chain_ip_address_table' _SERVICE_CHAIN_CF = 'service_chain_table' _SERVICE_CHAIN_UUID_CF = 'service_chain_uuid_table' _zk_path_prefix = '' _BGP_RTGT_MAX_ID = 1 << 24 _BGP_RTGT_ALLOC_PATH = "/id/bgp/route-targets/" _VN_MAX_ID = 1 << 24 _VN_ID_ALLOC_PATH = "/id/virtual-networks/" _SECURITY_GROUP_MAX_ID = 1 << 32 _SECURITY_GROUP_ID_ALLOC_PATH = "/id/security-groups/id/" _SERVICE_CHAIN_MAX_VLAN = 4093 _SERVICE_CHAIN_VLAN_ALLOC_PATH = "/id/service-chain/vlan/" @classmethod def get_db_info(cls): db_info = [(cls._KEYSPACE, [cls._RT_CF, cls._SC_IP_CF, cls._SERVICE_CHAIN_CF, cls._SERVICE_CHAIN_UUID_CF])] return db_info # end get_db_info def __init__(self, manager, zkclient): self._manager = manager self._args = manager._args self._zkclient = zkclient if self._args.cluster_id: self._keyspace = '%s_%s' % (self._args.cluster_id, self._KEYSPACE) self._zk_path_pfx = self._args.cluster_id + '/' else: self._keyspace = self._KEYSPACE self._zk_path_pfx = '' keyspaces = { self._keyspace: [(self._RT_CF, None), (self._SC_IP_CF, None), (self._SERVICE_CHAIN_CF, None), (self._SERVICE_CHAIN_UUID_CF, None)]} cass_server_list = self._args.cassandra_server_list if self._args.reset_config: cass_reset_config = [self._keyspace] else: cass_reset_config = [] super(SchemaTransformerDB, self).__init__( cass_server_list, self._args.cluster_id, keyspaces, manager.config_log, reset_config=cass_reset_config) SchemaTransformerDB._rt_cf = self._cf_dict[self._RT_CF] SchemaTransformerDB._sc_ip_cf = self._cf_dict[self._SC_IP_CF] SchemaTransformerDB._service_chain_cf = self._cf_dict[ self._SERVICE_CHAIN_CF] SchemaTransformerDB._service_chain_uuid_cf = self._cf_dict[ self._SERVICE_CHAIN_UUID_CF] # reset zookeeper config if self._args.reset_config: zkclient.delete_node(self._zk_path_pfx + "/id", True) self._vn_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx+self._VN_ID_ALLOC_PATH, self._VN_MAX_ID) self._sg_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx+self._SECURITY_GROUP_ID_ALLOC_PATH, self._SECURITY_GROUP_MAX_ID) # 0 is not a valid sg id any more. So, if it was previously allocated, # delete it and reserve it if self._sg_id_allocator.read(0) != '__reserved__': self._sg_id_allocator.delete(0) self._sg_id_allocator.reserve(0, '__reserved__') self._rt_allocator = IndexAllocator( zkclient, self._zk_path_pfx+self._BGP_RTGT_ALLOC_PATH, self._BGP_RTGT_MAX_ID, common.BGP_RTGT_MIN_ID) self._sc_vlan_allocator_dict = {} self._upgrade_vlan_alloc_path() # end __init__ def _upgrade_vlan_alloc_path(self): # In earlier releases, allocation path for vlans did not end with '/'. # This caused the allocated numbers to be just appended to the vm id # instead of being created as a child of it. That caused the vlan ids # to be leaked when process restarted. With that being fixed, we need # to change any vlan ids that were allocated in prior releases to the # new format. vlan_alloc_path = (self._zk_path_prefix + self._SERVICE_CHAIN_VLAN_ALLOC_PATH) for item in self._zkclient.get_children(vlan_alloc_path): try: # in the old format, item was vm id followed by 10 digit vlan # id allocated. Try to parse it to determine if it is still in # old format vm_id = uuid.UUID(item[:-10]) vlan_id = int(item[-10:]) except ValueError: continue sc_id = self._zkclient.read_node(vlan_alloc_path+item) self._zkclient.delete_node(vlan_alloc_path+item) self._zkclient.create_node( vlan_alloc_path+item[:-10]+'/'+item[-10:], sc_id) # end for item def allocate_service_chain_vlan(self, service_vm, service_chain): alloc_new = False if service_vm not in self._sc_vlan_allocator_dict: self._sc_vlan_allocator_dict[service_vm] = IndexAllocator( self._zkclient, (self._zk_path_prefix + self._SERVICE_CHAIN_VLAN_ALLOC_PATH + service_vm + '/'), self._SERVICE_CHAIN_MAX_VLAN) vlan_ia = self._sc_vlan_allocator_dict[service_vm] try: vlan = int( self._service_chain_cf.get(service_vm)[service_chain]) db_sc = vlan_ia.read(vlan) if (db_sc is None) or (db_sc != service_chain): alloc_new = True except (KeyError, NotFoundException): alloc_new = True if alloc_new: vlan = vlan_ia.alloc(service_chain) self._service_chain_cf.insert(service_vm, {service_chain: str(vlan)}) # Since vlan tag 0 is not valid, increment before returning return vlan + 1 # end allocate_service_chain_vlan def free_service_chain_vlan(self, service_vm, service_chain): try: vlan_ia = self._sc_vlan_allocator_dict[service_vm] vlan = int(self._service_chain_cf.get(service_vm)[service_chain]) self._service_chain_cf.remove(service_vm, [service_chain]) vlan_ia.delete(vlan) if vlan_ia.empty(): del self._sc_vlan_allocator_dict[service_vm] except (KeyError, NotFoundException): pass # end free_service_chain_vlan def get_route_target(self, ri_fq_name): try: return int(self._rt_cf.get(ri_fq_name)['rtgt_num']) except NotFoundException: return 0 def alloc_route_target(self, ri_fq_name, zk_only=False): alloc_new = False if zk_only: alloc_new = True else: rtgt_num = self.get_route_target(ri_fq_name) if rtgt_num < common.BGP_RTGT_MIN_ID: alloc_new = True else: rtgt_ri_fq_name_str = self._rt_allocator.read(rtgt_num) if (rtgt_ri_fq_name_str != ri_fq_name): alloc_new = True if (alloc_new): rtgt_num = self._rt_allocator.alloc(ri_fq_name) self._rt_cf.insert(ri_fq_name, {'rtgt_num': str(rtgt_num)}) return rtgt_num # end alloc_route_target def free_route_target_by_number(self, rtgt): self._rt_allocator.delete(rtgt) def free_route_target(self, ri_fq_name): try: rtgt = self.get_route_target(ri_fq_name) self._rt_cf.remove(ri_fq_name) except NotFoundException: pass self._rt_allocator.delete(rtgt) # end free_route_target def get_service_chain_ip(self, sc_name): try: addresses = self._sc_ip_cf.get(sc_name) return addresses.get('ip_address'), addresses.get('ipv6_address') except NotFoundException: return None, None def add_service_chain_ip(self, sc_name, ip, ipv6): self._sc_ip_cf.insert(sc_name, {'ip_address': ip, 'ipv6_address': ipv6}) def remove_service_chain_ip(self, sc_name): try: self._sc_ip_cf.remove(sc_name) except NotFoundException: pass def list_service_chain_uuid(self): try: return self._service_chain_uuid_cf.get_range() except NotFoundException: return [] def add_service_chain_uuid(self, name, value): self._service_chain_uuid_cf.insert(name, {'value': value}) def remove_service_chain_uuid(self, name): try: self._service_chain_uuid_cf.remove(name) except NotFoundException: pass def get_sg_from_id(self, sg_id): return self._sg_id_allocator.read(sg_id) def alloc_sg_id(self, name): return self._sg_id_allocator.alloc(name) def free_sg_id(self, sg_id): self._sg_id_allocator.delete(sg_id) def get_vn_from_id(self, vn_id): return self._vn_id_allocator.read(vn_id) def alloc_vn_id(self, name): return self._vn_id_allocator.alloc(name) def free_vn_id(self, vn_id): self._vn_id_allocator.delete(vn_id)
class SchemaTransformerDB(VncCassandraClient): _KEYSPACE = SCHEMA_KEYSPACE_NAME _RT_CF = 'route_target_table' _SC_IP_CF = 'service_chain_ip_address_table' _SERVICE_CHAIN_CF = 'service_chain_table' _SERVICE_CHAIN_UUID_CF = 'service_chain_uuid_table' _zk_path_prefix = '' _BGP_RTGT_MAX_ID = 1 << 24 _BGP_RTGT_ALLOC_PATH = "/id/bgp/route-targets/" _VN_MAX_ID = 1 << 24 _VN_ID_ALLOC_PATH = "/id/virtual-networks/" _SECURITY_GROUP_MAX_ID = 1 << 32 _SECURITY_GROUP_ID_ALLOC_PATH = "/id/security-groups/id/" _SERVICE_CHAIN_MAX_VLAN = 4093 _SERVICE_CHAIN_VLAN_ALLOC_PATH = "/id/service-chain/vlan/" @classmethod def get_db_info(cls): db_info = [(cls._KEYSPACE, [cls._RT_CF, cls._SC_IP_CF, cls._SERVICE_CHAIN_CF, cls._SERVICE_CHAIN_UUID_CF])] return db_info # end get_db_info def __init__(self, manager, zkclient): self._manager = manager self._args = manager._args self._zkclient = zkclient if self._args.cluster_id: self._keyspace = '%s_%s' % (self._args.cluster_id, self._KEYSPACE) self._zk_path_pfx = self._args.cluster_id + '/' else: self._keyspace = self._KEYSPACE self._zk_path_pfx = '' keyspaces = { self._keyspace: [(self._RT_CF, None), (self._SC_IP_CF, None), (self._SERVICE_CHAIN_CF, None), (self._SERVICE_CHAIN_UUID_CF, None)]} cass_server_list = self._args.cassandra_server_list if self._args.reset_config: cass_reset_config = [self._keyspace] else: cass_reset_config = [] super(SchemaTransformerDB, self).__init__( cass_server_list, self._args.cluster_id, keyspaces, manager.config_log, reset_config=cass_reset_config) SchemaTransformerDB._rt_cf = self._cf_dict[self._RT_CF] SchemaTransformerDB._sc_ip_cf = self._cf_dict[self._SC_IP_CF] SchemaTransformerDB._service_chain_cf = self._cf_dict[ self._SERVICE_CHAIN_CF] SchemaTransformerDB._service_chain_uuid_cf = self._cf_dict[ self._SERVICE_CHAIN_UUID_CF] # reset zookeeper config if self._args.reset_config: zkclient.delete_node(self._zk_path_pfx + "/id", True) self._vn_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx+self._VN_ID_ALLOC_PATH, self._VN_MAX_ID) self._sg_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx+self._SECURITY_GROUP_ID_ALLOC_PATH, self._SECURITY_GROUP_MAX_ID) # 0 is not a valid sg id any more. So, if it was previously allocated, # delete it and reserve it if self._sg_id_allocator.read(0) != '__reserved__': self._sg_id_allocator.delete(0) self._sg_id_allocator.reserve(0, '__reserved__') self._rt_allocator = IndexAllocator( zkclient, self._zk_path_pfx+self._BGP_RTGT_ALLOC_PATH, self._BGP_RTGT_MAX_ID, common.BGP_RTGT_MIN_ID) self._sc_vlan_allocator_dict = {} # end __init__ def allocate_service_chain_vlan(self, service_vm, service_chain): alloc_new = False if service_vm not in self._sc_vlan_allocator_dict: self._sc_vlan_allocator_dict[service_vm] = IndexAllocator( self._zkclient, (self._zk_path_prefix + self._SERVICE_CHAIN_VLAN_ALLOC_PATH + service_vm), self._SERVICE_CHAIN_MAX_VLAN) vlan_ia = self._sc_vlan_allocator_dict[service_vm] try: vlan = int( self._service_chain_cf.get(service_vm)[service_chain]) db_sc = vlan_ia.read(vlan) if (db_sc is None) or (db_sc != service_chain): alloc_new = True except (KeyError, NotFoundException): alloc_new = True if alloc_new: vlan = vlan_ia.alloc(service_chain) self._service_chain_cf.insert(service_vm, {service_chain: str(vlan)}) # Since vlan tag 0 is not valid, increment before returning return vlan + 1 # end allocate_service_chain_vlan def free_service_chain_vlan(self, service_vm, service_chain): try: vlan_ia = self._sc_vlan_allocator_dict[service_vm] vlan = int(self._service_chain_cf.get(service_vm)[service_chain]) self._service_chain_cf.remove(service_vm, [service_chain]) vlan_ia.delete(vlan) if vlan_ia.empty(): del self._sc_vlan_allocator_dict[service_vm] except (KeyError, NotFoundException): pass # end free_service_chain_vlan def get_route_target(self, ri_fq_name): try: return int(self._rt_cf.get(ri_fq_name)['rtgt_num']) except NotFoundException: return 0 def alloc_route_target(self, ri_fq_name, zk_only=False): alloc_new = False if zk_only: alloc_new = True else: rtgt_num = self.get_route_target(ri_fq_name) if rtgt_num < common.BGP_RTGT_MIN_ID: alloc_new = True else: rtgt_ri_fq_name_str = self._rt_allocator.read(rtgt_num) if (rtgt_ri_fq_name_str != ri_fq_name): alloc_new = True if (alloc_new): rtgt_num = self._rt_allocator.alloc(ri_fq_name) self._rt_cf.insert(ri_fq_name, {'rtgt_num': str(rtgt_num)}) return rtgt_num # end alloc_route_target def free_route_target_by_number(self, rtgt): self._rt_allocator.delete(rtgt) def free_route_target(self, ri_fq_name): try: rtgt = self.get_route_target(ri_fq_name) self._rt_cf.remove(ri_fq_name) except NotFoundException: pass self._rt_allocator.delete(rtgt) # end free_route_target def get_service_chain_ip(self, sc_name): try: return self._sc_ip_cf.get(sc_name)['ip_address'] except NotFoundException: return None def add_service_chain_ip(self, sc_name, ip): self._sc_ip_cf.insert(sc_name, {'ip_address': ip}) def remove_service_chain_ip(self, sc_name): try: self._sc_ip_cf.remove(sc_name) except NotFoundException: pass def list_service_chain_uuid(self): try: return self._service_chain_uuid_cf.get_range() except NotFoundException: return [] def add_service_chain_uuid(self, name, value): self._service_chain_uuid_cf.insert(name, {'value': value}) def remove_service_chain_uuid(self, name): try: self._service_chain_uuid_cf.remove(name) except NotFoundException: pass def get_sg_from_id(self, sg_id): return self._sg_id_allocator.read(sg_id) def alloc_sg_id(self, name): return self._sg_id_allocator.alloc(name) def free_sg_id(self, sg_id): self._sg_id_allocator.delete(sg_id) def get_vn_from_id(self, vn_id): return self._vn_id_allocator.read(vn_id) def alloc_vn_id(self, name): return self._vn_id_allocator.alloc(name) def free_vn_id(self, vn_id): self._vn_id_allocator.delete(vn_id)
class SchemaTransformerDB(VncCassandraClient): _KEYSPACE = SCHEMA_KEYSPACE_NAME _RT_CF = "route_target_table" _SC_IP_CF = "service_chain_ip_address_table" _SERVICE_CHAIN_CF = "service_chain_table" _SERVICE_CHAIN_UUID_CF = "service_chain_uuid_table" _zk_path_prefix = "" _BGP_RTGT_MAX_ID = 1 << 24 _BGP_RTGT_ALLOC_PATH = "/id/bgp/route-targets/" _VN_MAX_ID = 1 << 24 _VN_ID_ALLOC_PATH = "/id/virtual-networks/" _SECURITY_GROUP_MAX_ID = 1 << 32 _SECURITY_GROUP_ID_ALLOC_PATH = "/id/security-groups/id/" _SERVICE_CHAIN_MAX_VLAN = 4093 _SERVICE_CHAIN_VLAN_ALLOC_PATH = "/id/service-chain/vlan/" _BGPAAS_PORT_ALLOC_PATH = "/id/bgpaas/port/" @classmethod def get_db_info(cls): db_info = [(cls._KEYSPACE, [cls._RT_CF, cls._SC_IP_CF, cls._SERVICE_CHAIN_CF, cls._SERVICE_CHAIN_UUID_CF])] return db_info # end get_db_info def __init__(self, manager, zkclient): self._manager = manager self._args = manager._args self._zkclient = zkclient if self._args.cluster_id: self._zk_path_pfx = self._args.cluster_id + "/" else: self._zk_path_pfx = "" keyspaces = { self._KEYSPACE: { self._RT_CF: {}, self._SC_IP_CF: {}, self._SERVICE_CHAIN_CF: {}, self._SERVICE_CHAIN_UUID_CF: {}, } } cass_server_list = self._args.cassandra_server_list cred = None if self._args.cassandra_user is not None and self._args.cassandra_password is not None: cred = {"username": self._args.cassandra_user, "password": self._args.cassandra_password} super(SchemaTransformerDB, self).__init__( cass_server_list, self._args.cluster_id, keyspaces, None, manager.logger.log, reset_config=self._args.reset_config, credential=cred, ) SchemaTransformerDB._rt_cf = self._cf_dict[self._RT_CF] SchemaTransformerDB._sc_ip_cf = self._cf_dict[self._SC_IP_CF] SchemaTransformerDB._service_chain_cf = self._cf_dict[self._SERVICE_CHAIN_CF] SchemaTransformerDB._service_chain_uuid_cf = self._cf_dict[self._SERVICE_CHAIN_UUID_CF] # reset zookeeper config if self._args.reset_config: zkclient.delete_node(self._zk_path_pfx + self._BGP_RTGT_ALLOC_PATH, True) zkclient.delete_node(self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, True) zkclient.delete_node(self._zk_path_pfx + self._SERVICE_CHAIN_VLAN_ALLOC_PATH, True) # TODO(ethuleau): We keep the virtual network and security group ID # allocation in schema and in the vnc API for one # release overlap to prevent any upgrade issue. So the # following code need to be remove in release (3.2 + 1) self._vn_id_allocator = IndexAllocator(zkclient, self._zk_path_pfx + self._VN_ID_ALLOC_PATH, self._VN_MAX_ID) self._sg_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._SECURITY_GROUP_ID_ALLOC_PATH, self._SECURITY_GROUP_MAX_ID ) # 0 is not a valid sg id any more. So, if it was previously allocated, # delete it and reserve it if self._sg_id_allocator.read(0) != "__reserved__": self._sg_id_allocator.delete(0) self._sg_id_allocator.reserve(0, "__reserved__") self._rt_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGP_RTGT_ALLOC_PATH, self._BGP_RTGT_MAX_ID, common.BGP_RTGT_MIN_ID ) self._bgpaas_port_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, self._args.bgpaas_port_end - self._args.bgpaas_port_start, self._args.bgpaas_port_start, ) self._sc_vlan_allocator_dict = {} self._upgrade_vlan_alloc_path() # end __init__ def _upgrade_vlan_alloc_path(self): # In earlier releases, allocation path for vlans did not end with '/'. # This caused the allocated numbers to be just appended to the vm id # instead of being created as a child of it. That caused the vlan ids # to be leaked when process restarted. With that being fixed, we need # to change any vlan ids that were allocated in prior releases to the # new format. vlan_alloc_path = self._zk_path_prefix + self._SERVICE_CHAIN_VLAN_ALLOC_PATH for item in self._zkclient.get_children(vlan_alloc_path): try: # in the old format, item was vm id followed by 10 digit vlan # id allocated. Try to parse it to determine if it is still in # old format vm_id = uuid.UUID(item[:-10]) vlan_id = int(item[-10:]) except ValueError: continue sc_id = self._zkclient.read_node(vlan_alloc_path + item) self._zkclient.delete_node(vlan_alloc_path + item) self._zkclient.create_node(vlan_alloc_path + item[:-10] + "/" + item[-10:], sc_id) # end for item def allocate_service_chain_vlan(self, service_vm, service_chain): alloc_new = False if service_vm not in self._sc_vlan_allocator_dict: self._sc_vlan_allocator_dict[service_vm] = IndexAllocator( self._zkclient, (self._zk_path_prefix + self._SERVICE_CHAIN_VLAN_ALLOC_PATH + service_vm + "/"), self._SERVICE_CHAIN_MAX_VLAN, ) vlan_ia = self._sc_vlan_allocator_dict[service_vm] try: vlan = int(self.get_one_col(self._SERVICE_CHAIN_CF, service_vm, service_chain)) db_sc = vlan_ia.read(vlan) if (db_sc is None) or (db_sc != service_chain): alloc_new = True except (KeyError, VncError, NoIdError): # TODO(ethuleau): VncError is raised if more than one row was # fetched from db with get_one_col method. # Probably need to be cleaned alloc_new = True if alloc_new: vlan = vlan_ia.alloc(service_chain) self._service_chain_cf.insert(service_vm, {service_chain: str(vlan)}) # Since vlan tag 0 is not valid, increment before returning return vlan + 1 # end allocate_service_chain_vlan def free_service_chain_vlan(self, service_vm, service_chain): try: vlan_ia = self._sc_vlan_allocator_dict[service_vm] vlan = int(self.get_one_col(self._SERVICE_CHAIN_CF, service_vm, service_chain)) self._service_chain_cf.remove(service_vm, [service_chain]) vlan_ia.delete(vlan) if vlan_ia.empty(): del self._sc_vlan_allocator_dict[service_vm] except (KeyError, VncError, NoIdError): # TODO(ethuleau): VncError is raised if more than one row was # fetched from db with get_one_col method. # Probably need to be cleaned pass # end free_service_chain_vlan def get_route_target(self, ri_fq_name): try: return int(self.get_one_col(self._RT_CF, ri_fq_name, "rtgt_num")) except (VncError, NoIdError): # TODO(ethuleau): VncError is raised if more than one row was # fetched from db with get_one_col method. # Probably need to be cleaned return 0 def alloc_route_target(self, ri_fq_name, zk_only=False): alloc_new = False if zk_only: alloc_new = True else: rtgt_num = self.get_route_target(ri_fq_name) if rtgt_num < common.BGP_RTGT_MIN_ID: alloc_new = True else: rtgt_ri_fq_name_str = self._rt_allocator.read(rtgt_num) if rtgt_ri_fq_name_str != ri_fq_name: alloc_new = True if alloc_new: rtgt_num = self._rt_allocator.alloc(ri_fq_name) self._rt_cf.insert(ri_fq_name, {"rtgt_num": str(rtgt_num)}) return rtgt_num # end alloc_route_target def free_route_target_by_number(self, rtgt): self._rt_allocator.delete(rtgt) def free_route_target(self, ri_fq_name): try: rtgt = self.get_route_target(ri_fq_name) self._rt_cf.remove(ri_fq_name) except NotFoundException: pass self._rt_allocator.delete(rtgt) # end free_route_target def get_service_chain_ip(self, sc_name): addresses = self.get(self._SC_IP_CF, sc_name) if addresses: return addresses.get("ip_address"), addresses.get("ipv6_address") else: return None, None def add_service_chain_ip(self, sc_name, ip, ipv6): val = {} if ip: val["ip_address"] = ip if ipv6: val["ipv6_address"] = ipv6 self._sc_ip_cf.insert(sc_name, val) def remove_service_chain_ip(self, sc_name): try: self._sc_ip_cf.remove(sc_name) except NotFoundException: pass def list_service_chain_uuid(self): try: return self._service_chain_uuid_cf.get_range() except NotFoundException: return [] def add_service_chain_uuid(self, name, value): self._service_chain_uuid_cf.insert(name, {"value": value}) def remove_service_chain_uuid(self, name): try: self._service_chain_uuid_cf.remove(name) except NotFoundException: pass # TODO(ethuleau): We keep the virtual network and security group ID # allocation in schema and in the vnc API for one # release overlap to prevent any upgrade issue. So the # following code need to be remove in release (3.2 + 1) def get_sg_from_id(self, sg_id): return self._sg_id_allocator.read(sg_id) def alloc_sg_id(self, name): return self._sg_id_allocator.alloc(name) def free_sg_id(self, sg_id): self._sg_id_allocator.delete(sg_id) def get_vn_from_id(self, vn_id): return self._vn_id_allocator.read(vn_id) def alloc_vn_id(self, name): return self._vn_id_allocator.alloc(name) def free_vn_id(self, vn_id): self._vn_id_allocator.delete(vn_id) def get_bgpaas_port(self, port): return self._bgpaas_allocator.read(port) def alloc_bgpaas_port(self, name): return self._bgpaas_port_allocator.alloc(name) def free_bgpaas_port(self, port): self._bgpaas_port_allocator.delete(port)
def __init__(self, manager, zkclient): self._manager = manager self._args = manager._args self._zkclient = zkclient if self._args.cluster_id: self._zk_path_pfx = self._args.cluster_id + '/' else: self._zk_path_pfx = '' keyspaces = { self._KEYSPACE: { self._RT_CF: {}, self._SC_IP_CF: {}, self._SERVICE_CHAIN_CF: {}, self._SERVICE_CHAIN_UUID_CF: {} } } cass_server_list = self._args.cassandra_server_list cred = None if (self._args.cassandra_user is not None and self._args.cassandra_password is not None): cred = { 'username': self._args.cassandra_user, 'password': self._args.cassandra_password } super(SchemaTransformerDB, self).__init__(cass_server_list, self._args.cluster_id, keyspaces, None, manager.logger.log, reset_config=self._args.reset_config, credential=cred) SchemaTransformerDB._rt_cf = self._cf_dict[self._RT_CF] SchemaTransformerDB._sc_ip_cf = self._cf_dict[self._SC_IP_CF] SchemaTransformerDB._service_chain_cf = self._cf_dict[ self._SERVICE_CHAIN_CF] SchemaTransformerDB._service_chain_uuid_cf = self._cf_dict[ self._SERVICE_CHAIN_UUID_CF] # reset zookeeper config if self._args.reset_config: zkclient.delete_node(self._zk_path_pfx + self._BGP_RTGT_ALLOC_PATH, True) zkclient.delete_node( self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, True) zkclient.delete_node( self._zk_path_pfx + self._SERVICE_CHAIN_VLAN_ALLOC_PATH, True) # TODO(ethuleau): We keep the virtual network and security group ID # allocation in schema and in the vnc API for one # release overlap to prevent any upgrade issue. So the # following code need to be remove in release (3.2 + 1) self._vn_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._VN_ID_ALLOC_PATH, self._VN_MAX_ID) self._sg_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._SECURITY_GROUP_ID_ALLOC_PATH, self._SECURITY_GROUP_MAX_ID) # 0 is not a valid sg id any more. So, if it was previously allocated, # delete it and reserve it if self._sg_id_allocator.read(0) != '__reserved__': self._sg_id_allocator.delete(0) self._sg_id_allocator.reserve(0, '__reserved__') self._rt_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGP_RTGT_ALLOC_PATH, self._BGP_RTGT_MAX_ID, common.BGP_RTGT_MIN_ID) def _init_bgpaas_ports_index_allocator(): bgpaas_port_start = self._args.bgpaas_port_start bgpaas_port_end = self._args.bgpaas_port_end gsc_fq_name = ['default-global-system-config'] gsc_uuid = self._object_db.fq_name_to_uuid( obj_type='global_system_config', fq_name=gsc_fq_name) _, cfg = self._object_db.object_read('global_system_config', [gsc_uuid]) cfg_bgpaas_ports = cfg[0].get('bgpaas_parameters') if cfg_bgpaas_ports: bgpaas_port_start = cfg_bgpaas_ports['port_start'] bgpaas_port_end = cfg_bgpaas_ports['port_end'] self._bgpaas_port_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, bgpaas_port_end - bgpaas_port_start, bgpaas_port_start) _init_bgpaas_ports_index_allocator() self._sc_vlan_allocator_dict = {} self._upgrade_vlan_alloc_path()
def __init__(self, manager, zkclient): self._manager = manager self._args = manager._args self._zkclient = zkclient if self._args.cluster_id: self._zk_path_pfx = self._args.cluster_id + '/' else: self._zk_path_pfx = '' keyspaces = { self._KEYSPACE: {self._RT_CF: {}, self._SC_IP_CF: {}, self._SERVICE_CHAIN_CF: {}, self._SERVICE_CHAIN_UUID_CF: {}}} cass_server_list = self._args.cassandra_server_list cred = None if (self._args.cassandra_user is not None and self._args.cassandra_password is not None): cred={'username':self._args.cassandra_user, 'password':self._args.cassandra_password} super(SchemaTransformerDB, self).__init__( cass_server_list, self._args.cluster_id, keyspaces, None, manager.logger.log, reset_config=self._args.reset_config, credential=cred) SchemaTransformerDB._rt_cf = self._cf_dict[self._RT_CF] SchemaTransformerDB._sc_ip_cf = self._cf_dict[self._SC_IP_CF] SchemaTransformerDB._service_chain_cf = self._cf_dict[ self._SERVICE_CHAIN_CF] SchemaTransformerDB._service_chain_uuid_cf = self._cf_dict[ self._SERVICE_CHAIN_UUID_CF] # reset zookeeper config if self._args.reset_config: zkclient.delete_node( self._zk_path_pfx + self._BGP_RTGT_ALLOC_PATH, True) zkclient.delete_node( self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, True) zkclient.delete_node( self._zk_path_pfx + self._SERVICE_CHAIN_VLAN_ALLOC_PATH, True) # TODO(ethuleau): We keep the virtual network and security group ID # allocation in schema and in the vnc API for one # release overlap to prevent any upgrade issue. So the # following code need to be remove in release (3.2 + 1) self._vn_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx+self._VN_ID_ALLOC_PATH, self._VN_MAX_ID) self._sg_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx+self._SECURITY_GROUP_ID_ALLOC_PATH, self._SECURITY_GROUP_MAX_ID) # 0 is not a valid sg id any more. So, if it was previously allocated, # delete it and reserve it if self._sg_id_allocator.read(0) != '__reserved__': self._sg_id_allocator.delete(0) self._sg_id_allocator.reserve(0, '__reserved__') self._rt_allocator = IndexAllocator( zkclient, self._zk_path_pfx+self._BGP_RTGT_ALLOC_PATH, self._BGP_RTGT_MAX_ID, common.BGP_RTGT_MIN_ID) def _init_bgpaas_ports_index_allocator(): bgpaas_port_start = self._args.bgpaas_port_start bgpaas_port_end = self._args.bgpaas_port_end gsc_fq_name = ['default-global-system-config'] gsc_uuid = self._object_db.fq_name_to_uuid(obj_type='global_system_config', fq_name=gsc_fq_name) _, cfg = self._object_db.object_read('global_system_config', [gsc_uuid]) cfg_bgpaas_ports = cfg[0].get('bgpaas_parameters') if cfg_bgpaas_ports: bgpaas_port_start = cfg_bgpaas_ports['port_start'] bgpaas_port_end = cfg_bgpaas_ports['port_end'] self._bgpaas_port_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, bgpaas_port_end - bgpaas_port_start, bgpaas_port_start) _init_bgpaas_ports_index_allocator() self._sc_vlan_allocator_dict = {} self._upgrade_vlan_alloc_path()
class SchemaTransformerDB(VncObjectDBClient): _KEYSPACE = SCHEMA_KEYSPACE_NAME _RT_CF = 'route_target_table' _SC_IP_CF = 'service_chain_ip_address_table' _SERVICE_CHAIN_CF = 'service_chain_table' _SERVICE_CHAIN_UUID_CF = 'service_chain_uuid_table' _zk_path_prefix = '' _BGP_RTGT_MAX_ID = 1 << 24 _BGP_RTGT_ALLOC_PATH = "/id/bgp/route-targets/" _VN_MAX_ID = 1 << 24 _VN_ID_ALLOC_PATH = "/id/virtual-networks/" _SECURITY_GROUP_MAX_ID = 1 << 32 _SECURITY_GROUP_ID_ALLOC_PATH = "/id/security-groups/id/" _SERVICE_CHAIN_MAX_VLAN = 4093 _SERVICE_CHAIN_VLAN_ALLOC_PATH = "/id/service-chain/vlan/" _BGPAAS_PORT_ALLOC_PATH = "/id/bgpaas/port/" @classmethod def get_db_info(cls): db_info = [(cls._KEYSPACE, [ cls._RT_CF, cls._SC_IP_CF, cls._SERVICE_CHAIN_CF, cls._SERVICE_CHAIN_UUID_CF ])] return db_info # end get_db_info def __init__(self, manager, zkclient): self._manager = manager self._args = manager._args self._zkclient = zkclient if self._args.cluster_id: self._zk_path_pfx = self._args.cluster_id + '/' else: self._zk_path_pfx = '' keyspaces = { self._KEYSPACE: { self._RT_CF: {}, self._SC_IP_CF: {}, self._SERVICE_CHAIN_CF: {}, self._SERVICE_CHAIN_UUID_CF: {} } } cass_server_list = self._args.cassandra_server_list cred = None if (self._args.cassandra_user is not None and self._args.cassandra_password is not None): cred = { 'username': self._args.cassandra_user, 'password': self._args.cassandra_password } super(SchemaTransformerDB, self).__init__(cass_server_list, self._args.cluster_id, keyspaces, None, manager.logger.log, reset_config=self._args.reset_config, credential=cred) SchemaTransformerDB._rt_cf = self._cf_dict[self._RT_CF] SchemaTransformerDB._sc_ip_cf = self._cf_dict[self._SC_IP_CF] SchemaTransformerDB._service_chain_cf = self._cf_dict[ self._SERVICE_CHAIN_CF] SchemaTransformerDB._service_chain_uuid_cf = self._cf_dict[ self._SERVICE_CHAIN_UUID_CF] # reset zookeeper config if self._args.reset_config: zkclient.delete_node(self._zk_path_pfx + self._BGP_RTGT_ALLOC_PATH, True) zkclient.delete_node( self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, True) zkclient.delete_node( self._zk_path_pfx + self._SERVICE_CHAIN_VLAN_ALLOC_PATH, True) # TODO(ethuleau): We keep the virtual network and security group ID # allocation in schema and in the vnc API for one # release overlap to prevent any upgrade issue. So the # following code need to be remove in release (3.2 + 1) self._vn_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._VN_ID_ALLOC_PATH, self._VN_MAX_ID) self._sg_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._SECURITY_GROUP_ID_ALLOC_PATH, self._SECURITY_GROUP_MAX_ID) # 0 is not a valid sg id any more. So, if it was previously allocated, # delete it and reserve it if self._sg_id_allocator.read(0) != '__reserved__': self._sg_id_allocator.delete(0) self._sg_id_allocator.reserve(0, '__reserved__') self._rt_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGP_RTGT_ALLOC_PATH, self._BGP_RTGT_MAX_ID, common.BGP_RTGT_MIN_ID) def _init_bgpaas_ports_index_allocator(): bgpaas_port_start = self._args.bgpaas_port_start bgpaas_port_end = self._args.bgpaas_port_end gsc_fq_name = ['default-global-system-config'] gsc_uuid = self._object_db.fq_name_to_uuid( obj_type='global_system_config', fq_name=gsc_fq_name) _, cfg = self._object_db.object_read('global_system_config', [gsc_uuid]) cfg_bgpaas_ports = cfg[0].get('bgpaas_parameters') if cfg_bgpaas_ports: bgpaas_port_start = cfg_bgpaas_ports['port_start'] bgpaas_port_end = cfg_bgpaas_ports['port_end'] self._bgpaas_port_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, bgpaas_port_end - bgpaas_port_start, bgpaas_port_start) _init_bgpaas_ports_index_allocator() self._sc_vlan_allocator_dict = {} self._upgrade_vlan_alloc_path() # end __init__ def _upgrade_vlan_alloc_path(self): # In earlier releases, allocation path for vlans did not end with '/'. # This caused the allocated numbers to be just appended to the vm id # instead of being created as a child of it. That caused the vlan ids # to be leaked when process restarted. With that being fixed, we need # to change any vlan ids that were allocated in prior releases to the # new format. vlan_alloc_path = (self._zk_path_prefix + self._SERVICE_CHAIN_VLAN_ALLOC_PATH) for item in self._zkclient.get_children(vlan_alloc_path): try: # in the old format, item was vm id followed by 10 digit vlan # id allocated. Try to parse it to determine if it is still in # old format vm_id = uuid.UUID(item[:-10]) vlan_id = int(item[-10:]) except ValueError: continue sc_id = self._zkclient.read_node(vlan_alloc_path + item) self._zkclient.delete_node(vlan_alloc_path + item) self._zkclient.create_node( vlan_alloc_path + item[:-10] + '/' + item[-10:], sc_id) # end for item def allocate_service_chain_vlan(self, service_vm, service_chain): alloc_new = False if service_vm not in self._sc_vlan_allocator_dict: self._sc_vlan_allocator_dict[service_vm] = IndexAllocator( self._zkclient, (self._zk_path_prefix + self._SERVICE_CHAIN_VLAN_ALLOC_PATH + service_vm + '/'), self._SERVICE_CHAIN_MAX_VLAN) vlan_ia = self._sc_vlan_allocator_dict[service_vm] try: vlan = int( self.get_one_col(self._SERVICE_CHAIN_CF, service_vm, service_chain)) db_sc = vlan_ia.read(vlan) if (db_sc is None) or (db_sc != service_chain): alloc_new = True except (KeyError, VncError, NoIdError): # TODO(ethuleau): VncError is raised if more than one row was # fetched from db with get_one_col method. # Probably need to be cleaned alloc_new = True if alloc_new: vlan = vlan_ia.alloc(service_chain) self._service_chain_cf.insert(service_vm, {service_chain: str(vlan)}) # Since vlan tag 0 is not valid, increment before returning return vlan + 1 # end allocate_service_chain_vlan def free_service_chain_vlan(self, service_vm, service_chain): try: vlan_ia = self._sc_vlan_allocator_dict[service_vm] vlan = int( self.get_one_col(self._SERVICE_CHAIN_CF, service_vm, service_chain)) self._service_chain_cf.remove(service_vm, [service_chain]) vlan_ia.delete(vlan) if vlan_ia.empty(): del self._sc_vlan_allocator_dict[service_vm] except (KeyError, VncError, NoIdError): # TODO(ethuleau): VncError is raised if more than one row was # fetched from db with get_one_col method. # Probably need to be cleaned pass # end free_service_chain_vlan def get_route_target(self, ri_fq_name): try: return int(self.get_one_col(self._RT_CF, ri_fq_name, 'rtgt_num')) except (VncError, NoIdError): # TODO(ethuleau): VncError is raised if more than one row was # fetched from db with get_one_col method. # Probably need to be cleaned return 0 def alloc_route_target(self, ri_fq_name, zk_only=False): alloc_new = False if zk_only: alloc_new = True else: rtgt_num = self.get_route_target(ri_fq_name) if rtgt_num < common.BGP_RTGT_MIN_ID: alloc_new = True else: rtgt_ri_fq_name_str = self._rt_allocator.read(rtgt_num) if (rtgt_ri_fq_name_str != ri_fq_name): alloc_new = True if (alloc_new): rtgt_num = self._rt_allocator.alloc(ri_fq_name) self._rt_cf.insert(ri_fq_name, {'rtgt_num': str(rtgt_num)}) return rtgt_num # end alloc_route_target def free_route_target_by_number(self, rtgt): self._rt_allocator.delete(rtgt) def free_route_target(self, ri_fq_name): try: rtgt = self.get_route_target(ri_fq_name) self._rt_cf.remove(ri_fq_name) except NotFoundException: pass self._rt_allocator.delete(rtgt) # end free_route_target def get_service_chain_ip(self, sc_name): addresses = self.get(self._SC_IP_CF, sc_name) if addresses: return addresses.get('ip_address'), addresses.get('ipv6_address') else: return None, None def add_service_chain_ip(self, sc_name, ip, ipv6): val = {} if ip: val['ip_address'] = ip if ipv6: val['ipv6_address'] = ipv6 self._sc_ip_cf.insert(sc_name, val) def remove_service_chain_ip(self, sc_name): try: self._sc_ip_cf.remove(sc_name) except NotFoundException: pass def list_service_chain_uuid(self): try: return self._service_chain_uuid_cf.get_range() except NotFoundException: return [] def add_service_chain_uuid(self, name, value): self._service_chain_uuid_cf.insert(name, {'value': value}) def remove_service_chain_uuid(self, name): try: self._service_chain_uuid_cf.remove(name) except NotFoundException: pass # TODO(ethuleau): We keep the virtual network and security group ID # allocation in schema and in the vnc API for one # release overlap to prevent any upgrade issue. So the # following code need to be remove in release (3.2 + 1) def get_sg_from_id(self, sg_id): return self._sg_id_allocator.read(sg_id) def alloc_sg_id(self, name): return self._sg_id_allocator.alloc(name) def free_sg_id(self, sg_id): self._sg_id_allocator.delete(sg_id) def get_vn_from_id(self, vn_id): return self._vn_id_allocator.read(vn_id) def alloc_vn_id(self, name): return self._vn_id_allocator.alloc(name) def free_vn_id(self, vn_id): self._vn_id_allocator.delete(vn_id) def get_bgpaas_port(self, port): return self._bgpaas_allocator.read(port) def alloc_bgpaas_port(self, name): return self._bgpaas_port_allocator.alloc(name) def free_bgpaas_port(self, port): self._bgpaas_port_allocator.delete(port)
class SchemaTransformerDB(VncCassandraClient): _KEYSPACE = SCHEMA_KEYSPACE_NAME _RT_CF = 'route_target_table' _SC_IP_CF = 'service_chain_ip_address_table' _SERVICE_CHAIN_CF = 'service_chain_table' _SERVICE_CHAIN_UUID_CF = 'service_chain_uuid_table' _zk_path_prefix = '' _BGP_RTGT_MAX_ID = 1 << 24 _BGP_RTGT_ALLOC_PATH = "/id/bgp/route-targets/" _VN_MAX_ID = 1 << 24 _VN_ID_ALLOC_PATH = "/id/virtual-networks/" _SECURITY_GROUP_MAX_ID = 1 << 32 _SECURITY_GROUP_ID_ALLOC_PATH = "/id/security-groups/id/" _SERVICE_CHAIN_MAX_VLAN = 4093 _SERVICE_CHAIN_VLAN_ALLOC_PATH = "/id/service-chain/vlan/" _BGPAAS_PORT_ALLOC_PATH = "/id/bgpaas/port/" @classmethod def get_db_info(cls): db_info = [(cls._KEYSPACE, [ cls._RT_CF, cls._SC_IP_CF, cls._SERVICE_CHAIN_CF, cls._SERVICE_CHAIN_UUID_CF ])] return db_info # end get_db_info def __init__(self, manager, zkclient): self._manager = manager self._args = manager._args self._zkclient = zkclient if self._args.cluster_id: self._zk_path_pfx = self._args.cluster_id + '/' else: self._zk_path_pfx = '' keyspaces = { self._KEYSPACE: [(self._RT_CF, None), (self._SC_IP_CF, None), (self._SERVICE_CHAIN_CF, None), (self._SERVICE_CHAIN_UUID_CF, None)] } cass_server_list = self._args.cassandra_server_list super(SchemaTransformerDB, self).__init__(cass_server_list, self._args.cluster_id, keyspaces, None, manager.config_log, reset_config=self._args.reset_config) SchemaTransformerDB._rt_cf = self._cf_dict[self._RT_CF] SchemaTransformerDB._sc_ip_cf = self._cf_dict[self._SC_IP_CF] SchemaTransformerDB._service_chain_cf = self._cf_dict[ self._SERVICE_CHAIN_CF] SchemaTransformerDB._service_chain_uuid_cf = self._cf_dict[ self._SERVICE_CHAIN_UUID_CF] # reset zookeeper config if self._args.reset_config: zkclient.delete_node(self._zk_path_pfx + "/id", True) self._vn_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._VN_ID_ALLOC_PATH, self._VN_MAX_ID) self._sg_id_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._SECURITY_GROUP_ID_ALLOC_PATH, self._SECURITY_GROUP_MAX_ID) # 0 is not a valid sg id any more. So, if it was previously allocated, # delete it and reserve it if self._sg_id_allocator.read(0) != '__reserved__': self._sg_id_allocator.delete(0) self._sg_id_allocator.reserve(0, '__reserved__') self._rt_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGP_RTGT_ALLOC_PATH, self._BGP_RTGT_MAX_ID, common.BGP_RTGT_MIN_ID) self._bgpaas_port_allocator = IndexAllocator( zkclient, self._zk_path_pfx + self._BGPAAS_PORT_ALLOC_PATH, self._args.bgpaas_port_end - self._args.bgpaas_port_start, self._args.bgpaas_port_start) self._sc_vlan_allocator_dict = {} self._upgrade_vlan_alloc_path() # end __init__ def _upgrade_vlan_alloc_path(self): # In earlier releases, allocation path for vlans did not end with '/'. # This caused the allocated numbers to be just appended to the vm id # instead of being created as a child of it. That caused the vlan ids # to be leaked when process restarted. With that being fixed, we need # to change any vlan ids that were allocated in prior releases to the # new format. vlan_alloc_path = (self._zk_path_prefix + self._SERVICE_CHAIN_VLAN_ALLOC_PATH) for item in self._zkclient.get_children(vlan_alloc_path): try: # in the old format, item was vm id followed by 10 digit vlan # id allocated. Try to parse it to determine if it is still in # old format vm_id = uuid.UUID(item[:-10]) vlan_id = int(item[-10:]) except ValueError: continue sc_id = self._zkclient.read_node(vlan_alloc_path + item) self._zkclient.delete_node(vlan_alloc_path + item) self._zkclient.create_node( vlan_alloc_path + item[:-10] + '/' + item[-10:], sc_id) # end for item def allocate_service_chain_vlan(self, service_vm, service_chain): alloc_new = False if service_vm not in self._sc_vlan_allocator_dict: self._sc_vlan_allocator_dict[service_vm] = IndexAllocator( self._zkclient, (self._zk_path_prefix + self._SERVICE_CHAIN_VLAN_ALLOC_PATH + service_vm + '/'), self._SERVICE_CHAIN_MAX_VLAN) vlan_ia = self._sc_vlan_allocator_dict[service_vm] try: vlan = int(self._service_chain_cf.get(service_vm)[service_chain]) db_sc = vlan_ia.read(vlan) if (db_sc is None) or (db_sc != service_chain): alloc_new = True except (KeyError, NotFoundException): alloc_new = True if alloc_new: vlan = vlan_ia.alloc(service_chain) self._service_chain_cf.insert(service_vm, {service_chain: str(vlan)}) # Since vlan tag 0 is not valid, increment before returning return vlan + 1 # end allocate_service_chain_vlan def free_service_chain_vlan(self, service_vm, service_chain): try: vlan_ia = self._sc_vlan_allocator_dict[service_vm] vlan = int(self._service_chain_cf.get(service_vm)[service_chain]) self._service_chain_cf.remove(service_vm, [service_chain]) vlan_ia.delete(vlan) if vlan_ia.empty(): del self._sc_vlan_allocator_dict[service_vm] except (KeyError, NotFoundException): pass # end free_service_chain_vlan def get_route_target(self, ri_fq_name): try: return int(self._rt_cf.get(ri_fq_name)['rtgt_num']) except NotFoundException: return 0 def alloc_route_target(self, ri_fq_name, zk_only=False): alloc_new = False if zk_only: alloc_new = True else: rtgt_num = self.get_route_target(ri_fq_name) if rtgt_num < common.BGP_RTGT_MIN_ID: alloc_new = True else: rtgt_ri_fq_name_str = self._rt_allocator.read(rtgt_num) if (rtgt_ri_fq_name_str != ri_fq_name): alloc_new = True if (alloc_new): rtgt_num = self._rt_allocator.alloc(ri_fq_name) self._rt_cf.insert(ri_fq_name, {'rtgt_num': str(rtgt_num)}) return rtgt_num # end alloc_route_target def free_route_target_by_number(self, rtgt): self._rt_allocator.delete(rtgt) def free_route_target(self, ri_fq_name): try: rtgt = self.get_route_target(ri_fq_name) self._rt_cf.remove(ri_fq_name) except NotFoundException: pass self._rt_allocator.delete(rtgt) # end free_route_target def get_service_chain_ip(self, sc_name): try: addresses = self._sc_ip_cf.get(sc_name) return addresses.get('ip_address'), addresses.get('ipv6_address') except NotFoundException: return None, None def add_service_chain_ip(self, sc_name, ip, ipv6): val = {} if ip: val['ip_address'] = ip if ipv6: val['ipv6_address'] = ipv6 self._sc_ip_cf.insert(sc_name, val) def remove_service_chain_ip(self, sc_name): try: self._sc_ip_cf.remove(sc_name) except NotFoundException: pass def list_service_chain_uuid(self): try: return self._service_chain_uuid_cf.get_range() except NotFoundException: return [] def add_service_chain_uuid(self, name, value): self._service_chain_uuid_cf.insert(name, {'value': value}) def remove_service_chain_uuid(self, name): try: self._service_chain_uuid_cf.remove(name) except NotFoundException: pass def get_sg_from_id(self, sg_id): return self._sg_id_allocator.read(sg_id) def alloc_sg_id(self, name): return self._sg_id_allocator.alloc(name) def free_sg_id(self, sg_id): self._sg_id_allocator.delete(sg_id) def get_vn_from_id(self, vn_id): return self._vn_id_allocator.read(vn_id) def alloc_vn_id(self, name): return self._vn_id_allocator.alloc(name) def free_vn_id(self, vn_id): self._vn_id_allocator.delete(vn_id) def get_bgpaas_port(self, port): return self._bgpaas_allocator.read(port) def alloc_bgpaas_port(self, name): return self._bgpaas_port_allocator.alloc(name) def free_bgpaas_port(self, port): self._bgpaas_port_allocator.delete(port)