Exemplo n.º 1
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'],
            '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'],
            'virtual_network': ['service_instance'],
        },
        'logical_router': {
            'self': [],
            'virtual_machine_interface': [],
        },
        'floating_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])

        self._sandesh = Sandesh()
        # Reset the sandesh send rate limit value
        if args.sandesh_send_rate_limit is not None:
            SandeshSystem.set_sandesh_send_rate_limit(
                args.sandesh_send_rate_limit)
        sandesh.VnList.handle_request = self.sandesh_vn_handle_request
        sandesh.RoutintInstanceList.handle_request = \
            self.sandesh_ri_handle_request
        sandesh.ServiceChainList.handle_request = \
            self.sandesh_sc_handle_request
        sandesh.StObjectReq.handle_request = \
            self.sandesh_st_object_handle_request
        module = Module.SCHEMA_TRANSFORMER
        module_name = ModuleNames[module]
        node_type = Module2NodeType[module]
        node_type_name = NodeTypeNames[node_type]
        instance_id = INSTANCE_ID_DEFAULT
        hostname = socket.gethostname()
        self._sandesh.init_generator(
            module_name,
            hostname,
            node_type_name,
            instance_id,
            self._args.collectors,
            'to_bgp_context',
            int(args.http_server_port),
            ['cfgm_common', 'schema_transformer.sandesh'],
            self._disc,
            logger_class=args.logger_class,
            logger_config_file=args.logging_conf)
        self._sandesh.set_logging_params(enable_local_log=args.log_local,
                                         category=args.log_category,
                                         level=args.log_level,
                                         file=args.log_file,
                                         enable_syslog=args.use_syslog,
                                         syslog_facility=args.syslog_facility)
        ConnectionState.init(
            self._sandesh, hostname, module_name, instance_id,
            staticmethod(ConnectionState.get_process_state_cb), NodeStatusUVE,
            NodeStatus)

        self._sandesh.trace_buffer_create(name="MessageBusNotifyTraceBuf",
                                          size=1000)

        rabbit_servers = self._args.rabbit_server
        rabbit_port = self._args.rabbit_port
        rabbit_user = self._args.rabbit_user
        rabbit_password = self._args.rabbit_password
        rabbit_vhost = self._args.rabbit_vhost
        rabbit_ha_mode = self._args.rabbit_ha_mode

        self._db_resync_done = gevent.event.Event()

        q_name = 'schema_transformer.%s' % (socket.gethostname())
        self._vnc_kombu = VncKombuClient(rabbit_servers, rabbit_port,
                                         rabbit_user, rabbit_password,
                                         rabbit_vhost, rabbit_ha_mode, q_name,
                                         self._vnc_subscribe_callback,
                                         self.config_log)
        self._cassandra = SchemaTransformerDB(self, _zookeeper_client)
        DBBaseST.init(self, self._sandesh.logger(), self._cassandra)
        DBBaseST._sandesh = self._sandesh
        DBBaseST._vnc_lib = _vnc_lib
        ServiceChain.init()
        self.reinit()
        # create cpu_info object to send periodic updates
        sysinfo_req = False
        cpu_info = vnc_cpu_info.CpuInfo(module_name, instance_id, sysinfo_req,
                                        self._sandesh, 60)
        self._cpu_info = cpu_info
        self._db_resync_done.set()

    # end __init__

    def config_log(self, msg, level):
        self._sandesh.logger().log(SandeshLogger.get_py_logger_level(level),
                                   msg)

    def _vnc_subscribe_callback(self, oper_info):
        self._db_resync_done.wait()
        dependency_tracker = None
        try:
            msg = "Notification Message: %s" % (pformat(oper_info))
            self.config_log(msg, level=SandeshLevel.SYS_DEBUG)
            obj_type = oper_info['type'].replace('-', '_')
            obj_class = DBBaseST.get_obj_type_map().get(obj_type)
            if obj_class is None:
                return

            oper = oper_info['oper']
            obj_id = oper_info['uuid']
            notify_trace = MessageBusNotifyTrace(
                request_id=oper_info.get('request_id'),
                operation=oper,
                uuid=obj_id)
            if oper == 'CREATE':
                obj_dict = oper_info['obj_dict']
                obj_fq_name = ':'.join(obj_dict['fq_name'])
                obj = obj_class.locate(obj_fq_name)
                if obj is None:
                    self.config_log('%s id %s fq_name %s not found' %
                                    (obj_type, obj_id, obj_fq_name),
                                    level=SandeshLevel.SYS_INFO)
                    return
                dependency_tracker = DependencyTracker(
                    DBBaseST.get_obj_type_map(), self._REACTION_MAP)
                dependency_tracker.evaluate(obj_type, obj)
            elif oper == 'UPDATE':
                obj = obj_class.get_by_uuid(obj_id)
                old_dt = None
                if obj is not None:
                    old_dt = DependencyTracker(DBBaseST.get_obj_type_map(),
                                               self._REACTION_MAP)
                    old_dt.evaluate(obj_type, obj)
                else:
                    self.config_log('%s id %s not found' % (obj_type, obj_id),
                                    level=SandeshLevel.SYS_INFO)
                    return
                try:
                    obj.update()
                except NoIdError:
                    self.config_log('%s id %s update caused NoIdError' %
                                    (obj_type, obj_id),
                                    level=SandeshLevel.SYS_INFO)
                    return
                dependency_tracker = DependencyTracker(
                    DBBaseST.get_obj_type_map(), self._REACTION_MAP)
                dependency_tracker.evaluate(obj_type, obj)
                if old_dt:
                    for resource, ids in old_dt.resources.items():
                        if resource not in dependency_tracker.resources:
                            dependency_tracker.resources[resource] = ids
                        else:
                            dependency_tracker.resources[resource] = list(
                                set(dependency_tracker.resources[resource])
                                | set(ids))
            elif oper == 'DELETE':
                obj = obj_class.get_by_uuid(obj_id)
                if obj is None:
                    return
                dependency_tracker = DependencyTracker(
                    DBBaseST.get_obj_type_map(), self._REACTION_MAP)
                dependency_tracker.evaluate(obj_type, obj)
                obj_class.delete(obj.name)
            else:
                # unknown operation
                self.config_log('Unknown operation %s' % oper,
                                level=SandeshLevel.SYS_ERR)
                return

            if obj is None:
                self.config_log('Error while accessing %s uuid %s' %
                                (obj_type, obj_id))
                return

            notify_trace.fq_name = obj.name
            if not dependency_tracker:
                return

            notify_trace.dependency_tracker_resources = []
            for res_type, res_id_list in dependency_tracker.resources.items():
                if not res_id_list:
                    continue
                dtr = DependencyTrackerResource(obj_type=res_type,
                                                obj_keys=res_id_list)
                notify_trace.dependency_tracker_resources.append(dtr)
                cls = DBBaseST.get_obj_type_map().get(res_type)
                if cls is None:
                    continue
                for res_id in res_id_list:
                    res_obj = cls.get(res_id)
                    if res_obj is not None:
                        res_obj.evaluate()

            for vn_id in dependency_tracker.resources.get(
                    'virtual_network', []):
                vn = VirtualNetworkST.get(vn_id)
                if vn is not None:
                    vn.uve_send()
            # end for vn_id
        except Exception as e:
            string_buf = cStringIO.StringIO()
            cgitb_hook(file=string_buf, format="text")
            notify_trace.error = string_buf.getvalue()
            try:
                with open(self._args.trace_file, 'a') as err_file:
                    err_file.write(string_buf.getvalue())
            except IOError:
                self.config_log(string_buf.getvalue(),
                                level=SandeshLevel.SYS_ERR)
        finally:
            try:
                notify_trace.trace_msg(name='MessageBusNotifyTraceBuf',
                                       sandesh=self._sandesh)
            except Exception:
                pass

    # end _vnc_subscribe_callback

    # Clean up stale objects
    def reinit(self):
        GlobalSystemConfigST.reinit()
        BgpRouterST.reinit()
        LogicalRouterST.reinit()
        vn_list = list(VirtualNetworkST.list_vnc_obj())
        vn_id_list = [vn.uuid for vn in vn_list]
        ri_dict = {}
        service_ri_dict = {}
        for ri in DBBaseST.list_vnc_obj('routing_instance'):
            delete = False
            if ri.parent_uuid not in vn_id_list:
                delete = True
            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._sandesh._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._sandesh._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:
            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()

        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()

    # end process_stale_objects

    def sandesh_ri_build(self, vn_name, ri_name):
        vn = VirtualNetworkST.get(vn_name)
        sandesh_ri_list = []
        for riname in vn.routing_instances:
            ri = RoutingInstanceST.get(riname)
            sandesh_ri = sandesh.RoutingInstance(name=ri.obj.get_fq_name_str())
            sandesh_ri.service_chain = ri.service_chain
            sandesh_ri.connections = list(ri.connections)
            sandesh_ri_list.append(sandesh_ri)
        return sandesh_ri_list

    # end sandesh_ri_build

    def sandesh_ri_handle_request(self, req):
        # Return the list of VNs
        ri_resp = sandesh.RoutingInstanceListResp(routing_instances=[])
        if req.vn_name is None:
            for vn in VirtualNetworkST:
                sandesh_ri = self.sandesh_ri_build(vn, req.ri_name)
                ri_resp.routing_instances.extend(sandesh_ri)
        elif req.vn_name in VirtualNetworkST:
            self.sandesh_ri_build(req.vn_name, req.ri_name)
            ri_resp.routing_instances.extend(sandesh_ri)
        ri_resp.response(req.context())

    # end sandesh_ri_handle_request

    def sandesh_vn_build(self, vn_name):
        vn = VirtualNetworkST.get(vn_name)
        sandesh_vn = sandesh.VirtualNetwork(name=vn_name)
        sandesh_vn.policies = vn.network_policys.keys()
        sandesh_vn.connections = list(vn.connections)
        sandesh_vn.routing_instances = vn.routing_instances
        if vn.acl:
            sandesh_vn.acl = vn.acl.get_fq_name_str()
        if vn.dynamic_acl:
            sandesh_vn.dynamic_acl = vn.dynamic_acl.get_fq_name_str()

        return sandesh_vn

    # end sandesh_vn_build

    def sandesh_vn_handle_request(self, req):
        # Return the list of VNs
        vn_resp = sandesh.VnListResp(vn_names=[])
        if req.vn_name is None:
            for vn in VirtualNetworkST:
                sandesh_vn = self.sandesh_vn_build(vn)
                vn_resp.vn_names.append(sandesh_vn)
        elif req.vn_name in VirtualNetworkST:
            sandesh_vn = self.sandesh_vn_build(req.vn_name)
            vn_resp.vn_names.append(sandesh_vn)
        vn_resp.response(req.context())

    # end sandesh_vn_handle_request

    def sandesh_sc_handle_request(self, req):
        sc_resp = sandesh.ServiceChainListResp(service_chains=[])
        if req.sc_name is None:
            for sc in ServiceChain.values():
                sandesh_sc = sc.build_introspect()
                sc_resp.service_chains.append(sandesh_sc)
        elif req.sc_name in ServiceChain:
            sandesh_sc = ServiceChain[req.sc_name].build_introspect()
            sc_resp.service_chains.append(sandesh_sc)
        sc_resp.response(req.context())

    # end sandesh_sc_handle_request

    def sandesh_st_object_handle_request(self, req):
        st_resp = sandesh.StObjectListResp(objects=[])
        obj_type_map = DBBaseST.get_obj_type_map()
        if req.object_type is not None:
            if req.object_type not in obj_type_map:
                return st_resp
            obj_cls_list = [obj_type_map[req.object_type]]
        else:
            obj_cls_list = obj_type_map.values()
        for obj_cls in obj_cls_list:
            id_or_name = req.object_id_or_fq_name
            if id_or_name:
                obj = obj_cls.get(id_or_name) or obj_cls.get_by_uuid(
                    id_or_name)
                if obj is None:
                    continue
                st_resp.objects.append(obj.handle_st_object_req())
            else:
                for obj in obj_cls.values():
                    st_resp.objects.append(obj.handle_st_object_req())
        st_resp.response(req.context())

    # end sandesh_st_object_handle_request

    def reset(self):
        for cls in DBBaseST.get_obj_type_map().values():
            cls.reset()
        self._vnc_kombu.shutdown()
Exemplo n.º 2
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'],
            'floating_ip': ['virtual_machine', 'port_tuple'],
            'virtual_machine': [],
            'port_tuple': [],
            'bgp_as_a_service': [],
        },
        'virtual_network': {
            'self': ['network_policy'],
            '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'],
            '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'],
        },
        'logical_router': {
            'self': [],
            'virtual_machine_interface': [],
        },
        'floating_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])

        self._sandesh = Sandesh()
        # Reset the sandesh send rate limit value
        if args.sandesh_send_rate_limit is not None:
            SandeshSystem.set_sandesh_send_rate_limit(
                args.sandesh_send_rate_limit)
        sandesh.VnList.handle_request = self.sandesh_vn_handle_request
        sandesh.RoutintInstanceList.handle_request = \
            self.sandesh_ri_handle_request
        sandesh.ServiceChainList.handle_request = \
            self.sandesh_sc_handle_request
        sandesh.StObjectReq.handle_request = \
            self.sandesh_st_object_handle_request
        module = Module.SCHEMA_TRANSFORMER
        module_name = ModuleNames[module]
        node_type = Module2NodeType[module]
        node_type_name = NodeTypeNames[node_type]
        instance_id = INSTANCE_ID_DEFAULT
        hostname = socket.gethostname()
        self._sandesh.init_generator(
            module_name, hostname, node_type_name, instance_id,
            self._args.collectors, 'to_bgp_context',
            int(args.http_server_port),
            ['cfgm_common', 'schema_transformer.sandesh'], self._disc,
            logger_class=args.logger_class,
            logger_config_file=args.logging_conf)
        self._sandesh.set_logging_params(enable_local_log=args.log_local,
                                    category=args.log_category,
                                    level=args.log_level,
                                    file=args.log_file,
                                    enable_syslog=args.use_syslog,
                                    syslog_facility=args.syslog_facility)
        ConnectionState.init(self._sandesh, hostname, module_name, instance_id,
                staticmethod(ConnectionState.get_process_state_cb),
                NodeStatusUVE, NodeStatus)

        self._sandesh.trace_buffer_create(name="MessageBusNotifyTraceBuf",
                                          size=1000)

        rabbit_servers = self._args.rabbit_server
        rabbit_port = self._args.rabbit_port
        rabbit_user = self._args.rabbit_user
        rabbit_password = self._args.rabbit_password
        rabbit_vhost = self._args.rabbit_vhost
        rabbit_ha_mode = self._args.rabbit_ha_mode

        self._db_resync_done = gevent.event.Event()

        q_name = 'schema_transformer.%s' % (socket.gethostname())
        self._vnc_kombu = VncKombuClient(rabbit_servers, rabbit_port,
                                         rabbit_user, rabbit_password,
                                         rabbit_vhost, rabbit_ha_mode,
                                         q_name, self._vnc_subscribe_callback,
                                         self.config_log)
        self._cassandra = SchemaTransformerDB(self, _zookeeper_client)
        DBBaseST.init(self, self._sandesh.logger(), self._cassandra)
        DBBaseST._sandesh = self._sandesh
        DBBaseST._vnc_lib = _vnc_lib
        ServiceChain.init()
        self.reinit()
        # create cpu_info object to send periodic updates
        sysinfo_req = False
        cpu_info = vnc_cpu_info.CpuInfo(
            module_name, instance_id, sysinfo_req, self._sandesh, 60)
        self._cpu_info = cpu_info
        self._db_resync_done.set()

    # end __init__

    def config_log(self, msg, level):
        self._sandesh.logger().log(SandeshLogger.get_py_logger_level(level),
                                   msg)

    def _vnc_subscribe_callback(self, oper_info):
        self._db_resync_done.wait()
        dependency_tracker = None
        try:
            msg = "Notification Message: %s" % (pformat(oper_info))
            self.config_log(msg, level=SandeshLevel.SYS_DEBUG)
            obj_type = oper_info['type'].replace('-', '_')
            obj_class = DBBaseST.get_obj_type_map().get(obj_type)
            if obj_class is None:
                return

            oper = oper_info['oper']
            obj_id = oper_info['uuid']
            notify_trace = MessageBusNotifyTrace(
                request_id=oper_info.get('request_id'),
                operation=oper, uuid=obj_id)
            if oper == 'CREATE':
                obj_dict = oper_info['obj_dict']
                obj_fq_name = ':'.join(obj_dict['fq_name'])
                obj = obj_class.locate(obj_fq_name)
                if obj is None:
                    self.config_log('%s id %s fq_name %s not found' % (
                                    obj_type, obj_id, obj_fq_name),
                                    level=SandeshLevel.SYS_INFO)
                    return
                dependency_tracker = DependencyTracker(
                    DBBaseST.get_obj_type_map(), self._REACTION_MAP)
                dependency_tracker.evaluate(obj_type, obj)
            elif oper == 'UPDATE':
                obj = obj_class.get_by_uuid(obj_id)
                old_dt = None
                if obj is not None:
                    old_dt = DependencyTracker(
                        DBBaseST.get_obj_type_map(), self._REACTION_MAP)
                    old_dt.evaluate(obj_type, obj)
                else:
                    self.config_log('%s id %s not found' % (obj_type, obj_id),
                                    level=SandeshLevel.SYS_INFO)
                    return
                try:
                    obj.update()
                except NoIdError:
                    self.config_log('%s id %s update caused NoIdError' % (obj_type, obj_id),
                                    level=SandeshLevel.SYS_INFO)
                    return
                dependency_tracker = DependencyTracker(
                    DBBaseST.get_obj_type_map(), self._REACTION_MAP)
                dependency_tracker.evaluate(obj_type, obj)
                if old_dt:
                    for resource, ids in old_dt.resources.items():
                        if resource not in dependency_tracker.resources:
                            dependency_tracker.resources[resource] = ids
                        else:
                            dependency_tracker.resources[resource] = list(
                                set(dependency_tracker.resources[resource]) |
                                set(ids))
            elif oper == 'DELETE':
                obj = obj_class.get_by_uuid(obj_id)
                if obj is None:
                    return
                dependency_tracker = DependencyTracker(
                    DBBaseST.get_obj_type_map(), self._REACTION_MAP)
                dependency_tracker.evaluate(obj_type, obj)
                obj_class.delete(obj.name)
            else:
                # unknown operation
                self.config_log('Unknown operation %s' % oper,
                                level=SandeshLevel.SYS_ERR)
                return

            if obj is None:
                self.config_log('Error while accessing %s uuid %s' % (
                                obj_type, obj_id))
                return

            notify_trace.fq_name = obj.name
            if not dependency_tracker:
                return

            notify_trace.dependency_tracker_resources = []
            for res_type, res_id_list in dependency_tracker.resources.items():
                if not res_id_list:
                    continue
                dtr = DependencyTrackerResource(obj_type=res_type, obj_keys=res_id_list)
                notify_trace.dependency_tracker_resources.append(dtr)
                cls = DBBaseST.get_obj_type_map().get(res_type)
                if cls is None:
                    continue
                for res_id in res_id_list:
                    res_obj = cls.get(res_id)
                    if res_obj is not None:
                        res_obj.evaluate()

            for vn_id in dependency_tracker.resources.get('virtual_network', []):
                vn = VirtualNetworkST.get(vn_id)
                if vn is not None:
                    vn.uve_send()
            # end for vn_id
        except Exception as e:
            string_buf = cStringIO.StringIO()
            cgitb_hook(file=string_buf, format="text")
            notify_trace.error = string_buf.getvalue()
            try:
                with open(self._args.trace_file, 'a') as err_file:
                    err_file.write(string_buf.getvalue())
            except IOError:
                self.config_log(string_buf.getvalue(), level=SandeshLevel.SYS_ERR)
        finally:
            try:
                notify_trace.trace_msg(name='MessageBusNotifyTraceBuf',
                                       sandesh=self._sandesh)
            except Exception:
                pass


    # end _vnc_subscribe_callback

    # Clean up stale objects
    def reinit(self):
        GlobalSystemConfigST.reinit()
        BgpRouterST.reinit()
        LogicalRouterST.reinit()
        vn_list = list(VirtualNetworkST.list_vnc_obj())
        vn_id_list = [vn.uuid for vn in vn_list]
        ri_dict = {}
        service_ri_dict = {}
        for ri in DBBaseST.list_vnc_obj('routing_instance'):
            delete = False
            if ri.parent_uuid not in vn_id_list:
                delete = True
            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._sandesh._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._sandesh._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:
            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()

        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()
    # end process_stale_objects

    def sandesh_ri_build(self, vn_name, ri_name):
        vn = VirtualNetworkST.get(vn_name)
        sandesh_ri_list = []
        for riname in vn.routing_instances:
            ri = RoutingInstanceST.get(riname)
            sandesh_ri = sandesh.RoutingInstance(name=ri.obj.get_fq_name_str())
            sandesh_ri.service_chain = ri.service_chain
            sandesh_ri.connections = list(ri.connections)
            sandesh_ri_list.append(sandesh_ri)
        return sandesh_ri_list
    # end sandesh_ri_build

    def sandesh_ri_handle_request(self, req):
        # Return the list of VNs
        ri_resp = sandesh.RoutingInstanceListResp(routing_instances=[])
        if req.vn_name is None:
            for vn in VirtualNetworkST:
                sandesh_ri = self.sandesh_ri_build(vn, req.ri_name)
                ri_resp.routing_instances.extend(sandesh_ri)
        elif req.vn_name in VirtualNetworkST:
            self.sandesh_ri_build(req.vn_name, req.ri_name)
            ri_resp.routing_instances.extend(sandesh_ri)
        ri_resp.response(req.context())
    # end sandesh_ri_handle_request

    def sandesh_vn_build(self, vn_name):
        vn = VirtualNetworkST.get(vn_name)
        sandesh_vn = sandesh.VirtualNetwork(name=vn_name)
        sandesh_vn.policies = vn.network_policys.keys()
        sandesh_vn.connections = list(vn.connections)
        sandesh_vn.routing_instances = vn.routing_instances
        if vn.acl:
            sandesh_vn.acl = vn.acl.get_fq_name_str()
        if vn.dynamic_acl:
            sandesh_vn.dynamic_acl = vn.dynamic_acl.get_fq_name_str()

        return sandesh_vn
    # end sandesh_vn_build

    def sandesh_vn_handle_request(self, req):
        # Return the list of VNs
        vn_resp = sandesh.VnListResp(vn_names=[])
        if req.vn_name is None:
            for vn in VirtualNetworkST:
                sandesh_vn = self.sandesh_vn_build(vn)
                vn_resp.vn_names.append(sandesh_vn)
        elif req.vn_name in VirtualNetworkST:
            sandesh_vn = self.sandesh_vn_build(req.vn_name)
            vn_resp.vn_names.append(sandesh_vn)
        vn_resp.response(req.context())
    # end sandesh_vn_handle_request

    def sandesh_sc_handle_request(self, req):
        sc_resp = sandesh.ServiceChainListResp(service_chains=[])
        if req.sc_name is None:
            for sc in ServiceChain.values():
                sandesh_sc = sc.build_introspect()
                sc_resp.service_chains.append(sandesh_sc)
        elif req.sc_name in ServiceChain:
            sandesh_sc = ServiceChain[req.sc_name].build_introspect()
            sc_resp.service_chains.append(sandesh_sc)
        sc_resp.response(req.context())
    # end sandesh_sc_handle_request

    def sandesh_st_object_handle_request(self, req):
        st_resp = sandesh.StObjectListResp(objects=[])
        obj_type_map = DBBaseST.get_obj_type_map()
        if req.object_type is not None:
            if req.object_type not in obj_type_map:
                return st_resp
            obj_cls_list = [obj_type_map[req.object_type]]
        else:
            obj_cls_list = obj_type_map.values()
        for obj_cls in obj_cls_list:
            id_or_name = req.object_id_or_fq_name
            if id_or_name:
                obj = obj_cls.get(id_or_name) or obj_cls.get_by_uuid(id_or_name)
                if obj is None:
                    continue
                st_resp.objects.append(obj.handle_st_object_req())
            else:
                for obj in obj_cls.values():
                    st_resp.objects.append(obj.handle_st_object_req())
        st_resp.response(req.context())
    # end sandesh_st_object_handle_request

    def reset(self):
        for cls in DBBaseST.get_obj_type_map().values():
            cls.reset()
        self._vnc_kombu.shutdown()
Exemplo n.º 3
0
class VncAmqpHandle(object):
    def __init__(self, logger, db_cls, reaction_map, q_name_prefix, args=None):
        self.logger = logger
        self.db_cls = db_cls
        self.reaction_map = reaction_map
        self.q_name_prefix = q_name_prefix
        self._db_resync_done = gevent.event.Event()
        self._args = args

    def establish(self):
        q_name = '.'.join([self.q_name_prefix, socket.gethostname()])
        self._vnc_kombu = VncKombuClient(
            self._args.rabbit_server,
            self._args.rabbit_port,
            self._args.rabbit_user,
            self._args.rabbit_password,
            self._args.rabbit_vhost,
            self._args.rabbit_ha_mode,
            q_name,
            self._vnc_subscribe_callback,
            self.logger.log,
            rabbit_use_ssl=self._args.rabbit_use_ssl,
            kombu_ssl_version=self._args.kombu_ssl_version,
            kombu_ssl_keyfile=self._args.kombu_ssl_keyfile,
            kombu_ssl_certfile=self._args.kombu_ssl_certfile,
            kombu_ssl_ca_certs=self._args.kombu_ssl_ca_certs)

    def msgbus_store_err_msg(self, msg):
        self.msg_tracer.error = msg

    def msgbus_trace_msg(self):
        self.msg_tracer.trace_msg(name='MessageBusNotifyTraceBuf',
                                  sandesh=self.logger._sandesh)

    def log_exception(self):
        string_buf = cStringIO.StringIO()
        cgitb_hook(file=string_buf, format="text")
        self.logger.error(string_buf.getvalue())

        self.msgbus_store_err_msg(string_buf.getvalue())
        try:
            with open(self._args.trace_file, 'a') as err_file:
                err_file.write(string_buf.getvalue())
        except IOError:
            pass

    def _vnc_subscribe_callback(self, oper_info):
        self._db_resync_done.wait()
        try:
            self.oper_info = oper_info
            self.vnc_subscribe_actions()

        except ConnectionError:
            try:
                # retry write during api-server ConnectionError
                self.vnc_subscribe_actions()
            except ConnectionError:
                # log the exception, and exit during api-server
                # ConnectionError on retry to let standby to become active.
                self.log_exception()
                self.logger.error("Api-server connection lost. Exiting")
                self.close()
                raise SystemExit
            except Exception:
                self.log_exception()
        except Exception:
            self.log_exception()
        finally:
            try:
                self.msgbus_trace_msg()
            except Exception:
                pass
            del self.oper_info
            del self.obj_type
            del self.obj_class
            del self.obj
            del self.dependency_tracker

    def create_msgbus_trace(self, request_id, oper, uuid):
        self.msg_tracer = MessageBusNotifyTrace(request_id=request_id,
                                                operation=oper,
                                                uuid=uuid)

    def vnc_subscribe_actions(self):
        msg = "Notification Message: %s" % (pformat(self.oper_info))
        self.logger.debug(msg)

        self.obj = None
        self.dependency_tracker = None
        self.obj_type = self.oper_info['type'].replace('-', '_')
        self.obj_class = self.db_cls.get_obj_type_map().get(self.obj_type)
        if self.obj_class is None:
            return

        oper = self.oper_info['oper']
        obj_id = self.oper_info['uuid']
        self.create_msgbus_trace(self.oper_info.get('request_id'), oper,
                                 obj_id)
        if oper == 'CREATE':
            self.handle_create()
        elif oper == 'UPDATE':
            self.handle_update()
        elif oper == 'DELETE':
            self.handle_delete()
        else:
            self.handle_unknown()
            return
        if self.obj is None:
            self.logger.warning(
                "Object %s uuid %s was not found for operation %s" %
                (self.obj_type, obj_id, oper))
            return
        self.evaluate_dependency()

    def _get_key_from_oper_info(self):
        if self.db_cls._indexed_by_name:
            return ':'.join(self.oper_info['fq_name'])
        return self.oper_info['uuid']

    def handle_create(self):
        obj_key = self._get_key_from_oper_info()
        obj_id = self.oper_info['uuid']
        obj_fq_name = self.oper_info['fq_name']
        self.db_cls._object_db.cache_uuid_to_fq_name_add(
            obj_id, obj_fq_name, self.obj_type)
        self.obj = self.obj_class.locate(obj_key)
        if self.obj is None:
            self.logger.info('%s id %s fq_name %s not found' %
                             (self.obj_type, obj_id, obj_fq_name))
            return
        self.dependency_tracker = DependencyTracker(
            self.db_cls.get_obj_type_map(), self.reaction_map)
        self.dependency_tracker.evaluate(self.obj_type, self.obj)

    def handle_update(self):
        obj_id = self.oper_info['uuid']
        self.obj = self.obj_class.get_by_uuid(obj_id)
        old_dt = None
        if self.obj is not None:
            old_dt = DependencyTracker(self.db_cls.get_obj_type_map(),
                                       self.reaction_map)
            old_dt.evaluate(self.obj_type, self.obj)
        else:
            self.logger.info('%s id %s not found' % (self.obj_type, obj_id))
            return

        try:
            ret = self.obj.update()
            if ret is not None and not ret:
                # If update returns None, the function may not support a
                # return value, hence treat it as if something might have
                # changed. If a value is returned, use its truth value.
                # If it True, then some change was detected.
                # If no change, then terminate dependency tracker
                return
        except NoIdError:
            obj_id = self.oper_info['uuid']
            self.logger.warning('%s uuid %s update caused NoIdError' %
                                (self.obj_type, obj_id))
            return

        self.dependency_tracker = DependencyTracker(
            self.db_cls.get_obj_type_map(), self.reaction_map)
        self.dependency_tracker.evaluate(self.obj_type, self.obj)
        if old_dt:
            for resource, ids in old_dt.resources.items():
                if resource not in self.dependency_tracker.resources:
                    self.dependency_tracker.resources[resource] = ids
                else:
                    self.dependency_tracker.resources[resource] = list(
                        set(self.dependency_tracker.resources[resource])
                        | set(ids))

    def handle_delete(self):
        obj_id = self.oper_info['uuid']
        self.obj = self.obj_class.get_by_uuid(obj_id)
        self.db_cls._object_db.cache_uuid_to_fq_name_del(obj_id)
        if self.obj is None:
            return
        self.dependency_tracker = DependencyTracker(
            self.db_cls.get_obj_type_map(), self.reaction_map)
        self.dependency_tracker.evaluate(self.obj_type, self.obj)
        obj_key = self._get_key_from_oper_info()
        self.obj_class.delete(obj_key)

    def handle_unknown(self):
        # unknown operation
        self.logger.error('Unknown operation %s' % self.oper_info['oper'])

    def init_msgbus_fq_name(self):
        self.msg_tracer.fq_name = self.obj.name

    def init_msgbus_dtr(self):
        self.msg_tracer.dependency_tracker_resources = []

    def add_msgbus_dtr(self, res_type, res_id_list):
        dtr = DependencyTrackerResource(obj_type=res_type,
                                        obj_keys=res_id_list)
        self.msg_tracer.dependency_tracker_resources.append(dtr)

    def evaluate_dependency(self):
        if not self.dependency_tracker:
            return

        self.init_msgbus_fq_name()
        self.init_msgbus_dtr()

        for res_type, res_id_list in self.dependency_tracker.resources.items():
            if not res_id_list:
                continue
            self.add_msgbus_dtr(res_type, res_id_list)
            cls = self.db_cls.get_obj_type_map().get(res_type)
            if cls is None:
                continue
            for res_id in res_id_list:
                res_obj = cls.get(res_id)
                if res_obj is not None:
                    res_obj.evaluate()

    def close(self):
        self._vnc_kombu.shutdown()
Exemplo n.º 4
0
class VncAmqpHandle(object):
    def __init__(self, logger, db_cls, reaction_map, q_name_prefix, args=None):
        self.logger = logger
        self.db_cls = db_cls
        self.reaction_map = reaction_map
        self.q_name_prefix = q_name_prefix
        self._db_resync_done = gevent.event.Event()
        self._args = args

    def establish(self):
        q_name = '.'.join([self.q_name_prefix, socket.gethostname()])
        self._vnc_kombu = VncKombuClient(
            self._args.rabbit_server,
            self._args.rabbit_port,
            self._args.rabbit_user,
            self._args.rabbit_password,
            self._args.rabbit_vhost,
            self._args.rabbit_ha_mode,
            q_name,
            self._vnc_subscribe_callback,
            self.logger.log,
            rabbit_use_ssl=self._args.rabbit_use_ssl,
            kombu_ssl_version=self._args.kombu_ssl_version,
            kombu_ssl_keyfile=self._args.kombu_ssl_keyfile,
            kombu_ssl_certfile=self._args.kombu_ssl_certfile,
            kombu_ssl_ca_certs=self._args.kombu_ssl_ca_certs)

    def msgbus_store_err_msg(self, msg):
        self.msg_tracer.error = msg

    def msgbus_trace_msg(self):
        self.msg_tracer.trace_msg(name='MessageBusNotifyTraceBuf',
                                  sandesh=self.logger._sandesh)

    def _vnc_subscribe_callback(self, oper_info):
        self._db_resync_done.wait()
        try:
            self.oper_info = oper_info
            self.vnc_subscribe_actions()

        except Exception:
            string_buf = cStringIO.StringIO()
            cgitb_hook(file=string_buf, format="text")
            self.logger.error(string_buf.getvalue())

            self.msgbus_store_err_msg(string_buf.getvalue())
            try:
                with open(self._args.trace_file, 'a') as err_file:
                    err_file.write(string_buf.getvalue())
            except IOError:
                pass
        finally:
            try:
                self.msgbus_trace_msg()
            except Exception:
                pass
            del self.oper_info
            del self.obj_type
            del self.obj_class
            del self.obj
            del self.dependency_tracker

    def create_msgbus_trace(self, request_id, oper, uuid):
        self.msg_tracer = MessageBusNotifyTrace(request_id=request_id,
                                                operation=oper,
                                                uuid=uuid)

    def vnc_subscribe_actions(self):
        msg = "Notification Message: %s" % (pformat(self.oper_info))
        self.logger.debug(msg)

        self.obj = None
        self.dependency_tracker = None
        self.obj_type = self.oper_info['type'].replace('-', '_')
        self.obj_class = self.db_cls.get_obj_type_map().get(self.obj_type)
        if self.obj_class is None:
            return

        oper = self.oper_info['oper']
        obj_id = self.oper_info['uuid']
        self.create_msgbus_trace(self.oper_info.get('request_id'), oper,
                                 obj_id)
        if oper == 'CREATE':
            self.handle_create()
        elif oper == 'UPDATE':
            self.handle_update()
        elif oper == 'DELETE':
            self.handle_delete()
        else:
            self.handle_unknown()
            return
        if self.obj is None:
            self.logger.error('Error while accessing %s uuid %s' %
                              (self.obj_type, obj_id))
            return
        self.evaluate_dependency()

    def handle_create(self):
        obj_dict = self.oper_info['obj_dict']
        obj_key = self.db_cls.get_key_from_dict(obj_dict)
        obj_id = self.oper_info['uuid']
        obj_fq_name = obj_dict['fq_name']
        self.db_cls._object_db.cache_uuid_to_fq_name_add(
            obj_id, obj_fq_name, self.obj_type)
        self.obj = self.obj_class.locate(obj_key)
        if self.obj is None:
            self.logger.info('%s id %s fq_name %s not found' %
                             (self.obj_type, obj_id, obj_fq_name))
            return
        self.dependency_tracker = DependencyTracker(
            self.db_cls.get_obj_type_map(), self.reaction_map)
        self.dependency_tracker.evaluate(self.obj_type, self.obj)

    def handle_update(self):
        obj_id = self.oper_info['uuid']
        self.obj = self.obj_class.get_by_uuid(obj_id)
        old_dt = None
        if self.obj is not None:
            old_dt = DependencyTracker(self.db_cls.get_obj_type_map(),
                                       self.reaction_map)
            old_dt.evaluate(self.obj_type, self.obj)
        else:
            self.logger.info('%s id %s not found' % (self.obj_type, obj_id))
            return

        try:
            self.obj.update()
        except NoIdError:
            obj_id = self.oper_info['uuid']
            self.logger.warning('%s uuid %s update caused NoIdError' %
                                (self.obj_type, obj_id))
            return

        self.dependency_tracker = DependencyTracker(
            self.db_cls.get_obj_type_map(), self.reaction_map)
        self.dependency_tracker.evaluate(self.obj_type, self.obj)
        if old_dt:
            for resource, ids in old_dt.resources.items():
                if resource not in self.dependency_tracker.resources:
                    self.dependency_tracker.resources[resource] = ids
                else:
                    self.dependency_tracker.resources[resource] = list(
                        set(self.dependency_tracker.resources[resource])
                        | set(ids))

    def handle_delete(self):
        obj_id = self.oper_info['uuid']
        self.obj = self.obj_class.get_by_uuid(obj_id)
        self.db_cls._object_db.cache_uuid_to_fq_name_del(obj_id)
        if self.obj is None:
            return
        self.dependency_tracker = DependencyTracker(
            self.db_cls.get_obj_type_map(), self.reaction_map)
        self.dependency_tracker.evaluate(self.obj_type, self.obj)
        obj_key = self.db_cls.get_key_from_dict(self.oper_info['obj_dict'])
        self.obj_class.delete(obj_key)

    def handle_unknown(self):
        # unknown operation
        self.logger.error('Unknown operation %s' % self.oper_info['oper'])

    def init_msgbus_fq_name(self):
        self.msg_tracer.fq_name = self.obj.name

    def init_msgbus_dtr(self):
        self.msg_tracer.dependency_tracker_resources = []

    def add_msgbus_dtr(self, res_type, res_id_list):
        dtr = DependencyTrackerResource(obj_type=res_type,
                                        obj_keys=res_id_list)
        self.msg_tracer.dependency_tracker_resources.append(dtr)

    def evaluate_dependency(self):
        if not self.dependency_tracker:
            return

        self.init_msgbus_fq_name()
        self.init_msgbus_dtr()

        for res_type, res_id_list in self.dependency_tracker.resources.items():
            if not res_id_list:
                continue
            self.add_msgbus_dtr(res_type, res_id_list)
            cls = self.db_cls.get_obj_type_map().get(res_type)
            if cls is None:
                continue
            for res_id in res_id_list:
                res_obj = cls.get(res_id)
                if res_obj is not None:
                    res_obj.evaluate()

    def close(self):
        self._vnc_kombu.shutdown()
Exemplo n.º 5
0
class VncAmqpHandle(object):

    def __init__(self, logger, db_cls, reaction_map, q_name_prefix, args=None):
        self.logger = logger
        self.db_cls = db_cls
        self.reaction_map = reaction_map
        self.q_name_prefix = q_name_prefix
        self._db_resync_done = gevent.event.Event()
        self._args = args

    def establish(self):
        q_name = '.'.join([self.q_name_prefix, socket.gethostname()])
        self._vnc_kombu = VncKombuClient(
                self._args.rabbit_server, self._args.rabbit_port,
                self._args.rabbit_user, self._args.rabbit_password,
                self._args.rabbit_vhost, self._args.rabbit_ha_mode,
                q_name, self._vnc_subscribe_callback,
                self.logger.log, rabbit_use_ssl=self._args.rabbit_use_ssl,
                kombu_ssl_version=self._args.kombu_ssl_version,
                kombu_ssl_keyfile=self._args.kombu_ssl_keyfile,
                kombu_ssl_certfile=self._args.kombu_ssl_certfile,
                kombu_ssl_ca_certs=self._args.kombu_ssl_ca_certs)

    def msgbus_store_err_msg(self, msg):
        self.msg_tracer.error = msg

    def msgbus_trace_msg(self):
            self.msg_tracer.trace_msg(name='MessageBusNotifyTraceBuf',
                                      sandesh=self.logger._sandesh)

    def _vnc_subscribe_callback(self, oper_info):
        self._db_resync_done.wait()
        try:
            self.oper_info = oper_info
            self.vnc_subscribe_actions()

        except Exception:
            string_buf = cStringIO.StringIO()
            cgitb_hook(file=string_buf, format="text")
            self.logger.error(string_buf.getvalue())

            self.msgbus_store_err_msg(string_buf.getvalue())
            try:
                with open(self._args.trace_file, 'a') as err_file:
                    err_file.write(string_buf.getvalue())
            except IOError:
                pass
        finally:
            try:
                self.msgbus_trace_msg()
            except Exception:
                pass
            del self.oper_info
            del self.obj_type
            del self.obj_class
            del self.obj
            del self.dependency_tracker

    def create_msgbus_trace(self, request_id, oper, uuid):
        self.msg_tracer = MessageBusNotifyTrace(request_id=request_id,
                                                operation=oper, uuid=uuid)

    def vnc_subscribe_actions(self):
        msg = "Notification Message: %s" % (pformat(self.oper_info))
        self.logger.debug(msg)

        self.obj = None
        self.dependency_tracker = None
        self.obj_type = self.oper_info['type'].replace('-', '_')
        self.obj_class = self.db_cls.get_obj_type_map().get(self.obj_type)
        if self.obj_class is None:
            return

        oper = self.oper_info['oper']
        obj_id = self.oper_info['uuid']
        self.create_msgbus_trace(self.oper_info.get('request_id'),
                                 oper, obj_id)
        if oper == 'CREATE':
            self.handle_create()
        elif oper == 'UPDATE':
            self.handle_update()
        elif oper == 'DELETE':
            self.handle_delete()
        else:
            self.handle_unknown()
            return
        if self.obj is None:
            self.logger.error('Error while accessing %s uuid %s' % (
                self.obj_type, obj_id))
            return
        self.evaluate_dependency()

    def handle_create(self):
        obj_dict = self.oper_info['obj_dict']
        obj_key = self.db_cls.get_key_from_dict(obj_dict)
        obj_id = self.oper_info['uuid']
        obj_fq_name = obj_dict['fq_name']
        self.db_cls._object_db.cache_uuid_to_fq_name_add(
                obj_id, obj_fq_name, self.obj_type)
        self.obj = self.obj_class.locate(obj_key)
        if self.obj is None:
            self.logger.info('%s id %s fq_name %s not found' % (
                self.obj_type, obj_id, obj_fq_name))
            return
        self.dependency_tracker = DependencyTracker(
            self.db_cls.get_obj_type_map(), self.reaction_map)
        self.dependency_tracker.evaluate(self.obj_type, self.obj)

    def handle_update(self):
        obj_id = self.oper_info['uuid']
        self.obj = self.obj_class.get_by_uuid(obj_id)
        old_dt = None
        if self.obj is not None:
            old_dt = DependencyTracker(
                self.db_cls.get_obj_type_map(), self.reaction_map)
            old_dt.evaluate(self.obj_type, self.obj)
        else:
            self.logger.info('%s id %s not found' % (self.obj_type,
                                                     obj_id))
            return

        try:
            self.obj.update()
        except NoIdError:
            obj_id = self.oper_info['uuid']
            self.logger.warning('%s uuid %s update caused NoIdError' %
                                (self.obj_type, obj_id))
            return

        self.dependency_tracker = DependencyTracker(
                self.db_cls.get_obj_type_map(), self.reaction_map)
        self.dependency_tracker.evaluate(self.obj_type, self.obj)
        if old_dt:
            for resource, ids in old_dt.resources.items():
                if resource not in self.dependency_tracker.resources:
                    self.dependency_tracker.resources[resource] = ids
                else:
                    self.dependency_tracker.resources[resource] = list(
                        set(self.dependency_tracker.resources[resource]) |
                        set(ids))

    def handle_delete(self):
        obj_id = self.oper_info['uuid']
        self.obj = self.obj_class.get_by_uuid(obj_id)
        self.db_cls._object_db.cache_uuid_to_fq_name_del(obj_id)
        if self.obj is None:
            return
        self.dependency_tracker = DependencyTracker(
            self.db_cls.get_obj_type_map(), self.reaction_map)
        self.dependency_tracker.evaluate(self.obj_type, self.obj)
        obj_key = self.db_cls.get_key_from_dict(self.oper_info['obj_dict'])
        self.obj_class.delete(obj_key)

    def handle_unknown(self):
        # unknown operation
        self.logger.error('Unknown operation %s' % self.oper_info['oper'])

    def init_msgbus_fq_name(self):
        self.msg_tracer.fq_name = self.obj.name

    def init_msgbus_dtr(self):
        self.msg_tracer.dependency_tracker_resources = []

    def add_msgbus_dtr(self, res_type, res_id_list):
        dtr = DependencyTrackerResource(obj_type=res_type,
                                        obj_keys=res_id_list)
        self.msg_tracer.dependency_tracker_resources.append(dtr)

    def evaluate_dependency(self):
        if not self.dependency_tracker:
            return

        self.init_msgbus_fq_name()
        self.init_msgbus_dtr()

        for res_type, res_id_list in self.dependency_tracker.resources.items():
            if not res_id_list:
                continue
            self.add_msgbus_dtr(res_type, res_id_list)
            cls = self.db_cls.get_obj_type_map().get(res_type)
            if cls is None:
                continue
            for res_id in res_id_list:
                res_obj = cls.get(res_id)
                if res_obj is not None:
                    res_obj.evaluate()

    def close(self):
        self._vnc_kombu.shutdown()
Exemplo n.º 6
0
class VncAmqpHandle(object):
    def __init__(self,
                 sandesh,
                 logger,
                 db_cls,
                 reaction_map,
                 q_name_prefix,
                 rabbitmq_cfg,
                 host_ip,
                 trace_file=None,
                 timer_obj=None,
                 register_handler=True):
        self.sandesh = sandesh
        self.logger = logger
        self.db_cls = db_cls
        self.reaction_map = reaction_map
        self.q_name_prefix = q_name_prefix
        self._db_resync_done = gevent.event.Event()
        self._rabbitmq_cfg = rabbitmq_cfg
        self._trace_file = trace_file
        self.timer = timer_obj
        self.host_ip = host_ip
        self.register_handler = register_handler
        self._vnc_kombu = None

    def establish(self):
        q_name = '.'.join([self.q_name_prefix, socket.getfqdn(self.host_ip)])
        self._vnc_kombu = VncKombuClient(
            self._rabbitmq_cfg['servers'],
            self._rabbitmq_cfg['port'],
            self._rabbitmq_cfg['user'],
            self._rabbitmq_cfg['password'],
            self._rabbitmq_cfg['vhost'],
            self._rabbitmq_cfg['ha_mode'],
            q_name,
            self._vnc_subscribe_callback,
            self.logger.log,
            rabbit_use_ssl=self._rabbitmq_cfg['use_ssl'],
            kombu_ssl_version=self._rabbitmq_cfg['ssl_version'],
            kombu_ssl_keyfile=self._rabbitmq_cfg['ssl_keyfile'],
            kombu_ssl_certfile=self._rabbitmq_cfg['ssl_certfile'],
            kombu_ssl_ca_certs=self._rabbitmq_cfg['ssl_ca_certs'],
            register_handler=self.register_handler)

    def msgbus_store_err_msg(self, msg):
        self.msg_tracer.error = msg

    def msgbus_trace_msg(self):
        self.msg_tracer.trace_msg(name='MessageBusNotifyTraceBuf',
                                  sandesh=self.sandesh)

    def log_exception(self):
        string_buf = StringIO()
        cgitb_hook(file=string_buf, format="text")
        self.logger.error(string_buf.getvalue())
        self.msgbus_store_err_msg(string_buf.getvalue())
        if not self._trace_file:
            return
        try:
            with open(self._trace_file, 'a') as err_file:
                err_file.write(string_buf.getvalue())
        except IOError:
            pass

    def log_ignored_errors(self, obj_class):
        if not self._trace_file:
            return
        try:
            with open(self._trace_file, 'a') as err_file:
                for err_msg, tb in obj_class._ignored_errors.items():
                    err_file.write("\nIGNORING: %s\n%s" % (err_msg, tb))
        except IOError:
            pass
        finally:
            obj_class.clear_ignored_errors()

    def _vnc_subscribe_callback(self, oper_info):
        self._db_resync_done.wait()
        try:
            self.oper_info = oper_info
            self.vnc_subscribe_actions()

        except ConnectionError:
            try:
                # retry write during api-server ConnectionError
                self.vnc_subscribe_actions()
            except ConnectionError:
                # log the exception, and exit during api-server
                # ConnectionError on retry to let standby to become active.
                self.log_exception()
                self.logger.error("Api-server connection lost. Exiting")
                self.close()
                raise SystemExit
            except Exception:
                self.log_exception()
        except Exception:
            self.log_exception()
        finally:
            try:
                self.msgbus_trace_msg()
            except Exception:
                pass
            del self.oper_info
            del self.obj_type
            del self.obj_class
            del self.obj
            del self.dependency_tracker

    def create_msgbus_trace(self, request_id, oper, uuid):
        self.msg_tracer = MessageBusNotifyTrace(request_id=request_id,
                                                operation=oper,
                                                uuid=uuid)

    def vnc_subscribe_actions(self):
        msg = "Notification Message: %s" % (pformat(self.oper_info))
        self.logger.debug(msg)

        self.obj = None
        self.dependency_tracker = None
        self.obj_type = self.oper_info['type'].replace('-', '_')
        self.obj_class = self.db_cls.get_obj_type_map().get(self.obj_type)
        if self.obj_class is None:
            return

        oper = self.oper_info['oper']
        obj_id = self.oper_info['uuid']
        self.create_msgbus_trace(self.oper_info.get('request_id'), oper,
                                 obj_id)
        if oper == 'CREATE':
            self.handle_create()
        elif oper == 'UPDATE':
            self.handle_update()
        elif oper == 'DELETE':
            self.handle_delete()
        elif oper == 'UPDATE-IMPLICIT':
            # Ignore this operation
            return
        else:
            self.handle_unknown()
            return
        if self.obj is None:
            self.logger.warning(
                "Object %s uuid %s was not found for operation %s" %
                (self.obj_type, obj_id, oper))
            return
        self.evaluate_dependency()

    def _get_key_from_oper_info(self):
        if self.db_cls._indexed_by_name:
            return ':'.join(self.oper_info['fq_name'])
        return self.oper_info['uuid']

    def _set_meta(self):
        self.db_cls.set_meta({
            'request_id': self.oper_info.get('request-id'),
            'oper': self.oper_info.get('oper')
        })

    def handle_create(self):
        obj_key = self._get_key_from_oper_info()
        obj_id = self.oper_info['uuid']
        obj_fq_name = self.oper_info['fq_name']
        self.db_cls._object_db.cache_uuid_to_fq_name_add(
            obj_id, obj_fq_name, self.obj_type)
        self._set_meta()
        try:
            self.obj = self.obj_class.locate(obj_key)
        finally:
            self.log_ignored_errors(self.obj_class)
        if self.obj is None:
            self.logger.info('%s id %s fq_name %s not found' %
                             (self.obj_type, obj_id, obj_fq_name))
            return
        self.dependency_tracker = DependencyTracker(
            self.db_cls.get_obj_type_map(), self.reaction_map)
        self.dependency_tracker.evaluate(self.obj_type, self.obj)

    def handle_update(self):
        obj_id = self.oper_info['uuid']
        self.obj = self.obj_class.get_by_uuid(obj_id)
        old_dt = None
        if self.obj is not None:
            old_dt = DependencyTracker(self.db_cls.get_obj_type_map(),
                                       self.reaction_map)
            old_dt.evaluate(self.obj_type, self.obj)
        else:
            self.logger.info('%s id %s not found' % (self.obj_type, obj_id))
            return

        try:
            self._set_meta()
            ret = self.obj.update()
            if ret is not None and not ret:
                # If update returns None, the function may not support a
                # return value, hence treat it as if something might have
                # changed. If a value is returned, use its truth value.
                # If it True, then some change was detected.
                # If no change, then terminate dependency tracker
                return
        except NoIdError:
            obj_id = self.oper_info['uuid']
            self.logger.warning('%s uuid %s update caused NoIdError' %
                                (self.obj_type, obj_id))
            return

        self.dependency_tracker = DependencyTracker(
            self.db_cls.get_obj_type_map(), self.reaction_map)
        self.dependency_tracker.evaluate(self.obj_type, self.obj)
        if old_dt:
            for resource, ids in list(old_dt.resources.items()):
                if resource not in self.dependency_tracker.resources:
                    self.dependency_tracker.resources[resource] = ids
                else:
                    self.dependency_tracker.resources[resource] = list(
                        set(self.dependency_tracker.resources[resource])
                        | set(ids))

    def handle_delete(self):
        obj_id = self.oper_info['uuid']
        self.obj = self.obj_class.get_by_uuid(obj_id)
        self.db_cls._object_db.cache_uuid_to_fq_name_del(obj_id)
        if self.obj is None:
            return
        self.dependency_tracker = DependencyTracker(
            self.db_cls.get_obj_type_map(), self.reaction_map)
        self.dependency_tracker.evaluate(self.obj_type, self.obj)
        obj_key = self._get_key_from_oper_info()
        self._set_meta()
        self.obj_class.delete(obj_key)

    def handle_unknown(self):
        # unknown operation
        self.logger.error('Unknown operation %s' % self.oper_info['oper'])

    def init_msgbus_fq_name(self):
        self.msg_tracer.fq_name = self.obj.name

    def init_msgbus_dtr(self):
        self.msg_tracer.dependency_tracker_resources = []

    def add_msgbus_dtr(self, res_type, res_id_list):
        dtr = DependencyTrackerResource(obj_type=res_type,
                                        obj_keys=res_id_list)
        self.msg_tracer.dependency_tracker_resources.append(dtr)

    def evaluate_dependency(self):
        if not self.dependency_tracker:
            return

        self.init_msgbus_fq_name()
        self.init_msgbus_dtr()

        evaluate_kwargs = {}
        if self.timer and self.timer.yield_in_evaluate:
            evaluate_kwargs['timer'] = self.timer

        for res_type, res_id_list in list(
                self.dependency_tracker.resources.items()):
            if not res_id_list:
                continue
            self.add_msgbus_dtr(res_type, res_id_list)
            cls = self.db_cls.get_obj_type_map().get(res_type)
            if cls is None:
                continue
            for res_id in res_id_list:
                res_obj = cls.get(res_id)
                if res_obj is not None:
                    try:
                        if evaluate_kwargs:
                            res_obj.evaluate(**evaluate_kwargs)
                        else:
                            res_obj.evaluate()
                    finally:
                        self.log_ignored_errors(res_obj)
                    if self.timer:
                        self.timer.timed_yield()

    def close(self):
        if self._vnc_kombu is not None:
            # VncKombuClient is instancied when calling 'establish()',
            # if for some reasons (mostly related to cleanup after
            # exception handling) we call `close()` we should consider
            # a no-op.
            self._vnc_kombu.shutdown()
Exemplo n.º 7
0
class VncAmqpHandle(object):

    def __init__(self, sandesh, logger, db_cls, reaction_map, q_name_prefix,
                 rabbitmq_cfg, trace_file=None):
        self.sandesh = sandesh
        self.logger = logger
        self.db_cls = db_cls
        self.reaction_map = reaction_map
        self.q_name_prefix = q_name_prefix
        self._db_resync_done = gevent.event.Event()
        self._rabbitmq_cfg = rabbitmq_cfg
        self._trace_file = trace_file

    def establish(self):
        q_name = '.'.join([self.q_name_prefix, socket.gethostname()])
        self._vnc_kombu = VncKombuClient(
                self._rabbitmq_cfg['servers'], self._rabbitmq_cfg['port'],
                self._rabbitmq_cfg['user'], self._rabbitmq_cfg['password'],
                self._rabbitmq_cfg['vhost'], self._rabbitmq_cfg['ha_mode'],
                q_name, self._vnc_subscribe_callback,
                self.logger.log, rabbit_use_ssl=self._rabbitmq_cfg['use_ssl'],
                kombu_ssl_version=self._rabbitmq_cfg['ssl_version'],
                kombu_ssl_keyfile=self._rabbitmq_cfg['ssl_keyfile'],
                kombu_ssl_certfile=self._rabbitmq_cfg['ssl_certfile'],
                kombu_ssl_ca_certs=self._rabbitmq_cfg['ssl_ca_certs'])

    def msgbus_store_err_msg(self, msg):
        self.msg_tracer.error = msg

    def msgbus_trace_msg(self):
        self.msg_tracer.trace_msg(name='MessageBusNotifyTraceBuf',
                                  sandesh=self.sandesh)

    def log_exception(self):
        string_buf = cStringIO.StringIO()
        cgitb_hook(file=string_buf, format="text")
        self.logger.error(string_buf.getvalue())
        self.msgbus_store_err_msg(string_buf.getvalue())
        if not self._trace_file:
            return
        try:
            with open(self._trace_file, 'a') as err_file:
                err_file.write(string_buf.getvalue())
        except IOError:
            pass

    def _vnc_subscribe_callback(self, oper_info):
        self._db_resync_done.wait()
        try:
            self.oper_info = oper_info
            self.vnc_subscribe_actions()

        except ConnectionError:
            try:
                # retry write during api-server ConnectionError
                self.vnc_subscribe_actions()
            except ConnectionError:
                # log the exception, and exit during api-server
                # ConnectionError on retry to let standby to become active.
                self.log_exception()
                self.logger.error("Api-server connection lost. Exiting")
                self.close()
                raise SystemExit
            except Exception:
                self.log_exception()
        except Exception:
            self.log_exception()
        finally:
            try:
                self.msgbus_trace_msg()
            except Exception:
                pass
            del self.oper_info
            del self.obj_type
            del self.obj_class
            del self.obj
            del self.dependency_tracker

    def create_msgbus_trace(self, request_id, oper, uuid):
        self.msg_tracer = MessageBusNotifyTrace(request_id=request_id,
                                                operation=oper, uuid=uuid)

    def vnc_subscribe_actions(self):
        msg = "Notification Message: %s" % (pformat(self.oper_info))
        self.logger.debug(msg)

        self.obj = None
        self.dependency_tracker = None
        self.obj_type = self.oper_info['type'].replace('-', '_')
        self.obj_class = self.db_cls.get_obj_type_map().get(self.obj_type)
        if self.obj_class is None:
            return

        oper = self.oper_info['oper']
        obj_id = self.oper_info['uuid']
        self.create_msgbus_trace(self.oper_info.get('request_id'),
                                 oper, obj_id)
        if oper == 'CREATE':
            self.handle_create()
        elif oper == 'UPDATE':
            self.handle_update()
        elif oper == 'DELETE':
            self.handle_delete()
        elif oper == 'UPDATE-IMPLICIT':
            # Ignore this operation
            return
        else:
            self.handle_unknown()
            return
        if self.obj is None:
            self.logger.warning(
                    "Object %s uuid %s was not found for operation %s" %
                    (self. obj_type, obj_id, oper))
            return
        self.evaluate_dependency()

    def _get_key_from_oper_info(self):
        if self.db_cls._indexed_by_name:
            return ':'.join(self.oper_info['fq_name'])
        return self.oper_info['uuid']

    def handle_create(self):
        obj_key = self._get_key_from_oper_info()
        obj_id = self.oper_info['uuid']
        obj_fq_name = self.oper_info['fq_name']
        self.db_cls._object_db.cache_uuid_to_fq_name_add(
                obj_id, obj_fq_name, self.obj_type)
        self.obj = self.obj_class.locate(obj_key)
        if self.obj is None:
            self.logger.info('%s id %s fq_name %s not found' % (
                self.obj_type, obj_id, obj_fq_name))
            return
        self.dependency_tracker = DependencyTracker(
            self.db_cls.get_obj_type_map(), self.reaction_map)
        self.dependency_tracker.evaluate(self.obj_type, self.obj)

    def handle_update(self):
        obj_id = self.oper_info['uuid']
        self.obj = self.obj_class.get_by_uuid(obj_id)
        old_dt = None
        if self.obj is not None:
            old_dt = DependencyTracker(
                self.db_cls.get_obj_type_map(), self.reaction_map)
            old_dt.evaluate(self.obj_type, self.obj)
        else:
            self.logger.info('%s id %s not found' % (self.obj_type,
                                                     obj_id))
            return

        try:
            ret = self.obj.update()
            if ret is not None and not ret:
                # If update returns None, the function may not support a
                # return value, hence treat it as if something might have
                # changed. If a value is returned, use its truth value.
                # If it True, then some change was detected.
                # If no change, then terminate dependency tracker
                return
        except NoIdError:
            obj_id = self.oper_info['uuid']
            self.logger.warning('%s uuid %s update caused NoIdError' %
                                (self.obj_type, obj_id))
            return

        self.dependency_tracker = DependencyTracker(
                self.db_cls.get_obj_type_map(), self.reaction_map)
        self.dependency_tracker.evaluate(self.obj_type, self.obj)
        if old_dt:
            for resource, ids in old_dt.resources.items():
                if resource not in self.dependency_tracker.resources:
                    self.dependency_tracker.resources[resource] = ids
                else:
                    self.dependency_tracker.resources[resource] = list(
                        set(self.dependency_tracker.resources[resource]) |
                        set(ids))

    def handle_delete(self):
        obj_id = self.oper_info['uuid']
        self.obj = self.obj_class.get_by_uuid(obj_id)
        self.db_cls._object_db.cache_uuid_to_fq_name_del(obj_id)
        if self.obj is None:
            return
        self.dependency_tracker = DependencyTracker(
            self.db_cls.get_obj_type_map(), self.reaction_map)
        self.dependency_tracker.evaluate(self.obj_type, self.obj)
        obj_key = self._get_key_from_oper_info()
        self.obj_class.delete(obj_key)

    def handle_unknown(self):
        # unknown operation
        self.logger.error('Unknown operation %s' % self.oper_info['oper'])

    def init_msgbus_fq_name(self):
        self.msg_tracer.fq_name = self.obj.name

    def init_msgbus_dtr(self):
        self.msg_tracer.dependency_tracker_resources = []

    def add_msgbus_dtr(self, res_type, res_id_list):
        dtr = DependencyTrackerResource(obj_type=res_type,
                                        obj_keys=res_id_list)
        self.msg_tracer.dependency_tracker_resources.append(dtr)

    def evaluate_dependency(self):
        if not self.dependency_tracker:
            return

        self.init_msgbus_fq_name()
        self.init_msgbus_dtr()

        for res_type, res_id_list in self.dependency_tracker.resources.items():
            if not res_id_list:
                continue
            self.add_msgbus_dtr(res_type, res_id_list)
            cls = self.db_cls.get_obj_type_map().get(res_type)
            if cls is None:
                continue
            for res_id in res_id_list:
                res_obj = cls.get(res_id)
                if res_obj is not None:
                    res_obj.evaluate()

    def close(self):
        self._vnc_kombu.shutdown()