diff --git a/ovm/scripts/vm/hypervisor/ovm/OvmCommonModule.py b/ovm/scripts/vm/hypervisor/ovm/OvmCommonModule.py index 7eb2454239e..511d8d30a53 100755 --- a/ovm/scripts/vm/hypervisor/ovm/OvmCommonModule.py +++ b/ovm/scripts/vm/hypervisor/ovm/OvmCommonModule.py @@ -18,12 +18,14 @@ from xmlrpclib import Fault as XmlRpcFault from OVSCommons import * from OvmLoggerModule import OvmLogger from OVSXXenStore import xen_get_vm_path +from OVSSiteRMServer import get_master_ip HEARTBEAT_TIMESTAMP_FORMAT='%s' HEARTBEAT_TIMESTAMP_PATTERN='(\\d+.\d+<\/timestamp\>)' HEARTBEAT_DIR='heart_beat' ETC_HOSTS='/etc/hosts' HOSTNAME_FILE='/etc/sysconfig/network' +OWNER_FILE_PREFIX='host_' logger = OvmLogger('OvmCommon') @@ -124,4 +126,9 @@ def getVmNameFromConfigureFile(cfgPath): return value fd.close() raise Exception('Cannot find vm name in %s'%cfgPath) + +def makeOwnerFileName(): + hostIp = successToMap(get_master_ip())['ip'] + ownerFileName = OWNER_FILE_PREFIX + hostIp.replace('.', '_') + return ownerFileName diff --git a/ovm/scripts/vm/hypervisor/ovm/OvmHostModule.py b/ovm/scripts/vm/hypervisor/ovm/OvmHostModule.py index 983c50593f1..29a9f9ae393 100755 --- a/ovm/scripts/vm/hypervisor/ovm/OvmHostModule.py +++ b/ovm/scripts/vm/hypervisor/ovm/OvmHostModule.py @@ -176,6 +176,26 @@ class OvmHost(OvmObject): @staticmethod def getAllVms(): + def scanStoppedVmOnPrimaryStorage(vms): + def isMyVmDirLink(path): + return (islink(path) and exists(join(path, 'vm.cfg')) and ('-' in basename(path)) and (exists(join(path, makeOwnerFileName())))) + + mps = OvmStoragePool()._getAllMountPoints() + for mountPoint in mps: + runningPool = join(mountPoint, 'running_pool') + for dir in os.listdir(runningPool): + vmDir = join(runningPool, dir) + if not isMyVmDirLink(vmDir): + logger.debug(OvmHost.getAllVms, "%s is not our vm directory, skip it"%vmDir) + continue + if vms.has_key(dir): + logger.debug(OvmHost.getAllVms, "%s is already in running list, skip it"%dir) + continue + + logger.debug(OvmHost.getAllVms, "Found a stopped vm %s on primary storage %s, report it to management server" % (dir, mountPoint)) + vms[dir] = "DOWN" + + try: l = OvmHost()._getAllDomains() dct = {} @@ -184,6 +204,8 @@ class OvmHost(OvmObject): vmPath = host._getVmPathFromPrimaryStorage(name) vmStatus = db_get_vm(vmPath) dct[name] = vmStatus['status'] + + scanStoppedVmOnPrimaryStorage(dct) rs = toGson(dct) logger.info(OvmHost.getAllVms, rs) return rs diff --git a/ovm/scripts/vm/hypervisor/ovm/OvmVmModule.py b/ovm/scripts/vm/hypervisor/ovm/OvmVmModule.py index a804d9ccb48..b16c69fa809 100755 --- a/ovm/scripts/vm/hypervisor/ovm/OvmVmModule.py +++ b/ovm/scripts/vm/hypervisor/ovm/OvmVmModule.py @@ -16,7 +16,7 @@ from OVSXXenStore import xen_get_vm_path, xen_get_vnc_port from OVSDB import db_get_vm from OVSXMonitor import xen_get_vm_perf_metrics, xen_get_xm_info from OVSXXenVM import xen_migrate_vm -from OVSSiteRMVM import unregister_vm, register_vm +from OVSSiteRMVM import unregister_vm, register_vm, set_vm_status from OVSSiteVMInstall import install_vm_hvm from OVSSiteRMServer import get_master_ip from OVSXXenVMInstall import xen_change_vm_cdrom @@ -115,6 +115,23 @@ class OvmVm(OvmObject): vmType = successToMap(xen_get_vm_type(vmPath))['type'] return vmType.replace('hvm', 'HVM').replace('para', 'PV') + def _tapAOwnerFile(self, vmPath): + # Create a file with name convention 'host_ip_address' in vmPath + # Because xm list doesn't return vm that has been stopped, we scan + # primary storage for stopped vm. This file tells us which host it belongs + # to. The file is used in OvmHost.getAllVms() + self._cleanUpOwnerFile(vmPath) + ownerFileName = makeOwnerFileName() + fd = open(join(vmPath, ownerFileName), 'w') + fd.write(ownerFileName) + fd.close() + + def _cleanUpOwnerFile(self, vmPath): + for f in os.listdir(vmPath): + fp = join(vmPath, f) + if isfile(fp) and f.startswith(OWNER_FILE_PREFIX): + os.remove(join(vmPath, fp)) + @staticmethod def create(jsonString): def dumpCfg(vmName, cfgPath): @@ -256,6 +273,9 @@ class OvmVm(OvmObject): vmNameFile.write(vm.name) vmNameFile.close() + OvmVm()._tapAOwnerFile(rootDiskDir) + # set the VM to DOWN before starting, OVS agent will check this status + set_vm_status(vmPath, 'DOWN') if vm.bootDev == "HDD": return hddBoot(vm, vmPath) elif vm.bootDev == "CD": @@ -279,6 +299,8 @@ class OvmVm(OvmObject): logger.info(OvmVm.stop, "Stop vm %s"%vmName) vmPath = OvmHost()._vmNameToPath(vmName) + # set the VM to DOWN before starting, OVS agent will check this status + set_vm_status(vmPath, 'RUNNING') raiseExceptionIfFail(stop_vm(vmPath)) return SUCC() except Exception, e: @@ -429,6 +451,7 @@ class OvmVm(OvmObject): vmPath = OvmHost()._vmNameToPath(vmName) raiseExceptionIfFail(xen_migrate_vm(vmPath, targetHost)) unregister_vm(vmPath) + OvmVm()._cleanUpOwnerFile(vmPath) return SUCC() except Exception, e: errmsg = fmt_err_msg(e) @@ -440,6 +463,7 @@ class OvmVm(OvmObject): try: vmPath = OvmHost()._vmNameToPath(vmName) raiseExceptionIfFail(register_vm(vmPath)) + OvmVm()._tapAOwnerFile(vmPath) vncPort= successToMap(xen_get_vnc_port(vmName))['vnc_port'] rs = toGson({"vncPort":str(vncPort)}) logger.debug(OvmVm.register, rs)