def __init__(self, service_name=None): self.dfa_cfg = {} self._load_default_opts() args = sys.argv[1:] try: opts = [(args[i], args[i + 1]) for i in range(0, len(args), 2)] except IndexError: opts = [] cfgfile = cfg.find_config_files(service_name) for k, v in opts: if k == '--config-file': cfgfile.append(v) multi_parser = cfg.MultiConfigParser() read_ok = multi_parser.read(cfgfile) if len(read_ok) != len(cfgfile): raise cfg.Error(_LE("Failed to parse config file.")) for parsed_file in multi_parser.parsed: for parsed_item in parsed_file.keys(): if parsed_item not in self.dfa_cfg: self.dfa_cfg[parsed_item] = {} for key, value in parsed_file[parsed_item].items(): self.dfa_cfg[parsed_item][key] = value[0] # Convert it to object. self._cfg = utils.Dict2Obj(self.dfa_cfg)
def test_topo_disc_cb(self): """Test the topology discovery CB function. """ topo_dict = self._get_topo_disc_arg() topo_dict_final = self._get_topo_dict_final() topo_obj = common_utils.Dict2Obj(topo_dict) with mock.patch('time.ctime') as ctime_fn: ctime_fn.return_value = 'Jan 1' self.dfa_vdp_mgr.topo_disc_cb(self.uplink, topo_obj) self.rpc_client.make_msg.assert_called_with( 'save_topo_disc_params', {}, msg=jsonutils.dumps(topo_dict_final))
def failure_recovery(self, fail_info): """Failure recovery task. In case of failure in projects, network and VM create/delete, this task goes through all failure cases and try the request. """ # Read failed entries from project database and send request # (create/delete - depends on failure type) to DCNM # 1. Try failure recovery for create project. LOG.info(_LI("Started failure_recovery.")) projs = self.get_fialed_projects_entries(constants.CREATE_FAIL) for proj in projs: LOG.debug("Failure recovery for project %(name)s.", ({ 'name': proj.name })) # Try to create the project in DCNM try: self.dcnm_client.create_project( proj.name, self.cfg.dcnm.default_partition_name, proj.dci_id) except dexc.DfaClientRequestFailed as e: LOG.error( _LE("failure_recovery: Failed to create %(proj)s " "on DCNM : %(reason)s"), { 'proj': proj.name, 'reason': str(e) }) else: # Request is sent successfully, update the database. self.update_project_info_cache(proj.id, dci_id=proj.dci_id, name=proj.name, opcode='update') LOG.debug( 'Success on failure recovery for ' 'project %(name)s', {'name': proj.name}) # 1.1 Try failure recovery for update project. projs = self.get_fialed_projects_entries(constants.UPDATE_FAIL) for proj in projs: LOG.debug("Failure recovery for project %(name)s.", ({ 'name': proj.name })) # This was failure of updating DCI id of the project in DCNM. try: self.dcnm_client.update_project( proj.name, self.cfg.dcnm.default_partition_name, proj.dci_id) except dexc.DfaClientRequestFailed as exc: LOG.error( _LE("failure_recovery: Failed to update %(proj)s " "on DCNM : %(reason)s"), { 'proj': proj.name, 'reason': str(exc) }) else: # Request is sent successfully, update the database. self.update_project_info_cache(proj.id, dci_id=proj.dci_id, name=proj.name, opcode='update') LOG.debug( 'Success on failure recovery update for ' 'project %(name)s', {'name': proj.name}) # 2. Try failure recovery for create network. nets = self.get_all_networks() for net in nets: if (net.result == constants.CREATE_FAIL and net.source.lower() == 'openstack'): net_id = net.network_id try: subnets = self.neutron_event.nclient.list_subnets( network_id=net_id).get('subnets') except dexc.ConnectionFailed: LOG.exception(_LE('Failed to get subnets list.')) continue for subnet in subnets: tenant_name = self.get_project_name(subnet['tenant_id']) snet = utils.Dict2Obj(subnet) try: # Check if config_profile is not NULL. if not net.config_profile: cfgp, fwd_mod = (self.dcnm_client. get_config_profile_for_network( net.name)) net.config_profile = cfgp net.fwd_mod = fwd_mod self.dcnm_client.create_network( tenant_name, net, snet, self.dcnm_dhcp) except dexc.DfaClientRequestFailed: # Still is failure, only log the error. LOG.error(_LE('Failed to create network %(net)s.'), {'net': net.name}) else: # Request is sent to DCNM, update the database params = dict( columns=dict(config_profile=net.config_profile, fwd_mod=net.fwd_mod, result=constants.RESULT_SUCCESS)) self.update_network(net_id, **params) LOG.debug( "Success on failure recovery to create " "%(net)s", {'net': net.name}) # 3. Try Failure recovery for VM create and delete. instances = self.get_vms() for vm in instances: vm_info = dict(status=vm.status, vm_mac=vm.mac, segmentation_id=vm.segmentation_id, host=vm.host, port_uuid=vm.port_id, net_uuid=vm.network_id, oui=dict(ip_addr=vm.ip, vm_name=vm.name, vm_uuid=vm.instance_id, gw_mac=vm.gw_mac, fwd_mod=vm.fwd_mod, oui_id='cisco')) if vm.result == constants.CREATE_FAIL: try: self.neutron_event.send_vm_info(str(vm.host), str(vm_info)) except Exception as e: # Failed to send info to the agent. Keep the data in the # database as failure to send it later. LOG.error( _LE('Failed to send VM info to agent. ' 'Reason %s'), str(e)) else: params = dict(columns=dict( result=constants.RESULT_SUCCESS)) self.update_vm_db(vm.port_id, **params) LOG.info(_LI('Created VM %(vm)s.'), {'vm': vm.name}) for vm in instances: if vm.result == constants.DELETE_FAIL: vm_info['status'] = 'down' try: self.neutron_event.send_vm_info(str(vm.host), str(vm_info)) except Exception as e: LOG.error( _LE('Failed to send VM info to agent. ' 'Reason %s'), str(e)) else: self.delete_vm_db(vm.instance_id) LOG.info(_LI('Deleted VM %(vm)s from DB.'), {'vm': vm.name}) # 4. Try failure recovery for delete network. for net in nets: if (net.result == constants.DELETE_FAIL and net.source.lower() == 'openstack'): net_id = net.network_id segid = net.segmentation_id tenant_name = self.get_project_name(net.tenant_id) try: self.dcnm_client.delete_network(tenant_name, net) except dexc.DfaClientRequestFailed: # Still is failure, only log the error. LOG.error(_LE('Failed to delete network %(net)s.'), {'net': net.name}) else: # Request is sent to DCNM, delete the entry # from database and return the segmentation id to the # pool. self.delete_network_db(net_id) self.segmentation_pool.add(segid) LOG.debug( "Success on failure recovery to deleted " "%(net)s", {'net': net.name}) # 5. Try failure recovery for delete project. projs = self.get_fialed_projects_entries(constants.DELETE_FAIL) for proj in projs: LOG.debug("Failure recovery for project %(name)s.", ({ 'name': proj.name })) # Try to delete the project in DCNM try: self.dcnm_client.delete_project( proj.name, self.cfg.dcnm.default_partition_name) except dexc.DfaClientRequestFailed as e: # Failed to delete project in DCNM. # Save the info and mark it as failure and retry it later. LOG.error( _LE("Failure recovery is failed to delete " "%(project)s on DCNM : %(reason)s"), { 'project': proj.name, 'reason': str(e) }) else: # Delete was successful, now update the database. self.update_project_info_cache(proj.id, opcode='delete') LOG.debug( "Success on failure recovery to deleted " "%(project)s", {'project': proj.name}) # 6. DHCP port consistency check for HA. if self.need_dhcp_check(): nets = self.get_all_networks() for net in nets: net_id = net.network_id LOG.debug("dhcp consistency check for net id %s", net_id) self.correct_dhcp_ports(net_id) self.decrement_dhcp_check() LOG.info(_LI("Finished failure_recovery."))