def _replace_original_vm(self, removeOld): """ Remove the existing VM with the same name if requested, or error if there is a collision. """ vm = None try: vm = self.conn.lookupByName(self.name) except libvirt.libvirtError: pass if vm is None: return if not removeOld: raise RuntimeError( _("Domain named %s already exists!") % self.name) try: if vm.ID() != -1: logging.info("Destroying image %s" % self.name) vm.destroy() logging.info("Removing old definition for image %s" % self.name) vm.undefine() except libvirt.libvirtError, e: raise RuntimeError( _("Could not remove old vm '%s': %s") % (self.name, str(e)))
def set_port(self, val): if val is None: val = -1 elif type(val) is not int \ or (val != -1 and (val < 5900 or val > 65535)): raise ValueError, _("VNC port must be a number between 5900 and 65535, or -1 for auto allocation") self._port = val
def set_memory(self, val): if (type(val) is not type(1) or val <= 0): raise ValueError, _("Memory value must be an integer greater " "than 0") self._memory = val if self._maxmemory is None or self._maxmemory < val: self._maxmemory = val
def __init__(self, image, capabilities=None, boot_index=None, conn=None): Installer.Installer.__init__(self, conn=conn, caps=capabilities) self._arch = None self._image = image if not (self.conn or self._get_caps()): raise ValueError(_("'conn' or 'capabilities' must be specified.")) # Set boot _boot_caps/_boot_parameters if boot_index is None: self._boot_caps = match_boots(self._get_caps(), self.image.domain.boots) if self._boot_caps is None: raise ImageInstallerException(_("Could not find suitable boot " "descriptor for this host")) else: if (boot_index < 0 or (boot_index + 1) > len(image.domain.boots)): raise ValueError(_("boot_index out of range.")) self._boot_caps = image.domain.boots[boot_index] # Set up internal caps.guest object self._guest = self._get_caps().guestForOSType(self.boot_caps.type, self.boot_caps.arch) if self._guest is None: raise PlatformMatchException(_("Unsupported virtualization type: " "%s %s" % (self.boot_caps.type, self.boot_caps.arch))) self.os_type = self.boot_caps.type self._domain = self._guest.bestDomainType() self.type = self._domain.hypervisor_type self.arch = self._guest.arch
def is_conflict_net(self, conn, mac=None): """ is_conflict_net: determines if mac conflicts with others in system returns a two element tuple: first element is True if fatal collision occured second element is a string description of the collision. Non fatal collisions (mac addr collides with inactive guest) will return (False, "description of collision") """ mac = mac or self.macaddr if mac is None: return (False, None) vms, inactive_vm = _util.fetch_all_guests(conn) # get the Host's NIC MAC address hostdevs = [] if not self.is_remote(): hostdevs = _util.get_host_network_devices() if (_countMACaddr(vms, mac) > 0 or _countMACaddr(inactive_vm, mac) > 0): return (True, _("The MAC address you entered is already in use " "by another virtual machine.")) for dev in hostdevs: host_macaddr = dev[4] if mac.upper() == host_macaddr.upper(): return (True, _("The MAC address you entered conflicts with " "a device on the physical host.")) return (False, None)
def bestDomainType(self, accelerated=None, dtype=None, machine=None): domains = [] for d in self.domains: if dtype and d.hypervisor_type != dtype.lower(): continue if machine and machine not in d.machines: continue domains.append(d) if len(domains) == 0: domainerr = "" machineerr = "" if dtype: domainerr = _(", domain type '%s'") % dtype if machine: machineerr = _(", machine type '%s'") % machine error = (_("No domains available for virt type '%(type)s', " "arch '%(arch)s'") % {'type': self.os_type, 'arch': self.arch}) error += domainerr error += machineerr raise CapabilitiesParserException(error) return self._favoredDomain(accelerated, domains)
def __init__(self, conn=None, parsexml=None, parsexmlnode=None, caps=None): """ Initialize device state @param conn: libvirt connection to validate device against @type conn: virConnect """ XMLBuilderDomain.__init__(self, conn, parsexml, parsexmlnode, caps=caps) self.alias = VirtualDeviceAlias(conn, parsexml=parsexml, parsexmlnode=parsexmlnode, caps=caps) self.address = VirtualDeviceAddress(conn, parsexml=parsexml, parsexmlnode=parsexmlnode, caps=caps) if not self._virtual_device_type: raise ValueError(_("Virtual device type must be set in subclass.")) if self._virtual_device_type not in self.virtual_device_types: raise ValueError( _("Unknown virtual device type '%s'.") % self._virtual_device_type)
def _replace_original_vm(self, removeOld): """ Remove the existing VM with the same name if requested, or error if there is a collision. """ vm = None try: vm = self.conn.lookupByName(self.name) except libvirt.libvirtError: pass if vm is None: return if not removeOld: raise RuntimeError(_("Domain named %s already exists!") % self.name) try: if vm.ID() != -1: logging.info("Destroying image %s" % self.name) vm.destroy() logging.info("Removing old definition for image %s" % self.name) vm.undefine() except libvirt.libvirtError, e: raise RuntimeError(_("Could not remove old vm '%s': %s") % (self.name, str(e)))
def get_char_type_desc(char_type): """ Return a human readable description of the passed char type """ desc = "" if char_type == VirtualCharDevice.CHAR_PTY: desc = _("Pseudo TTY") elif char_type == VirtualCharDevice.CHAR_DEV: desc = _("Physical host character device") elif char_type == VirtualCharDevice.CHAR_STDIO: desc = _("Standard input/output") elif char_type == VirtualCharDevice.CHAR_PIPE: desc = _("Named pipe") elif char_type == VirtualCharDevice.CHAR_FILE: desc = _("Output to a file") elif char_type == VirtualCharDevice.CHAR_VC: desc = _("Virtual console") elif char_type == VirtualCharDevice.CHAR_NULL: desc = _("Null device") elif char_type == VirtualCharDevice.CHAR_TCP: desc = _("TCP net console") elif char_type == VirtualCharDevice.CHAR_UDP: desc = _("UDP net console") elif char_type == VirtualCharDevice.CHAR_UNIX: desc = _("Unix socket") return desc
def set_boot(self, val): self.cdrom = False boot = {} if type(val) == tuple: if len(val) != 2: raise ValueError(_("Must pass both a kernel and initrd")) (k, i) = val boot = {"kernel": k, "initrd": i} elif type(val) == dict: if "kernel" not in val or "initrd" not in val: raise ValueError(_("Must pass both a kernel and initrd")) boot = val elif type(val) == list: if len(val) != 2: raise ValueError(_("Must pass both a kernel and initrd")) boot = {"kernel": val[0], "initrd": val[1]} else: raise ValueError(_("Kernel and initrd must be specified by " "a list, dict, or tuple.")) self._install_bootconfig.kernel = boot.get("kernel") self._install_bootconfig.initrd = boot.get("initrd")
def __init__(self, conn, dev_type): if dev_type not in self.dev_types: raise ValueError( _("Unknown character device type '%s'") % dev_type) self._dev_type = dev_type self._virtual_device_type = self._dev_type VirtualDevice.VirtualDevice.__init__(self, conn) if not self._char_type: raise ValueError("Must not be instantiated through a subclass.") if self._char_type not in self.char_types: raise ValueError( _("Unknown character device type '%s'") % self._char_type) # Init self._source_path = None self._source_mode = self.CHAR_MODE_BIND self._source_host = "127.0.0.1" self._source_port = None self._target_type = None self._target_address = None self._target_port = None self._target_name = None self._bind_host = None self._bind_port = None self._protocol = self.CHAR_PROTOCOL_RAW
def __init__(self, image, capabilities=None, boot_index=None, conn=None): Installer.Installer.__init__(self, conn=conn, caps=capabilities) self._arch = None self._image = image if not (self.conn or self._get_caps()): raise ValueError(_("'conn' or 'capabilities' must be specified.")) # Set boot _boot_caps/_boot_parameters if boot_index is None: self._boot_caps = match_boots(self._get_caps(), self.image.domain.boots) if self._boot_caps is None: raise ImageInstallerException( _("Could not find suitable boot " "descriptor for this host")) else: if (boot_index < 0 or (boot_index + 1) > len(image.domain.boots)): raise ValueError(_("boot_index out of range.")) self._boot_caps = image.domain.boots[boot_index] # Set up internal caps.guest object self._guest = self._get_caps().guestForOSType(self.boot_caps.type, self.boot_caps.arch) if self._guest is None: raise PlatformMatchException( _("Unsupported virtualization type: " "%s %s" % (self.boot_caps.type, self.boot_caps.arch))) self.os_type = self.boot_caps.type self._domain = self._guest.bestDomainType() self.type = self._domain.hypervisor_type self.arch = self._guest.arch
def _validate_cpuset(conn, val): if val is None or val == "": return if type(val) is not type("string") or len(val) == 0: raise ValueError, _("cpuset must be string") if re.match("^[0-9,-]*$", val) is None: raise ValueError, _("cpuset can only contain numeric, ',', or " "'-' characters") pcpus = _util.get_phy_cpus(conn) for c in val.split(','): if c.find('-') != -1: (x, y) = c.split('-') if int(x) > int(y): raise ValueError, _("cpuset contains invalid format.") if int(x) >= pcpus or int(y) >= pcpus: raise ValueError, _("cpuset's pCPU numbers must be less " "than pCPUs.") else: if len(c) == 0: continue if int(c) >= pcpus: raise ValueError, _("cpuset's pCPU numbers must be less " "than pCPUs.") return
def set_conn(self, val): if not isinstance(val, libvirt.virConnect): raise ValueError(_("'conn' must be a libvirt connection object.")) if not _util.is_storage_capable(val): raise ValueError(_("Passed connection is not libvirt storage " "capable")) self._conn = val
def _get_source_xml(self): if not self.host: raise RuntimeError(_("Hostname is required")) if not self.source_path: raise RuntimeError(_("Host path is required")) xml = """ <host name="%s"/>\n""" % self.host + """ <device path="%s"/>\n""" % escape(self.source_path) return xml
def is_size_conflict(self): """ Report if requested size exceeds its pool's available amount @returns: 2 element tuple: 1. True if collision is fatal, false otherwise 2. String message if some collision was encountered. @rtype: 2 element C{tuple}: (C{bool}, C{str}) """ # pool info is [ pool state, capacity, allocation, available ] avail = self.pool.info()[3] if self.allocation > avail: return (True, _("There is not enough free space on the storage " "pool to create the volume. " "(%d M requested allocation > %d M available)" % \ ((self.allocation/(1024*1024)), (avail/(1024*1024))))) elif self.capacity > avail: return (False, _("The requested volume capacity will exceed the " "available pool space when the volume is fully " "allocated. " "(%d M requested capacity > %d M available)" % \ ((self.capacity/(1024*1024)), (avail/(1024*1024))))) return (False, "")
def __init__(self, conn=None, parsexml=None, parsexmlnode=None, caps=None): """ Initialize device state @param conn: libvirt connection to validate device against @type conn: virConnect """ XMLBuilderDomain.__init__(self, conn, parsexml, parsexmlnode, caps=caps) self.alias = VirtualDeviceAlias(conn, parsexml=parsexml, parsexmlnode=parsexmlnode, caps=caps) self.address = VirtualDeviceAddress(conn, parsexml=parsexml, parsexmlnode=parsexmlnode, caps=caps) if not self._virtual_device_type: raise ValueError(_("Virtual device type must be set in subclass.")) if self._virtual_device_type not in self.virtual_device_types: raise ValueError(_("Unknown virtual device type '%s'.") % self._virtual_device_type)
def __init__(self, conn=None): """ Initialize device state @param conn: libvirt connection to validate device against @type conn: virConnect """ if not self._virtual_device_type: raise ValueError(_("Virtual device type must be set in subclass.")) if self._virtual_device_type not in self.virtual_device_types: raise ValueError(_("Unknown virtual device type '%s'.") % self._virtual_device_type) if conn: if not isinstance(conn, libvirt.virConnect): raise ValueError, _("'conn' must be a virConnect instance") self._conn = conn self.__remote = None if self.conn: self.__remote = _util.is_uri_remote(self.conn.getURI()) self._caps = None if self.conn: self._caps = CapabilitiesParser.parse(self.conn.getCapabilities())
def set_model(self, new_model): if type(new_model) != str: raise ValueError, _("'model' must be a string, " " was '%s'." % type(new_model)) if not self.MODELS.count(new_model): raise ValueError, _("Unsupported watchdog model '%s'" % new_model) self._model = new_model
def parseXML(self, node): self.name = xpathString(node, "name") self.label = xpathString(node, "label") self.descr = xpathString(node, "description") self.version = xpathString(node, "name/@version") self.release = xpathString(node, "name/@release") for d in node.xpathEval("storage/disk"): disk = Disk(d) if disk.file is None: disk.id = "disk%d.img" % len(self.storage) disk.file = "disk%d.img" % (len(self.storage) + 1) if disk.id in self.storage: raise ParserException("Disk file '%s' defined twice" % disk.file) self.storage[disk.id] = disk lm = node.xpathEval("domain") if len(lm) == 1: self.domain = Domain(lm[0]) else: raise ParserException(_("Expected exactly one 'domain' element")) # Connect the disk maps to the disk definitions for boot in self.domain.boots: for d in boot.drives: if d.disk_id not in self.storage: raise ParserException( _("Disk entry for '%s' not found") % d.disk_id) d.disk = self.storage[d.disk_id]
def default_route(nic = None): if platform.system() == 'SunOS': cmd = [ '/usr/bin/netstat', '-rn' ] if nic: cmd += [ '-I', nic ] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) for line in proc.stdout.readlines(): vals = line.split() if len(vals) > 1 and vals[0] == 'default': return vals[1] return None route_file = "/proc/net/route" d = file(route_file) defn = 0 for line in d.xreadlines(): info = line.split() if (len(info) != 11): # 11 = typical num of fields in the file print >> stderr, _("Invalid line length while parsing %s.") %(route_file) print >> stderr, _("Defaulting bridge to xenbr%d") % (defn) break try: route = int(info[1],16) if route == 0: return info[0] except ValueError: continue return None
def devAddressToNodedev(conn, addrstr): """ Look up the passed host device address string as a libvirt node device, parse its xml, and return a NodeDevice instance. @param conn: libvirt.virConnect instance to perform the lookup on @param addrstr: host device string to parse and lookup - bus.addr (ex. 001.003 for a usb device) - vendor:product (ex. 0x1234:0x5678 for a usb device - (domain:)bus:slot.func (ex. 00:10.0 for a pci device) @param addrstr: C{str} """ if not is_nodedev_capable(conn): raise ValueError(_("Connection does not support host device " "enumeration.")) ret = _isAddressStr(addrstr) if not ret: raise ValueError(_("Could not determine format of '%s'") % addrstr) cmp_func, devtype = ret # Iterate over node devices and compare nodenames = conn.listDevices(devtype, 0) for name in nodenames: nodedev = _lookupNodeName(conn, name) if cmp_func(nodedev): return nodedev raise ValueError(_("Did not find a matching node device for '%s'") % addrstr)
def set_perms(self, val): if type(val) is not dict: raise ValueError(_("Permissions must be passed as a dict object")) for key in ["mode", "owner", "group"]: if not key in val: raise ValueError(_("Permissions must contain 'mode', 'owner' and 'group' keys.")) self._perms = val
def __init__(self, name, capacity, conn=None, pool_name=None, pool=None, allocation=0): """ @param name: Name for the new storage volume @param capacity: Total size of the new volume (in bytes) @param conn: optional virConnect instance to lookup pool_name on @param pool_name: optional pool_name to install on @param pool: virStoragePool object to install on @param allocation: amount of storage to actually allocate (default 0) """ if pool is None: if pool_name is None: raise ValueError(_("One of pool or pool_name must be " "specified.")) if conn is None: raise ValueError(_("'conn' must be specified with 'pool_name'")) pool = StorageVolume.lookup_pool_by_name(pool_name=pool_name, conn=conn) self._pool = None self.pool = pool StorageObject.__init__(self, object_type=StorageObject.TYPE_VOLUME, name=name, conn=self.pool._conn) self._allocation = None self._capacity = None self._format = None self._input_vol = None self.allocation = allocation self.capacity = capacity # Indicate that the volume installation has finished. Used to # definitively tell the storage progress thread to stop polling. self._install_finished = True
def is_size_conflict(self): """ Report if requested size exceeds its pool's available amount @returns: 2 element tuple: 1. True if collision is fatal, false otherwise 2. String message if some collision was encountered. @rtype: 2 element C{tuple}: (C{bool}, C{str}) """ # pool info is [ pool state, capacity, allocation, available ] avail = self.pool.info()[3] if self.allocation > avail: return (True, _("There is not enough free space on the storage " "pool to create the volume. " "(%d M requested allocation > %d M available)" % \ ((self.allocation / (1024 * 1024)), (avail / (1024 * 1024))))) elif self.capacity > avail: return (False, _("The requested volume capacity will exceed the " "available pool space when the volume is fully " "allocated. " "(%d M requested capacity > %d M available)" % \ ((self.capacity / (1024 * 1024)), (avail / (1024 * 1024))))) return (False, "")
def __init__(self, conn=None): """ Initialize device state @param conn: libvirt connection to validate device against @type conn: virConnect """ if not self._virtual_device_type: raise ValueError(_("Virtual device type must be set in subclass.")) if self._virtual_device_type not in self.virtual_device_types: raise ValueError( _("Unknown virtual device type '%s'.") % self._virtual_device_type) if conn: if not isinstance(conn, libvirt.virConnect): raise ValueError, _("'conn' must be a virConnect instance") self._conn = conn self.__remote = None if self.conn: self.__remote = _util.is_uri_remote(self.conn.getURI()) self._caps = None if self.conn: self._caps = CapabilitiesParser.parse(self.conn.getCapabilities())
def set_os_variant(self, val): if type(val) is not str: raise ValueError(_("OS variant must be a string.")) val = val.lower() if self.os_type: if self._OS_TYPES[self.os_type]["variants"].has_key(val): self._os_variant = val else: raise ValueError, _("OS variant '%(var)s' does not exist in " "our dictionary for OS type '%(ty)s'" ) % \ {'var' : val, 'ty' : self._os_type} else: found = False for ostype in self.list_os_types(): if self._OS_TYPES[ostype]["variants"].has_key(val) and \ not self._OS_TYPES[ostype]["variants"][val].get("skip"): logging.debug("Setting os type to '%s' for variant '%s'" %\ (ostype, val)) self.os_type = ostype self._os_variant = val found = True if not found: raise ValueError, _("Unknown OS variant '%s'" % val)
def set_boot(self, val): self.cdrom = False boot = {} if type(val) == tuple: if len(val) != 2: raise ValueError(_("Must pass both a kernel and initrd")) (k, i) = val boot = {"kernel": k, "initrd": i} elif type(val) == dict: if "kernel" not in val or "initrd" not in val: raise ValueError(_("Must pass both a kernel and initrd")) boot = val elif type(val) == list: if len(val) != 2: raise ValueError(_("Must pass both a kernel and initrd")) boot = {"kernel": val[0], "initrd": val[1]} else: raise ValueError( _("Kernel and initrd must be specified by " "a list, dict, or tuple.")) self._install_bootconfig.kernel = boot.get("kernel") self._install_bootconfig.initrd = boot.get("initrd")
def default_route(nic=None): if platform.system() == 'SunOS': cmd = [ '/usr/bin/netstat', '-rn' ] if nic: cmd += [ '-I', nic ] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) for line in proc.stdout.readlines(): vals = line.split() if len(vals) > 1 and vals[0] == 'default': return vals[1] return None route_file = "/proc/net/route" d = file(route_file) defn = 0 for line in d.xreadlines(): info = line.split() if (len(info) != 11): # 11 = typical num of fields in the file logging.warn(_("Invalid line length while parsing %s."), route_file) logging.warn(_("Defaulting bridge to xenbr%d"), defn) break try: route = int(info[1], 16) if route == 0: return info[0] except ValueError: continue return None
def devAddressToNodedev(conn, addrstr): """ Look up the passed host device address string as a libvirt node device, parse its xml, and return a NodeDevice instance. addrstr can be the following formats: bus.addr (ex. 001.003 for a usb device) vendor:product (ex. 0x1234:0x5678 for a usb device (domain:)bus:slot.func (ex. 00:10.0 for a pci device) @param conn: libvirt.virConnect instance to perform the lookup on @param name: host device string to parse and lookup """ if not is_nodedev_capable(conn): raise ValueError( _("Connection does not support host device " "enumeration.")) ret = _isAddressStr(addrstr) if not ret: raise ValueError(_("Could not determine format of '%s'") % addrstr) cmp_func, devtype = ret # Iterate over node devices and compare nodenames = conn.listDevices(devtype, 0) for name in nodenames: nodedev = _lookupNodeName(conn, name) if cmp_func(nodedev): return nodedev raise ValueError( _("Did not find a matching node device for '%s'") % addrstr)
def _set_conn(self, val): if not isinstance(val, libvirt.virConnect): raise ValueError(_("'conn' must be a libvirt connection object.")) if not support.check_conn_support(val, support.SUPPORT_CONN_INTERFACE): raise ValueError(_("Passed connection is not libvirt interface " "capable")) self._conn = val
def set_model(self, new_model): if type(new_model) != str: raise ValueError, _("'model' must be a string, " " was '%s'." % type(new_model)) if not self.MODELS.count(new_model): raise ValueError, _("Unsupported sound model '%s'" % new_model) self._model = new_model
class InterfaceProtocolIPAddress(object): def __init__(self, address, prefix=None): self._address = address self._prefix = prefix def _get_prefix(self): return self._prefix def _set_prefix(self, val): self._prefix = val prefix = property(_get_prefix, _set_prefix, doc=_("IPv6 address prefix")) def _get_address(self): return self._address def _set_address(self, val): self._address = val address = property(_get_address, _set_address, doc=_("IP address")) def get_xml_config(self): xml = " <ip address='%s'" % self.address if self.prefix is not None: xml += " prefix='%s'" % self.prefix xml += "/>\n" return xml
def is_conflict_net(self, conn): """is_conflict_net: determines if mac conflicts with others in system returns a two element tuple: first element is True if fatal collision occured second element is a string description of the collision. Non fatal collisions (mac addr collides with inactive guest) will return (False, "description of collision")""" if self.macaddr is None: return (False, None) vms, inactive_vm = _util.fetch_all_guests(conn) # get the Host's NIC MACaddress hostdevs = _util.get_host_network_devices() if self.countMACaddr(vms) > 0: return ( True, _("The MAC address you entered is already in use by another active virtual machine." )) for (dummy, dummy, dummy, dummy, host_macaddr) in hostdevs: if self.macaddr.upper() == host_macaddr.upper(): return ( True, _("The MAC address you entered conflicts with a device on the physical host." )) if self.countMACaddr(inactive_vm) > 0: return ( False, _("The MAC address you entered is already in use by another inactive virtual machine." )) return (False, None)
def validate_cpuset(conn, val): if val is None or val == "": return if type(val) is not type("string") or len(val) == 0: raise ValueError(_("cpuset must be string")) if re.match("^[0-9,-^]*$", val) is None: raise ValueError(_("cpuset can only contain numeric, ',', or " "'-' characters")) pcpus = _util.get_phy_cpus(conn) for c in val.split(','): # Redundant commas if not c: continue if "-" in c: (x, y) = c.split('-', 1) x = int(x) y = int(y) if x > y: raise ValueError(_("cpuset contains invalid format.")) if x >= pcpus or y >= pcpus: raise ValueError(_("cpuset's pCPU numbers must be less " "than pCPUs.")) else: if c.startswith("^"): c = c[1:] c = int(c) if c >= pcpus: raise ValueError(_("cpuset's pCPU numbers must be less " "than pCPUs."))
def setup_original(self): """ Validate and setup all parameters needed for the original (cloned) VM """ logging.debug("Validating original guest parameters") if self.original_guest == None and self.original_xml == None: raise RuntimeError(_("Original guest name or xml is required.")) if self.original_guest != None and not self.original_xml: self._original_dom = self._lookup_vm(self.original_guest) self.original_xml = self._original_dom.XMLDesc(0) # Pull clonable storage info from the original xml self._original_virtual_disks = self._get_original_devices_info( self._original_xml) logging.debug("Original paths: %s" % (self.original_devices)) logging.debug("Original sizes: %s" % (self.original_devices_size)) # If domain has devices to clone, it must be 'off' or 'paused' if (not self.clone_running and (self._original_dom and len(self.original_devices) != 0)): status = self._original_dom.info()[0] if status not in [ libvirt.VIR_DOMAIN_SHUTOFF, libvirt.VIR_DOMAIN_PAUSED ]: raise RuntimeError( _("Domain with devices to clone must be " "paused or shutoff."))
def parseXML(self, node): self.name = xpathString(node, "name") self.label = xpathString(node, "label") self.descr = xpathString(node, "description") self.version = xpathString(node, "name/@version") self.release = xpathString(node, "name/@release") for d in node.xpathEval("storage/disk"): disk = Disk(d) if disk.file is None: disk.id = "disk%d.img" % len(self.storage) disk.file = "disk%d.img" % (len(self.storage) + 1) if disk.id in self.storage: raise ParserException("Disk file '%s' defined twice" % disk.file) self.storage[disk.id] = disk lm = node.xpathEval("domain") if len(lm) == 1: self.domain = Domain(lm[0]) else: raise ParserException(_("Expected exactly one 'domain' element")) # Connect the disk maps to the disk definitions for boot in self.domain.boots: for d in boot.drives: if d.disk_id not in self.storage: raise ParserException(_("Disk entry for '%s' not found") % d.disk_id) d.disk = self.storage[d.disk_id]
def get_name(name, guest, image_name=None): prompt_txt = _("What is the name of your virtual machine?") err_txt = _("A name is required for the virtual machine.") if name is None: name = image_name prompt_loop(prompt_txt, err_txt, name, guest, "name")
def setup_original(self): """ Validate and setup all parameters needed for the original (cloned) VM """ logging.debug("Validating original guest parameters") if self.original_guest == None and self.original_xml == None: raise RuntimeError(_("Original guest name or xml is required.")) if self.original_guest != None and not self.original_xml: self._original_dom = self._lookup_vm(self.original_guest) self.original_xml = self._original_dom.XMLDesc(0) logging.debug("Original XML:\n%s", self.original_xml) self._guest = Guest.Guest(conn=self._hyper_conn, parsexml=self.original_xml) # Pull clonable storage info from the original xml self._original_virtual_disks = self._get_original_devices_info() logging.debug("Original paths: %s", self.original_devices) logging.debug("Original sizes: %s", self.original_devices_size) # If domain has devices to clone, it must be 'off' or 'paused' if (not self.clone_running and (self._original_dom and len(self.original_devices) != 0)): status = self._original_dom.info()[0] if status not in [libvirt.VIR_DOMAIN_SHUTOFF, libvirt.VIR_DOMAIN_PAUSED]: raise RuntimeError(_("Domain with devices to clone must be " "paused or shutoff."))
def _get_original_devices_info(self): clonelist = [] retdisks = [] for disk in self._guest.get_devices("disk"): if self._do_we_clone_device(disk): clonelist.append(disk) continue # Set up virtual disk to encapsulate all relevant path info for disk in clonelist: validate = not self.preserve_dest_disks try: if (disk.path and validate and not VirtualDisk.path_exists(self._hyper_conn, disk.path)): raise ValueError(_("Disk '%s' does not exist.") % disk.path) device = VirtualDisk.DEVICE_DISK if not disk.path: # Tell VirtualDisk we are a cdrom to allow empty media device = VirtualDisk.DEVICE_CDROM d = VirtualDisk(disk.path, conn=self._hyper_conn, device=device, driverType=disk.driver_type, validate=validate) d.target = disk.target except Exception, e: logging.debug("", exc_info=True) raise ValueError(_("Could not determine original disk " "information: %s" % str(e))) retdisks.append(d)
def __init__(self, conn, dev_type): if dev_type not in self.dev_types: raise ValueError(_("Unknown character device type '%s'") % dev_type) self._dev_type = dev_type self._virtual_device_type = self._dev_type VirtualDevice.VirtualDevice.__init__(self, conn) if not self._char_type: raise ValueError("Must not be instantiated through a subclass.") if self._char_type not in self.char_types: raise ValueError(_("Unknown character device type '%s'") % self._char_type) # Init self._source_path = None self._source_mode = self.CHAR_MODE_BIND self._source_host = "127.0.0.1" self._source_port = None self._target_type = None self._target_address = None self._target_port = None self._target_name = None self._bind_host = None self._bind_port = None self._protocol = self.CHAR_PROTOCOL_RAW
class NetworkFilesystemPool(StoragePool): """ Create a network mounted filesystem storage pool """ def get_volume_class(): return FileVolume get_volume_class = staticmethod(get_volume_class) formats = [ "auto", "nfs", "glusterfs"] # Register applicable property methods from parent class source_path = property(StoragePool.get_source_path, StoragePool.set_source_path, doc=_("Path on the host that is being shared.")) host = property(StoragePool.get_host, StoragePool.set_host, doc=_("Name of the host sharing the storage.")) target_path = property(StoragePool.get_target_path, StoragePool.set_target_path, doc=_("Location to mount the source device.")) def __init__(self, conn, name, source_path=None, host=None, target_path=None, format="auto", uuid=None): StoragePool.__init__(self, name=name, type=StoragePool.TYPE_NETFS, uuid=uuid, target_path=target_path, conn=conn) self.format = format if source_path: self.source_path = source_path if host: self.host = host def get_format(self): return self._format def set_format(self, val): if not val in self.formats: raise ValueError(_("Unknown Network Filesystem format: %s" % val)) self._format = val format = property(get_format, set_format, doc=_("Type of network filesystem.")) def _get_default_target_path(self): path = (DEFAULT_DIR_TARGET_BASE + self.name) return path def _get_target_xml(self): xml = " <path>%s</path>\n" % escape(self.target_path) return xml def _get_source_xml(self): if not self.host: raise RuntimeError(_("Hostname is required")) if not self.source_path: raise RuntimeError(_("Host path is required")) xml = """ <format type="%s"/>\n""" % self.format + \ """ <host name="%s"/>\n""" % self.host + \ """ <dir path="%s"/>\n""" % escape(self.source_path) return xml
def _upload_file(conn, meter, destpool, src): # Build stream object stream = conn.newStream(0) def safe_send(data): while True: ret = stream.send(data) if ret == 0 or ret == len(data): break data = data[ret:] # Build placeholder volume size = os.path.getsize(src) basename = os.path.basename(src) poolpath = _util.get_xml_path(destpool.XMLDesc(0), "/pool/target/path") name = Storage.StorageVolume.find_free_name(basename, pool_object=destpool) if name != basename: logging.debug("Generated non-colliding volume name %s", name) disk = VirtualDisk(conn=conn, path=os.path.join(poolpath, name), sizebytes=size, sparse=True) disk.setup_dev(meter=meter) vol = disk.vol_object if not vol: raise RuntimeError(_("Failed to lookup scratch media volume")) try: # Register upload offset = 0 length = size flags = 0 stream.upload(vol, offset, length, flags) # Open source file fileobj = file(src, "r") # Start transfer total = 0 meter.start(size=size, text=_("Transferring %s") % os.path.basename(src)) while True: # blocksize = (1024 ** 2) blocksize = 1024 data = fileobj.read(blocksize) if not data: break safe_send(data) total += len(data) meter.update(total) # Cleanup stream.finish() meter.end(size) except: if vol: vol.delete(0) raise return vol
def _get_source_xml(self): if not self.host: raise RuntimeError(_("Hostname is required")) if not self.source_path: raise RuntimeError(_("Host path is required")) xml = """ <host name="%s"/>\n""" % self.host + \ """ <device path="%s"/>\n""" % escape(self.source_path) return xml
def set_vcpus(self, val): maxvcpus = _util.get_max_vcpus(self.conn, self.type) if type(val) is not int or val < 1: raise ValueError, _("Number of vcpus must be a postive integer.") if val > maxvcpus: raise ValueError, _("Number of vcpus must be no greater than %d " "for this vm type.") % maxvcpus self._vcpus = val
class FilesystemPool(StoragePool): """ Create a formatted partition based storage pool """ def get_volume_class(): return FileVolume get_volume_class = staticmethod(get_volume_class) formats = [ "auto", "ext2", "ext3", "ext4", "ufs", "iso9660", "udf", "gfs", "gfs2", "vfat", "hfs+", "xfs" ] # Register applicable property methods from parent class perms = property(StorageObject.get_perms, StorageObject.set_perms) source_path = property(StoragePool.get_source_path, StoragePool.set_source_path, doc=_("The existing device to mount for the pool.")) target_path = property(StoragePool.get_target_path, StoragePool.set_target_path, doc=_("Location to mount the source device.")) def __init__(self, conn, name, source_path=None, target_path=None, format="auto", uuid=None, perms=None): StoragePool.__init__(self, name=name, type=StoragePool.TYPE_FS, target_path=target_path, uuid=uuid, conn=conn) self.format = format if source_path: self.source_path = source_path if perms: self.perms = perms def get_format(self): return self._format def set_format(self, val): if not val in self.formats: raise ValueError(_("Unknown Filesystem format: %s" % val)) self._format = val format = property(get_format, set_format, doc=_("Filesystem type of the source device.")) def _get_default_target_path(self): path = (DEFAULT_DIR_TARGET_BASE + self.name) return path def _get_target_xml(self): xml = " <path>%s</path>\n" % escape(self.target_path) + \ "%s" % self._get_perms_xml() return xml def _get_source_xml(self): if not self.source_path: raise RuntimeError(_("Device path is required")) xml = " <format type='%s'/>\n" % self.format + \ " <device path='%s'/>\n" % escape(self.source_path) return xml
def set_port(self, val): if val is None: val = -1 elif type(val) is not int \ or (val != -1 and (val < 5900 or val > 65535)): raise ValueError, _( "VNC port must be a number between 5900 and 65535, or -1 for auto allocation" ) self._port = val
def get_graphics(vnc, vncport, vnclisten, nographics, sdl, keymap, video_models, guest): video_models = video_models or [] if ((vnc and nographics) or (vnc and sdl) or (sdl and nographics)): raise ValueError, _("Can't specify more than one of VNC, SDL, " "or --nographics") for model in video_models: dev = virtinst.VirtualVideoDevice(guest.conn) dev.model_type = model guest.add_device(dev) if not (vnc or nographics or sdl): if "DISPLAY" in os.environ.keys(): logging.debug("DISPLAY is set: graphics defaulting to VNC.") vnc = True else: logging.debug("DISPLAY is not set: defaulting to nographics.") nographics = True if nographics is not None: guest.graphics_dev = None return # After this point, we are using graphics, so add a video device # if one wasn't passed if not video_models: guest.add_device(VirtualVideoDevice(conn=guest.conn)) if sdl is not None: guest.graphics_dev = VirtualGraphics(type=VirtualGraphics.TYPE_SDL) return if vnc is not None: guest.graphics_dev = VirtualGraphics(type=VirtualGraphics.TYPE_VNC) if vncport: guest.graphics_dev.port = vncport if vnclisten: guest.graphics_dev.listen = vnclisten if keymap: use_keymap = None if keymap.lower() == "local": use_keymap = virtinst.VirtualGraphics.KEYMAP_LOCAL elif keymap.lower() != "none": use_keymap = _util.check_keytable(keymap) if not use_keymap: raise ValueError(_("Didn't match keymap '%s' in keytable!") % keymap) guest.graphics_dev.keymap = use_keymap