def addNic(vmid, num, bridge="dummy", model="e1000", mac=None): vmid = params.convert(vmid, convert=int, gte=1) num = params.convert(num, convert=int, gte=0, lte=31) bridge = params.convert(bridge, convert=str) model = params.convert(model, convert=str, oneOf=["e1000", "i82551", "rtl8139"]) mac = params.convert(mac, convert=str, regExp="^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$", null=True) with locks[vmid]: _checkStatus(vmid, Status.Stopped) if num in getNicList(vmid): raise QMError(QMError.CODE_NIC_ALREADY_EXISTS, "Nic already exists", { "vmid": vmid, "num": num }) _set( vmid, **{ ("net%d" % num): "%s%s%s" % (model, ("=%s" % mac) if mac else "", (",bridge=%s" % bridge) if bridge else "") })
def startVnc(vmid, vncpassword, vncport, websockifyPort=None, websockifyCert=None): vmid = params.convert(vmid, convert=int, gte=1) vncpassword = params.convert(vncpassword, convert=unicode) vncport = params.convert(vncport, convert=int, gte=1, lt=2**16) with locks[vmid]: _checkStatus(vmid, Status.Running) _setVncPassword(vmid, vncpassword) vncPid = spawnDaemon([ "socat", "TCP-LISTEN:%d,reuseaddr,fork" % vncport, "UNIX-CLIENT:/var/run/qemu-server/%d.vnc" % vmid ]) websockifyPid = None try: if websockifyPort: websockifyPid = websockify.start(websockifyPort, vncport, websockifyCert) except: stopVnc(vncPid) raise return vncPid, websockifyPid
def startVnc(self, vmid, vncpassword, vncport, websockifyPort=None, websockifyCert=None): vmid = params.convert(vmid, convert=int, gte=1) vncpassword = params.convert(vncpassword, convert=unicode) vncport = params.convert(vncport, convert=int, gte=1, lt=2**16) with locks[vmid]: self._checkStatus(vmid, StateName.STARTED) self._setVncPassword(vmid, vncpassword) self._virsh("qemu-monitor-command", [ "vm_%d" % vmid, "--hmp", "change", "vnc", "unix:/var/run/qemu-server/%d.vnc,password" % vmid ]) vncPid = spawnDaemon([ "socat", "TCP-LISTEN:%d,reuseaddr,fork" % vncport, "UNIX-CLIENT:/var/run/qemu-server/%d.vnc" % vmid ]) websockifyPid = None try: if websockifyPort: websockifyPid = websockify.start(websockifyPort, vncport, websockifyCert) except: self.stopVnc(vncPid) raise return vncPid, websockifyPid
def create(path, format="qcow2", size=None, backingImage=None): format = params.convert(format, convert=str) path = params.convert(path, check=lambda p: not os.path.exists(p)) size = params.convert(size, convert=str, null=True) backingImage = params.convert(backingImage, check=os.path.exists, null=True) c = ["qemu-img", "create", "-f", format] if backingImage: c += ["-o", "backing_file=%s" % backingImage] c.append(path) if size and not backingImage: c.append(size) try: cmd.run(c) except CommandError, err: data = { "path": path, "format": format, "size": size, "backing_image": backingImage } data.update(err.data) raise QemuImgError(QemuImgError.CODE_FAILED_TO_CREATE, "Failed to create image", data)
def addNic(self, vmid, num, bridge="dummy", model="e1000", mac=None): vmid = params.convert(vmid, convert=int, gte=1) num = params.convert(num, convert=int, gte=0, lte=31) bridge = params.convert(bridge, convert=str) model = params.convert(model, convert=str, oneOf=["e1000", "i82551", "rtl8139"]) mac = params.convert(mac, convert=str, regExp="^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$", null=True) with locks[vmid]: self._checkStatus(vmid, [StateName.CREATED, StateName.PREPARED]) VirshError.check(num not in self.getNicList(vmid), VirshError.CODE_NIC_ALREADY_EXISTS, "Nic already exists", {"vmid: ": vmid, "num: ": num}) elementInterface = ET.Element("interface", {"type": "bridge"}) if mac: elementMac = ET.Element("mac", {"address": "%s" % mac}) elementInterface.append(elementMac) elementSource = ET.Element("source", {"bridge": bridge}) elementAlias = ET.Element("alias", {"name": "net%d" % num}) elementTarget = ET.Element("target", {"dev": "tap%di%d" % (vmid, num)}) elementModel = ET.Element("model", {"type": "%s" % model}) elementInterface.append(elementSource) elementInterface.append(elementTarget) elementInterface.append(elementAlias) elementInterface.append(elementModel) self.addToConfig(vmid, "devices", elementInterface)
def _control(vmid, execute, timeout=10, more_args=None, **arguments): if not more_args: more_args = {} vmid = params.convert(vmid, convert=int, gte=1) timeout = params.convert(timeout, convert=float, gt=0.0) execute = params.convert(execute, convert=str) if more_args: arguments.update(more_args) controlPath = _controlPath(vmid) QMError.check(os.path.exists(controlPath), QMError.CODE_CONTROL, "Control socket does not exist", {"socket": controlPath}) sock = None try: sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock.settimeout(timeout) sock.connect(controlPath) header = sock.recv(4096) try: header = json.loads(header) except Exception, exc: raise QMError(QMError.CODE_CONTROL, "Received invalid header", {"socket": controlPath, "header": header}) cmd = json.dumps({'execute': 'qmp_capabilities'}) sock.send(cmd+"\n") res = sock.recv(4096) try: res = json.loads(res) except Exception, exc: raise QMError(QMError.CODE_CONTROL, "Received invalid response", {"socket": controlPath, "response": res, "command": cmd})
def _configure(vmid, hda=None, hdb=None, fda=None, keyboard="en-us", localtime=False, tablet=True, highres=False, cores=1, memory=512): vmid = params.convert(vmid, convert=int, gte=1) hda = params.convert(hda, convert=str, null=True, check=qemu_img.check) hdb = params.convert(hdb, convert=str, null=True, check=qemu_img.check) fda = params.convert(fda, convert=str, null=True, check=qemu_img.check) # other parameters will be checked by _set options = {} # Set defaults options.update(acpi=True, boot="cd", hotplug=True, name="vm%d" % vmid, ostype="other", sockets=1) # Set standard parameters options.update(keyboard=keyboard, localtime=localtime, tablet=tablet, cores=cores, memory=memory, vga="std" if highres else "cirrus") # Setting KVM arguments not available in QM args = {} args["vnc"] = "unix:/var/run/qemu-server/%d.vnc,password" % vmid if fda: args['drive'] = "file=%s,index=0,if=floppy,cache=writethrough" % fda if hdb: args["hdb"] = hdb if hda: args["hda"] = hda if qmVersion < [1, 1]: args["chardev"] = "socket,id=qmp,path=%s,server,nowait" % _controlPath(vmid) args["mon"] = "chardev=qmp,mode=control" if args: argstr = " ".join(["-%s %s" % (key, value) for key, value in args.iteritems()]) options.update(args=argstr) _set(vmid, **options)
def mount(image, path, sync=False, readOnly=False, partition=0): image = params.convert(image, convert=str, check=os.path.exists) path = params.convert(path, convert=os.path.realpath, check=os.path.exists) partition = params.convert(partition, convert=int, gte=0, lte=4) ImageError.check(not _isMounted(path), ImageError.CODE_ALREADY_MOUNTED, "Path is already mounted", {"path": path}) options = ["loop"] if not partition else [] if sync: options.append("sync") if readOnly: options.append("ro") try: if partition: partitions = _getPartitions(image) start, size = partitions[partition - 1] start, size = start * 512, size * 512 ImageError.check(start > 0 and size > 0, ImageError.CODE_FAILED_TO_CREATE, "Wrong partition table", { "image": image, "table": partitions }) options += ["offset=%d" % start, "sizelimit=%d" % size] cmd.run(["mount", "-o%s" % ",".join(options), image, path]) except cmd.CommandError, err: raise ImageError(ImageError.CODE_FAILED_TO_MOUNT, "Failed to mount image", { "path": path, "image": image, "options": options, "error": repr(err) })
def _control(vmid, execute, timeout=10, more_args=None, **arguments): if not more_args: more_args = {} vmid = params.convert(vmid, convert=int, gte=1) timeout = params.convert(timeout, convert=float, gt=0.0) execute = params.convert(execute, convert=str) if more_args: arguments.update(more_args) controlPath = _controlPath(vmid) QMError.check(os.path.exists(controlPath), QMError.CODE_CONTROL, "Control socket does not exist", {"socket": controlPath}) sock = None try: sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock.settimeout(timeout) sock.connect(controlPath) header = sock.recv(4096) try: header = json.loads(header) except Exception, exc: raise QMError(QMError.CODE_CONTROL, "Received invalid header", { "socket": controlPath, "header": header }) cmd = json.dumps({'execute': 'qmp_capabilities'}) sock.send(cmd + "\n") res = sock.recv(4096) try: res = json.loads(res) except Exception, exc: raise QMError(QMError.CODE_CONTROL, "Received invalid response", { "socket": controlPath, "response": res, "command": cmd })
def stop(vmid, force=True, timeout=30): vmid = params.convert(vmid, convert=int, gte=1) force = params.convert(force, convert=bool) timeout = params.convert(timeout, convert=int, gte=0) with locks[vmid]: _checkStatus(vmid, Status.Running) _qm(vmid, "shutdown", ["-forceStop", str(force), "-timeout", str(timeout)]) _checkStatus(vmid, Status.Stopped)
def start(port, command): port = params.convert(port, convert=int, gte=1, lt=2**16) command = params.convert(command, convert=list) netstat.checkPortFree(port, tcp=True, ipv4=True) pid = spawnDaemon(["tcpserver", "-qHRl", "0", "0", str(port)] + command) try: wait.waitFor(lambda :netstat.isPortUsedBy(port, pid), failCond=lambda :not proc.isAlive(pid)) return pid except wait.WaitError: proc.autoKill(pid, group=True) raise
def addNic(vmid, num, bridge="dummy", model="e1000", mac=None): vmid = params.convert(vmid, convert=int, gte=1) num = params.convert(num, convert=int, gte=0, lte=31) bridge = params.convert(bridge, convert=str) model = params.convert(model, convert=str, oneOf=["e1000", "i82551", "rtl8139"]) mac = params.convert(mac, convert=str, regExp="^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$", null=True) with locks[vmid]: _checkStatus(vmid, Status.Stopped) if num in getNicList(vmid): raise QMError(QMError.CODE_NIC_ALREADY_EXISTS, "Nic already exists", {"vmid": vmid, "num": num}) _set(vmid, **{("net%d" % num): "%s%s%s" % (model, ("=%s" % mac) if mac else "", (",bridge=%s" % bridge) if bridge else "")})
def download(urls, dest, hash=None): urls = params.convert(urls, convert=list) dest = params.convert(dest, convert=os.path.realpath) hash = params.convert(hash, convert=str, null=True) path, fname = os.path.split(dest) Aria2Error.check(os.path.exists(path), Aria2Error.CODE_DEST_PATH_DOES_NOT_EXIST, "Destination path does not exit", {"path": path}) args = ["aria2c", "-d", path, "-o", fname, "-c", "-V", "--auto-file-renaming=false", "--allow-overwrite=true"] if hash: args.append("--checksum=%s" % hash) args += urls cmd.run(args)
def convert(src, dst, srcFormat="qcow2", dstFormat="qcow2", compress=True): src = params.convert(src, check=_checkImage) dst = params.convert(dst, check=lambda p: not os.path.exists(p)) srcFormat = params.convert(srcFormat, convert=str) dstFormat = params.convert(dstFormat, convert=str) try: cmd.run(["qemu-img", "convert", "-c" if compress else "", "-f", srcFormat, "-O", dstFormat, src, dst]) except CommandError, err: data = {"src": src, "dst": dst, "src_format": srcFormat, "dst_format": dstFormat} data.update(err.data) raise QemuImgError(QemuImgError.CODE_FAILED_TO_CONVERT, "Failed to convert image", data)
def httpd_start(folder, port): folder = params.convert(folder, convert=os.path.realpath, check=os.path.exists) port = params.convert(port, convert=int, gte=1, lt=2**16) netstat.checkPortFree(port) pid = spawnDaemon(["busybox", "httpd", "-f", "-p", str(port)], cwd=folder) try: wait.waitFor(lambda :netstat.isPortUsedBy(port, pid), failCond=lambda :not proc.isAlive(pid)) return pid except wait.WaitError: proc.autoKill(pid, group=True) raise
def start(port, command): port = params.convert(port, convert=int, gte=1, lt=2**16) command = params.convert(command, convert=list) netstat.checkPortFree(port, tcp=True, ipv4=True) pid = spawnDaemon(["tcpserver", "-qHRl", "0", "0", str(port)] + command) try: wait.waitFor(lambda: netstat.isPortUsedBy(port, pid), failCond=lambda: not proc.isAlive(pid)) return pid except wait.WaitError: proc.autoKill(pid, group=True) raise
def _imageInfo(path, format=None): format = params.convert(format, convert=str, null=True) path = params.convert(path, check=os.path.exists) try: if format: res = cmd.run(["qemu-img", "info", "-f", format, "--output=json", path]) else: res = cmd.run(["qemu-img", "info", "--output=json", path]) return json.loads(res) except CommandError, err: data = {"path": path} data.update(err.data) raise QemuImgError(QemuImgError.CODE_INVALID_IMAGE, "Invalid image", data)
def start(port, vncport, sslcert=None): port = params.convert(port, convert=int, gte=1, lt=2**16) vncport = params.convert(vncport, convert=int, gte=1, lt=2**16) sslcert = params.convert(sslcert, convert=str, null=True, check=os.path.exists) WebsockifyError.check(not netstat.isPortFree(vncport), WebsockifyError.CODE_DEST_PORT_FREE, "Destination port is free", {"port": vncport}) netstat.checkPortFree(port, tcp=True, ipv4=True) pid = spawnDaemon(["websockify", "0.0.0.0:%d" % port, "localhost:%d" % vncport] + (["--cert=%s" % sslcert] if sslcert else [])) try: wait.waitFor(lambda :netstat.isPortUsedBy(port, pid), failCond=lambda :not proc.isAlive(pid)) return pid except wait.WaitError: proc.autoKill(pid, group=True) raise
def start(iface, address, port, network_id, peers): iface = params.convert(iface, convert=str, check=lambda iface: not net.ifaceExists(iface)) address = params.convert(address, convert=str) port = params.convert(port, convert=int, gte=1, lt=2**16) network_id = params.convert(network_id, convert=int, gte=1, lt=1<<64) peers = params.convert(peers, convert=list) netstat.checkPortFree(port, tcp=False, udp=True, ipv4=True) connect = [] for p in peers: connect += ["-c", p] pid = spawnDaemon(["vpncloud", "-d", iface, "-l", "%s:%d" % (address, port), "--network-id", "%d" % network_id] + connect) wait.waitFor(lambda :net.ifaceExists(iface), failCond=lambda :not proc.isAlive(pid)) return pid
def httpd_start(folder, port): folder = params.convert(folder, convert=os.path.realpath, check=os.path.exists) port = params.convert(port, convert=int, gte=1, lt=2**16) netstat.checkPortFree(port) pid = spawnDaemon(["busybox", "httpd", "-f", "-p", str(port)], cwd=folder) try: wait.waitFor(lambda: netstat.isPortUsedBy(port, pid), failCond=lambda: not proc.isAlive(pid)) return pid except wait.WaitError: proc.autoKill(pid, group=True) raise
def create(path, size): path = params.convert(path, convert=os.path.realpath, check=lambda p: not os.path.exists(p)) size = params.convert(size, convert=int, gte=1) try: cmd.run(["mkfs.vfat", "-C", path, str(size)]) except cmd.CommandError, err: raise VFatError(VFatError.CODE_FAILED_TO_CREATE, "Failed to create image", { "path": path, "size": size, "error": repr(err) })
def _imageInfo(path, format=None): format = params.convert(format, convert=str, null=True) path = params.convert(path, check=os.path.exists) try: if format: res = cmd.run( ["qemu-img", "info", "-f", format, "--output=json", path]) else: res = cmd.run(["qemu-img", "info", "--output=json", path]) return json.loads(res) except CommandError, err: data = {"path": path} data.update(err.data) raise QemuImgError(QemuImgError.CODE_INVALID_IMAGE, "Invalid image", data)
def _configure(vmid, hda=None, hdb=None, fda=None, keyboard="en-us", localtime=False, tablet=True, highres=False, cores=1, memory=512): vmid = params.convert(vmid, convert=int, gte=1) hda = params.convert(hda, convert=str, null=True, check=qemu_img.check) hdb = params.convert(hdb, convert=str, null=True, check=qemu_img.check) fda = params.convert(fda, convert=str, null=True, check=qemu_img.check) # other parameters will be checked by _set options = {} # Set defaults options.update(acpi=True, boot="cd", hotplug=True, name="vm%d" % vmid, ostype="other", sockets=1) # Set standard parameters options.update(keyboard=keyboard, localtime=localtime, tablet=tablet, cores=cores, memory=memory, vga="std" if highres else "cirrus") # Setting KVM arguments not available in QM args = {} args["vnc"] = "unix:/var/run/qemu-server/%d.vnc,password" % vmid if fda: args['drive'] = "file=%s,index=0,if=floppy,cache=writethrough" % fda if hdb: args["hdb"] = hdb if hda: args["hda"] = hda if qmVersion < [1, 1]: args["chardev"] = "socket,id=qmp,path=%s,server,nowait" % _controlPath( vmid) args["mon"] = "chardev=qmp,mode=control" if args: argstr = " ".join( ["-%s %s" % (key, value) for key, value in args.iteritems()]) options.update(args=argstr) _set(vmid, **options)
def startVnc(vmid, vncpassword, vncport, websockifyPort=None, websockifyCert=None): vmid = params.convert(vmid, convert=int, gte=1) vncpassword = params.convert(vncpassword, convert=unicode) vncport = params.convert(vncport, convert=int, gte=1, lt=2**16) with locks[vmid]: _checkStatus(vmid, Status.Running) _setVncPassword(vmid, vncpassword) vncPid = spawnDaemon(["socat", "TCP-LISTEN:%d,reuseaddr,fork" % vncport, "UNIX-CLIENT:/var/run/qemu-server/%d.vnc" % vmid]) websockifyPid = None try: if websockifyPort: websockifyPid = websockify.start(websockifyPort, vncport, websockifyCert) except: stopVnc(vncPid) raise return vncPid, websockifyPid
def _getConfig(vmid): vmid = params.convert(vmid, convert=int, gte=1) config = {} for line in _qm(vmid, "config").splitlines(): key, value = line.split(": ") config[key] = value return config
def _set(vmid, **values): vmid = params.convert(vmid, convert=int, gte=1) values = params.convertMulti(values, _parameterTypes) _qm(vmid, "set", sum([["-%s" % key, unicode(value)] for key, value in values.iteritems()], [])) config = _getConfig(vmid) for key in values: QMError.check(key in config, QMError.CODE_PARAMETER_NOT_SET, "Parameter %r has not been set" % key, {"key": key, "value": values[key]})
def addNic(self, vmid, num, bridge="dummy", model="e1000", mac=None): vmid = params.convert(vmid, convert=int, gte=1) num = params.convert(num, convert=int, gte=0, lte=31) bridge = params.convert(bridge, convert=str) model = params.convert(model, convert=str, oneOf=["e1000", "i82551", "rtl8139"]) mac = params.convert(mac, convert=str, regExp="^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$", null=True) with locks[vmid]: self._checkStatus(vmid, [StateName.CREATED, StateName.PREPARED]) VirshError.check(num not in self.getNicList(vmid), VirshError.CODE_NIC_ALREADY_EXISTS, "Nic already exists", { "vmid: ": vmid, "num: ": num }) tree = ET.parse(self._configPath(vmid)) root = tree.getroot() elementInterface = ET.Element("interface", {"type": "bridge"}) if mac: elementMac = ET.Element("mac", {"address": "%s" % mac}) elementInterface.append(elementMac) elementSource = ET.Element("source", {"bridge": bridge}) elementAlias = ET.Element("alias", {"name": "net%d" % num}) elementTarget = ET.Element("target", {"dev": "tap%di%d" % (vmid, num)}) elementModel = ET.Element("model", {"type": "%s" % model}) elementInterface.append(elementSource) elementInterface.append(elementTarget) elementInterface.append(elementAlias) elementInterface.append(elementModel) for element in root.getchildren(): if element.tag == "devices": element.append(elementInterface) if not os.path.exists(os.path.dirname(self._configPath(vmid))): os.makedirs(os.path.dirname(self._configPath(vmid))) tree.write(self._configPath(vmid)) self._virsh("define", [self._configPath(vmid)])
def create(vmid, **config): vmid = params.convert(vmid, convert=int, gte=1) with locks[vmid]: _checkStatus(vmid, Status.NoSuchVm) _qm(vmid, "create") _checkStatus(vmid, Status.Stopped) _checkImageFolder(vmid) _configure(vmid, **config)
def create(path, format="qcow2", size=None, backingImage=None): format = params.convert(format, convert=str) path = params.convert(path, check=lambda p: not os.path.exists(p)) size = params.convert(size, convert=str, null=True) backingImage = params.convert(backingImage, check=os.path.exists, null=True) c = ["qemu-img", "create", "-f", format] if backingImage: c += ["-o", "backing_file=%s" % backingImage] c.append(path) if size and not backingImage: c.append(size) try: cmd.run(c) except CommandError, err: data = {"path": path, "format": format, "size": size, "backing_image": backingImage} data.update(err.data) raise QemuImgError(QemuImgError.CODE_FAILED_TO_CREATE, "Failed to create image", data)
def create(path, size, nested=False): path = params.convert(path, convert=os.path.realpath, check=lambda p: not os.path.exists(p)) size = params.convert(size, convert=int, gte=8192) nested = params.convert(nested, convert=bool) try: cmd.run( ["dd", "if=/dev/zero", "of=%s" % path, "bs=1k", "count=%d" % size]) device = path if nested: cmd.run(["sfdisk", path], input=",\n") partitions = _getPartitions(path) start, size = partitions[0] start, size = start * 512, size * 512 ImageError.check(start > 0 and size > 0, ImageError.CODE_FAILED_TO_CREATE, "Failed to create partition table", { "path": path, "table": partitions }) device = cmd.run([ "losetup", "-f", "--show", "--offset", str(start), "--sizelimit", str(size), path ]).splitlines()[0] ImageError.check(os.path.exists(device), ImageError.CODE_FAILED_TO_CREATE, "Failed to bind to loop device", { "path": path, "size": size, "loop_device": device }) cmd.run(["mkfs.vfat", device]) cmd.run(["sync"]) if nested: cmd.run(["losetup", "-d", device]) except cmd.CommandError, err: raise ImageError(ImageError.CODE_FAILED_TO_CREATE, "Failed to create image", { "path": path, "size": size, "error": repr(err) })
def startVnc(self, vmid,vncpassword, vncport, websockifyPort=None, websockifyCert=None): vmid = params.convert(vmid, convert=int, gte=1) vncpassword = params.convert(vncpassword, convert=unicode) vncport = params.convert(vncport, convert=int, gte=1, lt=2 ** 16) with locks[vmid]: self._checkStatus(vmid, StateName.STARTED) self._setVncPassword(vmid, vncpassword) self._virsh("qemu-monitor-command", ["vm_%d" % vmid, "--hmp", "change", "vnc", "unix:/var/run/qemu-server/%d.vnc,password" % vmid]) vncPid = spawnDaemon( ["socat", "TCP-LISTEN:%d,reuseaddr,fork" % vncport, "UNIX-CLIENT:/var/run/qemu-server/%d.vnc" % vmid]) websockifyPid = None try: if websockifyPort: websockifyPid = websockify.start(websockifyPort, vncport, websockifyCert) except: self.stopVnc(vncPid) raise return vncPid, websockifyPid
def _unset(vmid, keys, force=False): vmid = params.convert(vmid, convert=int, gte=1) _qm(vmid, "set", ["-delete", " ".join(keys), "-force", str(bool(force))]) config = _getConfig(vmid) for key in keys: QMError.check(not key in config, QMError.CODE_PARAMETER_STILL_SET, "Parameter %r has not been removed" % key, { "key": key, "value": config.get(key) })
def unmount(path, ignoreUnmounted=False): path = params.convert(path, convert=os.path.realpath, check=os.path.exists) if not _isMounted(path): if ignoreUnmounted: return raise ImageError(ImageError.CODE_ALREADY_UNMOUNTED, "Path is already unmounted", {"path": path}) try: cmd.run(["umount", path]) except cmd.CommandError, err: raise ImageError(ImageError.CODE_FAILED_TO_UNMOUNT, "Failed to unmount image", {"path": path, "error": repr(err)})
def create(path, size, nested=False): path = params.convert(path, convert=os.path.realpath, check=lambda p: not os.path.exists(p)) size = params.convert(size, convert=int, gte=8192) nested = params.convert(nested, convert=bool) try: cmd.run(["dd", "if=/dev/zero", "of=%s" % path, "bs=1k", "count=%d" % size]) device = path if nested: cmd.run(["sfdisk", path], input=",\n") partitions = _getPartitions(path) start, size = partitions[0] start, size = start * 512, size * 512 ImageError.check(start > 0 and size > 0, ImageError.CODE_FAILED_TO_CREATE, "Failed to create partition table", {"path": path, "table": partitions}) device = cmd.run(["losetup", "-f", "--show", "--offset", str(start), "--sizelimit", str(size), path]).splitlines()[0] ImageError.check(os.path.exists(device), ImageError.CODE_FAILED_TO_CREATE, "Failed to bind to loop device", {"path": path, "size": size, "loop_device": device}) cmd.run(["mkfs.vfat", device]) if nested: cmd.run(["losetup", "-d", device]) except cmd.CommandError, err: raise ImageError(ImageError.CODE_FAILED_TO_CREATE, "Failed to create image", {"path": path, "size": size, "error": repr(err)})
def mount(image, path, sync=False, readOnly=False, partition=0): image = params.convert(image, convert=str, check=os.path.exists) path = params.convert(path, convert=os.path.realpath, check=os.path.exists) partition = params.convert(partition, convert=int, gte=0, lte=4) ImageError.check(not _isMounted(path), ImageError.CODE_ALREADY_MOUNTED, "Path is already mounted", {"path": path}) options = ["loop"] if not partition else [] if sync: options.append("sync") if readOnly: options.append("ro") try: if partition: partitions = _getPartitions(image) start, size = partitions[partition-1] start, size = start * 512, size * 512 ImageError.check(start > 0 and size > 0, ImageError.CODE_FAILED_TO_CREATE, "Wrong partition table", {"image": image, "table": partitions}) options += ["offset=%d" % start, "sizelimit=%d" % size] cmd.run(["mount", "-o%s" % ",".join(options), image, path]) except cmd.CommandError, err: raise ImageError(ImageError.CODE_FAILED_TO_MOUNT, "Failed to mount image", {"path": path, "image": image, "options": options, "error": repr(err)})
def convert(src, dst, srcFormat="qcow2", dstFormat="qcow2", compress=True): src = params.convert(src, check=_checkImage) dst = params.convert(dst, check=lambda p: not os.path.exists(p)) srcFormat = params.convert(srcFormat, convert=str) dstFormat = params.convert(dstFormat, convert=str) try: cmd.run([ "qemu-img", "convert", "-c" if compress else "", "-f", srcFormat, "-O", dstFormat, src, dst ]) except CommandError, err: data = { "src": src, "dst": dst, "src_format": srcFormat, "dst_format": dstFormat } data.update(err.data) raise QemuImgError(QemuImgError.CODE_FAILED_TO_CONVERT, "Failed to convert image", data)
def mount(image, path, sync=False, readOnly=False): image = params.convert(image, convert=str, check=os.path.exists) path = params.convert(path, convert=os.path.realpath, check=os.path.exists) VFatError.check(not _isMounted(path), VFatError.CODE_ALREADY_MOUNTED, "Path is already mounted", {"path": path}) options = ["loop"] if sync: options.append("sync") if readOnly: options.append("ro") try: cmd.run(["mount", "-o%s" % ",".join(options), image, path]) except cmd.CommandError, err: raise VFatError(VFatError.CODE_FAILED_TO_MOUNT, "Failed to mount image", { "path": path, "image": image, "options": options, "error": repr(err) })
def addNetAdminCapabilitie(self,vmid): vmid = params.convert(vmid, convert=int, gte=1) with locks[vmid]: self._checkStatus(vmid, [StateName.CREATED, StateName.PREPARED]) elementFeatures = ET.Element("features") elementCapabilities = ET.Element("capabilities", {"policy": "default"}) elementNetAdmin = ET.Element("net_admin", {"state": "on"}) elementCapabilities.append(elementNetAdmin) elementFeatures.append(elementCapabilities) self.addToConfig(vmid, "domain", elementFeatures)
def startVnc(vmid, vncpassword, vncport, websockifyPort=None, websockifyCert=None): vmid = params.convert(vmid, convert=int, gte=1) vncpassword = params.convert(vncpassword, convert=unicode) vncport = params.convert(vncport, convert=int, gte=1, lt=2**16) with locks[vmid]: _checkStatus(vmid, Status.Running) _setVncPassword(vmid, vncpassword) vncPid = tcpserver.start(vncport, ["qm", "vncproxy", str(vmid)]) websockifyPid = None try: if websockifyPort: websockifyPid = websockify.start(websockifyPort, vncport, websockifyCert) except: stopVnc(vncPid) raise return vncPid, websockifyPid
def addNetTun(self, vmid): vmid = params.convert(vmid, convert=int, gte=1) with locks[vmid]: self._checkStatus(vmid, [StateName.CREATED, StateName.PREPARED]) elementHostDev = ET.Element("hostdev", {"mode": "capabilities", "type": "misc"}) elementSource = ET.Element("source") elementChar = ET.Element("char") elementChar.text = "/dev/net/tun" elementSource.append(elementChar) elementHostDev.append(elementSource) self.addToConfig(vmid, "devices", elementHostDev)
def start(port, vncport, sslcert=None): port = params.convert(port, convert=int, gte=1, lt=2**16) vncport = params.convert(vncport, convert=int, gte=1, lt=2**16) sslcert = params.convert(sslcert, convert=str, null=True, check=os.path.exists) WebsockifyError.check(not netstat.isPortFree(vncport), WebsockifyError.CODE_DEST_PORT_FREE, "Destination port is free", {"port": vncport}) netstat.checkPortFree(port, tcp=True, ipv4=True) pid = spawnDaemon( ["websockify", "0.0.0.0:%d" % port, "localhost:%d" % vncport] + ["--cert=%s" % sslcert] if sslcert else []) try: wait.waitFor(lambda: netstat.isPortUsedBy(port, pid), failCond=lambda: not proc.isAlive(pid)) return pid except wait.WaitError: proc.autoKill(pid, group=True) raise
def _set(vmid, **values): vmid = params.convert(vmid, convert=int, gte=1) values = params.convertMulti(values, _parameterTypes) _qm( vmid, "set", sum([["-%s" % key, unicode(value)] for key, value in values.iteritems()], [])) config = _getConfig(vmid) for key in values: QMError.check(key in config, QMError.CODE_PARAMETER_NOT_SET, "Parameter %r has not been set" % key, { "key": key, "value": values[key] })
def unmount(path, ignoreUnmounted=False): path = params.convert(path, convert=os.path.realpath, check=os.path.exists) if not _isMounted(path): if ignoreUnmounted: return raise VFatError(VFatError.CODE_ALREADY_UNMOUNTED, "Path is already unmounted", {"path": path}) try: cmd.run(["umount", path]) except cmd.CommandError, err: raise VFatError(VFatError.CODE_FAILED_TO_UNMOUNT, "Failed to unmount image", { "path": path, "error": repr(err) })
def start(self, vmid, detachInterfaces=True): vmid = params.convert(vmid, convert=int, gte=1) if not net.bridgeExists("dummy"): brctl.create("dummy") with locks[vmid]: self._checkStatus(vmid,[StateName.PREPARED]) self._virsh("start", ["vm_%s" % vmid]) self._checkStatus(vmid,[StateName.STARTED]) try: for ifname in self._getNicNames(vmid).values(): wait.waitFor(lambda :net.ifaceExists(ifname), failCond=lambda :self.getState(vmid) != StateName.STARTED) bridge = net.ifaceBridge(ifname) if bridge and detachInterfaces: brctl.detach(bridge, ifname) except: self._virsh("destroy", ["vm_%s" % vmid]) raise
def start(vmid, detachInterfaces=True): vmid = params.convert(vmid, convert=int, gte=1) if not net.bridgeExists("dummy"): brctl.create("dummy") with locks[vmid]: _checkStatus(vmid, Status.Stopped) _qm(vmid, ActionName.START) _checkStatus(vmid, Status.Running) try: for ifname in _getNicNames(vmid).values(): wait.waitFor(lambda :net.ifaceExists(ifname), failCond=lambda :_status(vmid) != Status.Running) bridge = net.ifaceBridge(ifname) if bridge and detachInterfaces: brctl.detach(bridge, ifname) except: stop(vmid) raise
def start(vmid, detachInterfaces=True): vmid = params.convert(vmid, convert=int, gte=1) if not net.bridgeExists("dummy"): brctl.create("dummy") with locks[vmid]: _checkStatus(vmid, Status.Stopped) _qm(vmid, ActionName.START) _checkStatus(vmid, Status.Running) try: for ifname in _getNicNames(vmid).values(): wait.waitFor(lambda: net.ifaceExists(ifname), failCond=lambda: _status(vmid) != Status.Running) bridge = net.ifaceBridge(ifname) if bridge and detachInterfaces: brctl.detach(bridge, ifname) except: stop(vmid) raise
def start(self, vmid, detachInterfaces=True): vmid = params.convert(vmid, convert=int, gte=1) if not net.bridgeExists("dummy"): brctl.create("dummy") with locks[vmid]: self._checkStatus(vmid, [StateName.PREPARED]) self._virsh("start", ["vm_%s" % vmid]) self._checkStatus(vmid, [StateName.STARTED]) try: for ifname in self._getNicNames(vmid).values(): wait.waitFor(lambda: net.ifaceExists(ifname), failCond=lambda: self.getState(vmid) != StateName.STARTED) bridge = net.ifaceBridge(ifname) if bridge and detachInterfaces: brctl.detach(bridge, ifname) except: self._virsh("destroy", ["vm_%s" % vmid]) raise
def _checkImageFolder(vmid): vmid = params.convert(vmid, convert=int, gte=1) if not os.path.exists(_imageFolder(vmid)): os.mkdir(_imageFolder(vmid))
def _getKvmCmd(vmid): vmid = params.convert(vmid, convert=int, gte=1) return _qm(vmid, "showcmd")
def destroy(vmid): vmid = params.convert(vmid, convert=int, gte=1) with locks[vmid]: _checkStatus(vmid, Status.Stopped) _qm(vmid, ActionName.DESTROY) _checkStatus(vmid, Status.NoSuchVm)
def isMounted(path): path = params.convert(path, convert=os.path.realpath, check=os.path.exists) return _isMounted(path)
def reset(vmid): vmid = params.convert(vmid, convert=int, gte=1) with locks[vmid]: _checkStatus(vmid, Status.Running) _qm(vmid, "reset") _checkStatus(vmid, Status.Running)
def configure(vmid, **config): vmid = params.convert(vmid, convert=int, gte=1) with locks[vmid]: _checkStatus(vmid, Status.Stopped) _configure(vmid, **config)