import subprocess import sys import os from AVCommon.logger import logging from time import sleep from datetime import datetime from ConfigParser import ConfigParser from pysphere import VIServer from pysphere import VIException from AVCommon import config class vSphere: def __init__(self, vm_path, sdk_host, sdk_user, sdk_domain, sdk_passwd): self.vm_path = vm_path self.sdk_host = sdk_host self.sdk_user = sdk_domain + "\\" + sdk_user self.sdk_passwd = sdk_passwd def __enter__(self): self.server = VIServer() self.server.connect(self.sdk_host, self.sdk_user, self.sdk_passwd) if config.verbose: logging.debug("connected to vSphere") vm = self.server.get_vm_by_path(self.vm_path) return vm def __exit__(self, type, value, traceback): try: self.server.disconnect() if config.verbose: logging.debug("disconnected from vSphere") except VIException as e: logging.debug("Problem in disconnection. Fault is: %s" % e.fault) pass class VMRun: def __init__(self, config_file): self.config = ConfigParser() self.config.read(config_file) self.path = self.config.get("vsphere", "path") self.host = self.config.get("vsphere", "host") self.domain = self.config.get("vsphere", "domain") self.user = self.config.get("vsphere", "user") self.passwd = self.config.get("vsphere", "passwd") def _run_cmd(self, vmx, cmd, args=[], vmx_creds=[], popen=False, bg=False, timeout=40): pargs = [self.path, "-T", "vc", "-h", self.host, "-u", "%s\\%s" % (self.domain, self.user), "-p", self.passwd, cmd, vmx.path] if vmx_creds != [] and len(vmx_creds) == 2: idx = pargs.index("-p") + 2 cred = "-gu %s -gp %s" % (vmx_creds[0], vmx_creds[1]) pargs = pargs[0:idx] + cred.split() + pargs[idx:] pargs.extend(args) if popen is True: return self._run_popen(pargs, timeout) elif bg is True: if config.verbose: logging.debug("running in bg mode") return self._run_bg(pargs) else: return self._run_call(pargs) def _run_call(self, pargs): if config.verbose: logging.debug("_run_call") return subprocess.call(pargs) def _run_bg(self, pargs): if config.verbose: logging.debug("_run_bg") subprocess.Popen(pargs, stdout=subprocess.PIPE) return True def _run_popen(self, pargs, timeout=40): if config.verbose: logging.debug("_run_popen") p = subprocess.Popen(pargs, stdout=subprocess.PIPE) executed = False tick = 0 while executed is False: sleep(20) tick += 1 if p.poll() is not None: # process is executed and ret.poll() has the return code executed = True if tick >= timeout * 3: logging.debug("run_popen timeout") return [] poll = p.poll() if poll==0: return p.communicate()[0] else: logging.debug("not poll: %s" % poll) return [] def startup(self, vmx): if config.verbose: logging.debug("[%s] Starting!\r\n" % vmx) self._run_cmd(vmx, "start") def shutdown(self, vmx): if config.verbose: logging.debug("[%s] Stopping!\r\n" % vmx) self._run_cmd(vmx, "stop") def shutdownUpgrade(self, vmx): #["/s","/t","0"]) r = self.executeCmd( vmx, "c:\\WINDOWS\\system32\\shutdown.exe", ["/s", "/t", "0"], timeout=105) if r is False: return False return True def reboot(self, vmx): if config.verbose: logging.debug("[%s] Rebooting!\r\n" % vmx) self._run_cmd(vmx, "reset", ["hard"]) def suspend(self, vmx): if config.verbose: logging.debug("[%s] Suspending!\r\n" % vmx) self._run_cmd(vmx, "suspend", ["soft"]) def createSnapshot(self, vmx, snapshot): if config.verbose: logging.debug("[%s] Creating snapshot %s.\n" % (vmx, snapshot)) self._run_cmd(vmx, "snapshot", [snapshot]) def deleteSnapshot(self, vmx, snapshot): if config.verbose: logging.debug("[%s] Deleting snapshot %s.\n" % (vmx, snapshot)) self._run_cmd(vmx, "deleteSnapshot", [snapshot]) def revertSnapshot(self, vmx, snapshot): if config.verbose: logging.debug("[%s] Reverting snapshot %s.\n" % (vmx, snapshot)) self._run_cmd(vmx, "revertToSnapshot", [snapshot]) def refreshSnapshot(self, vmx, delete=True): untouchables = [ "_datarecovery_"] #"ready", "activated", if config.verbose: logging.debug("[%s] Refreshing snapshot.\n" % vmx) # create new snapshot date = datetime.now().strftime('%Y%m%d-%H%M') snapshot = "auto_%s" % date untouchables.append(snapshot) self.createSnapshot(vmx, snapshot) if delete is True: snaps = self.listSnapshots(vmx) logging.debug("%s: snapshots %s" % (vmx,snaps)) if len(snaps) > 2: for s in snaps[0:-2]: logging.debug("checking %s" % s) if s not in untouchables: # and "manual" not in s: logging.debug("deleting %s" % s) self.deleteSnapshot(vmx, s) else: logging.debug("ignoring %s" % s) def revertLastSnapshot(self, vmx): snap = self.listSnapshots(vmx) if len(snap) > 0: for s in range(len(snap) - 1, -1, -1): snapshot = snap[s] if snapshot != "_datarecovery_": self.revertSnapshot(vmx, snap[s]) return "[%s] Reverted with snapshot %s" % (vmx, snap[s]) else: logging.debug("snapshot _datarecovery_ found!") return "%s, ERROR: no more snapshot to try" % vmx else: return "%s, ERROR: no snapshots!" % vmx def mkdirInGuest(self, vmx, dir_path): if config.verbose: logging.debug("[%s] Creating directory %s.\n" % (vmx, dir_path)) self._run_cmd(vmx, "CreateDirectoryInGuest", [ dir_path], [vmx.user, vmx.passwd]) def listDirectoryInGuest(self, vmx, dir_path): if config.verbose: logging.debug("[%s] Listing directory %s.\n" % (vmx, dir_path)) return self._run_cmd(vmx, "listDirectoryInGuest", [dir_path], [vmx.user, vmx.passwd], popen=True) def deleteDirectoryInGuest(self, vmx, dir_path): if config.verbose: logging.debug("[%s] Delete directory %s.\n" % (vmx, dir_path)) self._run_cmd( vmx, "deleteDirectoryInGuest", [dir_path], [vmx.user, vmx.passwd]) def copyFileToGuest(self, vmx, src_file, dst_file): if config.verbose: logging.debug("[%s] Copying file from %s to %s.\n" % (vmx, src_file, dst_file)) return self._run_cmd(vmx, "CopyFileFromHostToGuest", [src_file, dst_file], [vmx.user, vmx.passwd]) def copyFileFromGuest(self, vmx, src_file, dst_file): if config.verbose: logging.debug("[%s] Copying file from %s to %s.\n" % (vmx, src_file, dst_file)) return self._run_cmd(vmx, "CopyFileFromGuestToHost", [src_file, dst_file], [vmx.user, vmx.passwd]) def executeCmd(self, vmx, cmd, args=[], timeout=40, interactive=True, bg=False): if config.verbose: logging.debug("[%s] Executing %s with args %s" % (vmx, cmd, str(args))) if config.verbose: logging.debug("on %s with credentials %s %s" % (vmx, vmx.user, vmx.passwd)) logging.debug("Options: timeout: %s, interactive: %s, background: %s" % (timeout, interactive, bg)) cmds = [] if interactive is True: cmds.append("-interactive") cmds.append(cmd) cmds.extend(args) if config.verbose: logging.debug("background execution is %s" % bg) return self._run_cmd(vmx, "runProgramInGuest", cmds, [vmx.user, vmx.passwd], bg=bg, timeout=timeout) def runTest(self, vmx, script): return self.executeCmd(vmx, script, interactive=True) def listProcesses(self, vmx): if config.verbose: logging.debug("[%s] List processes\n" % vmx) return self._run_cmd(vmx, "listProcessesInGuest", vmx_creds=[vmx.user, vmx.passwd], popen=True) def takeScreenshot(self, vmx, out_img): if config.verbose: logging.debug("[%s] Taking screenshot.\n" % vmx) if config.verbose: logging.debug("CALLING FUNCTIONS WITH out img %s, u: %s, p: %s.\n" % (out_img, vmx.user, vmx.passwd)) self._run_cmd(vmx, "captureScreen", [out_img], [vmx.user, vmx.passwd]) return os.path.exists(out_img) def VMisRunning(self, vmx): res = self._run_cmd(vmx, "list", popen=True) if vmx.path[1:-1] in res: return True return False def listSnapshots(self, vmx): out = self._run_cmd(vmx, "listSnapshots", popen=True).split("\n") return out[1:-1] .