[libvirt] [PATCH v3] graphics: add support for action_if_connected in qemu
by Michal Prívozník
From: Michal Privoznik <mprivozn(a)redhat.com>
This option accepts 3 values:
-keep, to keep current client connected (Spice+VNC)
-disconnect, to disconnect client (Spice)
-fail, to fail setting password if there is a client connected (Spice)
---
diff to v2:
-fixed typo
-added test. However, functionality provided by this patch will show up
only when talking to qemu monitor (set_password command).
diff to v1:
-Eric's review suggestions included
-update 'Since'
docs/formatdomain.html.in | 13 +++++-
docs/schemas/domain.rng | 16 +++++++
src/conf/domain_conf.c | 44 ++++++++++++++++++-
src/conf/domain_conf.h | 11 +++++
src/libvirt_private.syms | 2 +
src/qemu/qemu_hotplug.c | 15 +++++-
.../qemuxml2argv-graphics-spice-timeout.xml | 2 +-
7 files changed, 94 insertions(+), 9 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 98fb2b4..2ed16ff 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1801,7 +1801,11 @@ qemu-kvm -net nic,model=? /dev/null
in clear text. The <code>keymap</code> attribute specifies the keymap
to use. It is possible to set a limit on the validity of the password
be giving an timestamp <code>passwdValidTo='2010-04-09T15:51:00'</code>
- assumed to be in UTC. NB, this may not be supported by all hypervisors.<br/>
+ assumed to be in UTC. <span class="since">Since 0.8.5</span>
+ The <code>connected</code> attribute allows control of connected client
+ during password changes. VNC accepts <code>keep</code> value only.
+ <span class="since">since 0.9.3</span>
+ NB, this may not be supported by all hypervisors.<br/>
<br/>
Rather than using listen/port, QEMU supports a <code>socket</code>
attribute for listening on a unix domain socket path.
@@ -1820,7 +1824,12 @@ qemu-kvm -net nic,model=? /dev/null
in clear text. The <code>keymap</code> attribute specifies the keymap
to use. It is possible to set a limit on the validity of the password
be giving an timestamp <code>passwdValidTo='2010-04-09T15:51:00'</code>
- assumed to be in UTC. NB, this may not be supported by all hypervisors.
+ assumed to be in UTC. <span class="since">Since 0.8.5</span>
+ The <code>connected</code> attribute allows control of connected client
+ during password changes. SPICE accepts <code>keep</code> to keep client
+ connected, <code>disconnect</code> to disconnect client and
+ <code>fail</code> to fail changing password. <span class="since">Since 0.9.3</span>
+ NB, this may not be supported by all hypervisors.
<span class="since">"spice" since 0.8.6</span>.
</p>
<p>
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 0be0371..e71b683 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -1250,6 +1250,13 @@
<data type="dateTime"/>
</attribute>
</optional>
+ <optional>
+ <attribute name="connected">
+ <choice>
+ <value>keep</value>
+ </choice>
+ </attribute>
+ </optional>
</group>
<group>
<attribute name="type">
@@ -1293,6 +1300,15 @@
<data type="dateTime"/>
</attribute>
</optional>
+ <optional>
+ <attribute name="connected">
+ <choice>
+ <value>fail</value>
+ <value>disconnect</value>
+ <value>keep</value>
+ </choice>
+ </attribute>
+ </optional>
<interleave>
<zeroOrMore>
<element name="channel">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 0d9fef4..19f22e0 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -311,6 +311,13 @@ VIR_ENUM_IMPL(virDomainGraphics, VIR_DOMAIN_GRAPHICS_TYPE_LAST,
"desktop",
"spice")
+VIR_ENUM_IMPL(virDomainGraphicsAuthConnected,
+ VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_LAST,
+ "default",
+ "fail",
+ "disconnect",
+ "keep")
+
VIR_ENUM_IMPL(virDomainGraphicsSpiceChannelName,
VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST,
"main",
@@ -3892,9 +3899,12 @@ error:
static int
-virDomainGraphicsAuthDefParseXML(xmlNodePtr node, virDomainGraphicsAuthDefPtr def)
+virDomainGraphicsAuthDefParseXML(xmlNodePtr node,
+ virDomainGraphicsAuthDefPtr def,
+ int type)
{
char *validTo = NULL;
+ char *connected = virXMLPropString(node, "connected");
def->passwd = virXMLPropString(node, "passwd");
@@ -3935,6 +3945,28 @@ virDomainGraphicsAuthDefParseXML(xmlNodePtr node, virDomainGraphicsAuthDefPtr de
def->expires = 1;
}
+ if (connected) {
+ int action = virDomainGraphicsAuthConnectedTypeFromString(connected);
+ if (action <= 0) {
+ virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown connected value %s"),
+ connected);
+ VIR_FREE(connected);
+ return -1;
+ }
+ VIR_FREE(connected);
+
+ /* VNC supports connected='keep' only */
+ if (type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
+ action != VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_KEEP) {
+ virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("VNC supports connected='keep' only"));
+ return -1;
+ }
+
+ def->connected = action;
+ }
+
return 0;
}
@@ -4004,7 +4036,8 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) {
!def->data.vnc.listenAddr[0])
VIR_FREE(def->data.vnc.listenAddr);
- if (virDomainGraphicsAuthDefParseXML(node, &def->data.vnc.auth) < 0)
+ if (virDomainGraphicsAuthDefParseXML(node, &def->data.vnc.auth,
+ def->type) < 0)
goto error;
} else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
char *fullscreen = virXMLPropString(node, "fullscreen");
@@ -4140,7 +4173,8 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) {
!def->data.spice.listenAddr[0])
VIR_FREE(def->data.spice.listenAddr);
- if (virDomainGraphicsAuthDefParseXML(node, &def->data.spice.auth) < 0)
+ if (virDomainGraphicsAuthDefParseXML(node, &def->data.spice.auth,
+ def->type) < 0)
goto error;
cur = node->children;
@@ -9075,6 +9109,10 @@ virDomainGraphicsAuthDefFormatAttr(virBufferPtr buf,
strftime(strbuf, sizeof(strbuf), "%Y-%m-%dT%H:%M:%S", tm);
virBufferAsprintf(buf, " passwdValidTo='%s'", strbuf);
}
+
+ if (def->connected)
+ virBufferEscapeString(buf, " connected='%s'",
+ virDomainGraphicsAuthConnectedTypeToString(def->connected));
}
static int
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 41c8136..6bfc337 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -640,12 +640,22 @@ enum virDomainGraphicsType {
VIR_DOMAIN_GRAPHICS_TYPE_LAST,
};
+enum virDomainGraphicsAuthConnectedType {
+ VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_DEFAULT = 0,
+ VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_FAIL,
+ VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_DISCONNECT,
+ VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_KEEP,
+
+ VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_LAST
+};
+
typedef struct _virDomainGraphicsAuthDef virDomainGraphicsAuthDef;
typedef virDomainGraphicsAuthDef *virDomainGraphicsAuthDefPtr;
struct _virDomainGraphicsAuthDef {
char *passwd;
unsigned int expires: 1; /* Whether there is an expiry time set */
time_t validTo; /* seconds since epoch */
+ int connected; /* action if connected */
};
enum virDomainGraphicsSpiceChannelName {
@@ -1546,6 +1556,7 @@ VIR_ENUM_DECL(virDomainHostdevSubsys)
VIR_ENUM_DECL(virDomainInput)
VIR_ENUM_DECL(virDomainInputBus)
VIR_ENUM_DECL(virDomainGraphics)
+VIR_ENUM_DECL(virDomainGraphicsAuthConnected)
VIR_ENUM_DECL(virDomainGraphicsSpiceChannelName)
VIR_ENUM_DECL(virDomainGraphicsSpiceChannelMode)
VIR_ENUM_DECL(virDomainGraphicsSpiceImageCompression)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 9d4e163..c43da44 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -269,6 +269,8 @@ virDomainFindByID;
virDomainFindByName;
virDomainFindByUUID;
virDomainGetRootFilesystem;
+virDomainGraphicsAuthConnectedTypeFromString;
+virDomainGraphicsAuthConnectedTypeToString;
virDomainGraphicsDefFree;
virDomainGraphicsSpiceChannelModeTypeFromString;
virDomainGraphicsSpiceChannelModeTypeToString;
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index d33fc87..da6629b 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1061,10 +1061,12 @@ qemuDomainChangeGraphics(struct qemud_driver *driver,
return -1;
}
- /* If a password lifetime was, or is set, then we must always run,
- * even if new password matches old password */
+ /* If a password lifetime was, or is set, or action if connected has
+ * changed, then we must always run, even if new password matches
+ * old password */
if (olddev->data.vnc.auth.expires ||
dev->data.vnc.auth.expires ||
+ olddev->data.vnc.auth.connected != dev->data.vnc.auth.connected ||
STRNEQ_NULLABLE(olddev->data.vnc.auth.passwd,
dev->data.vnc.auth.passwd)) {
VIR_DEBUG("Updating password on VNC server %p %p",
@@ -1080,6 +1082,7 @@ qemuDomainChangeGraphics(struct qemud_driver *driver,
dev->data.vnc.auth.passwd = NULL;
olddev->data.vnc.auth.validTo = dev->data.vnc.auth.validTo;
olddev->data.vnc.auth.expires = dev->data.vnc.auth.expires;
+ olddev->data.vnc.auth.connected = dev->data.vnc.auth.connected;
} else {
ret = 0;
}
@@ -1112,6 +1115,7 @@ qemuDomainChangeGraphics(struct qemud_driver *driver,
* even if new password matches old password */
if (olddev->data.spice.auth.expires ||
dev->data.spice.auth.expires ||
+ olddev->data.spice.auth.connected != dev->data.spice.auth.connected ||
STRNEQ_NULLABLE(olddev->data.spice.auth.passwd,
dev->data.spice.auth.passwd)) {
VIR_DEBUG("Updating password on SPICE server %p %p",
@@ -1127,6 +1131,7 @@ qemuDomainChangeGraphics(struct qemud_driver *driver,
dev->data.spice.auth.passwd = NULL;
olddev->data.spice.auth.validTo = dev->data.spice.auth.validTo;
olddev->data.spice.auth.expires = dev->data.spice.auth.expires;
+ olddev->data.spice.auth.connected = dev->data.spice.auth.connected;
} else {
VIR_DEBUG("Not updating since password didn't change");
ret = 0;
@@ -1812,16 +1817,20 @@ qemuDomainChangeGraphicsPasswords(struct qemud_driver *driver,
qemuDomainObjPrivatePtr priv = vm->privateData;
time_t now = time(NULL);
char expire_time [64];
+ const char *connected = NULL;
int ret;
if (!auth->passwd && !driver->vncPassword)
return 0;
+ if (auth->connected)
+ connected = virDomainGraphicsAuthConnectedTypeToString(auth->connected);
+
qemuDomainObjEnterMonitorWithDriver(driver, vm);
ret = qemuMonitorSetPassword(priv->mon,
type,
auth->passwd ? auth->passwd : defaultPasswd,
- NULL);
+ connected);
if (ret == -2) {
if (type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-timeout.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-timeout.xml
index 4c0c57e..6389de5 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-timeout.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-timeout.xml
@@ -71,7 +71,7 @@
</console>
<input type='tablet' bus='usb'/>
<input type='mouse' bus='ps2'/>
- <graphics type='spice' port='5900' autoport='no' passwd='sercet' passwdValidTo='2011-05-31T16:11:22'/>
+ <graphics type='spice' port='5900' autoport='no' passwd='sercet' passwdValidTo='2011-05-31T16:11:22' connected='disconnect'/>
<sound model='ac97'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</sound>
--
1.7.5.rc3
13 years, 5 months
[libvirt] [PATCH v4 2/4] vcpupin: implement the code to address the new API in the qemu driver
by Taku Izumi
This patch implements the code to address the new API
(virDomainPinVcpuFlags)
in the qemu driver.
Signed-off-by: Taku Izumi <izumi.taku(a)jp.fujitsu.com>
---
src/qemu/qemu_driver.c | 99
+++++++++++++++++++++++++++++++++++++------------
1 file changed, 76 insertions(+), 23 deletions(-)
Index: libvirt/src/qemu/qemu_driver.c
===================================================================
--- libvirt.orig/src/qemu/qemu_driver.c
+++ libvirt/src/qemu/qemu_driver.c
@@ -2880,17 +2880,24 @@ qemudDomainSetVcpus(virDomainPtr dom, un
static int
-qemudDomainPinVcpu(virDomainPtr dom,
- unsigned int vcpu,
- unsigned char *cpumap,
- int maplen) {
+qemudDomainPinVcpuFlags(virDomainPtr dom,
+ unsigned int vcpu,
+ unsigned char *cpumap,
+ int maplen,
+ unsigned int flags) {
+
struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
+ virDomainDefPtr persistentDef = NULL;
int maxcpu, hostcpus;
virNodeInfo nodeinfo;
int ret = -1;
+ bool isActive;
qemuDomainObjPrivatePtr priv;
+ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+ VIR_DOMAIN_AFFECT_CONFIG, -1);
+
qemuDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
qemuDriverUnlock(driver);
@@ -2903,9 +2910,18 @@ qemudDomainPinVcpu(virDomainPtr dom,
goto cleanup;
}
- if (!virDomainObjIsActive(vm)) {
- qemuReportError(VIR_ERR_OPERATION_INVALID,
- "%s",_("cannot pin vcpus on an inactive domain"));
+ isActive = virDomainObjIsActive(vm);
+ if (flags == VIR_DOMAIN_AFFECT_CURRENT) {
+ if (isActive)
+ flags = VIR_DOMAIN_AFFECT_LIVE;
+ else
+ flags = VIR_DOMAIN_AFFECT_CONFIG;
+ }
+
+ if (!isActive && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("a domain is inactive; can change only "
+ "persistent config"));
goto cleanup;
}
@@ -2918,27 +2934,54 @@ qemudDomainPinVcpu(virDomainPtr dom,
goto cleanup;
}
- if (nodeGetInfo(dom->conn, &nodeinfo) < 0)
- goto cleanup;
+ if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
+ if (!vm->persistent) {
+ qemuReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("cannot change persistent config of a transient
domain"));
+ goto cleanup;
+ }
+ if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps,
vm)))
+ goto cleanup;
+ }
- hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
- maxcpu = maplen * 8;
- if (maxcpu > hostcpus)
- maxcpu = hostcpus;
+ if (flags & VIR_DOMAIN_AFFECT_LIVE) {
- if (priv->vcpupids != NULL) {
- if (virProcessInfoSetAffinity(priv->vcpupids[vcpu],
- cpumap, maplen, maxcpu) < 0)
+ if (nodeGetInfo(dom->conn, &nodeinfo) < 0)
goto cleanup;
- } else {
- qemuReportError(VIR_ERR_NO_SUPPORT,
- "%s", _("cpu affinity is not supported"));
- goto cleanup;
+
+ hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
+ maxcpu = maplen * 8;
+ if (maxcpu > hostcpus)
+ maxcpu = hostcpus;
+
+ if (priv->vcpupids != NULL) {
+ if (virProcessInfoSetAffinity(priv->vcpupids[vcpu],
+ cpumap, maplen, maxcpu) < 0)
+ goto cleanup;
+ } else {
+ qemuReportError(VIR_ERR_NO_SUPPORT,
+ "%s", _("cpu affinity is not supported"));
+ goto cleanup;
+ }
+
+ if (virDomainVcpupinAdd(vm->def, cpumap, maplen, vcpu) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to update or add vcpupin xml of "
+ "a running domain"));
+ goto cleanup;
+ }
+
}
- if (virDomainVcpupinAdd(vm->def, cpumap, maplen, vcpu) < 0) {
- qemuReportError(VIR_ERR_INTERNAL_ERROR,
- "%s", _("failed to update or add vcpupin xml"));
+ if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
+
+ if (virDomainVcpupinAdd(persistentDef, cpumap, maplen, vcpu) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to update or add vcpupin xml of "
+ "a persistent domain"));
+ goto cleanup;
+ }
+ ret = virDomainSaveConfig(driver->configDir, persistentDef);
goto cleanup;
}
@@ -2951,6 +2994,15 @@ cleanup:
}
static int
+qemudDomainPinVcpu(virDomainPtr dom,
+ unsigned int vcpu,
+ unsigned char *cpumap,
+ int maplen) {
+ return qemudDomainPinVcpuFlags(dom, vcpu, cpumap, maplen,
+ VIR_DOMAIN_AFFECT_LIVE);
+}
+
+static int
qemudDomainGetVcpus(virDomainPtr dom,
virVcpuInfoPtr info,
int maxinfo,
@@ -8014,6 +8066,7 @@ static virDriver qemuDriver = {
.domainSetVcpusFlags = qemudDomainSetVcpusFlags, /* 0.8.5 */
.domainGetVcpusFlags = qemudDomainGetVcpusFlags, /* 0.8.5 */
.domainPinVcpu = qemudDomainPinVcpu, /* 0.4.4 */
+ .domainPinVcpuFlags = qemudDomainPinVcpuFlags, /* 0.9.2 */
.domainGetVcpus = qemudDomainGetVcpus, /* 0.4.4 */
.domainGetMaxVcpus = qemudDomainGetMaxVcpus, /* 0.4.4 */
.domainGetSecurityLabel = qemudDomainGetSecurityLabel, /* 0.6.1 */
13 years, 5 months
Re: [libvirt] 答复: does libvirt get disk->info.alias, when attaching a disk by virDomainAttachDevice?
by Wen Congyang
At 06/09/2011 05:26 PM, 李敬伟 Write:
> Thank you ,Wen Congyang.
> Do you know any rpm repository of libvirt 0.9.2 for Centos 5?
> You are using libvirt 0.9.2 on Centos 5?
I use the newest libvirt on RHEL6.
And I build rpm by hand.
You can use git to clone the tree from libvirt.org.
The steps to build a rpm package:
1. ./autogen.sh
2. make dist
3. rpmbuild --nodeps --define "_sourcedir `pwd`" -ba libvirt.spec
>
> -----邮件原件-----
> 发件人: Wen Congyang [mailto:wency@cn.fujitsu.com]
> 发送时间: 2011年6月9日 16:25
> 收件人: 李敬伟; libvir-list(a)redhat.com
> 主题: Re: [libvirt] does libvirt get disk->info.alias, when attaching a disk by virDomainAttachDevice?
>
> At 06/09/2011 01:26 PM, 李敬伟 Write:
>> Hi,
>> I am using libvirt 0.9.1 on CentOS 5.5 64bit ,
>> Created a vm :virsh create libvirt.xml
>> Attached a disk ,virsh attach-disk 3 /opt/vms/test.img vdb
>> When getting blosk stats ,virsh domblkstats 3 vdb ,it showed
>> error: Failed to get block stats 3 vdb
>> error: internal error missing disk device alias name for vdb
>
> I use the newest libvirt, and can not reproduce this problem.
> Please try the newest libvirt again.
>
>> while virsh domblkstat 3 vda, it showed
>> vda rd_req 6667
>> vda rd_bytes 154084864
>> vda wr_req 9530
>> vda wr_bytes 57196544
>>
>> I guess libvirt does not get disk->info.alias when attaching a disk,so it can not get block status.
>>
>> # virsh version
>> Compiled against library: libvir 0.9.1 Using library: libvir 0.9.1
>> Using API: QEMU 0.9.1 Running hypervisor: QEMU 0.9.1 # rpm -qa|grep
>> kvm
>> kmod-kvm-83-224.el5.centos.1
>> kvm-qemu-img-83-224.el5.centos.1
>> etherboot-zroms-kvm-5.4.4-13.el5.centos
>> kvm-83-224.el5.centos.1
>>
>>
>> Jingwei Li (lijingwei9060(a)gmail.com<mailto:lijingwei9060@gmail.com> or
>> lijw(a)bingosoft.net<mailto:lijw@bingosoft.net>)
>>
>>
>>
>>
>> --
>> libvir-list mailing list
>> libvir-list(a)redhat.com
>> https://www.redhat.com/mailman/listinfo/libvir-list
>
13 years, 5 months
[libvirt] [PATCH v4 3/4] vcpupin: implement the remote protocol to address the new API
by Taku Izumi
This patch implements the remote protocol to address the new API
(virDomainPinVcpuFlags).
Signd-off-by: Taku Izumi <izumi.taku(a)jp.fujitsu.com>
---
daemon/remote.c | 42
++++++++++++++++++++++++++++++++++++++++++
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 10 +++++++++-
src/remote_protocol-structs | 9 +++++++++
4 files changed, 61 insertions(+), 1 deletion(-)
Index: libvirt/src/remote/remote_protocol.x
===================================================================
--- libvirt.orig/src/remote/remote_protocol.x
+++ libvirt/src/remote/remote_protocol.x
@@ -837,6 +837,13 @@ struct remote_domain_pin_vcpu_args {
opaque cpumap<REMOTE_CPUMAP_MAX>;
};
+struct remote_domain_pin_vcpu_flags_args {
+ remote_nonnull_domain dom;
+ int vcpu;
+ opaque cpumap<REMOTE_CPUMAP_MAX>;
+ unsigned int flags;
+};
+
struct remote_domain_get_vcpus_args {
remote_nonnull_domain dom;
int maxinfo;
@@ -2297,7 +2304,8 @@ enum remote_procedure {
REMOTE_PROC_INTERFACE_CHANGE_COMMIT = 221, /* autogen autogen */
REMOTE_PROC_INTERFACE_CHANGE_ROLLBACK = 222, /* autogen autogen */
REMOTE_PROC_DOMAIN_GET_SCHEDULER_PARAMETERS_FLAGS = 223, /* skipgen
autogen */
- REMOTE_PROC_DOMAIN_EVENT_CONTROL_ERROR = 224 /* skipgen skipgen */
+ REMOTE_PROC_DOMAIN_EVENT_CONTROL_ERROR = 224, /* skipgen skipgen */
+ REMOTE_PROC_DOMAIN_PIN_VCPU_FLAGS = 225 /* skipgen autogen */
/*
* Notice how the entries are grouped in sets of 10 ?
Index: libvirt/src/remote_protocol-structs
===================================================================
--- libvirt.orig/src/remote_protocol-structs
+++ libvirt/src/remote_protocol-structs
@@ -529,6 +529,15 @@ struct remote_domain_pin_vcpu_args {
char * cpumap_val;
} cpumap;
};
+struct remote_domain_pin_vcpu_flags_args {
+ remote_nonnull_domain dom;
+ int vcpu;
+ struct {
+ u_int cpumap_len;
+ char * cpumap_val;
+ } cpumap;
+ u_int flags;
+};
struct remote_domain_get_vcpus_args {
remote_nonnull_domain dom;
int maxinfo;
Index: libvirt/src/remote/remote_driver.c
===================================================================
--- libvirt.orig/src/remote/remote_driver.c
+++ libvirt/src/remote/remote_driver.c
@@ -6259,6 +6259,7 @@ static virDriver remote_driver = {
.domainSetVcpusFlags = remoteDomainSetVcpusFlags, /* 0.8.5 */
.domainGetVcpusFlags = remoteDomainGetVcpusFlags, /* 0.8.5 */
.domainPinVcpu = remoteDomainPinVcpu, /* 0.3.0 */
+ .domainPinVcpuFlags = remoteDomainPinVcpuFlags, /* 0.9.2 */
.domainGetVcpus = remoteDomainGetVcpus, /* 0.3.0 */
.domainGetMaxVcpus = remoteDomainGetMaxVcpus, /* 0.3.0 */
.domainGetSecurityLabel = remoteDomainGetSecurityLabel, /* 0.6.1 */
Index: libvirt/daemon/remote.c
===================================================================
--- libvirt.orig/daemon/remote.c
+++ libvirt/daemon/remote.c
@@ -1277,6 +1277,48 @@ cleanup:
}
static int
+remoteDispatchDomainPinVcpuFlags(struct qemud_server *server
ATTRIBUTE_UNUSED,
+ struct qemud_client *client
ATTRIBUTE_UNUSED,
+ virConnectPtr conn,
+ remote_message_header *hdr
ATTRIBUTE_UNUSED,
+ remote_error *rerr,
+ remote_domain_pin_vcpu_flags_args *args,
+ void *ret ATTRIBUTE_UNUSED)
+{
+ virDomainPtr dom = NULL;
+ int rv = -1;
+
+ if (!conn) {
+ virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not
open"));
+ goto cleanup;
+ }
+
+ if (!(dom = get_nonnull_domain(conn, args->dom)))
+ goto cleanup;
+
+ if (args->cpumap.cpumap_len > REMOTE_CPUMAP_MAX) {
+ virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("cpumap_len >
REMOTE_CPUMAP_MAX"));
+ goto cleanup;
+ }
+
+ if (virDomainPinVcpuFlags(dom,
+ args->vcpu,
+ (unsigned char *) args->cpumap.cpumap_val,
+ args->cpumap.cpumap_len,
+ args->flags) < 0)
+ goto cleanup;
+
+ rv = 0;
+
+cleanup:
+ if (rv < 0)
+ remoteDispatchError(rerr);
+ if (dom)
+ virDomainFree(dom);
+ return rv;
+}
+
+static int
remoteDispatchDomainGetMemoryParameters(struct qemud_server *server
ATTRIBUTE_UNUSED,
struct qemud_client *client
13 years, 5 months
[libvirt] [PATCH v4 4/4] vcpupin: add the new option to "virsh vcpupin" command
by Taku Izumi
This patch adds the new option (--live, --config and --current) to
"virsh vcpupin" command. The behavior of above aption is the same as
that of "virsh setmem", "virsh setvcpus", and whatnot.
When the --config option is specified, the command affects a persistent
domain,
while --live option is specified, it affects a running (live) domain.
The --current option cannot be used with --config or --live at the same
time,
and when --current is specified, it affects a "current" domain.
Signed-off-by: Taku Izumi <izumi.taku(a)jp.fujitsu.com>
---
tools/virsh.c | 33 +++++++++++++++++++++++++++++++--
tools/virsh.pod | 8 +++++++-
2 files changed, 38 insertions(+), 3 deletions(-)
Index: libvirt/tools/virsh.c
===================================================================
--- libvirt.orig/tools/virsh.c
+++ libvirt/tools/virsh.c
@@ -2929,6 +2929,9 @@ static const vshCmdOptDef opts_vcpupin[]
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"vcpu", VSH_OT_INT, VSH_OFLAG_REQ, N_("vcpu number")},
{"cpulist", VSH_OT_DATA, VSH_OFLAG_REQ, N_("host cpu number(s) (comma
separated)")},
+ {"config", VSH_OT_BOOL, 0, N_("affect next boot")},
+ {"live", VSH_OT_BOOL, 0, N_("affect running domain")},
+ {"current", VSH_OT_BOOL, 0, N_("affect current domain")},
{NULL, 0, 0, NULL}
};
@@ -2945,6 +2948,26 @@ cmdVcpupin(vshControl *ctl, const vshCmd
int cpumaplen;
int i;
enum { expect_num, expect_num_or_comma } state;
+ int config = vshCommandOptBool(cmd, "config");
+ int live = vshCommandOptBool(cmd, "live");
+ int current = vshCommandOptBool(cmd, "current");
+ int flags = 0;
+
+ if (current) {
+ if (live || config) {
+ vshError(ctl, "%s", _("--current must be specified
exclusively"));
+ return false;
+ }
+ flags = VIR_DOMAIN_AFFECT_CURRENT;
+ } else {
+ if (config)
+ flags |= VIR_DOMAIN_AFFECT_CONFIG;
+ if (live)
+ flags |= VIR_DOMAIN_AFFECT_LIVE;
+ /* neither option is specified */
+ if (!live && !config)
+ flags = -1;
+ }
if (!vshConnectionUsability(ctl, ctl->conn))
return false;
@@ -3041,8 +3064,14 @@ cmdVcpupin(vshControl *ctl, const vshCmd
cpulist++;
} while (cpulist);
- if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) {
- ret = false;
+ if (flags == -1) {
+ if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) {
+ ret = false;
+ }
+ } else {
+ if (virDomainPinVcpuFlags(dom, vcpu, cpumap, cpumaplen, flags) !=
0) {
+ ret = false;
+ }
}
VIR_FREE(cpumap);
Index: libvirt/tools/virsh.pod
===================================================================
--- libvirt.orig/tools/virsh.pod
+++ libvirt/tools/virsh.pod
@@ -790,10 +790,16 @@ values; these two flags cannot both be s
Returns basic information about the domain virtual CPUs, like the number of
vCPUs, the running time, the affinity to physical processors.
-=item B<vcpupin> I<domain-id> I<vcpu> I<cpulist>
+=item B<vcpupin> I<domain-id> I<vcpu> I<cpulist> optional I<--live>
I<--config>
+I<--current>
Pin domain VCPUs to host physical CPUs. The I<vcpu> number must be provided
and I<cpulist> is a comma separated list of physical CPU numbers.
+If I<--live> is specified, affect a running guest.
+If I<--config> is specified, affect the next boot of a persistent guest.
+If I<--current> is specified, affect the current guest state.
+Both I<--live> and I<--config> flags may be given, but I<--current> is
exclusive.
+If no flag is specified, behavior is different depending on hypervisor.
=item B<vncdisplay> I<domain-id>
13 years, 5 months
[libvirt] [PATCH v4 1/4] vcpupin: introduce a new libvirt API
by Taku Izumi
This patch introduces a new libvirt API (virDomainPinVcpuFlags).
Signd-off-by: Taku Izumi <izumi.taku(a)jp.fujitsu.com>
---
include/libvirt/libvirt.h.in | 5 ++
src/driver.h | 7 +++
src/libvirt.c | 76
+++++++++++++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 1
4 files changed, 89 insertions(+)
Index: libvirt/include/libvirt/libvirt.h.in
===================================================================
--- libvirt.orig/include/libvirt/libvirt.h.in
+++ libvirt/include/libvirt/libvirt.h.in
@@ -1049,6 +1049,11 @@ int virDomainPinVcpu
unsigned int vcpu,
unsigned char *cpumap,
int maplen);
+int virDomainPinVcpuFlags (virDomainPtr domain,
+ unsigned int vcpu,
+ unsigned char *cpumap,
+ int maplen,
+ unsigned int flags);
/**
* VIR_USE_CPU:
Index: libvirt/src/driver.h
===================================================================
--- libvirt.orig/src/driver.h
+++ libvirt/src/driver.h
@@ -230,6 +230,12 @@ typedef int
unsigned char *cpumap,
int maplen);
typedef int
+ (*virDrvDomainPinVcpuFlags) (virDomainPtr domain,
+ unsigned int vcpu,
+ unsigned char *cpumap,
+ int maplen,
+ unsigned int flags);
+typedef int
(*virDrvDomainGetVcpus) (virDomainPtr domain,
virVcpuInfoPtr info,
int maxinfo,
@@ -671,6 +677,7 @@ struct _virDriver {
virDrvDomainSetVcpusFlags domainSetVcpusFlags;
virDrvDomainGetVcpusFlags domainGetVcpusFlags;
virDrvDomainPinVcpu domainPinVcpu;
+ virDrvDomainPinVcpuFlags domainPinVcpuFlags;
virDrvDomainGetVcpus domainGetVcpus;
virDrvDomainGetMaxVcpus domainGetMaxVcpus;
virDrvDomainGetSecurityLabel domainGetSecurityLabel;
Index: libvirt/src/libvirt.c
===================================================================
--- libvirt.orig/src/libvirt.c
+++ libvirt/src/libvirt.c
@@ -6709,6 +6709,82 @@ error:
}
/**
+ * virDomainPinVcpuFlags:
+ * @domain: pointer to domain object, or NULL for Domain0
+ * @vcpu: virtual CPU number
+ * @cpumap: 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.
+ * @maplen: number of bytes in cpumap, from 1 up to size of CPU map in
+ * underlying virtualization system (Xen...).
+ * If maplen < size, missing bytes are set to zero.
+ * If maplen > size, failure code is returned.
+ * @flags: bitwise-OR of virDomainModificationImpac
+ *
+ * Dynamically change the real CPUs which can be allocated to a virtual
CPU.
+ * This function requires privileged access to the hypervisor.
+ *
+ * @flags may include VIR_DOMAIN_PIN_VCPU_LIVE or
VIR_DOMAIN_PIN_VCPU_CONFIG.
+ * Both flags may be set.
+ * If VIR_DOMAIN_PIN_VCPU_LIVE is set, the change affects a running domain
+ * and may fail if domain is not alive.
+ * If VIR_DOMAIN_PIN_VCPU_CONFIG is set, the change affects persistent
state,
+ * and will fail for transient domains. If neither flag is specified (that
is,
+ * @flags is VIR_DOMAIN_PIN_VCPU_CURRENT), then an inactive domain modifies
+ * persistent setup, while an active domain is hypervisor-dependent on
whether
+ * just live or both live and persistent state is changed.
+ * Not all hypervisors can support all flag combinations.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ *
+ */
+int
+virDomainPinVcpuFlags(virDomainPtr domain, unsigned int vcpu,
+ unsigned char *cpumap, int maplen, unsigned int
flags)
+{
+ virConnectPtr conn;
+
+ VIR_DOMAIN_DEBUG(domain, "vcpu=%u, cpumap=%p, maplen=%d, flags=%u",
+ vcpu, cpumap, maplen, flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+ virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ if (domain->conn->flags & VIR_CONNECT_RO) {
+ virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ goto error;
+ }
+
+ if ((vcpu > 32000) || (cpumap == NULL) || (maplen < 1)) {
+ virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+ goto error;
+ }
+
+ conn = domain->conn;
+
+ if (conn->driver->domainPinVcpuFlags) {
+ int ret;
+ ret = conn->driver->domainPinVcpuFlags (domain, vcpu, cpumap,
maplen, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ virDispatchError(domain->conn);
+ return -1;
+
+}
+
+/**
* virDomainGetVcpus:
* @domain: pointer to domain object, or NULL for Domain0
* @info: pointer to an array of virVcpuInfo structures (OUT)
Index: libvirt/src/libvirt_public.syms
===================================================================
--- libvirt.orig/src/libvirt_public.syms
+++ libvirt/src/libvirt_public.syms
@@ -448,6 +448,7 @@ LIBVIRT_0.9.2 {
virInterfaceChangeBegin;
virInterfaceChangeCommit;
virInterfaceChangeRollback;
+ virDomainPinVcpuFlags;
} LIBVIRT_0.9.0;
# .... define new API here using predicted next version number ....
13 years, 5 months
[libvirt] [PATCH 4/4] vcpupin: add vcpupin resetting feature to qemu driver
by Taku Izumi
Pinning to all physical cpus means resetting, hence it is preferable to
delete vcpupin setting of XML.
This patch changes qemu driver to delete vcpupin setting by invoking
virDomainVcpupinDel API when pinning the specified virtual cpu to
all host physical cpus.
Signed-off-by: Taku Izumi <izumi.taku(a)jp.fujitsu.com>
---
src/qemu/qemu_driver.c | 64
+++++++++++++++++++++++++++++++++++--------------
1 file changed, 46 insertions(+), 18 deletions(-)
Index: libvirt/src/qemu/qemu_driver.c
===================================================================
--- libvirt.orig/src/qemu/qemu_driver.c
+++ libvirt/src/qemu/qemu_driver.c
@@ -2894,6 +2894,7 @@ qemudDomainPinVcpuFlags(virDomainPtr dom
int ret = -1;
bool isActive;
qemuDomainObjPrivatePtr priv;
+ bool canResetting = true;
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
VIR_DOMAIN_AFFECT_CONFIG, -1);
@@ -2944,15 +2945,23 @@ qemudDomainPinVcpuFlags(virDomainPtr dom
goto cleanup;
}
- if (flags & VIR_DOMAIN_AFFECT_LIVE) {
-
- if (nodeGetInfo(dom->conn, &nodeinfo) < 0)
- goto cleanup;
+ if (nodeGetInfo(dom->conn, &nodeinfo) < 0)
+ goto cleanup;
+ hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
+ maxcpu = maplen * 8;
+ if (maxcpu > hostcpus)
+ maxcpu = hostcpus;
+ /* pinning to all physical cpus means resetting,
+ * so check if we can reset setting.
+ */
+ for (int pcpu = 0; pcpu < hostcpus; pcpu++) {
+ if ((cpumap[pcpu/8] & (1 << (pcpu % 8))) == 0) {
+ canResetting = false;
+ break;
+ }
+ }
- hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
- maxcpu = maplen * 8;
- if (maxcpu > hostcpus)
- maxcpu = hostcpus;
+ if (flags & VIR_DOMAIN_AFFECT_LIVE) {
if (priv->vcpupids != NULL) {
if (virProcessInfoSetAffinity(priv->vcpupids[vcpu],
@@ -2964,23 +2973,42 @@ qemudDomainPinVcpuFlags(virDomainPtr dom
goto cleanup;
}
- if (virDomainVcpupinAdd(vm->def, cpumap, maplen, vcpu) < 0) {
- qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("failed to update or add vcpupin xml of "
- "a running domain"));
- goto cleanup;
+ if (canResetting) {
+ if (virDomainVcpupinDel(vm->def, vcpu) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to delete vcpupin xml of "
+ "a running domain"));
+ goto cleanup;
+ }
+ } else {
+ if (virDomainVcpupinAdd(vm->def, cpumap, maplen, vcpu) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to update or add vcpupin xml of "
+ "a running domain"));
+ goto cleanup;
+ }
}
}
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
- if (virDomainVcpupinAdd(persistentDef, cpumap, maplen, vcpu) < 0) {
- qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("failed to update or add vcpupin xml of "
- "a persistent domain"));
- goto cleanup;
+ if (canResetting) {
+ if (virDomainVcpupinDel(persistentDef, vcpu) < 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to delete vcpupin xml of "
+ "a persistent domain"));
+ goto cleanup;
+ }
+ } else {
+ if (virDomainVcpupinAdd(persistentDef, cpumap, maplen, vcpu) <
0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("failed to update or add vcpupin xml of "
+ "a persistent domain"));
+ goto cleanup;
+ }
}
+
ret = virDomainSaveConfig(driver->configDir, persistentDef);
goto cleanup;
}
13 years, 5 months
[libvirt] [PATCH 3/4] vcpupin: add virDomainVcpupinDel function
by Taku Izumi
This patch add the private API (virDomainVcpupinDel).
This API can delete the vcpupin setting of a specified virtual cpu.
Signed-off-by: Taku Izumi <izumi.taku(a)jp.fujitsu.com>
---
src/conf/domain_conf.c | 39 +++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 2 ++
src/libvirt_private.syms | 1 +
3 files changed, 42 insertions(+)
Index: libvirt/src/conf/domain_conf.c
===================================================================
--- libvirt.orig/src/conf/domain_conf.c
+++ libvirt/src/conf/domain_conf.c
@@ -8126,6 +8126,45 @@ cleanup:
return -1;
}
+int
+virDomainVcpupinDel(virDomainDefPtr def, int vcpu)
+{
+ int n;
+ bool deleted = false;
+ virDomainVcpupinDefPtr *vcpupin_list = def->cputune.vcpupin;
+
+ /* No vcpupin exists yet */
+ if (!def->cputune.nvcpupin) {
+ return 0;
+ }
+
+ for (n = 0; n < def->cputune.nvcpupin; n++) {
+ if (vcpupin_list[n]->vcpuid == vcpu) {
+ VIR_FREE(vcpupin_list[n]->cpumask);
+ VIR_FREE(vcpupin_list[n]);
+ memmove(&vcpupin_list[n],
+ &vcpupin_list[n+1],
+ (def->cputune.nvcpupin - n - 1) *
sizeof(virDomainVcpupinDef *));
+ deleted = true;
+ break;
+ }
+ }
+
+ if (!deleted)
+ return 0;
+
+ if (--def->cputune.nvcpupin == 0) {
+ virDomainVcpupinDefFree(def->cputune.vcpupin, 0);
+ } else {
+ if (VIR_REALLOC_N(def->cputune.vcpupin, def->cputune.nvcpupin) < 0)
{
+ virReportOOMError();
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
static int
virDomainLifecycleDefFormat(virBufferPtr buf,
int type,
Index: libvirt/src/conf/domain_conf.h
===================================================================
--- libvirt.orig/src/conf/domain_conf.h
+++ libvirt/src/conf/domain_conf.h
@@ -1381,6 +1381,8 @@ int virDomainVcpupinAdd(virDomainDefPtr
int maplen,
int vcpu);
+int virDomainVcpupinDel(virDomainDefPtr def, int vcpu);
+
int virDomainDiskIndexByName(virDomainDefPtr def, const char *name);
int virDomainDiskInsert(virDomainDefPtr def,
virDomainDiskDefPtr disk);
Index: libvirt/src/libvirt_private.syms
===================================================================
--- libvirt.orig/src/libvirt_private.syms
+++ libvirt/src/libvirt_private.syms
@@ -360,6 +360,7 @@ virDomainTimerTickpolicyTypeToString;
virDomainTimerTrackTypeFromString;
virDomainTimerTrackTypeToString;
virDomainVcpupinAdd;
+virDomainVcpupinDel;
virDomainVcpupinFindByVcpu;
virDomainVcpupinIsDuplicate;
virDomainVideoDefFree;
13 years, 5 months
[libvirt] [PATCH 2/4] vcpupin: add reset option to virsh vcpupin command
by Taku Izumi
When resetting vcpupin setting, we have to specify all host physical
cpus as a cpulist parameter of virsh vcpupin command. It's a little
tedious.
This patch changes to allow to receive the special keyword 'r' as a cpulist
parameter of virsh vcpupin command when resetting vcpupin setting.
If you set the following:
# virsh vcpupin VM 0 r
the vcpu0 will be pinned to all physical cpus.
Signed-off-by: Taku Izumi <izumi.taku(a)jp.fujitsu.com>
---
tools/virsh.c | 7 ++++++-
tools/virsh.pod | 2 ++
2 files changed, 8 insertions(+), 1 deletion(-)
Index: libvirt/tools/virsh.c
===================================================================
--- libvirt.orig/tools/virsh.c
+++ libvirt/tools/virsh.c
@@ -3010,8 +3010,13 @@ cmdVcpupin(vshControl *ctl, const vshCmd
/* Parse cpulist */
cur = cpulist;
- if (*cur == 0)
+ if (*cur == 0) {
goto parse_error;
+ } else if (*cur == 'r') {
+ for (cpu = 0; cpu < maxcpu; cpu++)
+ VIR_USE_CPU(cpumap, cpu);
+ *cur = 0;
+ }
while (*cur != 0) {
Index: libvirt/tools/virsh.pod
===================================================================
--- libvirt.orig/tools/virsh.pod
+++ libvirt/tools/virsh.pod
@@ -797,6 +797,8 @@ Pin domain VCPUs to host physical CPUs.
and I<cpulist> is a list of physical CPU numbers. Its syntax is a comma
separated list and a special markup using '-' and '^' (ex. '0-4', '0-3,^2')
can
also be allowed. The '-' denotes the range and the '^' denotes exclusive.
+If you want to reset vcpupin setting, that is, to pin vcpu all physical
cpus,
+simply specify 'r' as a cpulist.
If I<--live> is specified, affect a running guest.
If I<--config> is specified, affect the next boot of a persistent guest.
If I<--current> is specified, affect the current guest state.
13 years, 5 months
[libvirt] [PATCH 1/4] vcpupin: improve vcpupin definition of virsh vcpupin
by Taku Izumi
When using vcpupin command, we have to speficy comma-separated list as
cpulist,
but this is tedious in case the number of phsycal cpus is large.
This patch improves this by introducing special markup "-" and "^" which are
similar to XML schema of "cpuset" attribute.
That is:
# virsh vcpupin Guest 0 0-15,^8
is identical to
# virsh vcpupin Guest 0 0,1,2,3,4,5,6,7,9,10,11,12,13,14,15
NOTE: The expression is sequencially evaluated, so "0-15,^8" is not
identical
to "^8,0-15".
Signed-off-by: Taku Izumi <izumi.taku(a)jp.fujitsu.com>
---
tools/virsh.c | 125
+++++++++++++++++++++++++++++++-------------------------
tools/virsh.pod | 4 +
2 files changed, 73 insertions(+), 56 deletions(-)
Index: libvirt/tools/virsh.c
===================================================================
--- libvirt.orig/tools/virsh.c
+++ libvirt/tools/virsh.c
@@ -2946,8 +2946,9 @@ cmdVcpupin(vshControl *ctl, const vshCmd
bool ret = true;
unsigned char *cpumap;
int cpumaplen;
- int i;
- enum { expect_num, expect_num_or_comma } state;
+ int i, cpu, lastcpu, maxcpu;
+ bool unuse = false;
+ char *cur;
int config = vshCommandOptBool(cmd, "config");
int live = vshCommandOptBool(cmd, "live");
int current = vshCommandOptBool(cmd, "current");
@@ -3003,66 +3004,74 @@ cmdVcpupin(vshControl *ctl, const vshCmd
return false;
}
- /* Check that the cpulist parameter is a comma-separated list of
- * numbers and give an intelligent error message if not.
- */
- if (cpulist[0] == '\0') {
- vshError(ctl, "%s", _("cpulist: Invalid format. Empty string."));
- virDomainFree (dom);
- return false;
- }
+ maxcpu = VIR_NODEINFO_MAXCPUS(nodeinfo);
+ cpumaplen = VIR_CPU_MAPLEN(maxcpu);
+ cpumap = vshCalloc(ctl, 0, cpumaplen);
+
+ /* Parse cpulist */
+ cur = cpulist;
+ if (*cur == 0)
+ goto parse_error;
+
+ while (*cur != 0) {
+
+ /* the char '^' denotes exclusive */
+ if (*cur == '^') {
+ cur++;
+ unuse = true;
+ }
+
+ /* parse physical CPU number */
+ if (!c_isdigit(*cur))
+ goto parse_error;
+ cpu = virParseNumber(&cur);
+ if (cpu < 0) {
+ goto parse_error;
+ }
+ if (cpu >= maxcpu) {
+ vshError(ctl, _("Physical CPU %d doesn't exist."), cpu);
+ goto parse_error;
+ }
+ virSkipSpaces(&cur);
- state = expect_num;
- for (i = 0; cpulist[i]; i++) {
- switch (state) {
- case expect_num:
- if (!c_isdigit (cpulist[i])) {
- vshError(ctl, _("cpulist: %s: Invalid format. Expecting "
- "digit at position %d (near '%c')."),
- cpulist, i, cpulist[i]);
- virDomainFree (dom);
- return false;
+ if ((*cur == ',') || (*cur == 0)) {
+ if (unuse) {
+ VIR_UNUSE_CPU(cpumap, cpu);
+ } else {
+ VIR_USE_CPU(cpumap, cpu);
}
- state = expect_num_or_comma;
- break;
- case expect_num_or_comma:
- if (cpulist[i] == ',')
- state = expect_num;
- else if (!c_isdigit (cpulist[i])) {
- vshError(ctl, _("cpulist: %s: Invalid format. Expecting "
- "digit or comma at position %d (near
'%c')."),
- cpulist, i, cpulist[i]);
- virDomainFree (dom);
- return false;
+ } else if (*cur == '-') {
+ /* the char '-' denotes range */
+ if (unuse) {
+ goto parse_error;
+ }
+ cur++;
+ virSkipSpaces(&cur);
+ /* parse the end of range */
+ lastcpu = virParseNumber(&cur);
+ if (lastcpu < cpu) {
+ goto parse_error;
+ }
+ if (lastcpu >= maxcpu) {
+ vshError(ctl, _("Physical CPU %d doesn't exist."), maxcpu);
+ goto parse_error;
+ }
+ for (i = cpu; i <= lastcpu; i++) {
+ VIR_USE_CPU(cpumap, i);
}
+ virSkipSpaces(&cur);
}
- }
- if (state == expect_num) {
- vshError(ctl, _("cpulist: %s: Invalid format. Trailing comma "
- "at position %d."),
- cpulist, i);
- virDomainFree (dom);
- return false;
- }
- cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
- cpumap = vshCalloc(ctl, 1, cpumaplen);
-
- do {
- unsigned int cpu = atoi(cpulist);
-
- if (cpu < VIR_NODEINFO_MAXCPUS(nodeinfo)) {
- VIR_USE_CPU(cpumap, cpu);
+ if (*cur == ',') {
+ cur++;
+ virSkipSpaces(&cur);
+ unuse = false;
+ } else if (*cur == 0) {
+ break;
} else {
- vshError(ctl, _("Physical CPU %d doesn't exist."), cpu);
- VIR_FREE(cpumap);
- virDomainFree(dom);
- return false;
+ goto parse_error;
}
- cpulist = strchr(cpulist, ',');
- if (cpulist)
- cpulist++;
- } while (cpulist);
+ }
if (flags == -1) {
if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) {
@@ -3074,9 +3083,15 @@ cmdVcpupin(vshControl *ctl, const vshCmd
}
}
+cleanup:
VIR_FREE(cpumap);
virDomainFree(dom);
return ret;
+
+parse_error:
+ vshError(ctl, "%s", _("cpulist: Invalid format."));
+ ret = false;
+ goto cleanup;
}
/*
Index: libvirt/tools/virsh.pod
===================================================================
--- libvirt.orig/tools/virsh.pod
+++ libvirt/tools/virsh.pod
@@ -794,7 +794,9 @@ vCPUs, the running time, the affinity to
I<--current>
Pin domain VCPUs to host physical CPUs. The I<vcpu> number must be provided
-and I<cpulist> is a comma separated list of physical CPU numbers.
+and I<cpulist> is a list of physical CPU numbers. Its syntax is a comma
+separated list and a special markup using '-' and '^' (ex. '0-4', '0-3,^2')
can
+also be allowed. The '-' denotes the range and the '^' denotes exclusive.
If I<--live> is specified, affect a running guest.
If I<--config> is specified, affect the next boot of a persistent guest.
If I<--current> is specified, affect the current guest state.
13 years, 5 months