[PATCH 0 of 2] [RFC] (#2) Add boot order support for full virtualization environments

# HG changeset patch # User Richard Maciel <rmaciel@linux.vnet.ibm.com> # Date 1242071235 10800 # Node ID c0bd6c9a2c0084398784bb1ae36649bd3400e36c # Parent 5608b9455cd32fccbc324cd540c509d7230a113f This fix the generation of the <boot> tag on fully-virtualizable Xen guests. Right now it is generated with the boot device as a the value of the node (e.g. <boot>hd</boot>) However, the boot device must be a property of the node (e.g. <boot dev='hd'/>) Signed-off-by: Richard Maciel <rmaciel@linux.vnet.ibm.com> diff -r 5608b9455cd3 -r c0bd6c9a2c00 libxkutil/xmlgen.c --- a/libxkutil/xmlgen.c Mon Apr 27 17:05:48 2009 -0700 +++ b/libxkutil/xmlgen.c Mon May 11 16:47:15 2009 -0300 @@ -457,10 +457,12 @@ if (tmp == NULL) return XML_ERROR; - tmp = xmlNewChild(root, NULL, BAD_CAST "boot", BAD_CAST os->boot); + tmp = xmlNewChild(root, NULL, BAD_CAST "boot", NULL); if (tmp == NULL) return XML_ERROR; + xmlNewProp(tmp, BAD_CAST "dev", BAD_CAST os->boot); + tmp = xmlNewChild(root, NULL, BAD_CAST "features", NULL); xmlNewChild(tmp, NULL, BAD_CAST "pae", NULL); xmlNewChild(tmp, NULL, BAD_CAST "acpi", NULL);

# HG changeset patch # User Richard Maciel <rmaciel@linux.vnet.ibm.com> # Date 1242237321 10800 # Node ID e3ea69df8ae9fa611605843b471894c2baaa8bc0 # Parent c0bd6c9a2c0084398784bb1ae36649bd3400e36c Add boot order support Signed-off-by: Richard Maciel <rmaciel@linux.vnet.ibm.com> diff -r c0bd6c9a2c00 -r e3ea69df8ae9 libxkutil/device_parsing.c --- a/libxkutil/device_parsing.c Mon May 11 16:47:15 2009 -0300 +++ b/libxkutil/device_parsing.c Wed May 13 14:55:21 2009 -0300 @@ -810,6 +810,8 @@ static int parse_os(struct domain *dominfo, xmlNode *os) { xmlNode *child; + char **blist = NULL; + unsigned bl_size = 0; for (child = os->children; child != NULL; child = child->next) { if (XSTREQ(child->name, "type")) @@ -822,10 +824,23 @@ STRPROP(dominfo, os_info.pv.cmdline, child); else if (XSTREQ(child->name, "loader")) STRPROP(dominfo, os_info.fv.loader, child); - else if (XSTREQ(child->name, "boot")) - dominfo->os_info.fv.boot = get_attr_value(child, - "dev"); - else if (XSTREQ(child->name, "init")) + else if (XSTREQ(child->name, "boot")) { + char **tmp_list = NULL; + + tmp_list = (char **)realloc(blist, + (bl_size+1) * + sizeof(char *)); + if (tmp_list == NULL) { + // Nothing you can do. Just go on. + CU_DEBUG("Could not alloc space for " + "boot device"); + continue; + } + blist = tmp_list; + + blist[bl_size] = get_attr_value(child, "dev"); + bl_size++; + } else if (XSTREQ(child->name, "init")) STRPROP(dominfo, os_info.lxc.init, child); } @@ -843,6 +858,9 @@ else dominfo->type = -1; + dominfo->os_info.fv.bootlist = blist; + dominfo->os_info.fv.bootlist_ct = bl_size; + return 1; } @@ -1001,9 +1019,15 @@ free(dom->os_info.pv.cmdline); } else if ((dom->type == DOMAIN_XENFV) || (dom->type == DOMAIN_KVM) || (dom->type == DOMAIN_QEMU)) { + int i; + free(dom->os_info.fv.type); free(dom->os_info.fv.loader); - free(dom->os_info.fv.boot); + + for (i = 0; i < dom->os_info.fv.bootlist_ct; i++) { + free(dom->os_info.fv.bootlist[i]); + } + free(dom->os_info.fv.bootlist); } else if (dom->type == DOMAIN_LXC) { free(dom->os_info.lxc.type); free(dom->os_info.lxc.init); diff -r c0bd6c9a2c00 -r e3ea69df8ae9 libxkutil/device_parsing.h --- a/libxkutil/device_parsing.h Mon May 11 16:47:15 2009 -0300 +++ b/libxkutil/device_parsing.h Wed May 13 14:55:21 2009 -0300 @@ -99,7 +99,8 @@ struct fv_os_info { char *type; /* Should always be 'hvm' */ char *loader; - char *boot; + unsigned bootlist_ct; + char **bootlist; }; struct lxc_os_info { diff -r c0bd6c9a2c00 -r e3ea69df8ae9 libxkutil/xml_parse_test.c --- a/libxkutil/xml_parse_test.c Mon May 11 16:47:15 2009 -0300 +++ b/libxkutil/xml_parse_test.c Wed May 13 14:55:21 2009 -0300 @@ -28,6 +28,7 @@ static void print_os(struct domain *dom, FILE *d) { + int i; if (dom->type == DOMAIN_XENPV) { print_value(d, "Domain Type", "Xen PV"); @@ -39,13 +40,18 @@ print_value(d, "Domain Type", "Xen FV"); print_value(d, "Type", dom->os_info.fv.type); print_value(d, "Loader", dom->os_info.fv.loader); - print_value(d, "Boot", dom->os_info.fv.boot); + for (i = 0; i < dom->os_info.fv.bootlist_size; i++) { + print_value(d, "Boot", dom->os_info.fv.bootlist[i]); + } } else if ((dom->type == DOMAIN_KVM) || (dom->type == DOMAIN_QEMU)) { print_value(d, "Domain Type", "KVM/QEMU"); print_value(d, "Type", dom->os_info.fv.type); print_value(d, "Loader", dom->os_info.fv.loader); - print_value(d, "Boot", dom->os_info.fv.boot); + + for (i = 0; i < dom->os_info.fv.bootlist_size; i++) { + print_value(d, "Boot", dom->os_info.fv.bootlist[i]); + } } else if (dom->type == DOMAIN_LXC) { print_value(d, "Init", dom->os_info.lxc.init); } else { diff -r c0bd6c9a2c00 -r e3ea69df8ae9 libxkutil/xmlgen.c --- a/libxkutil/xmlgen.c Mon May 11 16:47:15 2009 -0300 +++ b/libxkutil/xmlgen.c Wed May 13 14:55:21 2009 -0300 @@ -439,6 +439,7 @@ { struct fv_os_info *os = &domain->os_info.fv; xmlNodePtr tmp; + unsigned i; if (os->type == NULL) os->type = strdup("hvm"); @@ -446,8 +447,11 @@ if (os->loader == NULL) os->loader = strdup("/usr/lib/xen/boot/hvmloader"); - if (os->boot == NULL) - os->boot = strdup("hd"); + if (os->bootlist_ct == 0) { + os->bootlist_ct = 1; + os->bootlist = (char **)calloc(1, sizeof(char *)); + os->bootlist[0] = strdup("hd"); + } tmp = xmlNewChild(root, NULL, BAD_CAST "type", BAD_CAST os->type); if (tmp == NULL) @@ -457,11 +461,13 @@ if (tmp == NULL) return XML_ERROR; - tmp = xmlNewChild(root, NULL, BAD_CAST "boot", NULL); - if (tmp == NULL) - return XML_ERROR; + for (i = 0; i < os->bootlist_ct; i++) { + tmp = xmlNewChild(root, NULL, BAD_CAST "boot", NULL); + if (tmp == NULL) + return XML_ERROR; - xmlNewProp(tmp, BAD_CAST "dev", BAD_CAST os->boot); + xmlNewProp(tmp, BAD_CAST "dev", BAD_CAST os->bootlist[i]); + } tmp = xmlNewChild(root, NULL, BAD_CAST "features", NULL); xmlNewChild(tmp, NULL, BAD_CAST "pae", NULL); @@ -475,21 +481,28 @@ { struct fv_os_info *os = &domain->os_info.fv; xmlNodePtr tmp; + unsigned i; if (os->type == NULL) os->type = strdup("hvm"); - if (os->boot == NULL) - os->boot = strdup("hd"); + if (os->bootlist_ct == 0) { + os->bootlist_ct = 1; + os->bootlist = (char **)calloc(1, sizeof(char *)); + os->bootlist[0] = strdup("hd"); + } tmp = xmlNewChild(root, NULL, BAD_CAST "type", BAD_CAST os->type); if (tmp == NULL) return XML_ERROR; - tmp = xmlNewChild(root, NULL, BAD_CAST "boot", NULL); - if (tmp == NULL) - return XML_ERROR; - xmlNewProp(tmp, BAD_CAST "dev", BAD_CAST os->boot); + for (i = 0; i < os->bootlist_ct; i++) { + tmp = xmlNewChild(root, NULL, BAD_CAST "boot", NULL); + if (tmp == NULL) + return XML_ERROR; + + xmlNewProp(tmp, BAD_CAST "dev", BAD_CAST os->bootlist[i]); + } return NULL; } diff -r c0bd6c9a2c00 -r e3ea69df8ae9 schema/VSSD.mof --- a/schema/VSSD.mof Mon May 11 16:47:15 2009 -0300 +++ b/schema/VSSD.mof Wed May 13 14:55:21 2009 -0300 @@ -27,7 +27,7 @@ [Description ("The device to boot from when in fully-virtualized mode." "One of hd,fd,cdrom.")] - string BootDevice; + string BootDevices[]; [Description ("The emulator the guest should use during runtime.")] string Emulator; @@ -42,8 +42,8 @@ class KVM_VirtualSystemSettingData : Virt_VirtualSystemSettingData { - [Description ("The device to boot from. One of hd,fd,cdrom.")] - string BootDevice; + [Description ("The list of devices to boot from. hd,fd,cdrom.")] + string BootDevices[]; [Description ("The emulator the guest should use during runtime.")] string Emulator; diff -r c0bd6c9a2c00 -r e3ea69df8ae9 src/Virt_VSSD.c --- a/src/Virt_VSSD.c Mon May 11 16:47:15 2009 -0300 +++ b/src/Virt_VSSD.c Wed May 13 14:55:21 2009 -0300 @@ -42,16 +42,58 @@ CMPIInstance *inst) { bool fv = true; + CMPIArray *array; if (dominfo->type == DOMAIN_XENFV) CMSetProperty(inst, "IsFullVirt", (CMPIValue *)&fv, CMPI_boolean); - if (dominfo->os_info.fv.boot != NULL) - CMSetProperty(inst, - "BootDevice", - (CMPIValue *)dominfo->os_info.fv.boot, - CMPI_chars); + if (dominfo->os_info.fv.bootlist_ct > 0) { + CMPICount i; + CMPICount bl_size; + CMPIStatus s; + + bl_size = (CMPICount)dominfo->os_info.fv.bootlist_ct; + + array = CMNewArray(_BROKER, + bl_size, + CMPI_string, + &s); + + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("Error creating BootDevice list"); + return; + } + + for (i = 0; i < bl_size; i++) { + CMPIString *cm_str; + + cm_str = CMNewString(_BROKER, + (const char *)dominfo->os_info.fv.bootlist[i], + &s); + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("Error adding item to BootDevice " + "list"); + continue; + } + + s = CMSetArrayElementAt(array, + i, + cm_str, + CMPI_string); + if (s.rc != CMPI_RC_OK) + CU_DEBUG("Error setting BootDevice array " + "element"); + } + + s = CMSetProperty(inst, + "BootDevices", + (CMPIValue *)array, + CMPI_stringA); + + if (s.rc != CMPI_RC_OK) + CU_DEBUG("Error setting BootDevices property"); + } } static void _set_pv_prop(struct domain *dominfo, diff -r c0bd6c9a2c00 -r e3ea69df8ae9 src/Virt_VirtualSystemManagementService.c --- a/src/Virt_VirtualSystemManagementService.c Mon May 11 16:47:15 2009 -0300 +++ b/src/Virt_VirtualSystemManagementService.c Wed May 13 14:55:21 2009 -0300 @@ -202,7 +202,13 @@ const char *pfx) { int ret; + CMPICount i; const char *val; + CMPIArray *bootlist; + CMPIStatus s; + CMPIData boot_elem; + char **tmp_str_arr; + if (STREQC(pfx, "KVM")) { if (system_has_kvm(pfx)) @@ -216,12 +222,69 @@ return 0; } - ret = cu_get_str_prop(inst, "BootDevice", &val); - if (ret != CMPI_RC_OK) - val = "hd"; + for (i = 0; i < domain->os_info.fv.bootlist_ct; i++) + free(domain->os_info.fv.bootlist[i]); - free(domain->os_info.fv.boot); - domain->os_info.fv.boot = strdup(val); + ret = cu_get_array_prop(inst, "BootDevices", &bootlist); + + if (ret == CMPI_RC_OK) { + CMPICount bl_size; + + bl_size = CMGetArrayCount(bootlist, &s); + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("Invalid BootDevice array size"); + return 0; + } + + tmp_str_arr = (char **)realloc(domain->os_info.fv.bootlist, + bl_size * sizeof(char *)); + + if (tmp_str_arr == NULL) { + CU_DEBUG("Could not alloc BootDevices array"); + return 0; + } + + for (i = 0; i < bl_size; i++) { + const char *str; + + boot_elem = CMGetArrayElementAt(bootlist, + i, + NULL); + + if (CMIsNullValue(boot_elem)) { + CU_DEBUG("Null BootDevice"); + return 0; + } + + free(domain->os_info.fv.bootlist[i]); + CU_DEBUG("Freed item from bootlist"); + + str = CMGetCharPtr(boot_elem.value.string); + + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("Could not extract char pointer from " + "CMPIArray"); + } + + tmp_str_arr[i] = strdup(str); + } + domain->os_info.fv.bootlist_ct = bl_size; + domain->os_info.fv.bootlist = tmp_str_arr; + + } else { + + CU_DEBUG("Failed to get BootDevices property"); + + tmp_str_arr = (char **)realloc(domain->os_info.fv.bootlist, + sizeof(char *)); + if (tmp_str_arr == NULL) + return 0; + + tmp_str_arr[0] = strdup("hd"); + + domain->os_info.fv.bootlist = tmp_str_arr; + domain->os_info.fv.bootlist_ct = 1; + } ret = cu_get_str_prop(inst, "Emulator", &val); if (ret != CMPI_RC_OK)

+ + tmp_list = (char **)realloc(blist, + (bl_size+1) *
Style-wise, the rest of the code uses (bl_size + 1).
diff -r c0bd6c9a2c00 -r e3ea69df8ae9 libxkutil/xml_parse_test.c --- a/libxkutil/xml_parse_test.c Mon May 11 16:47:15 2009 -0300 +++ b/libxkutil/xml_parse_test.c Wed May 13 14:55:21 2009 -0300 @@ -28,6 +28,7 @@ static void print_os(struct domain *dom, FILE *d) { + int i;
if (dom->type == DOMAIN_XENPV) { print_value(d, "Domain Type", "Xen PV"); @@ -39,13 +40,18 @@ print_value(d, "Domain Type", "Xen FV"); print_value(d, "Type", dom->os_info.fv.type); print_value(d, "Loader", dom->os_info.fv.loader); - print_value(d, "Boot", dom->os_info.fv.boot);
+ for (i = 0; i < dom->os_info.fv.bootlist_size; i++) {
This should be bootlist_ct.
+ print_value(d, "Boot", dom->os_info.fv.bootlist[i]); + } } else if ((dom->type == DOMAIN_KVM) || (dom->type == DOMAIN_QEMU)) { print_value(d, "Domain Type", "KVM/QEMU"); print_value(d, "Type", dom->os_info.fv.type); print_value(d, "Loader", dom->os_info.fv.loader); - print_value(d, "Boot", dom->os_info.fv.boot); + + for (i = 0; i < dom->os_info.fv.bootlist_size; i++) {
Same here.
+ } + + for (i = 0; i < bl_size; i++) { + CMPIString *cm_str; + + cm_str = CMNewString(_BROKER, + (const char *)dominfo->os_info.fv.bootlist[i], + &s); + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("Error adding item to BootDevice " + "list"); + continue; + } + + s = CMSetArrayElementAt(array, + i, + cm_str,
This should be (CMPIValue *)&cm_str
+ CMPI_string); + if (s.rc != CMPI_RC_OK) + CU_DEBUG("Error setting BootDevice array " + "element"); + } + + s = CMSetProperty(inst, + "BootDevices", + (CMPIValue *)array,
This should be (CMPIValue *)&array
+ + } else { + + CU_DEBUG("Failed to get BootDevices property"); + + tmp_str_arr = (char **)realloc(domain->os_info.fv.bootlist, + sizeof(char *)); + if (tmp_str_arr == NULL) + return 0; + + tmp_str_arr[0] = strdup("hd"); + + domain->os_info.fv.bootlist = tmp_str_arr; + domain->os_info.fv.bootlist_ct = 1; + }
Since you've added this here, I would remove the code that adds a default boot device in xmlgen - that allows you to remove some duplicate code. Plus, this follows convention - most of the defaults are set in VSMS - not in xmlgen itself. -- Kaitlin Rupert IBM Linux Technology Center kaitlin@linux.vnet.ibm.com
participants (2)
-
Kaitlin Rupert
-
Richard Maciel