Exemplo n.º 1
0
def _prepare_guest_kernel_and_ramdisk(config):
    """
    Use PyGrub to extract the kernel and ramdisk from the given disk image.
    """

    disk_image = config.getConfigItem(DomainConfig.DISK_IMAGE_PATH)

    # Use pygrub to extract the initrd and the kernel from the disk image.
    (status, output) = \
        commands.getstatusoutput("%s -q %s" % (PYGRUB, disk_image))
    if status != 0:
        raise VirtualizationException(
            "Error occurred while executing '%s' (status=%d). Output=%s" %
            (PYGRUB, status, output))

    # Now analyze the output and extract the names of the new kernel and initrd
    # images from it.
    (pygrub_kernel_path, pygrub_initrd_path) = \
        _extract_image_paths_from_pygrub_output(output)

    # Rename the extracted images to the names we are pointing to in the
    # configuration file.
    runtime_kernel_path = config.getConfigItem(DomainConfig.KERNEL_PATH)
    runtime_initrd_path = config.getConfigItem(DomainConfig.RAMDISK_PATH)

    try:
        os.rename(pygrub_kernel_path, runtime_kernel_path)
        os.rename(pygrub_initrd_path, runtime_initrd_path)
    except OSError:
        oe = sys.exc_info()[1]
        raise_with_tb(
            VirtualizationException(
                "Error occurred while renaming runtime image paths: %s" %
                str(oe)),
            sys.exc_info()[2])
Exemplo n.º 2
0
def _connect_to_hypervisor():
    """Connect to the hypervisor."""
    # First, attempt to import libvirt.  If we don't have that, we can't do
    # much else.
    try:
        import libvirt
    except ImportError as ie:
        raise VirtualizationException("Unable to locate libvirt: %s" % str(ie))

    # Attempt to connect to the hypervisor.
    try:
        connection = libvirt.open(None)
    except Exception as e:
        raise VirtualizationException("Could not connect to hypervisor: %s" % str(e))

    return connection
Exemplo n.º 3
0
def start_domain(uuid):
    """
    Boots the domain for the first time after installation is complete.
    """
    # Load the configuration file for this UUID.
    domain = DomainDirectory()
    config = domain.load_config(uuid)

    # Connect to the hypervisor.
    connection = libvirt.open(None)

    # We will attempt to determine if the domain is configured to use a
    # bootloader.  If not, we'll have to explicitly use the kernel and initrd
    # data provided in the config to start the domain.
    try:
        config.getConfigItem(DomainConfig.BOOTLOADER)
    except DomainConfigError:
        dce = sys.exc_info()[1]
        # No bootloader tag present.  Use pygrub to extract the kernel from
        # the disk image if its Xen. For fully virt we dont have pygrub, it
        # directly emulates the BIOS loading the first sector of the boot disk.
        if connection.getType() == 'Xen':
            # This uses pygrub which comes only with xen
            _prepare_guest_kernel_and_ramdisk(config)

    # Now, we'll restart the instance, this time using the re-create XML.
    try:
        domain = connection.createLinux(config.toXML(), 0)
    except Exception:
        e = sys.exc_info()[1]
        raise_with_tb(
            VirtualizationException(
                "Error occurred while attempting to recreate domain %s: %s" %
                (uuid, str(e))),
            sys.exc_info()[2])
Exemplo n.º 4
0
def _call_domain_control_routine(uuid, routine_name, *args):
    """
    Call a function in a domain, optionally with a set of arguments.
    """

    # If libvirt is not available, this is a no-op.
    if not libvirt: return

    # Lookup the domain by its UUID.
    (conn, domain) = _get_domain(uuid)

    # Get a reference to the domain's control routine.
    ctrl_func = None
    try:
        ctrl_func = getattr(domain, routine_name)
    except AttributeError:
        raise_with_tb(
            VirtualizationException("Unknown function: %s" % routine_name),
            sys.exc_info()[2])

    result = 0
    try:
        if sys.version_info[0] == 3:
            result = ctrl_func(*args)
        else:
            result = apply(ctrl_func, args)
    except TypeError:
        te = sys.exc_info()[1]
        raise_with_tb(
            VirtualizationException("Invalid arguments (%s) to %s: %s" %
                                    (str(args), routine_name, str(te))),
            sys.exc_info()[2])
    except libvirt.libvirtError:
        le = sys.exc_info()[1]
        raise_with_tb(
            VirtualizationException("LibVirt Error %s: %s" %
                                    (routine_name, str(le))),
            sys.exc_info()[2])

    # Handle the return code.  Anything non-zero is an error.
    if result != 0:
        raise_with_tb(
            VirtualizationException(
                "Could not perform function '%s' on domain %s.  Error: %s" %
                (routine_name, uuid, str(result))),
            sys.exc_info()[2])
Exemplo n.º 5
0
    def save_unknown_domain_configs(self, domain_uuids):
        """
        This function saves the configuration for any domains whose UUIDs are
        passed in the domain_uuids list.  If the UUID is already known, it is
        skipped.
        """

        for uuid in domain_uuids:

            uuid = sstr(uuid)
            # If we already have a config for this uuid, skip it.  Also, don't
            # try to figure out a config for a host UUID.
            if not is_host_uuid(uuid) and not self.is_known_config(uuid):

                # The UUID is a formatted string.  Turn it back into a number,
                # since that's what libvirt wants.
                dehyphenized_uuid = dehyphenize_uuid(uuid)
                uuid_as_num = binascii.unhexlify(dehyphenized_uuid)

                # Lookup the domain by its uuid.
                try:
                    domain = self.conn.lookupByUUID(uuid_as_num)
                except libvirt.libvirtError:
                    lve = sys.exc_info()[1]
                    raise VirtualizationException(
                        "Failed to obtain handle to domain %s: %s" %
                        (uuid, repr(lve)))

                # Now grab the XML description of the configuration.
                xml = domain.XMLDesc(0)

                # Write the xml out to a file so that we can load it into our
                # abstract DomainConfig object and manipulate it easily.
                cfg_file_path = self.__write_xml_file(uuid, xml)
                new_config = DomainConfig(self.__path, uuid)

                # Don't record the config this time if the domain is
                # installing; we don't want to restart the domain later and
                # make it re-install itself.
                if not new_config.isInstallerConfig():

                    # Now we'll reformat the configuration object so that it's
                    # valid the next time this domain runs..
                    self.__fixup_config_for_restart(new_config)

                    # The config is now prepared.  Save it and move on to the
                    # next uuid.
                    new_config.save()

                else:
                    # Remove the config file we just wrote.
                    os.unlink(cfg_file_path)
Exemplo n.º 6
0
def _get_domain(uuid):
    """
    Lookup the domain by its UUID.  If not found, raise an exception.
    """
    conn = libvirt.open(None)
    domain = None
    hyphenized_uuid = hyphenize_uuid(uuid)
    try:
        domain = conn.lookupByUUIDString(hyphenized_uuid)
    except libvirt.libvirtError:
        lve = sys.exc_info()[1]
        raise_with_tb(VirtualizationException("Domain UUID '%s' not found: %s" % (hyphenized_uuid, str(lve))),
                      sys.exc_info()[2])
    return (conn, domain)
Exemplo n.º 7
0
def _extract_image_paths_from_pygrub_output(output):
    """
    Searches for the paths of the kernel and initrd files in the output of
    pygrub.  If not found, a VirtualizationException is raised.  Otherwise,
    the (kernel_path, initrd_path) tuple is returned.
    """
    match = re.search("^linux \(kernel (\S+)\)\(ramdisk (\S+)\)", output,
                      re.MULTILINE)
    if match is None or len(match.groups()) != 2:
        raise VirtualizationException(
            "Could not locate kernel and initrd in pygrub output: %s" % output)

    kernel_path = match.group(1)
    initrd_path = match.group(2)

    return (kernel_path, initrd_path)
Exemplo n.º 8
0
def poll_state(uuid):
    """
    Polls just the state of the guest with the provided UUID.  This state is
    returned.
    """
    conn = libvirt.openReadOnly(None)
    if not conn:
        raise VirtualizationException("Failed to open connection to hypervisor.")

    # Attempt to connect to the domain.  Since there is technically no
    # "stopped" state, we will assume that if we cannot connect the domain is
    # not running.  Unfortunately, we can't really determine if the domain
    # actually exists.
    domain = None
    try:
        domain = conn.lookupByUUIDString(hyphenize_uuid(uuid))
    except libvirt.libvirtError:
        # Can't find domain.  Return stopped state.
        return State(None)

    # Now that we have the domain, lookup the state.
    domain_info = domain.info()
    return State(VIRT_STATE_NAME_MAP[domain_info[0]])
Exemplo n.º 9
0
 def __init__(self):
     self.__path = CONFIG_DIR
     self.conn = libvirt.openReadOnly(None)
     if not self.conn:
         raise VirtualizationException(
             "Failed to open connection to hypervisor.")
Exemplo n.º 10
0
def poll_hypervisor():
    """
    This function polls the hypervisor for information about the currently
    running set of domains.  It returns a dictionary object that looks like the
    following:

    { uuid : { 'name'        : '...',
               'uuid'        : '...',
               'virt_type'   : '...',
               'memory_size' : '...',
               'vcpus'       : '...',
               'state'       : '...' }, ... }
    """
    if not libvirt:
        return {}

    try:
        conn = libvirt.openReadOnly(None)
    except libvirt.libvirtError:
        # virConnectOpen() failed
        sys.stderr.write(rhncli.utf8_encode(_("Warning: Could not retrieve virtualization information!\n\t" +
                                              "libvirtd service needs to be running.\n")))
        conn = None

    if not conn:
        # No connection to hypervisor made
        return {}

    domainIDs = conn.listDomainsID()

    state = {}

    for domainID in domainIDs:
        try:
            domain = conn.lookupByID(domainID)
        except libvirt.libvirtError:
            lve = sys.exc_info()[1]
            raise_with_tb(VirtualizationException("Failed to obtain handle to domain %d: %s" % (domainID, repr(lve)),
                                                  sys.exc_info()[2]))

        uuid = binascii.hexlify(domain.UUID())
        # SEE: http://libvirt.org/html/libvirt-libvirt.html#virDomainInfo
        # for more info.
        domain_info = domain.info()

        # Set the virtualization type.  We can tell if the domain is fully virt
        # by checking the domain's OSType() attribute.
        virt_type = VirtualizationType.PARA
        if is_fully_virt(domain):
            virt_type = VirtualizationType.FULLY

        # we need to filter out the small per/minute KB changes
        # that occur inside a vm.  To do this we divide by 1024 to
        # drop our precision down to megabytes with an int then
        # back up to KB
        memory = int(domain_info[2] / 1024);
        memory = memory * 1024;
        properties = {
            PropertyType.NAME   : domain.name(),
            PropertyType.UUID   : uuid,
            PropertyType.TYPE   : virt_type,
            PropertyType.MEMORY : str(memory), # current memory
            PropertyType.VCPUS  : domain_info[3],
            PropertyType.STATE  : VIRT_STATE_NAME_MAP[domain_info[0]] }

        state[uuid] = properties

    if state: _log_debug("Polled state: %s" % repr(state))

    return state