[libvirt] [PATCH] python: Fix emulatorpin API bindings
by Peter Krempa
The addition of emulator pinning APIs didn't think of doing the right
job with python APIs for them. The default generator produced unusable
code for this.
This patch switches to proper code as in the case of domain Vcpu pining.
This change can be classified as a python API-breaker but in the state
the code was before I doubt anyone was able to use it successfully.
---
python/generator.py | 2 +
python/libvirt-override-api.xml | 18 +++++-
python/libvirt-override.c | 121 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 139 insertions(+), 2 deletions(-)
diff --git a/python/generator.py b/python/generator.py
index 6a25c2d..0aeb675 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -418,6 +418,8 @@ skip_impl = (
'virDomainPinVcpu',
'virDomainPinVcpuFlags',
'virDomainGetVcpuPinInfo',
+ 'virDomainGetEmulatorPinInfo',
+ 'virDomainPinEmulator',
'virSecretGetValue',
'virSecretSetValue',
'virSecretGetUUID',
diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml
index 5976fb2..c720610 100644
--- a/python/libvirt-override-api.xml
+++ b/python/libvirt-override-api.xml
@@ -237,10 +237,24 @@
<function name='virDomainGetVcpuPinInfo' file='python'>
<info>Query the CPU affinity setting of all virtual CPUs of domain</info>
<return type='unsigned char *' info='the array of cpumap'/>
- <arg name='domain' type='virDomainPtr' info='pointer to domain object, or NULL for Domain0'/>
+ <arg name='domain' type='virDomainPtr' info='pointer to domain object'/>
+ <arg name='flags' type='int' info='an OR'ed set of virDomainModificationImpact'/>
+ </function>
+ <function name='virDomainGetEmulatorPinInfo' file='python'>
+ <info>Query the CPU affinity setting of the emulator process of domain</info>
+ <return type='unsigned char *' info='the array of cpumap'/>
+ <arg name='domain' type='virDomainPtr' info='pointer to domain object'/>
<arg name='flags' type='int' info='an OR'ed set of virDomainModificationImpact'/>
</function>
- <function name='virDomainSetSchedulerParameters' file='python'>
+ <function name='virDomainPinEmulator' file='python'>
+ <info>Dynamically change the real CPUs which can be allocated to the emulator process of a domain.
+ This function requires privileged access to the hypervisor.</info>
+ <return type='int' info='0 in case of success, -1 in case of failure.'/>
+ <arg name='domain' type='virDomainPtr' info='pointer to domain object, or NULL for Domain0'/>
+ <arg name='cpumap' type='unsigned char *' info='pointer to a bit map of real CPUs (in 8-bit bytes) (IN) Each bit set to 1 means that corresponding CPU is usable. Bytes are stored in little-endian order: CPU0-7, 8-15... In each byte, lowest CPU number is least significant bit.'/>
+ <arg name='flags' type='int' info='flags to specify'/>
+ </function>
+ <function name='virDomainSetSchedulerParameters' file='python'>
<info>Change the scheduler parameters</info>
<return type='int' info='-1 in case of error, 0 in case of success.'/>
<arg name='domain' type='virDomainPtr' info='pointer to domain object'/>
diff --git a/python/libvirt-override.c b/python/libvirt-override.c
index 9637598..07e0221 100644
--- a/python/libvirt-override.c
+++ b/python/libvirt-override.c
@@ -1664,6 +1664,125 @@ cleanup:
return VIR_PY_NONE;
}
+
+static PyObject *
+libvirt_virDomainPinEmulator(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args)
+{
+ virDomainPtr domain;
+ PyObject *pyobj_domain, *pycpumap;
+ PyObject *ret = VIR_PY_INT_FAIL;
+ unsigned char *cpumap = NULL;
+ int cpumaplen, i, tuple_size, cpunum;
+ int i_retval;
+ unsigned int flags;
+
+ if (!PyArg_ParseTuple(args, (char *)"OOi:virDomainPinVcpu",
+ &pyobj_domain, &pycpumap, &flags))
+ goto cleanup;
+
+ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+ if ((cpunum = getPyNodeCPUCount(virDomainGetConnect(domain))) < 0)
+ goto cleanup;
+
+ cpumaplen = VIR_CPU_MAPLEN(cpunum);
+
+ if (!PyTuple_Check(pycpumap)) {
+ PyErr_SetString(PyExc_TypeError, "Unexpected type, tuple is required");
+ goto cleanup;
+ }
+
+ if ((tuple_size = PyTuple_Size(pycpumap)) == -1)
+ goto cleanup;
+
+ if (VIR_ALLOC_N(cpumap, cpumaplen) < 0)
+ goto cleanup;
+
+ for (i = 0; i < tuple_size; i++) {
+ PyObject *flag = PyTuple_GetItem(pycpumap, i);
+ bool b;
+
+ if (!flag || libvirt_boolUnwrap(flag, &b) < 0)
+ goto cleanup;
+
+ if (b)
+ VIR_USE_CPU(cpumap, i);
+ else
+ VIR_UNUSE_CPU(cpumap, i);
+ }
+
+ for (; i < cpunum; i++)
+ VIR_UNUSE_CPU(cpumap, i);
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ i_retval = virDomainPinEmulator(domain, cpumap, cpumaplen, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+
+ if (i_retval < 0)
+ goto cleanup;
+
+ ret = VIR_PY_INT_SUCCESS;
+
+cleanup:
+ VIR_FREE(cpumap);
+ return ret;
+}
+
+
+static PyObject *
+libvirt_virDomainGetEmulatorPinInfo(PyObject *self ATTRIBUTE_UNUSED,
+ PyObject *args)
+{
+ virDomainPtr domain;
+ PyObject *pyobj_domain;
+ PyObject *pycpumap = NULL;
+ unsigned char *cpumap = NULL;
+ size_t cpumaplen;
+ size_t pcpu;
+ unsigned int flags;
+ int ret;
+ int cpunum;
+
+ if (!PyArg_ParseTuple(args, (char *)"Oi:virDomainEmulatorPinInfo",
+ &pyobj_domain, &flags))
+ goto error;
+
+ domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+ if ((cpunum = getPyNodeCPUCount(virDomainGetConnect(domain))) < 0)
+ goto error;
+
+ cpumaplen = VIR_CPU_MAPLEN(cpunum);
+ if (VIR_ALLOC_N(cpumap, cpumaplen) < 0)
+ goto error;
+
+ LIBVIRT_BEGIN_ALLOW_THREADS;
+ ret = virDomainGetEmulatorPinInfo(domain, cpumap, cpumaplen, flags);
+ LIBVIRT_END_ALLOW_THREADS;
+ if (ret < 0)
+ goto error;
+
+ if (!(pycpumap = PyTuple_New(cpunum)))
+ goto error;
+
+ for (pcpu = 0; pcpu < cpunum; pcpu++)
+ PyTuple_SetItem(pycpumap, pcpu,
+ PyBool_FromLong(VIR_CPU_USABLE(cpumap, cpumaplen,
+ 0, pcpu)));
+
+ VIR_FREE(cpumap);
+
+ return pycpumap;
+
+error:
+ VIR_FREE(cpumap);
+ Py_XDECREF(pycpumap);
+
+ return VIR_PY_NONE;
+}
+
+
/************************************************************************
* *
* Global error handler at the Python level *
@@ -6705,6 +6824,8 @@ static PyMethodDef libvirtMethods[] = {
{(char *) "virDomainPinVcpu", libvirt_virDomainPinVcpu, METH_VARARGS, NULL},
{(char *) "virDomainPinVcpuFlags", libvirt_virDomainPinVcpuFlags, METH_VARARGS, NULL},
{(char *) "virDomainGetVcpuPinInfo", libvirt_virDomainGetVcpuPinInfo, METH_VARARGS, NULL},
+ {(char *) "virDomainGetEmulatorPinInfo", libvirt_virDomainGetEmulatorPinInfo, METH_VARARGS, NULL},
+ {(char *) "virDomainPinEmulator", libvirt_virDomainPinEmulator, METH_VARARGS, NULL},
{(char *) "virConnectListStoragePools", libvirt_virConnectListStoragePools, METH_VARARGS, NULL},
{(char *) "virConnectListDefinedStoragePools", libvirt_virConnectListDefinedStoragePools, METH_VARARGS, NULL},
{(char *) "virConnectListAllStoragePools", libvirt_virConnectListAllStoragePools, METH_VARARGS, NULL},
--
1.8.1.5
11 years, 7 months
[libvirt] [libvirt-designer PATCHv2] Add GvirDesignerDomain::osinfo_db
by Christophe Fergeau
virtxml was doing its own loading of the libosinfo database,
and gvir_designer_init() was loading it a second time.
By adding a GVirDesignerDomain::osinfo_db property, applications
can share the same OsinfoDb as libvirt-designer. The association
is made per libvirt-designer domain for more flexibility.
If no OsinfoDb is associated with a domain when needed,
libvirt-designer will automatically try to load it.
---
examples/virtxml.c | 2 ++
libvirt-designer/libvirt-designer-domain.c | 49 +++++++++++++++++++++++++++-
libvirt-designer/libvirt-designer-internal.h | 3 --
libvirt-designer/libvirt-designer-main.c | 12 -------
libvirt-designer/libvirt-designer-main.h | 2 ++
libvirt-designer/libvirt-designer.sym | 1 +
6 files changed, 53 insertions(+), 16 deletions(-)
diff --git a/examples/virtxml.c b/examples/virtxml.c
index a68843d..be6ee7a 100644
--- a/examples/virtxml.c
+++ b/examples/virtxml.c
@@ -559,6 +559,8 @@ main(int argc, char *argv[])
}
domain = gvir_designer_domain_new(os, platform, caps);
+ if (db != NULL)
+ g_object_set(G_OBJECT(domain), "osinfo-db", db, NULL);
gvir_designer_domain_setup_machine(domain, &error);
CHECK_ERROR;
diff --git a/libvirt-designer/libvirt-designer-domain.c b/libvirt-designer/libvirt-designer-domain.c
index 3e31bd1..b78b8d3 100644
--- a/libvirt-designer/libvirt-designer-domain.c
+++ b/libvirt-designer/libvirt-designer-domain.c
@@ -35,6 +35,7 @@ struct _GVirDesignerDomainPrivate
{
GVirConfigDomain *config;
GVirConfigCapabilities *caps;
+ OsinfoDb *osinfo_db;
OsinfoOs *os;
OsinfoPlatform *platform;
@@ -66,6 +67,7 @@ enum {
PROP_OS,
PROP_PLATFORM,
PROP_CAPS,
+ PROP_OSINFO_DB,
};
static void gvir_designer_domain_get_property(GObject *object,
@@ -83,6 +85,10 @@ static void gvir_designer_domain_get_property(GObject *object,
g_value_set_object(value, priv->config);
break;
+ case PROP_OSINFO_DB:
+ g_value_set_object(value, priv->osinfo_db);
+ break;
+
case PROP_OS:
g_value_set_object(value, priv->os);
break;
@@ -112,6 +118,11 @@ static void gvir_designer_domain_set_property(GObject *object,
GVirDesignerDomainPrivate *priv = design->priv;
switch (prop_id) {
+ case PROP_OSINFO_DB:
+ if (priv->osinfo_db)
+ g_object_unref(priv->osinfo_db);
+ priv->osinfo_db = g_value_dup_object(value);
+ break;
case PROP_OS:
if (priv->os)
g_object_unref(priv->os);
@@ -147,6 +158,8 @@ static void gvir_designer_domain_finalize(GObject *object)
g_object_unref(priv->caps);
if (priv->deployment)
g_object_unref(priv->deployment);
+ if (priv->osinfo_db)
+ g_object_unref(priv->osinfo_db);
G_OBJECT_CLASS(gvir_designer_domain_parent_class)->finalize(object);
}
@@ -171,6 +184,15 @@ static void gvir_designer_domain_class_init(GVirDesignerDomainClass *klass)
G_PARAM_STATIC_STRINGS));
g_object_class_install_property(object_class,
+ PROP_OSINFO_DB,
+ g_param_spec_object("osinfo-db",
+ "Osinfo Database",
+ "libosinfo database",
+ OSINFO_TYPE_DB,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE |
+ G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property(object_class,
PROP_OS,
g_param_spec_object("os",
"Os",
@@ -709,6 +731,23 @@ cleanup:
}
+static void gvir_designer_domain_load_osinfo_db(GVirDesignerDomain *domain)
+{
+ /* Init libosinfo and load databases from default paths */
+ /* XXX maybe we want to let users tell a different path via
+ * env variable or argv */
+ OsinfoLoader *osinfo_loader = NULL;
+ OsinfoDb *db;
+
+ osinfo_loader = osinfo_loader_new();
+ osinfo_loader_process_default_path(osinfo_loader, NULL);
+
+ db = osinfo_loader_get_db(osinfo_loader);
+ if (db != NULL)
+ g_object_set(G_OBJECT(domain), "osinfo-db", db, NULL);
+ g_object_unref(G_OBJECT(osinfo_loader));
+}
+
static OsinfoDeviceLink *
gvir_designer_domain_get_preferred_device(GVirDesignerDomain *design,
const char *class,
@@ -721,7 +760,15 @@ gvir_designer_domain_get_preferred_device(GVirDesignerDomain *design,
OsinfoDeviceLink *dev_link = NULL;
if (!deployment) {
- priv->deployment = deployment = osinfo_db_find_deployment(osinfo_db,
+ if (!priv->osinfo_db)
+ gvir_designer_domain_load_osinfo_db(design);
+
+ if (!priv->osinfo_db) {
+ g_set_error(error, GVIR_DESIGNER_DOMAIN_ERROR, 0,
+ "Unable to find any deployment in libosinfo database");
+ goto cleanup;
+ }
+ priv->deployment = deployment = osinfo_db_find_deployment(priv->osinfo_db,
priv->os,
priv->platform);
if (!deployment) {
diff --git a/libvirt-designer/libvirt-designer-internal.h b/libvirt-designer/libvirt-designer-internal.h
index bbef922..e95edfc 100644
--- a/libvirt-designer/libvirt-designer-internal.h
+++ b/libvirt-designer/libvirt-designer-internal.h
@@ -24,7 +24,4 @@
#ifndef __LIBVIRT_DESIGNER_INTERNAL_H__
#define __LIBVIRT_DESIGNER_INTERNAL_H__
-extern OsinfoLoader *osinfo_loader;
-extern OsinfoDb *osinfo_db;
-
#endif /* __LIBVIRT_DESIGNER_INTERNAL_H__ */
diff --git a/libvirt-designer/libvirt-designer-main.c b/libvirt-designer/libvirt-designer-main.c
index 5c70b57..927eb21 100644
--- a/libvirt-designer/libvirt-designer-main.c
+++ b/libvirt-designer/libvirt-designer-main.c
@@ -30,9 +30,6 @@
#include <libvirt-designer/libvirt-designer.h>
#include <libvirt-gconfig/libvirt-gconfig.h>
-OsinfoLoader *osinfo_loader = NULL;
-OsinfoDb *osinfo_db = NULL;
-
/**
* gvir_designer_init:
* @argc: (inout): pointer to application's argc
@@ -57,7 +54,6 @@ static void gvir_log_handler(const gchar *log_domain G_GNUC_UNUSED,
fprintf(stderr, "%s\n", message);
}
-
/**
* gvir_designer_init_check:
* @argc: (inout): pointer to application's argc
@@ -85,13 +81,5 @@ gboolean gvir_designer_init_check(int *argc,
gvir_log_handler, NULL);
#endif
- /* Init libosinfo and load databases from default paths */
- /* XXX maybe we want to let users tell a different path via
- * env variable or argv */
- osinfo_loader = osinfo_loader_new();
- osinfo_loader_process_default_path(osinfo_loader, NULL);
-
- osinfo_db = osinfo_loader_get_db(osinfo_loader);
-
return TRUE;
}
diff --git a/libvirt-designer/libvirt-designer-main.h b/libvirt-designer/libvirt-designer-main.h
index 2500ef7..5e82f8a 100644
--- a/libvirt-designer/libvirt-designer-main.h
+++ b/libvirt-designer/libvirt-designer-main.h
@@ -24,6 +24,8 @@
#error "Only <libvirt-gdesigner/libvirt-gdesigner.h> can be included directly."
#endif
+#include <osinfo/osinfo.h>
+
#ifndef __LIBVIRT_DESIGNER_MAIN_H__
#define __LIBVIRT_DESIGNER_MAIN_H__
diff --git a/libvirt-designer/libvirt-designer.sym b/libvirt-designer/libvirt-designer.sym
index 79db09f..6f63abc 100644
--- a/libvirt-designer/libvirt-designer.sym
+++ b/libvirt-designer/libvirt-designer.sym
@@ -2,6 +2,7 @@ LIBVIRT_DESIGNER_0.0.1 {
global:
gvir_designer_init;
gvir_designer_init_check;
+ gvir_designer_get_osinfo_db;
gvir_designer_domain_new;
gvir_designer_domain_get_type;
--
1.8.1.4
11 years, 7 months
[libvirt] [PATCH] replace ppce500v2 with ppce500
by Olivia Yin
---
docs/schemas/domaincommon.rng | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-ppc-dtb.args | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-ppc-dtb.xml | 2 +-
tests/testutilsqemu.c | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 90647df..5a871d6 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -367,7 +367,7 @@
<value>g3beige</value>
<value>mac99</value>
<value>prep</value>
- <value>ppce500v2</value>
+ <value>ppce500</value>
</choice>
</attribute>
</optional>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-ppc-dtb.args b/tests/qemuxml2argvdata/qemuxml2argv-ppc-dtb.args
index 93e8f9c..1ffd8be 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-ppc-dtb.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-ppc-dtb.args
@@ -1,5 +1,5 @@
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
-/usr/bin/qemu-system-ppc -S -M ppce500v2 -m 256 -smp 1 -nographic \
+/usr/bin/qemu-system-ppc -S -M ppce500 -m 256 -smp 1 -nographic \
-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
-kernel /media/ram/uImage -initrd /media/ram/ramdisk \
-append 'root=/dev/ram rw console=ttyS0,115200' -dtb /media/ram/test.dtb \
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-ppc-dtb.xml b/tests/qemuxml2argvdata/qemuxml2argv-ppc-dtb.xml
index 3674621..04f0eb6 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-ppc-dtb.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-ppc-dtb.xml
@@ -5,7 +5,7 @@
<currentMemory unit='KiB'>262144</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
- <type arch='ppc' machine='ppce500v2'>hvm</type>
+ <type arch='ppc' machine='ppce500'>hvm</type>
<kernel>/media/ram/uImage</kernel>
<initrd>/media/ram/ramdisk</initrd>
<cmdline>root=/dev/ram rw console=ttyS0,115200</cmdline>
diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c
index db15ee6..35d6158 100644
--- a/tests/testutilsqemu.c
+++ b/tests/testutilsqemu.c
@@ -97,7 +97,7 @@ static int testQemuAddPPCGuest(virCapsPtr caps)
static const char *machine[] = { "g3beige",
"mac99",
"prep",
- "ppce500v2" };
+ "ppce500" };
virCapsGuestMachinePtr *machines = NULL;
virCapsGuestPtr guest;
--
1.8.0
11 years, 7 months
[libvirt] [PATCH v3 0/4] Add cpuset cgroup support for LXC
by Gao feng
This patchset intend to add cpuset cgroup support for LXC.
in order to don't create too many redundant codes,
this patchset also rename some functions and structure.
Gao feng (4):
rename qemuGetNumadAdvice to virNumaGetAutoPlacementAdvice
LXC: allow uses advisory nodeset from querying numad
NUMA: cleanup for numa related codes
LXC: add cpuset cgroup support for lxc
include/libvirt/libvirt.h.in | 15 ----
po/POTFILES.in | 1 +
src/Makefile.am | 1 +
src/conf/domain_conf.c | 25 ++----
src/conf/domain_conf.h | 17 +---
src/libvirt_private.syms | 12 ++-
src/lxc/lxc_cgroup.c | 54 ++++++++++++-
src/lxc/lxc_cgroup.h | 2 +-
src/lxc/lxc_controller.c | 149 +++++++++++-----------------------
src/qemu/qemu_cgroup.c | 6 +-
src/qemu/qemu_driver.c | 2 +-
src/qemu/qemu_process.c | 155 +-----------------------------------
src/util/virnuma.c | 186 +++++++++++++++++++++++++++++++++++++++++++
src/util/virnuma.h | 73 +++++++++++++++++
tools/virsh-domain.c | 4 +-
15 files changed, 390 insertions(+), 312 deletions(-)
create mode 100644 src/util/virnuma.c
create mode 100644 src/util/virnuma.h
--
1.7.11.7
11 years, 7 months
[libvirt] [PATCH] fix TLS error with virNetServerClientCreateIdentity
by Olivia Yin
---
src/rpc/virnetserverclient.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c
index d407f5e..58fb0b4 100644
--- a/src/rpc/virnetserverclient.c
+++ b/src/rpc/virnetserverclient.c
@@ -687,6 +687,7 @@ virNetServerClientCreateIdentity(virNetServerClientPtr client)
}
#endif
+#if WITH_GNUTLS
if (client->tls) {
const char *identity = virNetTLSSessionGetX509DName(client->tls);
if (identity &&
@@ -695,6 +696,7 @@ virNetServerClientCreateIdentity(virNetServerClientPtr client)
goto cleanup;
}
}
+#endif
if (client->sock &&
virNetSocketGetSecurityContext(client->sock, &seccontext) < 0)
--
1.8.0
11 years, 7 months
[libvirt] [PATCH v5 0/3] qemu: -dtb option support
by Olivia Yin
Since v1.1 QEMU provides -dtb option to support loading device tree binary images.
These patches update qemu commands/capabilities for dtb and provide docs/tests.
Olivia Yin (3):
conf: support <dtb> tag in XML domain file
qemu: add dtb option supprt
selinux: deal with dtb file
docs/formatdomain.html.in | 5 +++
docs/schemas/domaincommon.rng | 6 ++++
src/conf/domain_conf.c | 4 ++
src/conf/domain_conf.h | 1 +
src/qemu/qemu_capabilities.c | 8 ++++-
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_command.c | 6 ++++
src/security/security_dac.c | 8 +++++
src/security/security_selinux.c | 8 +++++
src/security/virt-aa-helper.c | 4 ++
tests/qemuhelptest.c | 30 +++++++++++++------
tests/qemuxml2argvdata/qemuxml2argv-ppc-dtb.args | 1 +
tests/qemuxml2argvdata/qemuxml2argv-ppc-dtb.xml | 28 ++++++++++++++++++
tests/qemuxml2argvtest.c | 2 +
tests/testutilsqemu.c | 33 ++++++++++++++++++++++
15 files changed, 133 insertions(+), 12 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-ppc-dtb.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-ppc-dtb.xml
11 years, 7 months
[libvirt] [test-API][PATCH] The patch covers all nwfilter api provided by libvirt.py. It includes define/undefine/list nwfilters and check them via checking ebtables rule. The following new files are added. cases/nwfilter.conf repos/nwfilter/__init__.py repos/nwfilter/nwfilter_check.py * Check the nwfilter via checking ebtales repos/nwfilter/nwfilter_define.py * Define the nwfilter using specified value repos/nwfilter/nwfilter_list.py * List all of the available network filters repos/nwfilter/nwfilter_undef
by hongming
---
cases/nwfilter.conf | 59 +++++++++++++++++
repos/nwfilter/nwfilter_check.py | 120 +++++++++++++++++++++++++++++++++++
repos/nwfilter/nwfilter_define.py | 54 ++++++++++++++++
repos/nwfilter/nwfilter_list.py | 76 ++++++++++++++++++++++
repos/nwfilter/nwfilter_undefine.py | 43 +++++++++++++
repos/nwfilter/xmls/nwfilter.xml | 3 +
6 files changed, 355 insertions(+), 0 deletions(-)
create mode 100644 cases/nwfilter.conf
create mode 100644 repos/nwfilter/__init__.py
create mode 100644 repos/nwfilter/nwfilter_check.py
create mode 100644 repos/nwfilter/nwfilter_define.py
create mode 100644 repos/nwfilter/nwfilter_list.py
create mode 100644 repos/nwfilter/nwfilter_undefine.py
create mode 100644 repos/nwfilter/xmls/nwfilter.xml
diff --git a/cases/nwfilter.conf b/cases/nwfilter.conf
new file mode 100644
index 0000000..b394ee5
--- /dev/null
+++ b/cases/nwfilter.conf
@@ -0,0 +1,59 @@
+domain:install_linux_cdrom
+ guestname
+ $defaultname
+ guestos
+ $defaultos
+ guestarch
+ $defaultarch
+ vcpu
+ $defaultvcpu
+ memory
+ $defaultmem
+ hddriver
+ $defaulthd
+ nicdriver
+ $defaultnic
+ imageformat
+ qcow2
+ macaddr
+ 54:52:00:4a:16:30
+
+nwfilter:nwfilter_list
+
+# chain -- ipv4, ipv6, arp .etc
+# action -- mandatory; drop, accept, return
+# direction -- mandatory; must either be in, out or inout
+nwfilter:nwfilter_define
+ nwfiltername
+ disallow-arp
+ chain
+ arp
+ action
+ drop
+ direction
+ inout
+
+nwfilter:nwfilter_list
+
+nwfilter:nwfilter_check
+ nwfiltername
+ disallow-arp
+ guestname
+ $defaultname
+
+nwfilter:nwfilter_define
+ nwfiltername
+ disallow-ipv6
+ chain
+ ipv6
+ action
+ drop
+ direction
+ in
+
+nwfilter:nwfilter_undefine
+ nwfiltername
+ disallow-ipv6
+
+nwfilter:nwfilter_list
+
diff --git a/repos/nwfilter/__init__.py b/repos/nwfilter/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/repos/nwfilter/nwfilter_check.py b/repos/nwfilter/nwfilter_check.py
new file mode 100644
index 0000000..b2c7ece
--- /dev/null
+++ b/repos/nwfilter/nwfilter_check.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+import time
+import xml.dom.minidom
+
+from libvirt import libvirtError
+from utils import utils
+from xml.dom import minidom
+
+from src import sharedmod
+
+required_params = ('nwfiltername','guestname',)
+optional_params = {}
+
+EBTABLES = "ebtables -t nat -L"
+
+def get_ebtables():
+ """ Get the output of ebtables """
+ (status, output) = utils.exec_cmd(EBTABLES,shell=True)
+ logger.info("Execute command:" + EBTABLES)
+ ebtables_list = []
+
+ if status:
+ logger.error("Executing " + EBTABLES + " failed")
+ logger.error(output)
+ return False
+ else:
+ for i in range(len(output)):
+ ebtables_list.append(output[i])
+ logger.info("Get the output of ebtables list: %s" \
+ % ebtables_list)
+
+ return ebtables_list
+
+def check_ebtables(*args):
+ """ Check the ebtables """
+ (nwfiltername,conn)= args
+ ebtables_list = get_ebtables()
+
+ #Get the filter' attribute value
+ nwfilter_xml = conn.nwfilterLookupByName(nwfiltername).XMLDesc(0)
+ nwfilter_parsedxml = minidom.parseString(nwfilter_xml)
+ chain = nwfilter_parsedxml.getElementsByTagName("filter")[0].\
+ getAttribute("chain")
+ rule = nwfilter_parsedxml.getElementsByTagName("rule")[0]
+ action = rule.getAttribute("action").upper()
+ direction = rule.getAttribute("direction")
+ logger.info("The nwfilter chain:%s ,action:%s ,direction:%s " %\
+ (chain,action,direction) )
+ in_vnet_chain = "I-vnet0-" + chain
+ out_vnet_chain = "O-vnet0-" + chain
+
+ if cmp(direction,"inout") == 0 :
+ if len(ebtables_list) == 21 and in_vnet_chain in ebtables_list[-5]\
+ and out_vnet_chain in ebtables_list[-2] \
+ and action in ebtables_list[-1] \
+ and action in ebtables_list[-4]:
+ return True
+ else:
+ return False
+ elif cmp(direction,"in") == 0:
+ if len(ebtables_list) == 14 and out_vnet_chain in ebtables_list[-2]\
+ and action in ebtables_list[-1]:
+ return True
+ else:
+ return False
+
+ elif cmp(direction,"out") == 0:
+ if len(ebtables_list) == 14 and in_vnet_chain in ebtables_list[-2] \
+ and action in ebtables_list[-1]:
+ return True
+ else:
+ return False
+
+def nwfilter_check(params):
+ """Check the nwfilter via checking ebtales"""
+ global logger
+ logger = params['logger']
+ nwfiltername = params['nwfiltername']
+ guestname = params['guestname']
+ domain_nwfilter_xml = ""
+
+ conn = sharedmod.libvirtobj['conn']
+ domobj = conn.lookupByName(guestname)
+
+ try:
+
+ #Create the nwfilter's element and append it to domain xml
+ domxml = domobj.XMLDesc(0)
+ domain_parsedxml = minidom.parseString(domxml)
+ domain_ifxml = domain_parsedxml.getElementsByTagName("interface")
+ filterxml = domain_parsedxml.createElement("filterref")
+ filterxml.setAttribute("filter", nwfiltername)
+ domain_ifxml[0].appendChild(filterxml)
+
+ #Destroy the domain and redefine it with nwfilter
+ domobj.destroy()
+ time.sleep(5)
+ domobj.undefine()
+
+ #Define the new domain with the nwfilter
+ dom_nwfilter = conn.defineXML(domain_parsedxml.toxml())
+ logger.debug("The xml of new defined domain with nwfilter %s" % \
+ dom_nwfilter.XMLDesc(0))
+
+ #Start the new defined domain
+ dom_nwfilter.create()
+ time.sleep(5)
+
+ if check_ebtables(nwfiltername,conn):
+ logger.info("Successfully create nwfilter")
+ return 0
+ else:
+ logger.error("Failed to create nwfilter")
+ return 1
+
+ except libvirtError, e:
+ logger.error("API error message: %s" % e.message)
+ return 1
+
+ return 0
\ No newline at end of file
diff --git a/repos/nwfilter/nwfilter_define.py b/repos/nwfilter/nwfilter_define.py
new file mode 100644
index 0000000..e20fd2d
--- /dev/null
+++ b/repos/nwfilter/nwfilter_define.py
@@ -0,0 +1,54 @@
+#! /usr/bin/env python
+
+
+
+from libvirt import libvirtError
+from src import sharedmod
+
+
+required_params = ('nwfiltername','chain','action','direction')
+optional_params = {'xml' : 'xmls/nwfilter.xml',}
+
+def nwfilter_define(params):
+ """ Define network filters."""
+ logger = params['logger']
+ conn = sharedmod.libvirtobj['conn']
+ xmlstr = params['xml']
+ nwfiltername = params['nwfiltername']
+ chain = params['chain']
+ action = params['action']
+ direction = params['direction']
+
+
+ xmlstr = xmlstr.replace('NWFILTERNAME', nwfiltername)
+ xmlstr = xmlstr.replace('CHAIN', chain)
+ xmlstr = xmlstr.replace('ACTION', action)
+ xmlstr = xmlstr.replace('DIRECTION', direction)
+ try:
+ logger.info("nwfiltername:%s chain:%s action:%s direction:%s" % \
+ (nwfiltername,chain,action,direction))
+ logger.info("The nwfilter's xml is %s" % xmlstr)
+
+ #Define the nwfilter with given attribute value from nwfilter.conf"""
+ conn.nwfilterDefineXML(xmlstr)
+ nwfilterxml = conn.nwfilterLookupByName(nwfiltername).XMLDesc(0)
+
+ if nwfiltername in conn.listNWFilters():
+ logger.info("The nwfilter list includes the defined nwfilter")
+ if cmp(xmlstr,nwfilterxml):
+ logger.info("Successfully define the nwfilter %s" % \
+ nwfiltername)
+ return 0
+ else:
+ logger.error("Fail to define the nwfilter %s" % nwfiltername)
+ return 1
+ else:
+ logger.error("Failed,nwfilter list doesn't include the defined \
+ nwfilter")
+ return 1
+
+ except libvirtError, e:
+ logger.error("API error message: %s" % e.message)
+ return 1
+
+ return 0
\ No newline at end of file
diff --git a/repos/nwfilter/nwfilter_list.py b/repos/nwfilter/nwfilter_list.py
new file mode 100644
index 0000000..056ee1f
--- /dev/null
+++ b/repos/nwfilter/nwfilter_list.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+
+from libvirt import libvirtError
+from utils import utils
+
+from src import sharedmod
+
+required_params = ()
+optional_params = {}
+
+NWFILTER_LIST_API_DIR = "ls /etc/libvirt/nwfilter"
+
+def get_nwfilterlist_dir():
+ """ Get the nwfilter list from dir """
+
+ (status, output) = utils.exec_cmd(NWFILTER_LIST_API_DIR,shell=True)
+ logger.info("Execute command:" + NWFILTER_LIST_API_DIR)
+ nwfilter_list_api_dir = []
+ if status:
+ logger.error("Executing " + NWFILTER_LIST_API_DIR + " failed")
+ logger.error(output)
+ return False
+ else:
+ for i in range(len(output)):
+ nwfilter_list_api_dir.append(output[i][:-4])
+ logger.info("Get nwfilters name list under dir: %s" \
+ % nwfilter_list_api_dir)
+ return nwfilter_list_api_dir
+
+def nwfilter_list(params):
+ """ List all of the available network filters."""
+ global logger
+ logger = params['logger']
+ conn = sharedmod.libvirtobj['conn']
+
+ try:
+ #Get the nwfilter name list from API """
+ nwfilter_namelist_api = conn.listNWFilters()
+
+ #Get the nwfilter object list
+ nwfilter_list_api = conn.listAllNWFilters(0)
+ logger.info("The connection URI %s" % \
+ nwfilter_list_api[0].connect().getURI())
+
+ #Get the number of nwfilters from API
+ nwfilter_num = conn.numOfNWFilters()
+
+ nwfilter_list_dir = get_nwfilterlist_dir()
+ if nwfilter_num == len(nwfilter_list_api) and \
+ len(nwfilter_list_api) == len(nwfilter_list_dir) and \
+ cmp(nwfilter_namelist_api,nwfilter_list_dir):
+ logger.info("The number of available network filters is %s" % \
+ nwfilter_num)
+ else:
+ logger.error("Failed to get the nwfilters list")
+ return 1
+
+ for nwfilter_item in nwfilter_list_api:
+ if nwfilter_item.name()in nwfilter_list_dir and \
+ nwfilter_item.name()in nwfilter_namelist_api:
+ logger.info("The name is %s" % nwfilter_item.name())
+ else:
+ logger.error("Failed to get nwfilter's name.")
+ return 1
+ if cmp(str(nwfilter_item.UUID()),nwfilter_item.UUIDString()):
+ logger.info("The UUID is %s" % nwfilter_item.UUIDString())
+ else:
+ logger.error("Failed to get nwfilter's uuid.")
+ return 1
+
+
+ except libvirtError, e:
+ logger.error("API error message: %s" % e.message)
+ return 1
+
+ return 0
\ No newline at end of file
diff --git a/repos/nwfilter/nwfilter_undefine.py b/repos/nwfilter/nwfilter_undefine.py
new file mode 100644
index 0000000..b9ea332
--- /dev/null
+++ b/repos/nwfilter/nwfilter_undefine.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+
+from libvirt import libvirtError
+
+from src import sharedmod
+
+required_params = ('nwfiltername',)
+optional_params = {}
+
+def nwfilter_undefine(params):
+ """Undefine the specified nwfilter"""
+ logger = params['logger']
+ nwfiltername = params['nwfiltername']
+ conn = sharedmod.libvirtobj['conn']
+
+ try:
+ nwfilter = conn.nwfilterLookupByName(nwfiltername)
+ uuidstr = nwfilter.UUIDString()
+ uuid = nwfilter.UUID()
+ # Lookup by nwfilter's uuid string
+ nwfilter_uuidstr = conn.nwfilterLookupByUUIDString(uuidstr)
+ # Lookup by nwfilter's uuid
+ nwfilter_uuid = conn.nwfilterLookupByUUID(uuid)
+
+ # Check if the nwfilter lookup by name/uuid/uuidstr is the same one
+ if cmp(nwfilter,nwfilter_uuidstr) and cmp(nwfilter_uuidstr,\
+ nwfilter_uuid):
+ # Undefine the nwfilter
+ nwfilter.undefine()
+ # Check if the nwfiler list includes the undefined nwfilter
+ if nwfiltername not in conn.listNWFilters():
+ logger.info("Successfully undefine the nwfilter %s" % \
+ nwfiltername)
+ return 0
+ else:
+ logger.error("Failed to undefine the nwfilter %s" % nwfiltername)
+ return 1
+
+ except libvirtError, e:
+ logger.error("API error message: %s" % e.message)
+ return 1
+
+ return 0
diff --git a/repos/nwfilter/xmls/nwfilter.xml b/repos/nwfilter/xmls/nwfilter.xml
new file mode 100644
index 0000000..6d52d5d
--- /dev/null
+++ b/repos/nwfilter/xmls/nwfilter.xml
@@ -0,0 +1,3 @@
+<filter name='NWFILTERNAME' chain='CHAIN'>
+ <rule action='ACTION' direction='DIRECTION' priority='500'/>
+</filter>
--
1.7.7.6
11 years, 7 months
[libvirt] [PATCH] Fix --without-libvirtd builds
by Doug Goldstein
When building with --without-libvirtd and udev support is detected we
will fail to build with the following error:
node_device/node_device_udev.c:1608:37: error: unknown type name
'virStateInhibitCallback'
---
src/Makefile.am | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/Makefile.am b/src/Makefile.am
index 8b591d2..e361a6b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1237,6 +1237,7 @@ libvirt_driver_nodedev_la_CFLAGS = \
libvirt_driver_nodedev_la_LDFLAGS = $(AM_LDFLAGS)
libvirt_driver_nodedev_la_LIBADD =
+if WITH_LIBVIRTD
if WITH_HAL
libvirt_driver_nodedev_la_SOURCES += $(NODE_DEVICE_DRIVER_HAL_SOURCES)
libvirt_driver_nodedev_la_CFLAGS += $(HAL_CFLAGS)
@@ -1247,6 +1248,7 @@ libvirt_driver_nodedev_la_SOURCES += $(NODE_DEVICE_DRIVER_UDEV_SOURCES)
libvirt_driver_nodedev_la_CFLAGS += $(UDEV_CFLAGS) $(PCIACCESS_CFLAGS)
libvirt_driver_nodedev_la_LIBADD += $(UDEV_LIBS) $(PCIACCESS_LIBS)
endif
+endif
if WITH_DRIVER_MODULES
libvirt_driver_nodedev_la_LIBADD += ../gnulib/lib/libgnu.la
--
1.8.1.5
11 years, 7 months
[libvirt] [PATCH] rename tests/conftest.c
by Gene Czarcinski
To prevent confusion with configure's popular name
for a file, rename conftest.c to test_conf.c which
is consistent with the invoking test_conf.sh
Signed-off-by: Gene Czarcinski <gene(a)czarc.net>
---
tests/Makefile.am | 8 ++++----
tests/conftest.c | 48 ------------------------------------------------
tests/test_conf.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
tests/test_conf.sh | 2 +-
4 files changed, 53 insertions(+), 53 deletions(-)
delete mode 100644 tests/conftest.c
create mode 100644 tests/test_conf.c
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d3a7868..837ae93 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -88,7 +88,7 @@ EXTRA_DIST = \
xml2vmxdata \
.valgrind.supp
-test_helpers = commandhelper ssh conftest
+test_helpers = commandhelper ssh test_conf
test_programs = virshtest sockettest \
nodeinfotest virbuftest \
commandtest seclabeltest \
@@ -506,9 +506,9 @@ virshtest_SOURCES = \
testutils.c testutils.h
virshtest_LDADD = $(LDADDS)
-conftest_SOURCES = \
- conftest.c
-conftest_LDADD = $(LDADDS)
+test_conf_SOURCES = \
+ test_conf.c
+test_conf_LDADD = $(LDADDS)
nodeinfotest_SOURCES = \
nodeinfotest.c testutils.h testutils.c
diff --git a/tests/conftest.c b/tests/conftest.c
deleted file mode 100644
index d5467e8..0000000
--- a/tests/conftest.c
+++ /dev/null
@@ -1,48 +0,0 @@
-#include <config.h>
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include "virconf.h"
-#include "viralloc.h"
-
-int main(int argc, char **argv)
-{
- int ret, exit_code = EXIT_FAILURE;
- virConfPtr conf;
- int len = 10000;
- char *buffer = NULL;
-
- if (argc != 2) {
- fprintf(stderr, "Usage: %s conf_file\n", argv[0]);
- goto cleanup;
- }
-
- if (VIR_ALLOC_N(buffer, len) < 0) {
- fprintf(stderr, "out of memory\n");
- goto cleanup;
- }
- conf = virConfReadFile(argv[1], 0);
- if (conf == NULL) {
- fprintf(stderr, "Failed to process %s\n", argv[1]);
- goto cleanup;
- }
- ret = virConfWriteMem(buffer, &len, conf);
- if (ret < 0) {
- fprintf(stderr, "Failed to serialize %s back\n", argv[1]);
- goto cleanup;
- }
- virConfFree(conf);
- if (fwrite(buffer, 1, len, stdout) != len) {
- fprintf(stderr, "Write failed: %s\n", strerror(errno));
- goto cleanup;
- }
-
- exit_code = EXIT_SUCCESS;
-
-cleanup:
- VIR_FREE(buffer);
- return exit_code;
-}
diff --git a/tests/test_conf.c b/tests/test_conf.c
new file mode 100644
index 0000000..d5467e8
--- /dev/null
+++ b/tests/test_conf.c
@@ -0,0 +1,48 @@
+#include <config.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "virconf.h"
+#include "viralloc.h"
+
+int main(int argc, char **argv)
+{
+ int ret, exit_code = EXIT_FAILURE;
+ virConfPtr conf;
+ int len = 10000;
+ char *buffer = NULL;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s conf_file\n", argv[0]);
+ goto cleanup;
+ }
+
+ if (VIR_ALLOC_N(buffer, len) < 0) {
+ fprintf(stderr, "out of memory\n");
+ goto cleanup;
+ }
+ conf = virConfReadFile(argv[1], 0);
+ if (conf == NULL) {
+ fprintf(stderr, "Failed to process %s\n", argv[1]);
+ goto cleanup;
+ }
+ ret = virConfWriteMem(buffer, &len, conf);
+ if (ret < 0) {
+ fprintf(stderr, "Failed to serialize %s back\n", argv[1]);
+ goto cleanup;
+ }
+ virConfFree(conf);
+ if (fwrite(buffer, 1, len, stdout) != len) {
+ fprintf(stderr, "Write failed: %s\n", strerror(errno));
+ goto cleanup;
+ }
+
+ exit_code = EXIT_SUCCESS;
+
+cleanup:
+ VIR_FREE(buffer);
+ return exit_code;
+}
diff --git a/tests/test_conf.sh b/tests/test_conf.sh
index aa7abf6..2920e28 100755
--- a/tests/test_conf.sh
+++ b/tests/test_conf.sh
@@ -12,7 +12,7 @@ data_dir=$abs_srcdir/confdata
for f in $(cd "$data_dir" && echo *.conf)
do
i=`expr $i + 1`
- "$abs_builddir/conftest" "$data_dir/$f" > "$f-actual"
+ "$abs_builddir/test_conf" "$data_dir/$f" > "$f-actual"
expected="$data_dir"/`echo "$f" | sed s+\.conf$+\.out+`
if compare "$expected" "$f-actual"; then
ret=0
--
1.8.1.4
11 years, 7 months
[libvirt] [PATCH v3] add a boot option to do strict boot
by Amos Kong
Seabios already added a new device type to halt booting.
Qemu can add "HALT" at the end of bootindex string, then
seabios will halt booting after trying to boot from all
selected devices.
This patch added a new boot option to configure if boot
from un-selected devices.
This option only effects when boot priority is changed by
bootindex options, the old style(-boot order=..) will still
try to boot from un-selected devices.
v2: add HALT entry in get_boot_devices_list()
v3: rebase to latest qemu upstream
Signed-off-by: Amos Kong <akong(a)redhat.com>
---
As we discussed in the past, we need to introduce a general
query-config command to tell libvirt the supported options.
Anthony will do it?
http://lists.nongnu.org/archive/html/qemu-devel/2013-03/msg00349.html
---
qemu-options.hx | 8 ++++++--
vl.c | 25 ++++++++++++++++++++++++-
2 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/qemu-options.hx b/qemu-options.hx
index 30fb85d..06dd565 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -161,14 +161,14 @@ ETEXI
DEF("boot", HAS_ARG, QEMU_OPTION_boot,
"-boot [order=drives][,once=drives][,menu=on|off]\n"
- " [,splash=sp_name][,splash-time=sp_time][,reboot-timeout=rb_time]\n"
+ " [,splash=sp_name][,splash-time=sp_time][,reboot-timeout=rb_time][,strict=on|off]\n"
" 'drives': floppy (a), hard disk (c), CD-ROM (d), network (n)\n"
" 'sp_name': the file's name that would be passed to bios as logo picture, if menu=on\n"
" 'sp_time': the period that splash picture last if menu=on, unit is ms\n"
" 'rb_timeout': the timeout before guest reboot when boot failed, unit is ms\n",
QEMU_ARCH_ALL)
STEXI
-@item -boot [order=@var{drives}][,once=@var{drives}][,menu=on|off][,splash=@var{sp_name}][,splash-time=@var{sp_time}][,reboot-timeout=@var{rb_timeout}]
+@item -boot [order=@var{drives}][,once=@var{drives}][,menu=on|off][,splash=@var{sp_name}][,splash-time=@var{sp_time}][,reboot-timeout=@var{rb_timeout}][,strict=on|off]
@findex -boot
Specify boot order @var{drives} as a string of drive letters. Valid
drive letters depend on the target achitecture. The x86 PC uses: a, b
@@ -192,6 +192,10 @@ when boot failed, then reboot. If @var{rb_timeout} is '-1', guest will not
reboot, qemu passes '-1' to bios by default. Currently Seabios for X86
system support it.
+Do strict boot via @option{strict=on} as far as firmware/BIOS
+supports it. This only effects when boot priority is changed by
+bootindex options. The default is non-strict boot.
+
@example
# try to boot from network first, then from hard disk
qemu-system-i386 -boot order=nc
diff --git a/vl.c b/vl.c
index ce51e65..aeed7f4 100644
--- a/vl.c
+++ b/vl.c
@@ -234,6 +234,7 @@ int ctrl_grab = 0;
unsigned int nb_prom_envs = 0;
const char *prom_envs[MAX_PROM_ENVS];
int boot_menu;
+bool boot_strict;
uint8_t *boot_splash_filedata;
size_t boot_splash_filedata_size;
uint8_t qemu_extra_params_fw[2];
@@ -458,6 +459,9 @@ static QemuOptsList qemu_boot_opts = {
}, {
.name = "reboot-timeout",
.type = QEMU_OPT_STRING,
+ }, {
+ .name = "strict",
+ .type = QEMU_OPT_STRING,
},
{ /*End of list */ }
},
@@ -1267,6 +1271,12 @@ char *get_boot_devices_list(size_t *size)
*size = total;
+ if (boot_strict && *size > 0) {
+ list[total-1] = '\n';
+ list = g_realloc(list, total + 4);
+ memcpy(&list[total], "HALT", 4);
+ *size = total + 4;
+ }
return list;
}
@@ -3131,7 +3141,7 @@ int main(int argc, char **argv, char **envp)
static const char * const params[] = {
"order", "once", "menu",
"splash", "splash-time",
- "reboot-timeout", NULL
+ "reboot-timeout", "strict", NULL
};
char buf[sizeof(boot_devices)];
char *standard_boot_devices;
@@ -3174,6 +3184,19 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
}
+ if (get_param_value(buf, sizeof(buf),
+ "strict", optarg)) {
+ if (!strcmp(buf, "on")) {
+ boot_strict = true;
+ } else if (!strcmp(buf, "off")) {
+ boot_strict = false;
+ } else {
+ fprintf(stderr,
+ "qemu: invalid option value '%s'\n",
+ buf);
+ exit(1);
+ }
+ }
if (!qemu_opts_parse(qemu_find_opts("boot-opts"),
optarg, 0)) {
exit(1);
--
1.7.1
11 years, 7 months