//! //! Generates the XML content for a given volume //! //! @param[in] volumeId the volume identifier string (vol-XXXXXXXX) //! @param[in] instance a pointer to our instance structure //! @param[in] localDevReal a string containing the target device name //! @param[in] remoteDev a string containing the disk path. //! //! @return The results of calling write_xml_file() //! //! @see write_xml_file() //! int gen_volume_xml(const char *volumeId, const ncInstance * instance, const char *localDevReal, const char *remoteDev) { int ret = EUCA_ERROR; char bitness[4] = ""; char path[MAX_PATH] = ""; xmlDocPtr doc = NULL; xmlNodePtr volumeNode = NULL; xmlNodePtr hypervisor = NULL; xmlNodePtr os = NULL; xmlNodePtr backing = NULL; xmlNodePtr root = NULL; xmlNodePtr disk = NULL; INIT(); pthread_mutex_lock(&xml_mutex); { doc = xmlNewDoc(BAD_CAST "1.0"); volumeNode = xmlNewNode(NULL, BAD_CAST "volume"); xmlDocSetRootElement(doc, volumeNode); // hypervisor-related specs hypervisor = xmlNewChild(volumeNode, NULL, BAD_CAST "hypervisor", NULL); _ATTRIBUTE(hypervisor, "type", instance->hypervisorType); _ATTRIBUTE(hypervisor, "capability", hypervsorCapabilityTypeNames[instance->hypervisorCapability]); snprintf(bitness, 4, "%d", instance->hypervisorBitness); _ATTRIBUTE(hypervisor, "bitness", bitness); _ELEMENT(volumeNode, "id", volumeId); _ELEMENT(volumeNode, "user", instance->userId); _ELEMENT(volumeNode, "instancePath", instance->instancePath); // OS-related specs os = _NODE(volumeNode, "os"); _ATTRIBUTE(os, "platform", instance->platform); _ATTRIBUTE(os, "virtioRoot", _BOOL(config_use_virtio_root)); _ATTRIBUTE(os, "virtioDisk", _BOOL(config_use_virtio_disk)); _ATTRIBUTE(os, "virtioNetwork", _BOOL(config_use_virtio_net)); //! backing specification (@todo maybe expand this with device maps or whatnot?) backing = xmlNewChild(volumeNode, NULL, BAD_CAST "backing", NULL); root = xmlNewChild(backing, NULL, BAD_CAST "root", NULL); assert(instance->params.root); _ATTRIBUTE(root, "type", ncResourceTypeName[instance->params.root->type]); // volume information disk = _ELEMENT(volumeNode, "diskPath", remoteDev); _ATTRIBUTE(disk, "targetDeviceType", "disk"); _ATTRIBUTE(disk, "targetDeviceName", localDevReal); _ATTRIBUTE(disk, "targetDeviceBus", "scsi"); _ATTRIBUTE(disk, "sourceType", "block"); snprintf(path, sizeof(path), EUCALYPTUS_VOLUME_XML_PATH_FORMAT, instance->instancePath, volumeId); ret = write_xml_file(doc, instance->instanceId, path, "volume"); xmlFreeDoc(doc); } pthread_mutex_unlock(&xml_mutex); return (ret); }
int gen_libvirt_attach_xml (const char *volumeId, const ncInstance *instance, const char * localDevReal, const char * remoteDev, char * xml, unsigned int xml_size) { INIT(); int ret = 1; pthread_mutex_lock (&xml_mutex); xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0"); xmlNodePtr volumeNode = xmlNewNode (NULL, BAD_CAST "volume"); xmlDocSetRootElement (doc, volumeNode); { // hypervisor-related specs xmlNodePtr hypervisor = xmlNewChild (volumeNode, NULL, BAD_CAST "hypervisor", NULL); _ATTRIBUTE(hypervisor, "type", instance->hypervisorType); _ATTRIBUTE(hypervisor, "capability", hypervsorCapabilityTypeNames[instance->hypervisorCapability]); char bitness[4]; snprintf(bitness, 4,"%d", instance->hypervisorBitness); _ATTRIBUTE(hypervisor, "bitness", bitness); } _ELEMENT(volumeNode, "id", volumeId); _ELEMENT(volumeNode, "user", instance->userId); _ELEMENT(volumeNode, "instancePath", instance->instancePath); { // OS-related specs xmlNodePtr os = _NODE(volumeNode, "os"); _ATTRIBUTE(os, "platform", instance->platform); _ATTRIBUTE(os, "virtioRoot", _BOOL(config_use_virtio_root)); _ATTRIBUTE(os, "virtioDisk", _BOOL(config_use_virtio_disk)); _ATTRIBUTE(os, "virtioNetwork", _BOOL(config_use_virtio_net)); } { // backing specification (TODO: maybe expand this with device maps or whatnot?) xmlNodePtr backing = xmlNewChild (volumeNode, NULL, BAD_CAST "backing", NULL); xmlNodePtr root = xmlNewChild (backing, NULL, BAD_CAST "root", NULL); assert (instance->params.root); _ATTRIBUTE(root, "type", ncResourceTypeName[instance->params.root->type]); } { // volume information xmlNodePtr disk = _ELEMENT(volumeNode, "diskPath", remoteDev); _ATTRIBUTE(disk, "targetDeviceType", "disk"); _ATTRIBUTE(disk, "targetDeviceName", localDevReal); _ATTRIBUTE(disk, "targetDeviceBus", "scsi"); _ATTRIBUTE(disk, "sourceType", "block"); } char path [MAX_PATH]; snprintf (path, sizeof (path), EUCALYPTUS_VOLUME_XML_PATH_FORMAT, instance->instancePath, volumeId); ret = write_xml_file (doc, instance->instanceId, path, "volume") || apply_xslt_stylesheet (xslt_path, path, NULL, xml, xml_size); logprintfl (EUCATRACE, "XML={%s}\n", xml); xmlFreeDoc(doc); pthread_mutex_unlock (&xml_mutex); return ret; }
// Encodes instance metadata (contained in ncInstance struct) in XML // and writes it to file instance->xmlFilePath (/path/to/instance/instance.xml) // That file gets processed through tools/libvirt.xsl (/etc/eucalyptus/libvirt.xsl) // to produce /path/to/instance/libvirt.xml file that is passed to libvirt create. int gen_instance_xml (const ncInstance * instance) { INIT(); int ret = 1; pthread_mutex_lock (&xml_mutex); xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0"); xmlNodePtr instanceNode = xmlNewNode (NULL, BAD_CAST "instance"); xmlDocSetRootElement (doc, instanceNode); { // hypervisor-related specs xmlNodePtr hypervisor = xmlNewChild (instanceNode, NULL, BAD_CAST "hypervisor", NULL); _ATTRIBUTE(hypervisor, "type", instance->hypervisorType); _ATTRIBUTE(hypervisor, "capability", hypervsorCapabilityTypeNames[instance->hypervisorCapability]); char bitness[4]; snprintf(bitness, 4,"%d", instance->hypervisorBitness); _ATTRIBUTE(hypervisor, "bitness", bitness); } { // backing specification (TODO: maybe expand this with device maps or whatnot?) xmlNodePtr backing = xmlNewChild (instanceNode, NULL, BAD_CAST "backing", NULL); xmlNodePtr root = xmlNewChild (backing, NULL, BAD_CAST "root", NULL); assert (instance->params.root); _ATTRIBUTE(root, "type", ncResourceTypeName[instance->params.root->type]); } _ELEMENT(instanceNode, "name", instance->instanceId); _ELEMENT(instanceNode, "uuid", instance->uuid); _ELEMENT(instanceNode, "reservation", instance->reservationId); _ELEMENT(instanceNode, "user", instance->userId); _ELEMENT(instanceNode, "dnsName", instance->dnsName); _ELEMENT(instanceNode, "privateDnsName", instance->privateDnsName); _ELEMENT(instanceNode, "instancePath", instance->instancePath); if (instance->params.kernel) { char * path = instance->params.kernel->backingPath; if (path_check (path, "kernel")) goto free; // sanity check _ELEMENT(instanceNode, "kernel", path); } if (instance->params.ramdisk) { char * path = instance->params.ramdisk->backingPath; if (path_check (path, "ramdisk")) goto free; // sanity check _ELEMENT(instanceNode, "ramdisk", path); } _ELEMENT(instanceNode, "consoleLogPath", instance->consoleFilePath); _ELEMENT(instanceNode, "userData", instance->userData); _ELEMENT(instanceNode, "launchIndex", instance->launchIndex); char cores_s [10]; snprintf (cores_s, sizeof (cores_s), "%d", instance->params.cores); _ELEMENT(instanceNode, "cores", cores_s); char memory_s [10]; snprintf (memory_s, sizeof (memory_s), "%d", instance->params.mem * 1024); _ELEMENT(instanceNode, "memoryKB", memory_s); { // SSH-key related xmlNodePtr key = _NODE(instanceNode, "key"); _ATTRIBUTE(key, "isKeyInjected", _BOOL(instance->do_inject_key)); _ATTRIBUTE(key, "sshKey", instance->keyName); } { // OS-related specs xmlNodePtr os = _NODE(instanceNode, "os"); _ATTRIBUTE(os, "platform", instance->platform); _ATTRIBUTE(os, "virtioRoot", _BOOL(config_use_virtio_root)); _ATTRIBUTE(os, "virtioDisk", _BOOL(config_use_virtio_disk)); _ATTRIBUTE(os, "virtioNetwork", _BOOL(config_use_virtio_net)); } { // disks specification xmlNodePtr disks = _NODE(instanceNode, "disks"); // the first disk should be the root disk (at least for Windows) for (int root=1; root>=0; root--){ for (int i=0; i<EUCA_MAX_VBRS && i<instance->params.virtualBootRecordLen; i++) { const virtualBootRecord * vbr = &(instance->params.virtualBootRecord[i]); // skip empty entries, if any if (vbr==NULL) continue; // do EMI on the first iteration of the outer loop if (root && vbr->type != NC_RESOURCE_IMAGE) continue; // ignore EMI on the second iteration of the outer loop if (!root && vbr->type == NC_RESOURCE_IMAGE) continue; // skip anything without a device on the guest, e.g., kernel and ramdisk if (!strcmp ("none", vbr->guestDeviceName)) continue; // for Linux instances on Xen, partitions can be used directly, so disks can be skipped unless booting from EBS if (strstr (instance->platform, "linux") && strstr (instance->hypervisorType, "xen")) { if (vbr->partitionNumber == 0 && vbr->type == NC_RESOURCE_IMAGE) { continue; } } else { // on all other os + hypervisor combinations, disks are used, so partitions must be skipped if (vbr->partitionNumber > 0) { continue; } } xmlNodePtr disk = _ELEMENT(disks, "diskPath", vbr->backingPath); _ATTRIBUTE(disk, "targetDeviceType", libvirtDevTypeNames[vbr->guestDeviceType]); _ATTRIBUTE(disk, "targetDeviceName", vbr->guestDeviceName); char devstr[SMALL_CHAR_BUFFER_SIZE]; snprintf(devstr, SMALL_CHAR_BUFFER_SIZE, "%s", vbr->guestDeviceName); if (config_use_virtio_root) { devstr[0] = 'v'; _ATTRIBUTE(disk, "targetDeviceNameVirtio", devstr); _ATTRIBUTE(disk, "targetDeviceBusVirtio", "virtio"); } _ATTRIBUTE(disk, "targetDeviceBus", libvirtBusTypeNames[vbr->guestDeviceBus]); _ATTRIBUTE(disk, "sourceType", libvirtSourceTypeNames[vbr->backingType]); if (root) { xmlNodePtr rootNode = _ELEMENT(disks, "root", NULL); _ATTRIBUTE(rootNode, "device", devstr); char root_uuid[64] = ""; if (get_blkid (vbr->backingPath, root_uuid, sizeof(root_uuid)) == 0) { assert (strlen (root_uuid)); _ATTRIBUTE(rootNode, "uuid", root_uuid); } } } if (strlen (instance->floppyFilePath)) { _ELEMENT(disks, "floppyPath", instance->floppyFilePath); } } } if (instance->params.nicType!=NIC_TYPE_NONE) { // NIC specification xmlNodePtr nics = _NODE(instanceNode, "nics"); xmlNodePtr nic = _NODE(nics, "nic"); _ATTRIBUTE(nic, "bridgeDeviceName", instance->params.guestNicDeviceName); _ATTRIBUTE(nic, "mac", instance->ncnet.privateMac); } ret = write_xml_file (doc, instance->instanceId, instance->xmlFilePath, "instance"); free: xmlFreeDoc(doc); pthread_mutex_unlock (&xml_mutex); return ret; }