Example #1
0
    def __init__(self, args=None):
        self._args = args
        self._fabric_rt_inst_obj = None

        # Initialize discovery client
        self._disc = None
        if self._args.disc_server_ip and self._args.disc_server_port:
            self._disc = client.DiscoveryClient(
                self._args.disc_server_ip,
                self._args.disc_server_port,
                ModuleNames[Module.SCHEMA_TRANSFORMER])

        # Initialize logger
        self.logger = SchemaTransformerLogger(self._disc, args)

        # Initialize amqp
        self._vnc_amqp = STAmqpHandle(self.logger,
                self._REACTION_MAP, self._args)
        self._vnc_amqp.establish()
        try:
            # Initialize cassandra
            self._object_db = SchemaTransformerDB(self, _zookeeper_client)
            DBBaseST.init(self, self.logger, self._object_db)
            DBBaseST._sandesh = self.logger._sandesh
            DBBaseST._vnc_lib = _vnc_lib
            ServiceChain.init()
            self.reinit()
            self._vnc_amqp._db_resync_done.set()
        except Exception as e:
            # If any of the above tasks like CassandraDB read fails, cleanup
            # the RMQ constructs created earlier and then give up.
            self._vnc_amqp.close()
            raise e
Example #2
0
    def __init__(self, st_logger=None, args=None):
        self._args = args
        self._fabric_rt_inst_obj = None
        self.timer_obj = self.STtimer(self._args.zk_timeout)

        if st_logger is not None:
            self.logger = st_logger
        else:
            # Initialize logger
            self.logger = SchemaTransformerLogger(args)

        # Initialize amqp
        self._vnc_amqp = STAmqpHandle(self.logger, self.REACTION_MAP,
                                      self._args, timer_obj=self.timer_obj)
        self._vnc_amqp.establish()
        SchemaTransformer._schema_transformer = self
        try:
            # Initialize cassandra
            self._object_db = SchemaTransformerDB(self, _zookeeper_client)
            DBBaseST.init(self, self.logger, self._object_db)
            DBBaseST._sandesh = self.logger._sandesh
            DBBaseST._vnc_lib = _vnc_lib
            ServiceChain.init()
            self.reinit()
            self._vnc_amqp._db_resync_done.set()
        except Exception as e:
            self._vnc_amqp._db_resync_done.set()
            # If any of the above tasks like CassandraDB read fails, cleanup
            # the RMQ constructs created earlier and then give up.
            SchemaTransformer.destroy_instance()
            SchemaTransformer._schema_transformer = None
            raise
Example #3
0
def main(args_str=None):
    global _zookeeper_client

    if not args_str:
        args_str = ' '.join(sys.argv[1:])
    args = parse_args(args_str)
    args._args_list = args_str
    if args.cluster_id:
        client_pfx = args.cluster_id + '-'
        zk_path_pfx = args.cluster_id + '/'
    else:
        client_pfx = ''
        zk_path_pfx = ''

    # randomize collector list
    args.random_collectors = args.collectors
    if args.collectors:
        args.random_collectors = random.sample(args.collectors,
                                               len(args.collectors))

    # Initialize logger without introspect thread
    st_logger = SchemaTransformerLogger(args, http_server_port=-1)

    # Initialize AMQP handler then close it to be sure remain queue of a
    # precedent run is cleaned
    vnc_amqp = STAmqpHandle(st_logger, SchemaTransformer.REACTION_MAP, args)
    vnc_amqp.establish()
    vnc_amqp.close()
    st_logger.debug("Removed remained AMQP queue")

    # Waiting to be elected as master node
    if 'host_ip' in args:
        host_ip = args.host_ip
    else:
        host_ip = socket.gethostbyname(socket.getfqdn())
    _zookeeper_client = ZookeeperClient(client_pfx+"schema", args.zk_server_ip,
                                        host_ip, zk_timeout=args.zk_timeout)
    st_logger.notice("Waiting to be elected as master...")
    _zookeeper_client.master_election(zk_path_pfx + "/schema-transformer",
                                      os.getpid(), run_schema_transformer,
                                      st_logger, args)
Example #4
0
class SchemaTransformer(object):

    _REACTION_MAP = {
        'routing_instance': {
            'self': ['virtual_network'],
        },
        'virtual_machine_interface': {
            'self': ['virtual_machine', 'port_tuple', 'virtual_network',
                     'bgp_as_a_service'],
            'virtual_network': ['virtual_machine', 'port_tuple',
                                'bgp_as_a_service'],
            'logical_router': ['virtual_network'],
            'instance_ip': ['virtual_machine', 'port_tuple', 'bgp_as_a_service', 'virtual_network'],
            'floating_ip': ['virtual_machine', 'port_tuple'],
            'alias_ip': ['virtual_machine', 'port_tuple'],
            'virtual_machine': ['virtual_network'],
            'port_tuple': ['virtual_network'],
            'bgp_as_a_service': [],
        },
        'virtual_network': {
            'self': ['network_policy', 'route_table'],
            'routing_instance': ['network_policy'],
            'network_policy': [],
            'virtual_machine_interface': [],
            'route_table': [],
        },
        'virtual_machine': {
            'self': ['service_instance'],
            'virtual_machine_interface': ['service_instance'],
            'service_instance': ['virtual_machine_interface']
        },
        'port_tuple': {
            'self': ['service_instance'],
            'virtual_machine_interface': ['service_instance'],
            'service_instance': ['virtual_machine_interface']
        },
        'service_instance': {
            'self': ['network_policy', 'virtual_machine', 'port_tuple'],
            'route_table': ['network_policy', 'virtual_machine', 'port_tuple'],
            'routing_policy': ['network_policy'],
            'route_aggregate': ['network_policy'],
            'virtual_machine': ['network_policy'],
            'port_tuple': ['network_policy'],
            'network_policy': ['virtual_machine', 'port_tuple']
        },
        'network_policy': {
            'self': ['virtual_network', 'network_policy', 'service_instance'],
            'service_instance': ['virtual_network'],
            'network_policy': ['virtual_network'],
            'virtual_network': ['virtual_network', 'network_policy',
                                'service_instance']
        },
        'security_group': {
            'self': ['security_group'],
            'security_group': [],
        },
        'route_table': {
            'self': ['virtual_network', 'service_instance', 'logical_router'],
            'virtual_network': ['service_instance'],
            'logical_router': ['service_instance'],
        },
        'logical_router': {
            'self': ['route_table'],
            'virtual_machine_interface': [],
            'route_table': [],
        },
        'floating_ip': {
            'self': ['virtual_machine_interface'],
        },
        'alias_ip': {
            'self': ['virtual_machine_interface'],
        },
        'instance_ip': {
            'self': ['virtual_machine_interface'],
        },
        'bgp_as_a_service': {
            'self': ['bgp_router'],
            'virtual_machine_interface': ['bgp_router']
        },
        'bgp_router': {
            'self': [],
            'bgp_as_a_service': [],
        },
        'global_system_config': {
            'self': [],
        },
        'routing_policy': {
            'self': ['service_instance'],
        },
        'route_aggregate': {
            'self': ['service_instance'],
        }
    }

    def __init__(self, args=None):
        self._args = args
        self._fabric_rt_inst_obj = None

        # Initialize discovery client
        self._disc = None
        if self._args.disc_server_ip and self._args.disc_server_port:
            self._disc = client.DiscoveryClient(
                self._args.disc_server_ip,
                self._args.disc_server_port,
                ModuleNames[Module.SCHEMA_TRANSFORMER])

        # Initialize logger
        self.logger = SchemaTransformerLogger(self._disc, args)

        # Initialize amqp
        self._vnc_amqp = STAmqpHandle(self.logger,
                self._REACTION_MAP, self._args)
        self._vnc_amqp.establish()
        try:
            # Initialize cassandra
            self._object_db = SchemaTransformerDB(self, _zookeeper_client)
            DBBaseST.init(self, self.logger, self._object_db)
            DBBaseST._sandesh = self.logger._sandesh
            DBBaseST._vnc_lib = _vnc_lib
            ServiceChain.init()
            self.reinit()
            self._vnc_amqp._db_resync_done.set()
        except Exception as e:
            # If any of the above tasks like CassandraDB read fails, cleanup
            # the RMQ constructs created earlier and then give up.
            self._vnc_amqp.close()
            raise e
    # end __init__

    # Clean up stale objects
    def reinit(self):
        GlobalSystemConfigST.reinit()
        BgpRouterST.reinit()
        LogicalRouterST.reinit()
        vn_list = list(VirtualNetworkST.list_vnc_obj())
        vn_id_list = set([vn.uuid for vn in vn_list])
        ri_dict = {}
        service_ri_dict = {}
        ri_deleted = {}
        for ri in DBBaseST.list_vnc_obj('routing_instance'):
            delete = False
            if ri.parent_uuid not in vn_id_list:
                delete = True
                ri_deleted.setdefault(ri.parent_uuid, []).append(ri.uuid)
            else:
                # if the RI was for a service chain and service chain no
                # longer exists, delete the RI
                sc_id = RoutingInstanceST._get_service_id_from_ri(
                    ri.get_fq_name_str())
                if sc_id:
                    if sc_id not in ServiceChain:
                        delete = True
                    else:
                        service_ri_dict[ri.get_fq_name_str()] = ri
                else:
                    ri_dict[ri.get_fq_name_str()] = ri
            if delete:
                try:
                    ri_obj = RoutingInstanceST(ri.get_fq_name_str(), ri)
                    ri_obj.delete_obj()
                except NoIdError:
                    pass
                except Exception as e:
                    self.logger.error(
                            "Error while deleting routing instance %s: %s"%(
                            ri.get_fq_name_str(), str(e)))

        # end for ri

        sg_list = list(SecurityGroupST.list_vnc_obj())
        sg_id_list = [sg.uuid for sg in sg_list]
        sg_acl_dict = {}
        vn_acl_dict = {}
        for acl in DBBaseST.list_vnc_obj('access_control_list'):
            delete = False
            if acl.parent_type == 'virtual-network':
                if acl.parent_uuid in vn_id_list:
                    vn_acl_dict[acl.uuid] = acl
                else:
                    delete = True
            elif acl.parent_type == 'security-group':
                if acl.parent_uuid in sg_id_list:
                    sg_acl_dict[acl.uuid] = acl
                else:
                    delete = True
            else:
                delete = True

            if delete:
                try:
                    _vnc_lib.access_control_list_delete(id=acl.uuid)
                except NoIdError:
                    pass
                except Exception as e:
                    self.logger.error(
                            "Error while deleting acl %s: %s"%(
                            acl.uuid, str(e)))
        # end for acl

        gevent.sleep(0.001)
        for sg in sg_list:
            SecurityGroupST.locate(sg.get_fq_name_str(), sg, sg_acl_dict)

        # update sg rules after all SG objects are initialized to avoid
        # rewriting of ACLs multiple times
        for sg in SecurityGroupST.values():
            sg.update_policy_entries()

        gevent.sleep(0.001)
        RouteTargetST.reinit()
        for vn in vn_list:
            if vn.uuid in ri_deleted:
                vn_ri_list = vn.get_routing_instances() or []
                new_vn_ri_list = [vn_ri for vn_ri in vn_ri_list
                                  if vn_ri['uuid'] not in ri_deleted[vn.uuid]]
                vn.routing_instances = new_vn_ri_list
            VirtualNetworkST.locate(vn.get_fq_name_str(), vn, vn_acl_dict)
        for ri_name, ri_obj in ri_dict.items():
            RoutingInstanceST.locate(ri_name, ri_obj)
        # Initialize service instance RI's after Primary RI's
        for si_ri_name, si_ri_obj in service_ri_dict.items():
            RoutingInstanceST.locate(si_ri_name, si_ri_obj)

        NetworkPolicyST.reinit()
        gevent.sleep(0.001)
        VirtualMachineInterfaceST.reinit()

        gevent.sleep(0.001)
        InstanceIpST.reinit()
        gevent.sleep(0.001)
        FloatingIpST.reinit()
        AliasIpST.reinit()

        gevent.sleep(0.001)
        for si in ServiceInstanceST.list_vnc_obj():
            si_st = ServiceInstanceST.locate(si.get_fq_name_str(), si)
            if si_st is None:
                continue
            for ref in si.get_virtual_machine_back_refs() or []:
                vm_name = ':'.join(ref['to'])
                vm = VirtualMachineST.locate(vm_name)
                si_st.virtual_machines.add(vm_name)
            props = si.get_service_instance_properties()
            if not props.auto_policy:
                continue
            si_st.add_properties(props)

        gevent.sleep(0.001)
        RoutingPolicyST.reinit()
        gevent.sleep(0.001)
        RouteAggregateST.reinit()
        gevent.sleep(0.001)
        PortTupleST.reinit()
        BgpAsAServiceST.reinit()
        RouteTableST.reinit()

        # evaluate virtual network objects first because other objects,
        # e.g. vmi, depend on it.
        for vn_obj in VirtualNetworkST.values():
            vn_obj.evaluate()
        for cls in DBBaseST.get_obj_type_map().values():
            if cls is VirtualNetworkST:
                continue
            for obj in cls.values():
                obj.evaluate()
        self.process_stale_objects()
    # end reinit

    def cleanup(self):
        # TODO cleanup sandesh context
        pass
    # end cleanup

    def process_stale_objects(self):
        for sc in ServiceChain.values():
            if sc.created_stale:
                sc.destroy()
            if sc.present_stale:
                sc.delete()
            for rinst in RoutingInstanceST.values():
                if rinst.stale_route_targets:
                    rinst.update_route_target_list(
                            rt_del=rinst.stale_route_targets)
    # end process_stale_objects

    def reset(self):
        for cls in DBBaseST.get_obj_type_map().values():
            cls.reset()
        self._vnc_amqp.close()
    # end reset

    def sighup_handler(self):
        if self._conf_file:
            config = ConfigParser.SafeConfigParser()
            config.read(self._conf_file)
            if 'DEFAULTS' in config.sections():
                try:
                    collectors = config.get('DEFAULTS', 'collectors')
                    if type(collectors) is str:
                        collectors = collectors.split()
                        new_chksum = hashlib.md5("".join(collectors)).hexdigest()
                        if new_chksum != self._chksum:
                            self._chksum = new_chksum
                            config.random_collectors = random.sample(collectors, len(collectors))
                            self.logger.sandesh_reconfig_collectors(config)
                except ConfigParser.NoOptionError as e:
                    pass
Example #5
0
class SchemaTransformer(object):

    REACTION_MAP = {
        'routing_instance': {
            'self': ['virtual_network'],
        },
        'virtual_machine_interface': {
            'self': [
                'virtual_machine', 'port_tuple', 'virtual_network',
                'bgp_as_a_service'
            ],
            'virtual_network':
            ['virtual_machine', 'port_tuple', 'bgp_as_a_service'],
            'logical_router': ['virtual_network'],
            'instance_ip': [
                'virtual_machine', 'port_tuple', 'bgp_as_a_service',
                'virtual_network'
            ],
            'floating_ip': ['virtual_machine', 'port_tuple'],
            'alias_ip': ['virtual_machine', 'port_tuple'],
            'virtual_machine': ['virtual_network'],
            'port_tuple': ['virtual_network'],
            'bgp_as_a_service': [],
        },
        'virtual_network': {
            'self': ['network_policy', 'route_table'],
            'routing_instance': ['network_policy'],
            'network_policy': [],
            'virtual_machine_interface': [],
            'route_table': [],
            'bgpvpn': [],
        },
        'virtual_machine': {
            'self': ['service_instance'],
            'virtual_machine_interface': ['service_instance'],
            'service_instance': ['virtual_machine_interface']
        },
        'port_tuple': {
            'self': ['service_instance'],
            'virtual_machine_interface': ['service_instance'],
            'service_instance': ['virtual_machine_interface']
        },
        'service_instance': {
            'self': ['network_policy', 'virtual_machine', 'port_tuple'],
            'route_table': ['network_policy', 'virtual_machine', 'port_tuple'],
            'routing_policy': ['network_policy'],
            'route_aggregate': ['network_policy'],
            'virtual_machine': ['network_policy'],
            'port_tuple': ['network_policy'],
            'network_policy': ['virtual_machine', 'port_tuple']
        },
        'network_policy': {
            'self': [
                'security_logging_object', 'virtual_network', 'network_policy',
                'service_instance'
            ],
            'service_instance': ['virtual_network'],
            'network_policy': ['virtual_network'],
            'virtual_network':
            ['virtual_network', 'network_policy', 'service_instance']
        },
        'security_group': {
            'self': ['security_group', 'security_logging_object'],
            'security_group': [],
        },
        'security_logging_object': {
            'self': [],
            'network_policy': [],
            'security_group': [],
        },
        'route_table': {
            'self': ['virtual_network', 'service_instance', 'logical_router'],
            'virtual_network': ['service_instance'],
            'logical_router': ['service_instance'],
        },
        'logical_router': {
            'self': ['route_table'],
            'virtual_machine_interface': [],
            'route_table': [],
            'bgpvpn': [],
        },
        'floating_ip': {
            'self': ['virtual_machine_interface'],
        },
        'alias_ip': {
            'self': ['virtual_machine_interface'],
        },
        'instance_ip': {
            'self': ['virtual_machine_interface'],
        },
        'bgp_as_a_service': {
            'self': ['bgp_router'],
            'virtual_machine_interface': ['bgp_router']
        },
        'bgp_router': {
            'self': [],
            'bgp_as_a_service': [],
        },
        'global_system_config': {
            'self': [],
        },
        'routing_policy': {
            'self': ['service_instance'],
        },
        'route_aggregate': {
            'self': ['service_instance'],
        },
        'bgpvpn': {
            'self': ['virtual_network', 'logical_router'],
            'virtual_network': [],
            'logical_router': [],
        },
    }

    _schema_transformer = None

    def __init__(self, st_logger=None, args=None):
        self._args = args
        self._fabric_rt_inst_obj = None

        if st_logger is not None:
            self.logger = st_logger
        else:
            # Initialize logger
            self.logger = SchemaTransformerLogger(args)

        # Initialize amqp
        self._vnc_amqp = STAmqpHandle(self.logger, self.REACTION_MAP,
                                      self._args)
        self._vnc_amqp.establish()
        SchemaTransformer._schema_transformer = self
        try:
            # Initialize cassandra
            self._object_db = SchemaTransformerDB(self, _zookeeper_client)
            DBBaseST.init(self, self.logger, self._object_db)
            DBBaseST._sandesh = self.logger._sandesh
            DBBaseST._vnc_lib = _vnc_lib
            ServiceChain.init()
            self.reinit()
            self._vnc_amqp._db_resync_done.set()
        except Exception as e:
            # If any of the above tasks like CassandraDB read fails, cleanup
            # the RMQ constructs created earlier and then give up.
            SchemaTransformer.destroy_instance()
            SchemaTransformer._schema_transformer = None
            raise

    # end __init__

    # Clean up stale objects
    def reinit(self):
        GlobalSystemConfigST.reinit()
        BgpRouterST.reinit()
        BgpvpnST.reinit()
        LogicalRouterST.reinit()
        gevent.sleep(0.001)
        for si in ServiceInstanceST.list_vnc_obj():
            try:
                si_st = ServiceInstanceST.locate(si.get_fq_name_str(), si)
                if si_st is None:
                    continue
                for ref in si.get_virtual_machine_back_refs() or []:
                    vm_name = ':'.join(ref['to'])
                    vm = VirtualMachineST.locate(vm_name)
                    si_st.virtual_machines.add(vm_name)
                props = si.get_service_instance_properties()
                if not props.auto_policy:
                    continue
                si_st.add_properties(props)
            except Exception as e:
                self.logger.error("Error in reinit service instance %s: %s" %
                                  (si.get_fq_name_str(), str(e)))

        vn_list = list(VirtualNetworkST.list_vnc_obj())
        vn_id_list = set([vn.uuid for vn in vn_list])
        ri_dict = {}
        service_ri_dict = {}
        ri_deleted = {}
        for ri in DBBaseST.list_vnc_obj('routing_instance'):
            delete = False
            if ri.parent_uuid not in vn_id_list:
                delete = True
                ri_deleted.setdefault(ri.parent_uuid, []).append(ri.uuid)
            else:
                try:
                    # if the RI was for a service chain and service chain no
                    # longer exists, delete the RI
                    sc_id = RoutingInstanceST._get_service_id_from_ri(
                        ri.get_fq_name_str())
                    if sc_id:
                        if sc_id not in ServiceChain:
                            delete = True
                        else:
                            service_ri_dict[ri.get_fq_name_str()] = ri
                    else:
                        ri_dict[ri.get_fq_name_str()] = ri
                except Exception as e:
                    self.logger.error(
                        "Error while reinitializing routing instance %s: %s" %
                        (ri.get_fq_name_str(), str(e)))
            if delete:
                try:
                    ri_obj = RoutingInstanceST(ri.get_fq_name_str(), ri)
                    ri_obj.delete_obj()
                except NoIdError:
                    pass
                except Exception as e:
                    self.logger.error(
                        "Error while deleting routing instance %s: %s" %
                        (ri.get_fq_name_str(), str(e)))
        # end for ri

        sg_list = list(SecurityGroupST.list_vnc_obj())
        sg_id_list = [sg.uuid for sg in sg_list]
        sg_acl_dict = {}
        vn_acl_dict = {}
        for acl in DBBaseST.list_vnc_obj('access_control_list',
                                         fields=['access_control_list_hash']):
            delete = False
            if acl.parent_type == 'virtual-network':
                if acl.parent_uuid in vn_id_list:
                    vn_acl_dict[acl.uuid] = acl
                else:
                    delete = True
            elif acl.parent_type == 'security-group':
                if acl.parent_uuid in sg_id_list:
                    sg_acl_dict[acl.uuid] = acl
                else:
                    delete = True
            else:
                delete = True

            if delete:
                try:
                    _vnc_lib.access_control_list_delete(id=acl.uuid)
                except NoIdError:
                    pass
                except Exception as e:
                    self.logger.error("Error while deleting acl %s: %s" %
                                      (acl.uuid, str(e)))
        # end for acl

        gevent.sleep(0.001)
        for sg in sg_list:
            try:
                SecurityGroupST.locate(sg.get_fq_name_str(), sg, sg_acl_dict)
            except Exception as e:
                self.logger.error("Error in reinit security-group %s: %s" %
                                  (sg.get_fq_name_str(), str(e)))

        # update sg rules after all SG objects are initialized to avoid
        # rewriting of ACLs multiple times
        for sg in SecurityGroupST.values():
            try:
                sg.update_policy_entries()
            except Exception as e:
                self.logger.error("Error in updating SG policies %s: %s" %
                                  (sg.name, str(e)))

        gevent.sleep(0.001)
        RouteTargetST.reinit()
        for vn in vn_list:
            if vn.uuid in ri_deleted:
                vn_ri_list = vn.get_routing_instances() or []
                new_vn_ri_list = [
                    vn_ri for vn_ri in vn_ri_list
                    if vn_ri['uuid'] not in ri_deleted[vn.uuid]
                ]
                vn.routing_instances = new_vn_ri_list
            try:
                VirtualNetworkST.locate(vn.get_fq_name_str(), vn, vn_acl_dict)
            except Exception as e:
                self.logger.error("Error in reinit virtual network %s: %s" %
                                  (vn.get_fq_name_str(), str(e)))
        for ri_name, ri_obj in ri_dict.items():
            try:
                RoutingInstanceST.locate(ri_name, ri_obj)
            except Exception as e:
                self.logger.error("Error in reinit routing instance %s: %s" %
                                  (ri_name, str(e)))
        # Initialize service instance RI's after Primary RI's
        for si_ri_name, si_ri_obj in service_ri_dict.items():
            try:
                RoutingInstanceST.locate(si_ri_name, si_ri_obj)
            except Exception as e:
                self.logger.error("Error in reinit routing instance %s: %s" %
                                  (si_ri_name, str(e)))

        NetworkPolicyST.reinit()
        gevent.sleep(0.001)
        VirtualMachineInterfaceST.reinit()

        gevent.sleep(0.001)
        InstanceIpST.reinit()
        gevent.sleep(0.001)
        FloatingIpST.reinit()
        AliasIpST.reinit()

        gevent.sleep(0.001)
        RoutingPolicyST.reinit()
        gevent.sleep(0.001)
        RouteAggregateST.reinit()
        gevent.sleep(0.001)
        PortTupleST.reinit()
        BgpAsAServiceST.reinit()
        RouteTableST.reinit()

        # evaluate virtual network objects first because other objects,
        # e.g. vmi, depend on it.
        for vn_obj in VirtualNetworkST.values():
            try:
                vn_obj.evaluate()
            except Exception as e:
                self.logger.error(
                    "Error in reinit evaluate virtual network %s: %s" %
                    (vn_obj.name, str(e)))
        for cls in DBBaseST.get_obj_type_map().values():
            if cls is VirtualNetworkST:
                continue
            for obj in cls.values():
                try:
                    obj.evaluate()
                except Exception as e:
                    self.logger.error("Error in reinit evaluate %s %s: %s" %
                                      (cls.obj_type, obj.name, str(e)))
        self.process_stale_objects()

    # end reinit

    def cleanup(self):
        # TODO cleanup sandesh context
        pass

    # end cleanup

    def process_stale_objects(self):
        for sc in ServiceChain.values():
            if sc.created_stale:
                sc.destroy()
            if sc.present_stale:
                sc.delete()
            for rinst in RoutingInstanceST.values():
                if rinst.stale_route_targets:
                    rinst.update_route_target_list(
                        rt_del=rinst.stale_route_targets)

    # end process_stale_objects

    @classmethod
    def get_instance(cls):
        return cls._schema_transformer

    @classmethod
    def destroy_instance(cls):
        inst = cls.get_instance()
        inst._vnc_amqp.close()
        for obj_cls in DBBaseST.get_obj_type_map().values():
            obj_cls.reset()
        DBBase.clear()
        inst._object_db = None
        cls._schema_transformer = None

    def sighup_handler(self):
        if self._conf_file:
            config = ConfigParser.SafeConfigParser()
            config.read(self._conf_file)
            if 'DEFAULTS' in config.sections():
                try:
                    collectors = config.get('DEFAULTS', 'collectors')
                    if type(collectors) is str:
                        collectors = collectors.split()
                        new_chksum = hashlib.md5(
                            "".join(collectors)).hexdigest()
                        if new_chksum != self._chksum:
                            self._chksum = new_chksum
                            config.random_collectors = random.sample(
                                collectors, len(collectors))
                        # Reconnect to achieve load-balance irrespective of list
                        self.logger.sandesh_reconfig_collectors(config)
                except ConfigParser.NoOptionError as e:
                    pass
Example #6
0
class SchemaTransformer(object):

    _REACTION_MAP = {
        'routing_instance': {
            'self': ['virtual_network'],
        },
        'virtual_machine_interface': {
            'self': [
                'virtual_machine', 'port_tuple', 'virtual_network',
                'bgp_as_a_service'
            ],
            'virtual_network':
            ['virtual_machine', 'port_tuple', 'bgp_as_a_service'],
            'logical_router': ['virtual_network'],
            'instance_ip': [
                'virtual_machine', 'port_tuple', 'bgp_as_a_service',
                'virtual_network'
            ],
            'floating_ip': ['virtual_machine', 'port_tuple'],
            'alias_ip': ['virtual_machine', 'port_tuple'],
            'virtual_machine': ['virtual_network'],
            'port_tuple': ['virtual_network'],
            'bgp_as_a_service': [],
        },
        'virtual_network': {
            'self': ['network_policy', 'route_table'],
            'routing_instance': ['network_policy'],
            'network_policy': [],
            'virtual_machine_interface': [],
            'route_table': [],
        },
        'virtual_machine': {
            'self': ['service_instance'],
            'virtual_machine_interface': ['service_instance'],
            'service_instance': ['virtual_machine_interface']
        },
        'port_tuple': {
            'self': ['service_instance'],
            'virtual_machine_interface': ['service_instance'],
            'service_instance': ['virtual_machine_interface']
        },
        'service_instance': {
            'self': ['network_policy', 'virtual_machine', 'port_tuple'],
            'route_table': ['network_policy', 'virtual_machine', 'port_tuple'],
            'routing_policy': ['network_policy'],
            'route_aggregate': ['network_policy'],
            'virtual_machine': ['network_policy'],
            'port_tuple': ['network_policy'],
            'network_policy': ['virtual_machine', 'port_tuple']
        },
        'network_policy': {
            'self': ['virtual_network', 'network_policy', 'service_instance'],
            'service_instance': ['virtual_network'],
            'network_policy': ['virtual_network'],
            'virtual_network':
            ['virtual_network', 'network_policy', 'service_instance']
        },
        'security_group': {
            'self': ['security_group'],
            'security_group': [],
        },
        'route_table': {
            'self': ['virtual_network', 'service_instance', 'logical_router'],
            'virtual_network': ['service_instance'],
            'logical_router': ['service_instance'],
        },
        'logical_router': {
            'self': ['route_table'],
            'virtual_machine_interface': [],
            'route_table': [],
        },
        'floating_ip': {
            'self': ['virtual_machine_interface'],
        },
        'alias_ip': {
            'self': ['virtual_machine_interface'],
        },
        'instance_ip': {
            'self': ['virtual_machine_interface'],
        },
        'bgp_as_a_service': {
            'self': ['bgp_router'],
            'virtual_machine_interface': ['bgp_router']
        },
        'bgp_router': {
            'self': [],
            'bgp_as_a_service': [],
        },
        'global_system_config': {
            'self': [],
        },
        'routing_policy': {
            'self': ['service_instance'],
        },
        'route_aggregate': {
            'self': ['service_instance'],
        }
    }

    def __init__(self, args=None):
        self._args = args
        self._fabric_rt_inst_obj = None

        # Initialize discovery client
        self._disc = None
        if self._args.disc_server_ip and self._args.disc_server_port:
            self._disc = client.DiscoveryClient(
                self._args.disc_server_ip, self._args.disc_server_port,
                ModuleNames[Module.SCHEMA_TRANSFORMER])

        # Initialize logger
        self.logger = SchemaTransformerLogger(self._disc, args)

        # Initialize amqp
        self._vnc_amqp = STAmqpHandle(self.logger, self._REACTION_MAP,
                                      self._args)
        self._vnc_amqp.establish()
        try:
            # Initialize cassandra
            self._cassandra = SchemaTransformerDB(self, _zookeeper_client)
            DBBaseST.init(self, self.logger, self._cassandra)
            DBBaseST._sandesh = self.logger._sandesh
            DBBaseST._vnc_lib = _vnc_lib
            ServiceChain.init()
            self.reinit()
            self._vnc_amqp._db_resync_done.set()
        except Exception as e:
            # If any of the above tasks like CassandraDB read fails, cleanup
            # the RMQ constructs created earlier and then give up.
            self._vnc_amqp.close()
            raise e

    # end __init__

    # Clean up stale objects
    def reinit(self):
        GlobalSystemConfigST.reinit()
        BgpRouterST.reinit()
        LogicalRouterST.reinit()
        vn_list = list(VirtualNetworkST.list_vnc_obj())
        vn_id_list = set([vn.uuid for vn in vn_list])
        ri_dict = {}
        service_ri_dict = {}
        ri_deleted = {}
        for ri in DBBaseST.list_vnc_obj('routing_instance'):
            delete = False
            if ri.parent_uuid not in vn_id_list:
                delete = True
                ri_deleted.setdefault(ri.parent_uuid, []).append(ri.uuid)
            else:
                # if the RI was for a service chain and service chain no
                # longer exists, delete the RI
                sc_id = RoutingInstanceST._get_service_id_from_ri(
                    ri.get_fq_name_str())
                if sc_id:
                    if sc_id not in ServiceChain:
                        delete = True
                    else:
                        service_ri_dict[ri.get_fq_name_str()] = ri
                else:
                    ri_dict[ri.get_fq_name_str()] = ri
            if delete:
                try:
                    ri_obj = RoutingInstanceST(ri.get_fq_name_str(), ri)
                    ri_obj.delete_obj()
                except NoIdError:
                    pass
                except Exception as e:
                    self.logger.error(
                        "Error while deleting routing instance %s: %s",
                        ri.get_fq_name_str(), str(e))

        # end for ri

        sg_list = list(SecurityGroupST.list_vnc_obj())
        sg_id_list = [sg.uuid for sg in sg_list]
        sg_acl_dict = {}
        vn_acl_dict = {}
        for acl in DBBaseST.list_vnc_obj('access_control_list'):
            delete = False
            if acl.parent_type == 'virtual-network':
                if acl.parent_uuid in vn_id_list:
                    vn_acl_dict[acl.uuid] = acl
                else:
                    delete = True
            elif acl.parent_type == 'security-group':
                if acl.parent_uuid in sg_id_list:
                    sg_acl_dict[acl.uuid] = acl
                else:
                    delete = True
            else:
                delete = True

            if delete:
                try:
                    _vnc_lib.access_control_list_delete(id=acl.uuid)
                except NoIdError:
                    pass
                except Exception as e:
                    self.logger.error("Error while deleting acl %s: %s",
                                      acl.uuid, str(e))
        # end for acl

        gevent.sleep(0.001)
        for sg in sg_list:
            SecurityGroupST.locate(sg.get_fq_name_str(), sg, sg_acl_dict)

        # update sg rules after all SG objects are initialized to avoid
        # rewriting of ACLs multiple times
        for sg in SecurityGroupST.values():
            sg.update_policy_entries()

        gevent.sleep(0.001)
        RouteTargetST.reinit()
        for vn in vn_list:
            if vn.uuid in ri_deleted:
                vn_ri_list = vn.get_routing_instances() or []
                new_vn_ri_list = [
                    vn_ri for vn_ri in vn_ri_list
                    if vn_ri['uuid'] not in ri_deleted[vn.uuid]
                ]
                vn.routing_instances = new_vn_ri_list
            VirtualNetworkST.locate(vn.get_fq_name_str(), vn, vn_acl_dict)
        for ri_name, ri_obj in ri_dict.items():
            RoutingInstanceST.locate(ri_name, ri_obj)
        # Initialize service instance RI's after Primary RI's
        for si_ri_name, si_ri_obj in service_ri_dict.items():
            RoutingInstanceST.locate(si_ri_name, si_ri_obj)

        NetworkPolicyST.reinit()
        gevent.sleep(0.001)
        VirtualMachineInterfaceST.reinit()

        gevent.sleep(0.001)
        InstanceIpST.reinit()
        gevent.sleep(0.001)
        FloatingIpST.reinit()
        AliasIpST.reinit()

        gevent.sleep(0.001)
        for si in ServiceInstanceST.list_vnc_obj():
            si_st = ServiceInstanceST.locate(si.get_fq_name_str(), si)
            if si_st is None:
                continue
            for ref in si.get_virtual_machine_back_refs() or []:
                vm_name = ':'.join(ref['to'])
                vm = VirtualMachineST.locate(vm_name)
                si_st.virtual_machines.add(vm_name)
            props = si.get_service_instance_properties()
            if not props.auto_policy:
                continue
            si_st.add_properties(props)

        gevent.sleep(0.001)
        RoutingPolicyST.reinit()
        gevent.sleep(0.001)
        RouteAggregateST.reinit()
        gevent.sleep(0.001)
        PortTupleST.reinit()
        BgpAsAServiceST.reinit()
        RouteTableST.reinit()

        # evaluate virtual network objects first because other objects,
        # e.g. vmi, depend on it.
        for vn_obj in VirtualNetworkST.values():
            vn_obj.evaluate()
        for cls in DBBaseST.get_obj_type_map().values():
            if cls is VirtualNetworkST:
                continue
            for obj in cls.values():
                obj.evaluate()
        self.process_stale_objects()

    # end reinit

    def cleanup(self):
        # TODO cleanup sandesh context
        pass

    # end cleanup

    def process_stale_objects(self):
        for sc in ServiceChain.values():
            if sc.created_stale:
                sc.destroy()
            if sc.present_stale:
                sc.delete()
            for rinst in RoutingInstanceST.values():
                if rinst.stale_route_targets:
                    rinst.update_route_target_list(
                        rt_del=rinst.stale_route_targets)

    # end process_stale_objects

    def reset(self):
        for cls in DBBaseST.get_obj_type_map().values():
            cls.reset()
        self._vnc_amqp.close()