def start(host, port): assert host assert process.portFree(host, port) host.execute("vtund -s -f %s" % _configPath(port)) util.waitFor(lambda :fileutil.existsFile(host, "/var/run/vtund.server.pid"), 5.0) assert fileutil.existsFile(host, "/var/run/vtund.server.pid") fileutil.copy(host, "/var/run/vtund.server.pid", _pidFile(port))
def getState(host, port): assert host if not fileutil.existsFile(host, _configPath(port)): return generic.State.CREATED if not fileutil.existsFile(host, _pidFile(port)): return generic.State.PREPARED if not process.processRunning(host, _pidFile(port), "vtund"): return generic.State.PREPARED return generic.State.STARTED
def useImage(host, vmid, image, move=False): assert fileutil.existsFile(host, image), "Image file does not exist" assert getState(host, vmid) == generic.State.PREPARED, "VM must be stopped to change image" _qm(host, vmid, "set", "--ide0 undef") imagePath = _imagePath(vmid) fileutil.mkdir(host, _imagePathDir(vmid)) if move: fileutil.move(host, image, imagePath) else: fileutil.copy(host, image, imagePath) fileutil.chown(host, imagePath, "root:root") _qm(host, vmid, "set", "--ide0=local:%s/disk.qcow2" % vmid) assert fileutil.existsFile(host, imagePath)
def checkImage(host, path): assert host assert fileutil.existsFile(host, path) try: res = host.execute("qemu-img info -f qcow2 %s" % util.escape(path)) except exceptions.CommandError, err: return err.errorMessage
def getState(host, vmid): assert vmid if process.processRunning(host, _pidFile(vmid), "python"): return generic.State.STARTED if fileutil.existsFile(host, _imagePath(vmid)): return generic.State.PREPARED return generic.State.CREATED
def useImage(host, vmid, image, forceGzip=False): assert getState(host, vmid) == generic.State.PREPARED, "VM not prepared" assert fileutil.existsFile(host, image), "Image does not exist" dst = _imagePath(vmid) fileutil.delete(host, dst, recursive=True) fileutil.mkdir(host, dst) fileutil.unpackdir(host, image, dst, "-z" if forceGzip else "")
def checkImage(host, path): assert host assert fileutil.existsFile(host, path) try: res = host.execute("tar -tzvf %s ./sbin/init" % util.escape(path)) fault.check("0/0" in res, "Image contents not owned by root") except exceptions.CommandError, err: return err.errorMessage
def useImage(host, vmid, image, move=False): assert fileutil.existsFile(host, image), "Image file does not exist" try: host.execute("qemu-img check -f qcow2 %s; echo $?" % util.escape(image)) except exceptions.CommandError, exc: #Error 1: Leaked clusters, "This means waste of disk space, but no harm to data." if not exc.errorCode in [1]: raise
def migrate(src_host, src_vmid, dst_host, dst_vmid, template, ifaces): assert getState(dst_host, dst_vmid) == generic.State.CREATED, "Destination VM already exists" state = getState(src_host, src_vmid) if state == generic.State.CREATED: #nothing to do return #create a tmp directory on both hosts src_tmp = "/tmp/%s" % uuid.uuid1() dst_tmp = "/tmp/%s" % uuid.uuid1() fileutil.mkdir(src_host, src_tmp) fileutil.mkdir(dst_host, dst_tmp) #create destination vm create(dst_host, dst_vmid, template) try: #transfer vm disk image copyImage(src_host, src_vmid, "%s/disk.tar" % src_tmp) fileutil.fileTransfer(src_host, "%s/disk.tar" % src_tmp, dst_host, "%s/disk.tar" % dst_tmp, compressed=True) if state == generic.State.STARTED: #prepare rdiff before snapshot to save time src_host.execute("rdiff signature %(tmp)s/disk.tar %(tmp)s/rdiff.sigs" % {"tmp": src_tmp}) #create a memory snapshot on old host res = _vzctl(src_host, src_vmid, "chkpnt", ["--dumpfile", "%s/openvz.dump" % src_tmp]) assert fileutil.existsFile(src_host, "%s/openvz.dump" % src_tmp), "Failed to create snapshot: %s" % res try: fileutil.fileTransfer(src_host, "%s/openvz.dump" % src_tmp, dst_host, "%s/openvz.dump" % dst_tmp, compressed=True) #create and transfer a disk image rdiff copyImage(src_host, src_vmid, "%s/disk2.tar" % src_tmp) src_host.execute("rdiff -- delta %(tmp)s/rdiff.sigs %(disk)s - | gzip > %(tmp)s/disk.rdiff.gz" % {"tmp": src_tmp, "disk": "%s/disk2.tar" % src_tmp}) fileutil.fileTransfer(src_host, "%s/disk.rdiff.gz" % src_tmp, dst_host, "%s/disk.rdiff.gz" % dst_tmp, direct=True) #patch disk image with the rdiff dst_host.execute("gunzip < %(tmp)s/disk.rdiff.gz | rdiff -- patch %(tmp)s/disk.tar - %(tmp)s/disk-patched.tar" % {"tmp": dst_tmp}) fileutil.move(dst_host,"%s/disk-patched.tar" % dst_tmp, "%s/disk.tar" % dst_tmp) except: _vzctl(src_host, src_vmid, "restore", ["--dumpfile", "%s/openvz.dump" % src_tmp]) raise #use disk image on new host useImage(dst_host, dst_vmid, "%s/disk.tar" % dst_tmp) for iface in ifaces: addInterface(dst_host, dst_vmid, iface) if state == generic.State.STARTED: try: #restore snapshot _vzctl(dst_host, dst_vmid, "restore", ["--dumpfile", "%s/openvz.dump" % dst_tmp]) assert getState(dst_host, dst_vmid) == generic.State.STARTED except: _vzctl(src_host, src_vmid, "restore", ["--dumpfile", "%s/openvz.dump" % src_tmp]) raise except: destroy(dst_host, dst_vmid) fileutil.delete(src_host, src_tmp, recursive=True) fileutil.delete(dst_host, dst_tmp, recursive=True) raise #destroy vm on old host destroy(src_host, src_vmid) #remove tmp directories fileutil.delete(src_host, src_tmp, recursive=True) fileutil.delete(dst_host, dst_tmp, recursive=True)
def getState(endpoint): assert _isEndpoint(endpoint) host = endpoint.getHost() assert host if not fileutil.existsDir(host, _configDir(endpoint)): return generic.State.CREATED if not fileutil.existsFile(host, _pidFile(endpoint)): return generic.State.PREPARED if not process.processRunning(host, _pidFile(endpoint), "tincd"): return generic.State.PREPARED return generic.State.STARTED
def downloadCaptureUri(host, name, onlyLatest=False): filename = "%s.pcap" % name path = host.getHostServer().randomFilename() if onlyLatest: print path latest = util.lines(host.execute("ls -t1 %s | head -n1" % _remoteDir(name)))[0] if latest: fileutil.copy(host, "%s/%s" % (_remoteDir(name), latest), path) else: host.execute("tcpslice -w %s %s/*" % (path, _remoteDir(name))) if not fileutil.existsFile(host, path) or not fileutil.fileSize(host, path): raise fault.new("No packages captured yet") return host.getHostServer().downloadGrant(path, filename=filename)
def useImage(host, vmid, image): #FIXME check script sanity assert getState(host, vmid) == generic.State.PREPARED, "VM not prepared" assert fileutil.existsFile(host, image), "Image does not exist" fileutil.copy(host, image, _imagePath(vmid))
def copyImage(host, vmid, file): assert getState(host, vmid) != generic.State.CREATED, "VM must be prepared" fileutil.copy(host, _imagePath(vmid), file) assert fileutil.existsFile(host, file)
def downloadCaptureUri(host, name): filename = "%s.pcap" % name path = host.getHostServer().randomFilename() host.execute("tcpslice -w %s %s/*" % (path, _remoteDir(name))) assert fileutil.existsFile(host, path), "No packages captured yet" return host.getHostServer().downloadGrant(path, filename=filename)
def downloadCaptureUri(host, name): filename = "%s.pcap" % name path = hostserver.randomFilename(host) host.execute("tcpslice -w %s %s/*" % (path, _remoteDir(name))) assert fileutil.existsFile(host, path) return hostserver.downloadGrant(host, path, filename)
host.execute("qemu-img check -f qcow2 %s; echo $?" % util.escape(image)) except exceptions.CommandError, exc: #Error 1: Leaked clusters, "This means waste of disk space, but no harm to data." if not exc.errorCode in [1]: raise assert getState(host, vmid) == generic.State.PREPARED, "VM must be stopped to change image" _qm(host, vmid, "set", ["--ide0", "undef"]) imagePath = _imagePath(vmid) fileutil.mkdir(host, _imagePathDir(vmid)) if move: fileutil.move(host, image, imagePath) else: fileutil.copy(host, image, imagePath) fileutil.chown(host, imagePath, "root:root") _qm(host, vmid, "set", ["--ide0", "local:%d/disk.qcow2" % vmid]) assert fileutil.existsFile(host, imagePath) def _vncPidfile(vmid): return "%s/vnc-%d.pid" % (config.REMOTE_DIR, vmid) def vncRunning(host, vmid, port): return process.processRunning(host, _vncPidfile(vmid), "tcpserver") def startVnc(host, vmid, port, password): assert getState(host, vmid) == generic.State.STARTED, "VM must be running to start vnc" assert process.portFree(host, port) host.execute("tcpserver -qHRl 0 0 %d qm vncproxy %d %s & echo $! > %s" % ( port, vmid, util.escape(password), _vncPidfile(vmid) )) assert not process.portFree(host, port) def stopVnc(host, vmid, port): process.killPidfile(host, _vncPidfile(vmid))
def copyImage(host, vmid, file, forceGzip=False): assert getState(host, vmid) != generic.State.CREATED, "VM must be prepared" fileutil.packdir(host, file, _imagePath(vmid), "--numeric-owner " + ("-z" if forceGzip else "")) assert fileutil.existsFile(host, file)