[Libvir] PATCH: Support <on_reboot>poweroff</on_reboot> in QEMU/KVM
by Daniel P. Berrange
Currently in the QEMU driver we don't support any of the customizable
shutdown operation behaviour elements in the XML. ie
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
This was principally because we don't particularly have a good way to actually
implement some of them. Well, QEMU 0.9.0 added a -no-reboot flag which could
be used to force a 'reboot' inside the guest to behaviour like a shutdown.
So we can now support at least the <on_reboot> element with 'destroy' or
'restart' behaviours.
This turns out to be critical for provisioning guests, because the initial
install uses a different VM configs, from later runtime, eg boot from ISO,
vs boot from Disk.
The attached patch adds support for accepting <on_reboot> when defining new
domain configs. When dumping XML we will also add <on_poweroff> and
<on_crash> elements to at least indicate what our behaviour is, though the
user can't customize them.
In doing this patch I had to change the way we read data from QEMU. We
were over the 4096 buffer size, and also in some cases we were getting a
short read which meant we lost the end of the help message. We now have
a buffer of 8k (max QEMU help is 5k currently), and read in a loop until
EOF or 8k is hit.
Dan.
--
|=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=|
|=- Perl modules: http://search.cpan.org/~danberr/ -=|
|=- Projects: http://freshmeat.net/~danielpb/ -=|
|=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
17 years, 6 months
[Libvir] Remote patch, 2007-05-01
by Richard W.M. Jones
This is a patch against CVS -- in other words, it includes the two
previous patches I sent to this list today.
Compared to the previous patch, it's just bug fixes and testing.
Sorry, these patches are getting rather huge. Unfortunately I can't see
any sensible way to split it up. For the most part you either have
remote support or you don't.
Rich.
--
Emerging Technologies, Red Hat http://et.redhat.com/~rjones/
64 Baker Street, London, W1U 7DF Mobile: +44 7866 314 421
Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod
Street, Windsor, Berkshire, SL4 1TE, United Kingdom.
Registered in England and Wales under Company Registration No. 3798903
Directors: Michael Cunningham (USA), Charlie Peters (USA) and David
Owens (Ireland)
17 years, 6 months
[Libvir] RFC: Behaviour of virConnectSave, Restore and CoreDump in the remote case
by Richard W.M. Jones
virDomainSave (for example) is currently defined like this:
/**
* virDomainSave:
* @domain: a domain object
* @to: path for the output file
*
* This method will suspend a domain and save its memory contents to
* a file on disk. After the call, if successful, the domain is not
* listed as running anymore (this may be a problem).
* Use virDomainRestore() to restore a domain after saving.
*
* Returns 0 in case of success and -1 in case of failure.
*/
In the remote case there are, I think, three possible things that this
call could do:
(A) Copy the image over the network connection to save it locally
This is possibly the most "authentic" option. Callers using remote can
specify a local path and the image file will appear at that path,
locally, making the remote case reasonably transparent.
However image files are usually pretty large, and copying them over a
network connection could be slow. In particular the network connection
may be over loopback -- eg. in the case where we are allowing ordinary
users to connect to a locally running libvirtd with elevated
priviledges. (It's quite hard in general to determine if remote is
really connected to a different machine, eg. think about the case where
we are using ssh tunnels).
In some ways this is the most secure option. The image or core dump is
written by the user process, so there is no way to get a daemon with
elevated privs to write over a file in /etc for example.
(B) Save it remotely
Remote isn't transparent. We save it remotely.
We could consider adding a virDomainSaveLocal API call for the case when
we really want to save it locally.
(C) Do nothing / present an error
Recognise that remote cannot deal with this at the moment, and don't
implement this call. Perhaps come back to it later in the context of
remote storage management.
Opinions?
Rich.
--
Emerging Technologies, Red Hat http://et.redhat.com/~rjones/
64 Baker Street, London, W1U 7DF Mobile: +44 7866 314 421
Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod
Street, Windsor, Berkshire, SL4 1TE, United Kingdom.
Registered in England and Wales under Company Registration No. 3798903
Directors: Michael Cunningham (USA), Charlie Peters (USA) and David
Owens (Ireland)
17 years, 6 months
[Libvir] [PATCH] increase storage domains of a definition file
by S.Sakamoto
Hi,
When I install by virt-intall with long command
(e.g."# /usr/sbin/virt-install --name testvm --ram 350 --vcpus 2 --file /root/test.img --file-size 1 --file /root/tmp02.img --
file-size 1 --file /root/tmp03.img --file-size 1 --file /root/tmp04.img --file-size 1 --file /root/tmp05.img --file-size
1 --file /root/tmp06.img --file-size 1 --file /root/tmp07.img --file-size 1 --file /root/tmp08.img --file-size 1 --file
/root/tmp09.img --file-size 1 --file /root/tmp10.img --file-size 1 --file /root/tmp11.img --file-size 1 --file
/root/tmp12.img --file-size 1 --file /root/tmp13.img --file-size 1 --file /root/tmp14.img --file-size 1 --file
/root/tmp15.img --file-size 1 --file /root/tmp16.img --file-size 1 --vnc --paravirt --location ftp://xx.xx.xx.xx/rhel5ga_x86 --noautoconsole --
debug"),
put out "abort".
Because a definition file is long, it overflows from buffer.
So, this patch increase buffer size.
Signed-off-by: Shigeki Sakamoto <fj0588di(a)aa.jp.fujitsu.com>
Thanks,
Shigeki Sakamoto.
Index: src/internal.h
===================================================================
RCS file: /data/cvs/libvirt/src/internal.h,v
retrieving revision 1.37
diff -u -p -r1.37 internal.h
--- src/internal.h 4 Apr 2007 14:19:49 -0000 1.37
+++ src/internal.h 19 Apr 2007 11:01:12 -0000
@@ -106,6 +106,11 @@ extern "C" {
#define VIR_CONNECT_RO 1
/**
+ * buffer size for definition file
+ */
+#define VIR_XML_STRING_BUFLEN (1024 + PATH_MAX * 16 + FILENAME_MAX * 16)
+
+/**
* _virConnect:
*
* Internal structure associated to a connection
Index: src/xend_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xend_internal.c,v
retrieving revision 1.109
diff -u -p -r1.109 xend_internal.c
--- src/xend_internal.c 13 Apr 2007 14:08:38 -0000 1.109
+++ src/xend_internal.c 19 Apr 2007 11:01:16 -0000
@@ -587,7 +587,7 @@ static int
xend_op_ext2(virConnectPtr xend, const char *path, char *error,
size_t n_error, const char *key, va_list ap)
{
- char ops[1024];
+ char ops[VIR_XML_STRING_BUFLEN];
const char *k = key, *v;
int offset = 0;
Index: src/xml.c
===================================================================
RCS file: /data/cvs/libvirt/src/xml.c,v
retrieving revision 1.72
diff -u -p -r1.72 xml.c
--- src/xml.c 13 Apr 2007 00:43:57 -0000 1.72
+++ src/xml.c 19 Apr 2007 11:01:20 -0000
@@ -1165,7 +1165,7 @@ virDomainParseXMLDesc(virConnectPtr conn
{
xmlDocPtr xml = NULL;
xmlNodePtr node;
- char *ret = NULL, *nam = NULL;
+ char *nam = NULL;
virBuffer buf;
xmlChar *prop;
xmlParserCtxtPtr pctxt;
@@ -1182,10 +1182,9 @@ virDomainParseXMLDesc(virConnectPtr conn
if (name != NULL)
*name = NULL;
- ret = malloc(1000);
- if (ret == NULL)
+ buf.content = malloc(1000);
+ if (buf.content == NULL)
return (NULL);
- buf.content = ret;
buf.size = 1000;
buf.use = 0;
@@ -1376,7 +1375,7 @@ virDomainParseXMLDesc(virConnectPtr conn
else
free(nam);
- return (ret);
+ return (buf.content);
error:
if (nam != NULL)
@@ -1389,8 +1388,8 @@ virDomainParseXMLDesc(virConnectPtr conn
xmlFreeDoc(xml);
if (pctxt != NULL)
xmlFreeParserCtxt(pctxt);
- if (ret != NULL)
- free(ret);
+ if (buf.content != NULL)
+ free(buf.content);
return (NULL);
}
17 years, 6 months
[Libvir] Proposed remote protocol (XDR source file qemud/remote_protocol.x)
by Richard W.M. Jones
Attached are the args (*_args) and return structures (*_ret) for all the
calls covered by the remote protocol, that is to say everything except
Save, Restore and CoreDump (see previous email).
The only problem area are the upper limits imposed on the lengths of
various strings and arrays. The upper limits seem to be required for
safely decoding messages from untrusted sources. Some of them however
would impose limits on such things as the number of CPUs supported, and
perhaps those limits are too low (or too high)? I don't really have any
experience of the sort of huge machines that people might be running
libvirt on.
Rich.
--
Emerging Technologies, Red Hat http://et.redhat.com/~rjones/
64 Baker Street, London, W1U 7DF Mobile: +44 7866 314 421
Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod
Street, Windsor, Berkshire, SL4 1TE, United Kingdom.
Registered in England and Wales under Company Registration No. 3798903
Directors: Michael Cunningham (USA), Charlie Peters (USA) and David
Owens (Ireland)
/* -*- c -*-
* remote_protocol.x: private protocol for communicating between
* remote_internal driver and libvirtd. This protocol is
* internal and may change at any time.
*
* Copyright (C) 2006-2007 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
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Richard Jones <rjones(a)redhat.com>
*/
/* Notes:
*
* (1) The protocol is internal and may change at any time, without
* notice. Do not use it. Instead link to libvirt and use the remote
* driver.
*
* (2) See bottom of this file for a description of the home-brew RPC.
*
* (3) Authentication/encryption is done outside this protocol.
*
* (4) For namespace reasons, all exported names begin 'remote_' or
* 'REMOTE_'. This makes names quite long.
*/
%#include "libvirt/libvirt.h"
/*----- Data types. -----*/
/* Maximum total message size (serialised). */
const REMOTE_MESSAGE_MAX = 262144;
/* Length of long, but not unbounded, strings.
* This is an arbitrary limit designed to stop the decoder from trying
* to allocate unbounded amounts of memory when fed with a bad message.
*/
const REMOTE_STRING_MAX = 65536;
/* A long string, which may NOT be NULL. */
typedef string remote_nonnull_string<REMOTE_STRING_MAX>;
/* A long string, which may be NULL. */
typedef remote_nonnull_string *remote_string;
/* This just places an upper limit on the length of lists of
* domain IDs which may be sent via the protocol.
*/
const REMOTE_DOMAIN_ID_LIST_MAX = 4096;
/* Upper limit on lists of domain names. */
const REMOTE_DOMAIN_NAME_LIST_MAX = 256;
/* Upper limit on cpumap (bytes) passed to virDomainPinVcpu. */
const REMOTE_CPUMAP_MAX = 256;
/* Upper limit on number of info fields returned by virDomainGetVcpus. */
const REMOTE_VCPUINFO_MAX = 2048;
/* Upper limit on cpumaps (bytes) passed to virDomainGetVcpus. */
const REMOTE_CPUMAPS_MAX = 16384;
/* Upper limit on lists of network names. */
const REMOTE_NETWORK_NAME_LIST_MAX = 256;
/* Domains and networks are represented on the wire by (name, UUID). */
typedef opaque remote_uuid[VIR_UUID_BUFLEN];
struct remote_name {
remote_nonnull_string name;
remote_uuid uuid;
};
/* A domain or network which may not be NULL. */
typedef struct remote_name remote_nonnull_domain;
typedef struct remote_name remote_nonnull_network;
/* A domain or network which may be NULL. */
typedef remote_nonnull_domain *remote_domain;
typedef remote_nonnull_network *remote_network;
/* Error message. See <virterror.h> for explanation of fields. */
/* NB. Fields "code", "domain" and "level" are really enums. The
* numeric value should remain compatible between libvirt and
* libvirtd. This means, no changing or reordering the enums as
* defined in <virterror.h> (but we don't do that anyway, for separate
* ABI reasons).
*/
struct remote_error {
int code;
int domain;
remote_string message;
int level;
remote_domain dom;
remote_string str1;
remote_string str2;
remote_string str3;
int int1;
int int2;
remote_network net;
};
/* Wire encoding of virVcpuInfo. */
struct remote_vcpu_info {
unsigned int number;
int state;
unsigned hyper cpu_time;
int cpu;
};
/*----- Calls. -----*/
/* For each call we may have a 'remote_CALL_args' and 'remote_CALL_ret'
* type. These are omitted when they are NULL. The virConnectPtr
* is not passed at all (it is inferred on the remote server from the
* connection). Errors are returned implicitly in the RPC protocol.
*/
struct remote_open_args {
/* NB. "name" might be NULL although in practice you can't
* yet do that using the remote_internal driver.
*/
remote_string name;
int flags;
};
struct remote_get_type_ret {
remote_nonnull_string type;
};
struct remote_get_version_ret {
hyper hv_ver;
};
struct remote_get_max_vcpus_args {
/* The only backend which supports this call is Xen HV, and
* there the type is ignored so it could be NULL.
*/
remote_string type;
};
struct remote_get_max_vcpus_ret {
int max_vcpus;
};
struct remote_node_get_info_ret {
string model<32>;
hyper memory;
int cpus;
int mhz;
int nodes;
int sockets;
int cores;
int threads;
};
struct remote_get_capabilities_ret {
remote_nonnull_string capabilities;
};
struct remote_list_domains_args {
int maxids;
};
struct remote_list_domains_ret {
int ids<REMOTE_DOMAIN_ID_LIST_MAX>;
};
struct remote_num_of_domains_ret {
int num;
};
struct remote_domain_create_linux_args {
remote_nonnull_string xml_desc;
int flags;
};
struct remote_domain_create_linux_ret {
remote_nonnull_domain dom;
};
struct remote_domain_lookup_by_id_args {
int id;
};
struct remote_domain_lookup_by_id_ret {
/* XXX "Not found" semantic is ill-defined. */
remote_nonnull_domain dom;
};
struct remote_domain_lookup_by_uuid_args {
remote_uuid uuid;
};
struct remote_domain_lookup_by_uuid_ret {
/* XXX "Not found" semantic is ill-defined. */
remote_nonnull_domain dom;
};
struct remote_domain_lookup_by_name_args {
remote_nonnull_string name;
};
struct remote_domain_lookup_by_name_ret {
/* XXX "Not found" semantic is ill-defined. */
remote_nonnull_domain dom;
};
struct remote_domain_suspend_args {
remote_nonnull_domain dom;
};
struct remote_domain_resume_args {
remote_nonnull_domain dom;
};
struct remote_domain_shutdown_args {
remote_nonnull_domain dom;
};
struct remote_domain_reboot_args {
remote_nonnull_domain dom;
int flags;
};
struct remote_domain_destroy_args {
remote_nonnull_domain dom;
};
struct remote_domain_get_os_type_args {
remote_nonnull_domain dom;
};
struct remote_domain_get_os_type_ret {
remote_nonnull_string type;
};
struct remote_domain_get_max_memory_args {
remote_nonnull_domain dom;
};
struct remote_domain_get_max_memory_ret {
unsigned hyper memory;
};
struct remote_domain_set_max_memory_args {
remote_nonnull_domain dom;
unsigned hyper memory;
};
struct remote_domain_set_memory_args {
remote_nonnull_domain dom;
unsigned hyper memory;
};
struct remote_domain_get_info_args {
remote_nonnull_domain dom;
};
struct remote_domain_get_info_ret {
unsigned char state;
unsigned hyper max_mem;
unsigned hyper memory;
unsigned short nr_virt_cpu;
/* XXX cpu_time is declared as unsigned long long */
unsigned hyper cpu_time;
};
/* XXX Save, Restore, CoreDump not yet implemented because we
* don't know where we will write the images.
*/
struct remote_domain_dump_xml_args {
remote_nonnull_domain dom;
int flags;
};
struct remote_domain_dump_xml_ret {
remote_nonnull_string xml;
};
struct remote_domain_list_defined_domains_args {
int maxnames;
};
struct remote_domain_list_defined_domains_ret {
remote_nonnull_string names<REMOTE_DOMAIN_NAME_LIST_MAX>;
};
struct remote_domain_num_of_defined_domains_ret {
int num;
};
struct remote_domain_create_args {
remote_nonnull_domain dom;
};
struct remote_domain_define_xml_args {
remote_nonnull_string xml;
};
struct remote_domain_define_xml_ret {
remote_nonnull_domain dom;
};
struct remote_domain_undefine_args {
remote_nonnull_domain dom;
};
struct remote_domain_set_vcpus_args {
int nvcpus;
};
struct remote_domain_pin_vcpu_args {
int vcpu;
opaque cpumap<REMOTE_CPUMAP_MAX>;
};
struct remote_domain_get_vcpus_args {
remote_nonnull_domain dom;
int maxinfo;
int maplen;
};
struct remote_domain_get_vcpus_ret {
remote_vcpu_info info<REMOTE_VCPUINFO_MAX>;
opaque cpumaps<REMOTE_CPUMAPS_MAX>;
};
struct remote_domain_get_max_vcpus_args {
remote_nonnull_domain dom;
};
struct remote_domain_get_max_vcpus_ret {
int num;
};
struct remote_domain_attach_device_args {
remote_nonnull_domain dom;
remote_nonnull_string xml;
};
struct remote_domain_detach_device_args {
remote_nonnull_domain dom;
remote_nonnull_string xml;
};
struct remote_domain_get_autostart_args {
remote_nonnull_domain dom;
};
struct remote_domain_get_autostart_ret {
int autostart;
};
struct remote_domain_set_autostart_args {
remote_nonnull_domain dom;
int autostart;
};
/* Network calls: */
struct remote_num_of_networks_ret {
int num;
};
struct remote_list_networks_args {
int maxnames;
};
struct remote_list_networks_ret {
remote_nonnull_string names<REMOTE_NETWORK_NAME_LIST_MAX>;
};
struct remote_num_of_defined_networks_ret {
int num;
};
struct remote_list_defined_networks_args {
int maxnames;
};
struct remote_list_defined_networks_ret {
remote_nonnull_string names<REMOTE_NETWORK_NAME_LIST_MAX>;
};
struct remote_network_lookup_by_uuid_args {
remote_uuid uuid;
};
struct remote_network_lookup_by_uuid_ret {
/* XXX "Not found" semantic is ill-defined. */
remote_nonnull_network net;
};
struct remote_network_lookup_by_name_args {
remote_nonnull_string name;
};
struct remote_network_lookup_by_name_ret {
/* XXX "Not found" semantic is ill-defined. */
remote_nonnull_network net;
};
struct remote_network_create_xml_args {
remote_nonnull_string xml;
};
struct remote_network_create_xml_ret {
remote_nonnull_network net;
};
struct remote_network_define_xml_args {
remote_nonnull_string xml;
};
struct remote_network_define_xml_ret {
remote_nonnull_network net;
};
struct remote_network_undefine_args {
remote_nonnull_network net;
};
struct remote_network_create_args {
remote_nonnull_network net;
};
struct remote_network_destroy_args {
remote_nonnull_network net;
};
struct remote_network_dump_xml_args {
remote_nonnull_network net;
int flags;
};
struct remote_network_dump_xml_ret {
remote_nonnull_string xml;
};
struct remote_network_get_bridge_name_args {
remote_nonnull_network net;
};
struct remote_network_get_bridge_name_ret {
remote_nonnull_string name;
};
struct remote_network_get_autostart_args {
remote_nonnull_network net;
};
struct remote_network_get_autostart_ret {
int autostart;
};
struct remote_network_set_autostart_args {
remote_nonnull_network net;
int autostart;
};
/*----- Protocol. -----*/
/* Define the program number, protocol version and procedure numbers here. */
const REMOTE_PROGRAM = 0x20008086;
const REMOTE_PROTOCOL_VERSION = 1;
enum remote_procedure {
REMOTE_PROC_OPEN = 1,
REMOTE_PROC_CLOSE = 2,
REMOTE_PROC_GET_CAPABILITIES = 3
};
/* Custom RPC structure. */
/* Each message consists of:
* int length Number of bytes in message _including_ length.
* remote_message_header Header.
* then either: args Arguments (for REMOTE_CALL).
* or: ret Return (for REMOTE_REPLY, status = REMOTE_OK)
* or: remote_error Error (for REMOTE_REPLY, status = REMOTE_ERROR)
*
* The first two words (length, program number) are meant to be compatible
* with the qemud protocol (qemud/protocol.x), although the rest of the
* messages are completely different.
*/
enum remote_message_direction {
REMOTE_CALL = 0, /* client -> server */
REMOTE_REPLY = 1, /* server -> client */
REMOTE_MESSAGE = 2 /* server -> client, asynchronous [NYI] */
};
enum remote_message_status {
/* Status is always REMOTE_OK for calls.
* For replies, indicates no error.
*/
REMOTE_OK = 0,
/* For replies, indicates that an error happened, and a struct
* remote_error follows.
*/
REMOTE_ERROR = 1
};
struct remote_message_header {
unsigned prog; /* REMOTE_PROGRAM */
unsigned vers; /* REMOTE_PROTOCOL_VERSION */
remote_procedure proc; /* REMOTE_PROC_x */
remote_message_direction direction;
unsigned serial; /* Serial number of message. */
remote_message_status status;
};
/*
* vim: set tabstop=4:
* vim: set shiftwidth=4:
* vim: set expandtab:
*/
/*
* Local variables:
* indent-tabs-mode: nil
* c-indent-level: 4
* c-basic-offset: 4
* tab-width: 4
* End:
*/
17 years, 6 months