protected Map<Long, AgentVmInfo> convertToInfos(final Map<String, Pair<String, State>> newStates) { final HashMap<Long, AgentVmInfo> map = new HashMap<Long, AgentVmInfo>(); if (newStates == null) { return map; } Collection<VirtualMachineGuru<? extends VMInstanceVO>> vmGurus = _vmGurus.values(); boolean is_alien_vm = true; long alien_vm_count = -1; for (Map.Entry<String, Pair<String, State>> entry : newStates.entrySet()) { is_alien_vm = true; for (VirtualMachineGuru<? extends VMInstanceVO> vmGuru : vmGurus) { String name = entry.getKey(); VMInstanceVO vm = vmGuru.findByName(name); if (vm != null) { map.put(vm.getId(), new AgentVmInfo(entry.getKey(), vmGuru, vm, entry.getValue().second(), entry.getValue().first())); is_alien_vm = false; break; } Long id = vmGuru.convertToId(name); if (id != null) { map.put(id, new AgentVmInfo(entry.getKey(), vmGuru, null, entry.getValue().second(), entry.getValue().first())); is_alien_vm = false; break; } } // alien VMs if (is_alien_vm){ map.put(alien_vm_count--, new AgentVmInfo(entry.getKey(), null, null, entry.getValue().second(), entry.getValue().first())); s_logger.warn("Found an alien VM " + entry.getKey()); } } return map; }该方法会在开始定义一个map作为返回值,之后遍历db中所有的vm(vmGurus)并与newStates比较,判断为alien的vm会赋一个负数值,并放入map中返回给上一级方法,其中map的value是newAgentVmInfo(),传入参数中guru和vm为null。上一级方法调用者为:deltaSync和fullSync。
public void deltaSync(Map<String, Pair<String, State>> newStates) { Map<Long, AgentVmInfo> states = convertToInfos(newStates); for (Map.Entry<Long, AgentVmInfo> entry : states.entrySet()) { AgentVmInfo info = entry.getValue(); VMInstanceVO vm = info.vm; Command command = null; if (vm != null) { Host host = _resourceMgr.findHostByGuid(info.getHostUuid()); long hId = host.getId(); HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType()); command = compareState(hId, vm, info, false, hvGuru.trackVmHostChange()); } else { if (s_logger.isDebugEnabled()) { s_logger.debug("Cleaning up a VM that is no longer found <deltaSync>: " + info.name); } command = cleanup(info.name); } if (command != null){ try { Host host = _resourceMgr.findHostByGuid(info.getHostUuid()); if (host != null){ Answer answer = _agentMgr.send(host.getId(), cleanup(info.name)); if (!answer.getResult()) { s_logger.warn("Unable to stop a VM due to " + answer.getDetails()); } } } catch (Exception e) { s_logger.warn("Unable to stop a VM due to " + e.getMessage()); } } } }fullSync中有类似逻辑,会在host刚刚加入CS或者重启CSmanagement-server的时候调用到,代码见fullSync最后一段逻辑:
for (final AgentVmInfo left : infos.values()) { if (!VirtualMachineName.isValidVmName(left.name)) continue; // if the vm doesn't follow CS naming ignore it for stopping try { Host host = _hostDao.findByGuid(left.getHostUuid()); if (host != null){ s_logger.warn("Stopping a VM which we do not have any record of " + left.name); Answer answer = _agentMgr.send(host.getId(), cleanup(left.name)); if (!answer.getResult()) { s_logger.warn("Unable to stop a VM due to " + answer.getDetails()); } } } catch (Exception e) { s_logger.warn("Unable to stop a VM due to " + e.getMessage()); } }第一行中的if语句给出了一个合理的设计,如果命名不符合CS命名规则,则不对该VM做任何处理,如果命名规则符合CS的命名规则,则会进入cleanup流程,这样既不会删除原有vm,同时又保证了CS的管理的虚拟机有唯一的命名。
if (VirtualMachineName.isValidVmName(info.name)){ command =cleanup(info.name); }