[libvirt] [PATCH] util: refactor iptables command construction into multiple steps
by Natanael Copa
Instead of creating an iptables command in one shot, do it in steps
so we can add conditional options like physdev and protocol.
This removes code duplication while keeping existing behaviour.
Signed-off-by: Natanael Copa <ncopa(a)alpinelinux.org>
---
This started with me wanting to add support for setting the public ip source
address when network mode='nat' and there are multiple public ip addresses
on the external interface.
On IRC we talked about adding an option in the xml like this:
<network>
<forward mode='nat' publicaddr='n.n.n.n'/>
</network>
Which would make iptables use '-j SNAT --to-source n.n.n.n' instead of
'-j MASQUERADE'.
However with the current approach we would need to construct 8 different
iptables command combinations, hence the need for refactoring.
Thanks!
src/util/iptables.c | 130 +++++++++++++++++++++++-----------------------------
1 file changed, 58 insertions(+), 72 deletions(-)
diff --git a/src/util/iptables.c b/src/util/iptables.c
index 00a1c29..407ca3a 100644
--- a/src/util/iptables.c
+++ b/src/util/iptables.c
@@ -127,15 +127,10 @@ iptRulesNew(const char *table,
return NULL;
}
-static int ATTRIBUTE_SENTINEL
-iptablesAddRemoveRule(iptRules *rules, int family, int action,
- const char *arg, ...)
+static virCommandPtr
+iptablesCommandNew(iptRules *rules, int family, int action)
{
- va_list args;
- int ret;
virCommandPtr cmd = NULL;
- const char *s;
-
#if HAVE_FIREWALLD
virIpTablesInitialize();
if (firewall_cmd_path) {
@@ -152,16 +147,36 @@ iptablesAddRemoveRule(iptRules *rules, int family, int action,
virCommandAddArgList(cmd, "--table", rules->table,
action == ADD ? "--insert" : "--delete",
- rules->chain, arg, NULL);
+ rules->chain, NULL);
+ return cmd;
+}
+
+static int
+iptablesCommandRunAndFree(virCommandPtr cmd)
+{
+ int ret;
+ ret = virCommandRun(cmd, NULL);
+ virCommandFree(cmd);
+ return ret;
+}
+
+static int ATTRIBUTE_SENTINEL
+iptablesAddRemoveRule(iptRules *rules, int family, int action,
+ const char *arg, ...)
+{
+ va_list args;
+ virCommandPtr cmd = NULL;
+ const char *s;
+
+ cmd = iptablesCommandNew(rules, family, action);
+ virCommandAddArg(cmd, arg);
va_start(args, arg);
while ((s = va_arg(args, const char *)))
virCommandAddArg(cmd, s);
va_end(args);
- ret = virCommandRun(cmd, NULL);
- virCommandFree(cmd);
- return ret;
+ return iptablesCommandRunAndFree(cmd);
}
/**
@@ -370,28 +385,24 @@ iptablesForwardAllowOut(iptablesContext *ctx,
{
int ret;
char *networkstr;
+ virCommandPtr cmd = NULL;
if (!(networkstr = iptablesFormatNetwork(netaddr, prefix)))
return -1;
- if (physdev && physdev[0]) {
- ret = iptablesAddRemoveRule(ctx->forward_filter,
- VIR_SOCKET_ADDR_FAMILY(netaddr),
- action,
- "--source", networkstr,
- "--in-interface", iface,
- "--out-interface", physdev,
- "--jump", "ACCEPT",
- NULL);
- } else {
- ret = iptablesAddRemoveRule(ctx->forward_filter,
- VIR_SOCKET_ADDR_FAMILY(netaddr),
- action,
- "--source", networkstr,
- "--in-interface", iface,
- "--jump", "ACCEPT",
- NULL);
- }
+ cmd = iptablesCommandNew(ctx->forward_filter,
+ VIR_SOCKET_ADDR_FAMILY(netaddr),
+ action);
+ virCommandAddArgList(cmd,
+ "--source", networkstr,
+ "--in-interface", iface, NULL);
+
+ if (physdev && physdev[0])
+ virCommandAddArgList(cmd, "--out-interface", physdev, NULL);
+
+ virCommandAddArgList(cmd, "--jump", "ACCEPT", NULL);
+
+ ret = iptablesCommandRunAndFree(cmd);
VIR_FREE(networkstr);
return ret;
}
@@ -797,6 +808,7 @@ iptablesForwardMasquerade(iptablesContext *ctx,
{
int ret;
char *networkstr;
+ virCommandPtr cmd = NULL;
if (!(networkstr = iptablesFormatNetwork(netaddr, prefix)))
return -1;
@@ -810,49 +822,23 @@ iptablesForwardMasquerade(iptablesContext *ctx,
return -1;
}
- if (protocol && protocol[0]) {
- if (physdev && physdev[0]) {
- ret = iptablesAddRemoveRule(ctx->nat_postrouting,
- AF_INET,
- action,
- "--source", networkstr,
- "-p", protocol,
- "!", "--destination", networkstr,
- "--out-interface", physdev,
- "--jump", "MASQUERADE",
- "--to-ports", "1024-65535",
- NULL);
- } else {
- ret = iptablesAddRemoveRule(ctx->nat_postrouting,
- AF_INET,
- action,
- "--source", networkstr,
- "-p", protocol,
- "!", "--destination", networkstr,
- "--jump", "MASQUERADE",
- "--to-ports", "1024-65535",
- NULL);
- }
- } else {
- if (physdev && physdev[0]) {
- ret = iptablesAddRemoveRule(ctx->nat_postrouting,
- AF_INET,
- action,
- "--source", networkstr,
- "!", "--destination", networkstr,
- "--out-interface", physdev,
- "--jump", "MASQUERADE",
- NULL);
- } else {
- ret = iptablesAddRemoveRule(ctx->nat_postrouting,
- AF_INET,
- action,
- "--source", networkstr,
- "!", "--destination", networkstr,
- "--jump", "MASQUERADE",
- NULL);
- }
- }
+ cmd = iptablesCommandNew(ctx->nat_postrouting, AF_INET, action);
+ virCommandAddArgList(cmd, "--source", networkstr, NULL);
+
+ if (protocol && protocol[0])
+ virCommandAddArgList(cmd, "-p", protocol, NULL);
+
+ virCommandAddArgList(cmd, "!", "--destination", networkstr, NULL);
+
+ if (physdev && physdev[0])
+ virCommandAddArgList(cmd, "--out-interface", physdev, NULL);
+
+ virCommandAddArgList(cmd, "--jump", "MASQUERADE", NULL);
+
+ if (protocol && protocol[0])
+ virCommandAddArgList(cmd, "--to-ports", "1024-65535", NULL);
+
+ ret = iptablesCommandRunAndFree(cmd);
VIR_FREE(networkstr);
return ret;
}
--
1.8.0
12 years
[libvirt] [PATCH] qemu: capabilities: fix machine name/canonical swappage
by Cole Robinson
Things are supposed to look like:
<machine canonical='pc-0.12'>pc</machine>
But are currently swapped. This can cause many VMs to revert to having
machine type='pc' which will affect save/restore across qemu upgrades.
---
src/qemu/qemu_capabilities.c | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 668935e..01a1b98 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -2046,20 +2046,15 @@ qemuCapsProbeQMPMachineTypes(qemuCapsPtr caps,
for (i = 0 ; i < nmachines ; i++) {
if (machines[i]->alias) {
- if (!(caps->machineAliases[i] = strdup(machines[i]->name))) {
- virReportOOMError();
- goto cleanup;
- }
- if (!(caps->machineTypes[i] = strdup(machines[i]->alias))) {
- virReportOOMError();
- goto cleanup;
- }
- } else {
- if (!(caps->machineTypes[i] = strdup(machines[i]->name))) {
+ if (!(caps->machineAliases[i] = strdup(machines[i]->alias))) {
virReportOOMError();
goto cleanup;
}
}
+ if (!(caps->machineTypes[i] = strdup(machines[i]->name))) {
+ virReportOOMError();
+ goto cleanup;
+ }
if (machines[i]->isDefault)
defIdx = i;
}
--
1.8.0
12 years
[libvirt] Fix virGet{User, Group}IDByName when the user/group cannot be found
by Christophe Fergeau
Hey,
I've been having issues recently after upgrading to a newer libvirt on a
RHEL6 box. 'virsh start vmname' fails with
'error :internal error Failed to get user record for name '107': No such
file or directory '
Looking deeper into this, this comes from 'user not found' errors from
getpwnam_r/getgrnam_r not being correctly handled. This patch series attempts
to improve that, but I'm not that happy with the seemingly random values of
errno being checked there.
Christophe
12 years
[libvirt] [PATCH] virsh: Fix usage of header termios.h
by Peter Krempa
The termios struct exported by the termios.h header is used as an
argument for vshMakeStdinRaw(). The header isn't used anywhere in
tools/virsh-domain.c.
This patch adds the header to the header declaring vshMakeStdinRaw() and
removes other places in virsh.
---
tools/console.h | 4 +++-
tools/virsh-domain.c | 1 -
tools/virsh.c | 1 -
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/console.h b/tools/console.h
index 962594c..46255b8 100644
--- a/tools/console.h
+++ b/tools/console.h
@@ -1,7 +1,7 @@
/*
* console.c: A dumb serial console client
*
- * Copyright (C) 2007, 2010 Red Hat, Inc.
+ * Copyright (C) 2007, 2010, 2012 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -25,6 +25,8 @@
# ifndef WIN32
+# include <termios.h>
+
int vshRunConsole(virDomainPtr dom,
const char *dev_name,
const char *escape_seq,
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 1f7aff7..96e62fc 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -30,7 +30,6 @@
#include <poll.h>
#include <signal.h>
#include <sys/time.h>
-#include <termios.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
diff --git a/tools/virsh.c b/tools/virsh.c
index 322f778..b4829a3 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -42,7 +42,6 @@
#include <sys/stat.h>
#include <inttypes.h>
#include <strings.h>
-#include <termios.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
--
1.8.0
12 years
[libvirt] [PATCH 00/15 v5] Unprivileged SG_IO support
by Osier Yang
Hi,
As a result of RFC [1], this implements the unprivleged SG_IO
support. Testing is not that enough, but I'd like see the
reviewing earlier, and meanwhile I'm not going to give up
the further testing.
v4 - v5 (5 new patches):
* Set sysfs unpriv_sgio when attaching disk
* Restore sysfs unpriv_sgio when detaching disk
* Error out when attaching disk if it's shared by other
(domains), and the disk conf conflicts.
* Do not restore sysfs unpriv_sgio when detaching disk
if the disk is still being used by other domain(s)
* Dump the original unpriv_sgio state in status XML,
so that it won't be lost after restarting or reloading
libvirtd.
v3 - v4:
* Rebase on the top
* More testing
v2 - v3:
* Change the XML tag name to "cdbfilter"
* Maintain an internal list of shared disks for QEMU driver.
Patches 1/10 ~ 4/10 are to introduce the internal list for shared
disks.
Osier Yang (15):
qemu: Introduce a list to maintain the shared disks between domains
qemu: Init/Free the list with the driver's lifecyle
qemu: Add/remove the shared disk entry during domain's lifecyle
qemu: Add/Remove the entry of sharedDisks when live
attaching/detaching
docs: Add docs and rng schema for new XML cdbfilter
conf: Parse and format the new XML tag cdbfilter
util: Prepare helpers for unpriv_sgio setting
qemu: Manage disk's cdbfilter in domain's lifecycle
qemu: Do not restore the sysfs unpriv_sgio if the disk is being
shared
qemu: Error out when domain starting if the cdbfilter setting
conflicts
qemu: Set unpriv_sgio when attaching disk
qemu: Restore unpriv_sgio when detaching disk
qemu: Error out if the shared disk conf conflicts with others when
attaching
qemu: Do not restore unpriv_sgio if the disk is shared by other
domain
conf: Save disk's original unpriv_sgio state into status XML
docs/formatdomain.html.in | 13 ++-
docs/schemas/domaincommon.rng | 52 ++++--
src/conf/domain_conf.c | 106 ++++++++++--
src/conf/domain_conf.h | 13 ++
src/libvirt_private.syms | 5 +
src/qemu/qemu_conf.c | 170 ++++++++++++++++++++
src/qemu/qemu_conf.h | 30 ++++
src/qemu/qemu_driver.c | 78 +++++++++
src/qemu/qemu_process.c | 141 ++++++++++++++++-
src/qemu/qemu_process.h | 4 +
src/util/util.c | 145 +++++++++++++++++
src/util/util.h | 7 +
...ml2argv-disk-scsi-lun-passthrough-cdbfilter.xml | 32 ++++
tests/qemuxml2xmltest.c | 1 +
14 files changed, 761 insertions(+), 36 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-lun-passthrough-cdbfilter.xml
Regards,
Osier
12 years
[libvirt] [PATCH v5] qemu: Allow the user to specify vendor and product for disk
by Osier Yang
QEMU supports setting vendor and product strings for disk since
1.2.0 (only scsi-disk, scsi-hd, scsi-cd support it), this patch
exposes it with new XML elements <vendor> and <product> of disk
device.
v4 - v5:
* Just rebasing
v3 - v4:
* Per Paolo's feedback, allows all printable chars.
---
I think it's pretty straightforward to ACK now, any one can review
it?
---
docs/formatdomain.html.in | 11 +++++
docs/schemas/domaincommon.rng | 14 ++++++
src/conf/domain_conf.c | 44 ++++++++++++++++++++
src/conf/domain_conf.h | 2 +
src/libvirt_private.syms | 1 +
src/qemu/qemu_command.c | 29 +++++++++++++
src/util/util.c | 12 +++++
src/util/util.h | 1 +
...qemuxml2argv-disk-scsi-disk-vpd-build-error.xml | 35 ++++++++++++++++
.../qemuxml2argv-disk-scsi-disk-vpd.args | 13 ++++++
.../qemuxml2argv-disk-scsi-disk-vpd.xml | 38 +++++++++++++++++
tests/qemuxml2argvtest.c | 8 ++++
tests/qemuxml2xmltest.c | 2 +
13 files changed, 210 insertions(+), 0 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd-build-error.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 0574e68..30fb021 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1657,6 +1657,17 @@
of 16 hexadecimal digits.
<span class='since'>Since 0.10.1</span>
</dd>
+ <dt><code>vendor</code></dt>
+ <dd>If present, this element specifies the vendor of a virtual hard
+ disk or CD-ROM device. It must not be longer than 8 printable
+ characters.
+ <span class='since'>Since 1.0.1</span>
+ </dd>
+ <dt><code>product</code></dt>
+ <dd>If present, this element specifies the product of a virtual hard
+ disk or CD-ROM device. It must not be longer than 16 printable
+ <span class='since'>Since 1.0.1</span>
+ </dd>
<dt><code>host</code></dt>
<dd>The <code>host</code> element supports 4 attributes, viz. "name",
"port", "transport" and "socket", which specify the hostname, the port
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 0e85739..14344e2 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -905,6 +905,20 @@
<ref name="wwn"/>
</element>
</optional>
+ <optional>
+ <element name="vendor">
+ <data type="string">
+ <param name="pattern">[x20-x7E]{0,8}</param>
+ </data>
+ </element>
+ </optional>
+ <optional>
+ <element name="product">
+ <data type="string">
+ <param name="pattern">[x20-x7E]{0,16}</param>
+ </data>
+ </element>
+ </optional>
</interleave>
</define>
<define name="snapshot">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 4ffb39d..6aa5f79 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -985,6 +985,8 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def)
VIR_FREE(def->mirror);
VIR_FREE(def->auth.username);
VIR_FREE(def->wwn);
+ VIR_FREE(def->vendor);
+ VIR_FREE(def->product);
if (def->auth.secretType == VIR_DOMAIN_DISK_SECRET_TYPE_USAGE)
VIR_FREE(def->auth.secret.usage);
virStorageEncryptionFree(def->encryption);
@@ -3505,6 +3507,8 @@ cleanup:
goto cleanup;
}
+#define VENDOR_LEN 8
+#define PRODUCT_LEN 16
/* Parse the XML definition for a disk
* @param node XML nodeset to parse for disk definition
@@ -3558,6 +3562,8 @@ virDomainDiskDefParseXML(virCapsPtr caps,
char *logical_block_size = NULL;
char *physical_block_size = NULL;
char *wwn = NULL;
+ char *vendor = NULL;
+ char *product = NULL;
if (VIR_ALLOC(def) < 0) {
virReportOOMError();
@@ -3926,6 +3932,36 @@ virDomainDiskDefParseXML(virCapsPtr caps,
if (!virValidateWWN(wwn))
goto error;
+ } else if (!vendor &&
+ xmlStrEqual(cur->name, BAD_CAST "vendor")) {
+ vendor = (char *)xmlNodeGetContent(cur);
+
+ if (strlen(vendor) > VENDOR_LEN) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("disk vendor is more than 8 characters"));
+ goto error;
+ }
+
+ if (!virStrIsPrint(vendor)) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("disk vendor is not printable string"));
+ goto error;
+ }
+ } else if (!product &&
+ xmlStrEqual(cur->name, BAD_CAST "product")) {
+ product = (char *)xmlNodeGetContent(cur);
+
+ if (strlen(vendor) > PRODUCT_LEN) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("disk product is more than 16 characters"));
+ goto error;
+ }
+
+ if (!virStrIsPrint(product)) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("disk product is not printable string"));
+ goto error;
+ }
} else if (xmlStrEqual(cur->name, BAD_CAST "boot")) {
/* boot is parsed as part of virDomainDeviceInfoParseXML */
}
@@ -4222,6 +4258,10 @@ virDomainDiskDefParseXML(virCapsPtr caps,
serial = NULL;
def->wwn = wwn;
wwn = NULL;
+ def->vendor = vendor;
+ vendor = NULL;
+ def->product = product;
+ product = NULL;
if (driverType) {
def->format = virStorageFileFormatTypeFromString(driverType);
@@ -4296,6 +4336,8 @@ cleanup:
VIR_FREE(logical_block_size);
VIR_FREE(physical_block_size);
VIR_FREE(wwn);
+ VIR_FREE(vendor);
+ VIR_FREE(product);
ctxt->node = save_ctxt;
return def;
@@ -12144,6 +12186,8 @@ virDomainDiskDefFormat(virBufferPtr buf,
virBufferAddLit(buf, " <transient/>\n");
virBufferEscapeString(buf, " <serial>%s</serial>\n", def->serial);
virBufferEscapeString(buf, " <wwn>%s</wwn>\n", def->wwn);
+ virBufferEscapeString(buf, " <vendor>%s</vendor>\n", def->vendor);
+ virBufferEscapeString(buf, " <product>%s</product>\n", def->product);
if (def->encryption) {
virBufferAdjustIndent(buf, 6);
if (virStorageEncryptionFormat(buf, def->encryption) < 0)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 4ab15e9..7ad5377 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -602,6 +602,8 @@ struct _virDomainDiskDef {
char *serial;
char *wwn;
+ char *vendor;
+ char *product;
int cachemode;
int error_policy; /* enum virDomainDiskErrorPolicy */
int rerror_policy; /* enum virDomainDiskErrorPolicy */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index bc01fe5..499ab3b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1298,6 +1298,7 @@ virSetUIDGID;
virSkipSpaces;
virSkipSpacesAndBackslash;
virSkipSpacesBackwards;
+virStrIsPrint;
virStrToDouble;
virStrToLong_i;
virStrToLong_l;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 1805625..826086c 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -2576,6 +2576,13 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
}
}
+ if ((disk->vendor || disk->product) &&
+ disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Only scsi disk supports vendor and product"));
+ goto error;
+ }
+
if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
/* make sure that both the bus and the qemu binary support
* type='lun' (SG_IO).
@@ -2603,6 +2610,11 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
_("Setting wwn is not supported for lun device"));
goto error;
}
+ if (disk->vendor || disk->product) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting vendor or product is not supported for lun device"));
+ goto error;
+ }
}
switch (disk->bus) {
@@ -2652,6 +2664,17 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
goto error;
}
+ /* Properties wwn, vendor and product were introduced in the
+ * same QEMU release (1.2.0).
+ */
+ if ((disk->vendor || disk->product) &&
+ !qemuCapsGet(caps, QEMU_CAPS_SCSI_DISK_WWN)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting vendor or product for scsi disk is not "
+ "supported by this QEMU"));
+ goto error;
+ }
+
controllerModel =
virDomainDiskFindControllerModel(def, disk,
VIR_DOMAIN_CONTROLLER_TYPE_SCSI);
@@ -2797,6 +2820,12 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
if (disk->wwn)
virBufferAsprintf(&opt, ",wwn=%s", disk->wwn);
+ if (disk->vendor)
+ virBufferAsprintf(&opt, ",vendor=%s", disk->vendor);
+
+ if (disk->product)
+ virBufferAsprintf(&opt, ",product=%s", disk->product);
+
if (virBufferError(&opt)) {
virReportOOMError();
goto error;
diff --git a/src/util/util.c b/src/util/util.c
index 2fd0f2c..95b0a06 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -3113,3 +3113,15 @@ virValidateWWN(const char *wwn) {
return true;
}
+
+bool
+virStrIsPrint(const char *str)
+{
+ int i;
+
+ for (i = 0; str[i]; i++)
+ if (!c_isprint(str[i]))
+ return false;
+
+ return true;
+}
diff --git a/src/util/util.h b/src/util/util.h
index 4316ab1..6d5dd03 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -280,4 +280,5 @@ bool virIsDevMapperDevice(const char *dev_name) ATTRIBUTE_NONNULL(1);
bool virValidateWWN(const char *wwn);
+bool virStrIsPrint(const char *str);
#endif /* __VIR_UTIL_H__ */
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd-build-error.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd-build-error.xml
new file mode 100644
index 0000000..ca68275
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd-build-error.xml
@@ -0,0 +1,35 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='cdrom'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='sda' bus='virtio'/>
+ <vendor>SEAGATE</vendor>
+ <product>ST3146707LC</product>
+ </disk>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='sdb' bus='scsi'/>
+ <vendor>SEAGATE</vendor>
+ <product>ST3567807GD</product>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'/>
+ <controller type='scsi' index='0' model='virtio-scsi'/>
+ <controller type='scsi' index='1' model='lsilogic'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.args
new file mode 100644
index 0000000..f5c1999
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.args
@@ -0,0 +1,13 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+/usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
+-device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x3 \
+-device lsi,id=scsi1,bus=pci.0,addr=0x4 \
+-usb \
+-drive file=/dev/HostVG/QEMUGuest1,if=none,id=drive-scsi0-0-0-0 \
+-device scsi-cd,bus=scsi0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0-0-0-0,\
+id=scsi0-0-0-0,vendor=SEAGATE,product=ST3146707LC \
+-drive file=/dev/HostVG/QEMUGuest2,if=none,id=drive-scsi1-0-0 \
+-device scsi-hd,bus=scsi1.0,scsi-id=0,drive=drive-scsi1-0-0,\
+id=scsi1-0-0,vendor=SEAGATE,product=ST3567807GD \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.xml
new file mode 100644
index 0000000..96786e3
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-vpd.xml
@@ -0,0 +1,38 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219136</memory>
+ <currentMemory unit='KiB'>219136</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='cdrom'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='sda' bus='scsi'/>
+ <readonly/>
+ <vendor>SEAGATE</vendor>
+ <product>ST3146707LC</product>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='sdb' bus='scsi'/>
+ <readonly/>
+ <vendor>SEAGATE</vendor>
+ <product>ST3567807GD</product>
+ <address type='drive' controller='1' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'/>
+ <controller type='scsi' index='0' model='virtio-scsi'/>
+ <controller type='scsi' index='1' model='lsilogic'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 5822cae..bb233ed 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -507,6 +507,14 @@ mymain(void)
QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
QEMU_CAPS_SCSI_CD, QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI_PCI,
QEMU_CAPS_SCSI_DISK_WWN);
+ DO_TEST("disk-scsi-disk-vpd",
+ QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
+ QEMU_CAPS_SCSI_CD, QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI_PCI,
+ QEMU_CAPS_SCSI_DISK_WWN);
+ DO_TEST_FAILURE("disk-scsi-disk-vpd-build-error",
+ QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
+ QEMU_CAPS_SCSI_CD, QEMU_CAPS_SCSI_LSI, QEMU_CAPS_VIRTIO_SCSI_PCI,
+ QEMU_CAPS_SCSI_DISK_WWN);
DO_TEST("disk-scsi-vscsi",
QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
DO_TEST("disk-scsi-virtio-scsi",
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 3d8176c..c2d3dd3 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -239,6 +239,8 @@ mymain(void)
DO_TEST("seclabel-none");
DO_TEST("numad-static-vcpu-no-numatune");
+ DO_TEST("disk-scsi-disk-vpd");
+
/* These tests generate different XML */
DO_TEST_DIFFERENT("balloon-device-auto");
DO_TEST_DIFFERENT("channel-virtio-auto");
--
1.7.7.6
12 years
[libvirt] virsh list --all not showing domain
by Andy Howell
I'm running libvirt 0.9.13 on Ubuntu 12.10. I created a qemu VM from an existing image. I
able to start and stop it, but networing was not working. After a reboot of my laptop, I
can not long see the machine.
virsh list --all
Id Name State
----------------------------------------------------
The config file exists for the machine in /etc/libvirt/qemu/suse10.xml
How do I get virsh to see it again?
Thanks,
Andy
12 years
[libvirt] [PATCH 0/5] Add API to allow TCP connection tunelling using virStreams
by Peter Krempa
This series adds ability for the qemu driver to tunnel connections to TCP
ports from the host. This is useful for enabling remote VNC/SPICE sessions
without the need to configure SSH tunnels or portforwards and without the
need to open the ports for public.
There's also an advantage for tools such as virt-viewer that have to guess the remote
connection parameters and you have to hope that nothing is in your way. With
spice/VNC clients that have support for read/write callbacks, this would allow also
direct connection without an intermediate socket.
The API and tunelling works but there's no (stable and good working) client for
this API. I hacked up a dirty netcat-like terminal into virsh for testing
purposes (see patch 5/5) but that isn't what I'd like to see.
The client should be able to open a listening socket and when a client connects
to it, it opens a stream and connects it to the remote host.
For the client there are two options:
1) do all the stuff in virsh: + one tool to rule them all
- i'd like to daemonize it and I don't know if that's okay in virsh
2) add a new tool "virtunnel": + less virsh pollution
- separate tool ...
I'd like to hear your opinion on this question.
(note: this is my personal effort, I'm annoyed of opening ssh tunnels to remote displays on my server
and I don't want to open the ports to public. )
After this it would be great to add support for this to virt-viewer.
Peter Krempa (5):
api: Add API to allow TCP tunneling through streams to the host
fdstream: Add support for TCP connections of streams
qemu: Add configuration options to enable TCP tunelling
qemu: Implement virNodeTunnelTcp for the qemu driver
NOT_TO_BE_APPLIED_UPSTREAM: quick and dirty virsh client to test the
stuff
include/libvirt/libvirt.h.in | 11 +++++++
src/driver.h | 8 +++++
src/fdstream.c | 73 ++++++++++++++++++++++++++++++++++++++++++++
src/fdstream.h | 5 +++
src/libvirt.c | 67 ++++++++++++++++++++++++++++++++++++++++
src/libvirt_private.syms | 1 +
src/libvirt_public.syms | 1 +
src/qemu/qemu.conf | 16 ++++++++++
src/qemu/qemu_conf.c | 26 ++++++++++++++++
src/qemu/qemu_conf.h | 13 ++++++++
src/qemu/qemu_driver.c | 45 +++++++++++++++++++++++++++
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 9 +++++-
src/remote_protocol-structs | 6 ++++
src/rpc/gendispatch.pl | 1 +
tools/console.c | 66 +++++++++++++++++++++------------------
tools/console.h | 11 +++----
tools/virsh-domain.c | 18 ++++++++---
tools/virsh-host.c | 60 ++++++++++++++++++++++++++++++++++++
19 files changed, 396 insertions(+), 42 deletions(-)
--
1.8.0
12 years
[libvirt] [test-API][PATCH] Add 2 vcpupin cases cover config and live flags
by Wayne Sun
* use pinVcpuFlags to pin domain vcpu to host cpu
* 2 cases cover config and live flags
* cpulist with '^', '-' and ',' is supported to give multiple
host cpus
* vcpus and vcpuPinInfo are used as part of the checking
* a sample conf is added
Signed-off-by: Wayne Sun <gsun(a)redhat.com>
---
cases/vcpupin.conf | 67 +++++++++++++++
repos/setVcpus/vcpupin_config.py | 174 ++++++++++++++++++++++++++++++++++++++
repos/setVcpus/vcpupin_live.py | 166 ++++++++++++++++++++++++++++++++++++
3 files changed, 407 insertions(+), 0 deletions(-)
create mode 100644 cases/vcpupin.conf
create mode 100644 repos/setVcpus/vcpupin_config.py
create mode 100644 repos/setVcpus/vcpupin_live.py
diff --git a/cases/vcpupin.conf b/cases/vcpupin.conf
new file mode 100644
index 0000000..880247f
--- /dev/null
+++ b/cases/vcpupin.conf
@@ -0,0 +1,67 @@
+domain:install_linux_cdrom
+ guestname
+ $defaultname
+ guestos
+ $defaultos
+ guestarch
+ $defaultarch
+ vcpu
+ 4
+ memory
+ $defaultmem
+ hddriver
+ $defaulthd
+ nicdriver
+ $defaultnic
+ imageformat
+ qcow2
+
+setVcpus:vcpupin_live
+ guestname
+ $defaultname
+ vcpu
+ 0
+ cpulist
+ 2,4-6,^4
+
+setVcpus:vcpupin_live
+ guestname
+ $defaultname
+ vcpu
+ 1
+ cpulist
+ 3
+
+domain:destroy
+ guestname
+ $defaultname
+
+setVcpus:vcpupin_config
+ guestname
+ $defaultname
+ vcpu
+ 2
+ cpulist
+ 0-8,^1
+
+setVcpus:vcpupin_config
+ guestname
+ $defaultname
+ vcpu
+ 3
+ cpulist
+ ^2,0-8
+
+domain:start
+ guestname
+ $defaultname
+
+domain:destroy
+ guestname
+ $defaultname
+
+domain:undefine
+ guestname
+ $defaultname
+
+options cleanup=enable
diff --git a/repos/setVcpus/vcpupin_config.py b/repos/setVcpus/vcpupin_config.py
new file mode 100644
index 0000000..12d9598
--- /dev/null
+++ b/repos/setVcpus/vcpupin_config.py
@@ -0,0 +1,174 @@
+#!/usr/bin/env python
+# Test domain vcpu pin with flag VIR_DOMAIN_AFFECT_CONFIG, check
+# domain config xml with vcpupin configuration.
+
+import re
+from xml.dom import minidom
+
+import libvirt
+from libvirt import libvirtError
+
+from src import sharedmod
+from utils import utils
+
+required_params = ('guestname', 'vcpu', 'cpulist',)
+optional_params = {}
+
+def vcpupin_check(domobj, vcpu, cpumap):
+ """check domain config xml with vcpupin element
+ """
+ guestxml = domobj.XMLDesc(2)
+ logger.debug("domain %s xml :\n%s" %(domobj.name(), guestxml))
+
+ doc = minidom.parseString(guestxml)
+ vcpupin = doc.getElementsByTagName('vcpupin')
+ if not vcpupin:
+ logger.error("no vcpupin element in domain xml")
+ return 1
+
+ for i in range(len(vcpupin)):
+ if vcpupin[i].hasAttribute('vcpu') and \
+ vcpupin[i].hasAttribute('cpuset'):
+ vcpu_attr = vcpupin[i].getAttributeNode('vcpu')
+ cpu_attr = vcpupin[i].getAttributeNode('cpuset')
+ if int(vcpu_attr.nodeValue) == vcpu:
+ cpulist = cpu_attr.nodeValue
+ if cpulist == '':
+ cpumap_tmp = ()
+ for i in range(maxcpu):
+ cpumap_tmp += (False,)
+ else:
+ cpumap_tmp = get_cpumap(cpulist)
+
+ if cpumap_tmp == cpumap:
+ logger.info("cpuset is as expected in domain xml")
+ return 0
+ else:
+ logger.error("cpuset is not as expected in domain xml")
+ return 1
+
+ if i == len(vcpupin) - 1:
+ logger.error("the vcpupin element with given vcpu is not found")
+ return 1
+
+def format_cpumap(cpulist, cpumap_test):
+ """ format cpumap base on cpulist
+ """
+ cpumap = ()
+
+ try:
+ if re.match('\^', cpulist):
+ unuse = int(re.split('\^', cpulist)[1])
+ for i in range(maxcpu):
+ if i == unuse:
+ cpumap += (False,)
+ else:
+ cpumap += (cpumap_test[i],)
+
+ elif '-' in cpulist:
+ cpu_list = re.split('-', cpulist)
+ if not len(cpu_list) == 2:
+ return False
+ if not int(cpu_list[1]) < maxcpu:
+ logger.error("cpulist: out of host cpu range")
+ return False
+ if int(cpu_list[1]) < int(cpu_list[0]):
+ return False
+
+ for i in range(maxcpu):
+ if i in range(int(cpu_list[0]), int(cpu_list[1])+1):
+ cpumap += (True,)
+ else:
+ cpumap += (cpumap_test[i],)
+
+ else:
+ for i in range(maxcpu):
+ if i == int(cpulist):
+ cpumap += (True,)
+ else:
+ cpumap += (cpumap_test[i],)
+
+ return cpumap
+ except ValueError, e:
+ logger.error("ValueError: " + str(e))
+ return False
+
+def get_cpumap(cpulist):
+ """get cpumap base on given cpulist
+ """
+ cpumap_test = ()
+ for i in range(maxcpu):
+ cpumap_test += (False,)
+
+ if ',' in cpulist:
+ cpu_list = re.split(',', cpulist)
+ for i in range(len(cpu_list)):
+ cpumap = format_cpumap(cpu_list[i], cpumap_test)
+ if cpumap:
+ cpumap_test = cpumap
+ else:
+ return False
+ return cpumap
+
+ else:
+ cpumap = format_cpumap(cpulist, cpumap_test)
+ if cpumap:
+ return cpumap
+ else:
+ return False
+
+def vcpupin_config(params):
+ """pin domain vcpu to host cpu with config flag
+ """
+ global logger
+ logger = params['logger']
+ params.pop('logger')
+ guestname = params['guestname']
+ vcpu = int(params['vcpu'])
+ cpulist = params['cpulist']
+
+ logger.info("the name of virtual machine is %s" % guestname)
+ logger.info("the given vcpu is %s" % vcpu)
+ logger.info("the given cpulist is %s" % cpulist)
+
+ global maxcpu
+ maxcpu = utils.get_host_cpus()
+ logger.info("%s physical cpu on host" % maxcpu)
+
+ conn = sharedmod.libvirtobj['conn']
+
+ try:
+ domobj = conn.lookupByName(guestname)
+ cpumap = get_cpumap(cpulist)
+ if not cpumap:
+ logger.error("cpulist: Invalid format")
+ return 1
+
+ logger.debug("cpumap for vcpu pin is:")
+ logger.debug(cpumap)
+
+ logger.info("pin domain vcpu %s to host cpulist %s with flag: %s" %
+ (vcpu, cpulist, libvirt.VIR_DOMAIN_AFFECT_CONFIG))
+ domobj.pinVcpuFlags(vcpu, cpumap, libvirt.VIR_DOMAIN_AFFECT_CONFIG)
+
+ logger.info("check vcpu pin info")
+ ret = domobj.vcpuPinInfo(libvirt.VIR_DOMAIN_AFFECT_CONFIG)
+ logger.debug("vcpu pin info is:")
+ logger.debug(ret)
+ if ret[vcpu] == cpumap:
+ logger.info("vcpu pin info is expected")
+ else:
+ logger.error("vcpu pin info is not expected")
+ return 1
+ except libvirtError, e:
+ logger.error("libvirt call failed: " + str(e))
+ return 1
+
+ logger.info("check domain vcpupin configuration in xml")
+ ret = vcpupin_check(domobj, vcpu, cpumap)
+ if ret:
+ logger.error("domain vcpu pin check failed")
+ return 1
+ else:
+ logger.info("domain vcpu pin check succeed")
+ return 0
diff --git a/repos/setVcpus/vcpupin_live.py b/repos/setVcpus/vcpupin_live.py
new file mode 100644
index 0000000..09744a5
--- /dev/null
+++ b/repos/setVcpus/vcpupin_live.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python
+# Test domain vcpu pin with flag VIR_DOMAIN_AFFECT_LIVE, check
+# vcpu subprocess status under domain task list on host.
+
+import re
+
+import libvirt
+from libvirt import libvirtError
+
+from src import sharedmod
+from utils import utils
+
+required_params = ('guestname', 'vcpu', 'cpulist',)
+optional_params = {}
+
+def vcpupin_check(guestname, vcpu, cpumap):
+ """check vcpu subprocess status of the running virtual machine
+ grep Cpus_allowed_list /proc/PID/task/*/status
+ """
+ tmp_str = ''
+ cmd = "cat /var/run/libvirt/qemu/%s.pid" % guestname
+ status, pid = utils.exec_cmd(cmd, shell=True)
+ if status:
+ logger.error("failed to get the pid of domain %s" % guestname)
+ return 1
+
+ cmd = "grep Cpus_allowed_list /proc/%s/task/*/status" % pid[0]
+ status, output = utils.exec_cmd(cmd, shell=True)
+ logger.debug("command '%s' output is:" % cmd)
+ for i in range(len(output)):
+ tmp_str += ''.join(output[i]) + '\n'
+ logger.debug(tmp_str)
+
+ task_list = output[1:]
+ vcpu_task = task_list[int(vcpu)]
+ cpulist = vcpu_task.split('\t')[1]
+ ret = get_cpumap(cpulist)
+ if ret == cpumap:
+ logger.info("vcpu process cpus allowed list is expected")
+ return 0
+ else:
+ logger.error("vcpu process cpus allowed list is not expected")
+ return 1
+
+def format_cpumap(cpulist, cpumap_test):
+ """ format cpumap base on cpulist
+ """
+ cpumap = ()
+
+ try:
+ if re.match('\^', cpulist):
+ unuse = int(re.split('\^', cpulist)[1])
+ for i in range(maxcpu):
+ if i == unuse:
+ cpumap += (False,)
+ else:
+ cpumap += (cpumap_test[i],)
+
+ elif '-' in cpulist:
+ cpu_list = re.split('-', cpulist)
+ if not len(cpu_list) == 2:
+ return False
+ if not int(cpu_list[1]) < maxcpu:
+ logger.error("cpulist: out of host cpu range")
+ return False
+ if int(cpu_list[1]) < int(cpu_list[0]):
+ return False
+
+ for i in range(maxcpu):
+ if i in range(int(cpu_list[0]), int(cpu_list[1])+1):
+ cpumap += (True,)
+ else:
+ cpumap += (cpumap_test[i],)
+
+ else:
+ for i in range(maxcpu):
+ if i == int(cpulist):
+ cpumap += (True,)
+ else:
+ cpumap += (cpumap_test[i],)
+
+ return cpumap
+ except ValueError, e:
+ logger.error("ValueError: " + str(e))
+ return False
+
+def get_cpumap(cpulist):
+ """get cpumap base on given cpulist
+ """
+ cpumap_test = ()
+ for i in range(maxcpu):
+ cpumap_test += (False,)
+
+ if ',' in cpulist:
+ cpu_list = re.split(',', cpulist)
+ for i in range(len(cpu_list)):
+ cpumap = format_cpumap(cpu_list[i], cpumap_test)
+ if cpumap:
+ cpumap_test = cpumap
+ else:
+ return False
+ return cpumap
+
+ else:
+ cpumap = format_cpumap(cpulist, cpumap_test)
+ if cpumap:
+ return cpumap
+ else:
+ return False
+
+def vcpupin_live(params):
+ """pin domain vcpu to host cpu with live flag
+ """
+ global logger
+ logger = params['logger']
+ params.pop('logger')
+ guestname = params['guestname']
+ vcpu = int(params['vcpu'])
+ cpulist = params['cpulist']
+
+ logger.info("the name of virtual machine is %s" % guestname)
+ logger.info("the given vcpu is %s" % vcpu)
+ logger.info("the given cpulist is %s" % cpulist)
+
+ global maxcpu
+ maxcpu = utils.get_host_cpus()
+ logger.info("%s physical cpu on host" % maxcpu)
+
+ conn = sharedmod.libvirtobj['conn']
+
+ try:
+ domobj = conn.lookupByName(guestname)
+ cpumap = get_cpumap(cpulist)
+ if not cpumap:
+ logger.error("cpulist: Invalid format")
+ return 1
+
+ logger.debug("cpumap for vcpu pin is:")
+ logger.debug(cpumap)
+
+ logger.info("pin domain vcpu %s to host cpu %s with flag: %s" %
+ (vcpu, cpulist, libvirt.VIR_DOMAIN_AFFECT_LIVE))
+ domobj.pinVcpuFlags(vcpu, cpumap, libvirt.VIR_DOMAIN_AFFECT_LIVE)
+
+ logger.info("check vcpus info")
+ ret = domobj.vcpus()
+ logger.debug("vcpus info is:")
+ logger.debug(ret)
+ if ret[1][vcpu] == cpumap:
+ logger.info("vcpus info is expected")
+ else:
+ logger.error("vcpus info is not expected")
+ return 1
+
+ except libvirtError, e:
+ logger.error("libvirt call failed: " + str(e))
+ return 1
+
+ logger.info("check vcpu pin status on host")
+ ret = vcpupin_check(guestname, vcpu, cpumap)
+ if ret:
+ logger.error("domain vcpu pin failed")
+ return 1
+ else:
+ logger.info("domain vcpu pin succeed")
+ return 0
--
1.7.1
12 years
[libvirt] RFC: Enable Libvirt to handle OVA installation
by Ata Bohra
This is a proposal to enhance Libvirt library to handle OVA package installation. OVA:
OVA is one of the widely accepted and consortium defined/maintained format for
Virtual Machine distros. Technically it is a tar file with three main components:
1. VMX descriptor (XML file defining virtual machine specifics such as: virtual hardware etc.
2. VMDKs in a compressed format.
3. Manifest file. Proposal:
1. Expose a public API method to allow an application to invoke OVA installation with
a file pointer to OVA file.
2. OVA util file:
This file understands the OVA formats and rips out the given package to extract specific information:
2.1. int get_vmx(char *vmx):
method can return VMX descriptor associated with a given OVA file.
2.2. int get_vmdks(struct ova_type *ova):
method that seek the OVA file and populate ova_type struct which may look like;
typedef struct disk_list_tag {
char *file_name;
off_t file_size;
off_t file_offset;
struct disk_list_tag *next;
};
typedef struct ova_type {
int num_vmdks;
ova_list *head;
}
2. Hypervisor specific changes:
It can be done in more than one way:
2.1: Enhance hypervisor driver function to implement hypervisor specific routines to
perform OVA installations.
2.2.: Append a new driver to handle OVA installation such as virOvaDriver, main routines can be:
open() : parse OVA using util functions.
close()
list_disk(): may display disk names
install() (Please suggest if there can be more routines to this driver, it can be enhanced later as well).
It is possible to design this driver to handle OVA parsing as well, but I think keeping it in
'util' may make that code available for all hypervisors given OVA format does not change per
hypervisor. I'm inclined more towards 2.2 design as it is more generic and provides room for furture extensions. Looking forward for comments/suggestions. Thanks!Ata
12 years