Beispiel #1
0
def cleanupExtraDiskImages(dir, references, diskSection):
    """
    Check if any image file is referred more than once, and remove extra copies

    @param dir: directory path to Ovf file/disk image files
    @type dir: String
    """
    # Get file list from References and list of disks from DiskSection
    refList = Ovf.getDict(references)['children']
    diskList = Ovf.getDict(diskSection)['children']

    # Clean up image files referred more than once
    for file in refList:
        fileId = file['ovf:id']
        source = os.path.join(dir, file['ovf:href'])
        fileRefCnt = 0
        prefCnt = 0
        for disk in diskList:
            if disk.has_key('ovf:fileRef'):
                if disk['ovf:fileRef'] == fileId:
                    fileRefCnt = fileRefCnt + 1

            if disk.has_key('ovf:parentRef'):
                if disk['ovf:parentRef'] == fileId:
                    prefCnt = prefCnt + 1

        if fileRefCnt >= 2 or prefCnt >= 2:
            if os.path.isfile(source):
                os.remove(source)
Beispiel #2
0
    def doChecksum(self, stamp="auto"):
        """
        This method will optionally take a time stamp. If the file is not
        local it will use time.gmtime() to set the checksumstamp. Otherwise
        it will use the file descriptor to extract that information. The method
        will then perform a SHA1 checksum of the file and store the results in
        checksum.

        @type stamp: time in UTC.
        @param stamp: Time stamp of the file. (Last modify)

        """
        refFile = self.getFileObject()
        if stamp != "auto":
            self.setChecksum(stamp)
        else:
            mtime = None
            try:
                mtime = os.fstat(refFile.fileno())[stat.ST_MTIME]
            except:
                # if the fstat failed, call with no args
                self.setChecksumStamp()

            if mtime != None:
                # if fstat succeeded call it with mtime
                self.setChecksumStamp(mtime)

        self.checksum = Ovf.sha1sumFile(refFile)
Beispiel #3
0
def getOvfNetworks(virtualHardware, configId=None):
    """
    Retrieves network interface information for the virtual machine from the Ovf file.

    @param virtualHardware: Ovf VirtualSystem Node
    @type virtualHardware: DOM Element

    @param configId: configuration name
    @type configId: String

    @return: list of dictionaries, seeL{Interface Elements<networkElement>}
    @rtype: list

    @todo: stubbed function, needs work
    """
    netList = []
    rasd = Ovf.getDict(virtualHardware, configId)['children']

    ovfNetDeviceList = []
    for resource in rasd:
        if resource['name'] == 'Item':
            if resource['rasd:ResourceType'] == '10':
                ovfNetDeviceList.append(resource)

    # create a dict for each device
    # We currently only support the libvirt virtual network interface.  We
    # also assume that the network currently exists.  The default network
    # is "default".
    for netDevice in ovfNetDeviceList:
        netAttach = 'default'
        if netDevice.has_key('rasd:Connection'):
            netConnect = netDevice['rasd:Connection']
        netList.append(dict(interfaceType = 'network', sourceName = netConnect))

    return netList
Beispiel #4
0
def getReferencedFilesFromManifest(fileName):
    """
    get a list of OvfReferencedFile objects mentioned in OVF Manifest file
    @type  fileName: string
    @param fileName: path to a file to read Manifest file from
    @rtype : list of OvfReferencedFile objects
    @return: list of OvfReferencedFile objects that appear in manifest
    """
    try:
        files = []
        mfFD = open(fileName, "r")  # only need to read the contents

        line = mfFD.readline()

        prefix = "SHA1("

        while line:
            txt = line.strip()
            newLn = txt.split("=")  # newLn is what we get from the .mf file
            # when you append newLn it returns as a list so need to add both elements
            partial = newLn[0].split(prefix)  # this will return ['', 'ourOVF.ovf)']
            # still need to take out the last )
            name = partial[1].split(")")
            # the above line will return ['Ubuntu-0.vmdk', '']
            href = name[0]  # the name will always be stored in name[0]
            sumSection = txt.split("=")
            ans = sumSection[1].strip()
            path = Ovf.href2abspath(href, fileName)
            files.append(OvfReferencedFile.OvfReferencedFile(path, href, ans))
            line = mfFD.readline()  # get the next line

        return files

    except Exception, e:
        raise e
Beispiel #5
0
def getPropertiesForNode(node, configuration):
    """
    Generate an array of tuples containing the environment information
    for a single node (vs or vsc)
    @type node: DOM node
    @param node: virtual system or collection DOM node
    @type configuration: String
    @param configuration: Configuration being used.  Can be None

    @rtype: array
    @return: array of [(key, property node, value)]
    """
    # Start by getting all product sections for this node
    productSections = Ovf.getChildNodes(node, (Ovf.hasTagName,
                                               'ProductSection'))
    retArray = []

    # it's valid for there to be 0 product sections
    if productSections != []:
        for prodNode in productSections:
            prodClass = prodNode.getAttribute('ovf:class')
            if prodClass != '':
                prodClass += '.'
            prodInstance = prodNode.getAttribute('ovf:instance')
            if prodInstance != '':
                prodInstance = '.' + prodInstance

            properties = Ovf.getChildNodes(prodNode,
                                           (Ovf.hasTagName, 'Property'))

            if properties == []:
                continue

            for propertyNode in properties:
                attributes = Ovf.getAttributes(propertyNode)
                if not attributes.has_key('ovf:key'):
                    raise RuntimeError, 'Node missing required attribute ' +\
                                        'ovf:key'

                propKey = prodClass + attributes['ovf:key'] + prodInstance
                retArray.append((propKey, propertyNode,
                                getPropertyDefaultValue(propertyNode,\
                                                        configuration)))

    return retArray
Beispiel #6
0
def getOvfVcpu(virtualHardware, configId=None):
    """
    Retrieves the number of virtual CPUs to be allocated for the virtual
    machine from the Ovf file.

    @param virtualHardware: Ovf VirtualSystem Node
    @type virtualHardware: DOM Element

    @param configId: configuration name
    @type configId: String

    @return: quantity of virtual cpu's
    @rtype: String
    """
    vcpu = ''
    rasd = Ovf.getDict(virtualHardware, configId)['children']
    for resource in rasd:
        if(resource.has_key('rasd:ResourceType') and
           resource['rasd:ResourceType'] == '3'):
            vcpu = resource['rasd:VirtualQuantity']

    return vcpu
Beispiel #7
0
def getPropertyDefaultValue(propertyNode, configuration):
    """
    Get the default value for a given Property node.  The value returned is
    based on this priority:
    1) value node for given configuration
    2) ovf:value attribute
    3) first Value node
    @type propertyNode: DOM node
    @param propertyNode: Property node
    @type configuration: String
    @param configuration: Configuration used to select the default value

    @rtype: String
    @return: Default value for node.  May be empty string.  None if no default
             was specified
    """
    if not configuration:
        docNode = propertyNode.parentNode
        while docNode.nodeType != Node.DOCUMENT_NODE:
            docNode = docNode.parentNode
            if not docNode:
                raise RuntimeError, "Unable to find document node"

        configuration = Ovf.getDefaultConfiguration(docNode)

    if configuration:
        valueNodes = Ovf.getChildNodes(propertyNode,
                                       (Ovf.hasTagName, 'Value'),
                                       (Ovf.hasAttribute, 'ovf:configuration',
                                        configuration))
        if valueNodes:
            attributes = Ovf.getAttributes(valueNodes[0])
            if attributes.has_key('ovf:value'):
                return attributes['ovf:value']

    attributes = Ovf.getAttributes(propertyNode)
    if attributes.has_key('ovf:value'):
        return attributes['ovf:value']

    valueNodes = Ovf.getChildNodes(propertyNode, (Ovf.hasTagName, 'Value'))
    if valueNodes:
        attributes = Ovf.getAttributes(valueNodes[0])
        if attributes.has_key('ovf:value'):
            return attributes['ovf:value']

    return None
Beispiel #8
0
def getOvfCurrentMemory(virtualHardware, configId=None):
    """
    Retrieves the amount of memory (kB) to be allocated for the virtual machine
    from the Ovf file.

    @note: DSP0004 v2.5.0 outlines the Programmatic Unit forms for
    OVF. This pertains specifically to rasd:AllocationUnits, which accepts
    both the current and deprecated forms. New implementations should not
    use Unit Qualifiers as this form is deprecated.
        - PUnit form, as in "byte * 2^20"
        - PUnit form w/ Units Qualifier(deprecated), as in "MegaBytes"

    @param virtualHardware: Ovf VirtualSystem Node
    @type virtualHardware: DOM Element

    @param configId: configuration name
    @type configId: String

    @return: memory in kB
    @rtype: String
    """
    memory = ''

    # TODO: needs to use bound:normal, if it is present
    rasd = Ovf.getDict(virtualHardware, configId)['children']
    for resource in rasd:
        if(resource.has_key('rasd:ResourceType') and
           resource['rasd:ResourceType'] == '4'):
            memoryQuantity = resource['rasd:VirtualQuantity']
            memoryUnits = resource['rasd:AllocationUnits']

            if(memoryUnits.startswith('byte') or
                 memoryUnits.startswith('bit')):
                # Calculate PUnit numerical factor
                memoryUnits = memoryUnits.replace('^','**')

                # Determine PUnit Quantifier DMTF DSP0004, {byte, bit}
                # Convert to kilobytes
                memoryUnits = memoryUnits.split(' ', 1)
                quantifier = memoryUnits[0]
                if quantifier == 'byte':
                    memoryUnits[0] = '2**-10'
                elif quantifier == 'bit':
                    memoryUnits[0] = '2**-13'
                else:
                    raise ValueError("Incompatible PUnit quantifier for memory.")

                memoryUnits = ' '.join(memoryUnits)
                memoryFactor = int(eval(memoryUnits))

            else:
                if memoryUnits.startswith('Kilo'):
                    memoryFactor = 1
                elif memoryUnits.startswith('Mega'):
                    memoryFactor = 1024
                elif memoryUnits.startswith('Giga'):
                    memoryFactor = 2048
                else:
                    raise ValueError("Incompatible PUnit quantifier for memory.")

                if memoryUnits.endswith('Bytes'):
                    memoryFactor *= 1
                elif memoryUnits.endswith('Bits'):
                    memoryFactor *= 0.125
                else:
                    raise ValueError("Incompatible PUnit quantifier for memory.")

            memory = str(int(memoryQuantity) * memoryFactor)

    return memory
Beispiel #9
0
def getOvfStartup(ovf):
    """
    Returns a schedule representing the startup order for a virtual
    appliance from an ovf.

    @param ovf: Ovf file
    @type ovf: DOM Document

    @rtype: dictionary
    @return: startup dictionary of domains
    """
    startupDict = dict(boot='',
                       entities=dict())

    systems = startupDict['entities']

    # Create a list of all startup sections
    startupSections = Ovf.getNodes(ovf, (Ovf.hasTagName, 'StartupSection'))

    # Create an entry in startup dictionary for each entry in Startup sections
    for section in startupSections:
        for item in section.getElementsByTagName('Item'):
            attributes = []
            for i in range(item.attributes.length):
                attr = item.attributes.item(i)
                if attr.name == 'ovf:id':
                    sysId = attr.value
                elif(attr.name == 'ovf:order' or
                   attr.name == 'ovf:startDelay'):
                    attributes.append((attr.name, attr.value))

            # Store attribute pairs in dicitonary
            virtualSys = dict(attributes)
            if not virtualSys.has_key('ovf:order'):
                virtualSys['ovf:order'] = '0'
            if not virtualSys.has_key('ovf:startDelay'):
                virtualSys['ovf:startDelay'] = '0'

            parentId = section.parentNode.getAttribute('ovf:id')
            if not systems.has_key(parentId):
                systems[parentId] = dict(systems=[])
            systems[parentId]['systems'].append(sysId)
            systems[sysId] = virtualSys

    # Create a default entry for each system not in a startup section
    for each in Ovf.getNodes(ovf, (Ovf.hasTagName, 'VirtualSystem')):
        sysId = each.getAttribute('ovf:id')

        # If parentNode is Envelope, set as root system
        # else, trace back and fill in missing parent info
        if each.parentNode.tagName == 'Envelope':
            startupDict['boot'] = sysId
            systems[sysId] = {'ovf:order':'0', 'ovf:startDelay':'0'}
        else:
            parent = each.parentNode
            parentId = parent.getAttribute('ovf:id')
            if systems.has_key(parentId) and \
                not systems.has_key(sysId):
                systems[parentId]['systems'].append(sysId)
                systems[sysId] = {'ovf:order':'0', 'ovf:startDelay':'0'}

            # set parent info
            if parent.parentNode.tagName == 'Envelope':
                startupDict['boot'] = parentId

            while(not systems.has_key(parentId)):
                systems[parentId] = {'systems':[]}
                systems[parentId]['systems'].append(sysId)
                systems[sysId] = {'ovf:order':'0', 'ovf:startDelay':'0'}

                # Increment, if not at root
                if parent.parentNode.tagName == 'Envelope':
                    startupDict['boot'] = parentId
                else:
                    parent = parent.parentNode
                    sysId = parentId
                    parentId = parent.getAttribute('ovf:id')

    return startupDict
Beispiel #10
0
def getOvfDomains(ovf, path, hypervisor=None, configId=None, envDirectory=None):
    """
    Returns a dictionary with all of the VirtualSystems in an ovf
    listed as keys with the libvirt domain, for the specified configuration,
    stored as the value.

    @param ovf: Ovf file
    @type ovf: DOM Document

    @param path: path to Ovf file
    @type path: String

    @param configId: configuration name
    @type configId: String

    @todo: needs work, very basic, assumes hypervisor type
    """
    domains = dict()
    #directory = os.path.abspath(path.rsplit("/", 1)[0])
    directory = path

    if configId == None:
        configId = Ovf.getDefaultConfiguration(ovf)
    else:
        if not Ovf.isConfiguration(ovf, configId):
            raise RuntimeError("OvfLibvirt.getOvfDomains: configuration " +
                                configId + " not found.")

    # Get Nodes
    references = Ovf.getElementsByTagName(ovf, 'References')
    diskSection = Ovf.getElementsByTagName(ovf, 'DiskSection')

    if len(references) is not 1:
        raise NotImplementedError("OvfLibvirt.getOvfDomain: Unable to locate" +
                                  " a single References node.")
    elif len(diskSection) is not 1:
        raise NotImplementedError("OvfLibvirt.getOvfDomain: Unable to locate" +
                                  " a single DiskSection node.")
    else:
        refs = references[0]
        disks = diskSection[0]

    # For each system, create libvirt domain description
    for system in Ovf.getNodes(ovf, (Ovf.hasTagName, 'VirtualSystem')):
        ovfId = system.getAttribute('ovf:id')

        # Get VirtualHardwareSection
        virtualHardwareSection = Ovf.getElementsByTagName(system,
                                                          'VirtualHardwareSection')

        if len(virtualHardwareSection) is not 1:
            raise NotImplementedError("OvfLibvirt.getOvfDomain: Unable to locate" +
                                      " a single VirtualHardwareSection node.")
        else:
            virtualHardware = virtualHardwareSection[0]

            #metadata
            name = nameElement(ovfId)

            #resources
            memory = memoryElement(getOvfMemory(virtualHardware, configId))
            vcpu = vcpuElement(getOvfVcpu(virtualHardware, configId))

            #domain
            if not hypervisor:
                hypervisor = OvfPlatform.getVsSystemType(system)
            else:
                hypervisor = hypervisor.lower()
            domainType = getDomainTypeForVsType(hypervisor)
            domain = domainElement(domainType)

            #boot
            bootElements(domain, hypervisor)

            #time
            clock = clockElement('utc')

            #features
            features = featuresElement(acpi=True)

            #life cycle
            onPowerOff = onPowerOffElement('destroy')
            onReboot = onRebootElement('restart')
            onCrash = onCrashElement('destroy')

            #devices - graphics
            graphics = graphicsElement('vnc', 'localhost', '-1')

            #devices - console
            console = consoleElement('pty', '0')

            #devices
            devices = devicesElement(graphics, console)

            #disks
            envFile = None
            if envDirectory:
                envFile = os.path.join(envDirectory, ovfId + '.iso')
            diskDicts = getOvfDisks(virtualHardware, directory, refs,
                                    disks, configId, envFile)
            for dsk in diskDicts:
                addDevice(devices, diskElement(dsk))

            #network
            netDicts = getOvfNetworks(virtualHardware, configId)
            for networkDict in netDicts:
                network = networkElement(networkDict)
                addDevice(devices, network)

            #document
            document = libvirtDocument(domain, name, memory, vcpu,
                                       clock, features, onPowerOff,
                                       onReboot, onCrash, devices)

        domains[ovfId] = Ovf.xmlString(document)

    # Delete any extra copies of disk images
    cleanupExtraDiskImages(directory, refs, disks)

    return domains
Beispiel #11
0
def getOvfDisks(virtualHardware, dir, references, diskSection=None,
                configId=None, envFile=None):
    """
    Retrieves disk device information for the virtual machine
    from the Ovf file.

    @param ovf: Ovf file
    @type ovf: DOM Document

    @param virtualHardware: Ovf VirtualSystem Node
    @type virtualHardware: DOM Element

    @param configId: configuration name
    @type configId: String

    @return: list of dictionaries, see L{Disk Element<diskElement>}
    @rtype: list
    """
    disks = ()
    logicalNames = ['hda', 'hdb', 'hdd', 'hde', 'hdf']

    rasd = Ovf.getDict(virtualHardware, configId)['children']

    ovfDiskList = []
    for resource in rasd:
        if resource['name'] == 'Item':
            if resource['rasd:ResourceType'] == '14':
                ovfDiskList.append(('fd', resource))
            elif resource['rasd:ResourceType'] == '15':
                ovfDiskList.append(('cdrom', resource))
            elif resource['rasd:ResourceType'] == '17':
                ovfDiskList.append(('disk', resource))

    for each in ovfDiskList:
        hostResources = []

        #resource dictionary
        ovfDisk = each[1]

        #disk device: hd, fd, or cdrom
        device = each[0]

        #source file
        source = None
        hostResource = ovfDisk['rasd:HostResource']
        resourceId = hostResource.rsplit('/', 1).pop()
        if hostResource.startswith('ovf:/disk/'):
            diskList = Ovf.getDict(diskSection)['children']

            for child in diskList:
                #Create a tuple (file hostResource, diskId, referred?)
                #flag to check if the disk is referred
                referedDisk = 0
                if child['ovf:diskId'] == resourceId:
                    #Check for disks referred as parentRef.
                    #Add parentRef disk first, as it could be the
                    # operating system disk image
                    if child.has_key('ovf:parentRef'):
                        parentref = child['ovf:parentRef']
                        for pref in diskList:
                            if pref['ovf:diskId'] == parentref:
                                referedDisk = 1
                                hostResource = 'ovf://file/' + pref['ovf:fileRef']
                                diskResource = (hostResource, resourceId, referedDisk)
                                hostResources.append(diskResource)
                                break

                    # and the disk referred by the VMs HostResource
                    #Check to see if the fileRef is referred by more than one disk
                    referedDisk = 0
                    hostResource = 'ovf://file/' + child['ovf:fileRef']
                    refcnt = 0
                    myFileRef = child['ovf:fileRef']
                    for disk in diskList:
                        if disk['ovf:fileRef'] == myFileRef:
                            refcnt = refcnt + 1
                    if refcnt > 1:
                        referedDisk = 1
                    diskResource = (hostResource, resourceId, referedDisk)
                    hostResources.append(diskResource)
        for resource in hostResources:
            (hostResource, diskId, referedDisk) = resource
            resourceId = hostResource.rsplit('/', 1).pop()
            refList = Ovf.getDict(references)['children']

            for child in refList:
                if child['ovf:id'] == resourceId:
                    source = os.path.join(dir, child['ovf:href'])
                    if referedDisk == 1:
                        simage = source
                        diskpath = source.rsplit('/', 1)[0]
                        diskimage = source.rsplit('/', 1)[1]
                        diskname = diskimage.split('.')[0]
                        disknameext = diskimage.split('.')[1]
                        newdiskname = diskname + '-' + diskId
                        if disknameext != None:
                            source = os.path.join(diskpath, newdiskname + '.' + disknameext)
                        else:
                            source = os.path.join(diskpath, newdiskname)
                        dimage = source
                        shutil.copy(simage, dimage)

            if source == None:
                raise ValueError(hostResource)

            #target bus
            parentType = None
            parentId = int(ovfDisk['rasd:Parent'])
            for presource in rasd:
                if presource['name'] == 'Item':
                    instId = int(presource['rasd:InstanceID'])
                    if instId == parentId:
                        parentType = presource['rasd:ResourceType']
                        break

            if(parentType == '5'):
                bus = 'ide'
            elif(parentType == '6'):
                bus = 'scsi'
            else:
                raise ValueError

            #default not read-only
            ro = False

            #target device
            if(device == 'cdrom'):
                ro = True
                dev = 'hdc'
            else:
                dev = logicalNames.pop(0)

            libvirtDisk = dict(diskType='file',
                               diskDevice=device,
                               sourceFile=source,
                               targetBus=bus,
                               targetDev=dev,
                               readonly=ro)
            disks += (libvirtDisk,)

    # add the environment iso
    if envFile:
        disks += (dict(diskType = 'file',
                      targetDev = 'hdc:cdrom',
                      sourceFile = os.path.abspath(envFile),
                      targetBus = 'ide',
                      diskDevice = 'cdrom',
                      readonly = True),)

    return disks