Ejemplo n.º 1
0
        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)
Ejemplo n.º 2
0
    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))
Ejemplo n.º 3
0
    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()
Ejemplo n.º 4
0
    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()
Ejemplo n.º 5
0
    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()
Ejemplo n.º 6
0
    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
Ejemplo n.º 7
0
    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
Ejemplo n.º 8
0
 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))
Ejemplo n.º 9
0
 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))
Ejemplo n.º 10
0
        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)
Ejemplo n.º 11
0
        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)
Ejemplo n.º 12
0
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)
Ejemplo n.º 13
0
    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()
Ejemplo n.º 14
0
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)
Ejemplo n.º 15
0
    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()
Ejemplo n.º 16
0
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
Ejemplo n.º 17
0
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)
Ejemplo n.º 18
0
    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()
Ejemplo n.º 19
0
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)
Ejemplo n.º 20
0
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)
Ejemplo n.º 21
0
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)
Ejemplo n.º 22
0
    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()
Ejemplo n.º 23
0
    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()
Ejemplo n.º 24
0
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)
Ejemplo n.º 25
0
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)