[libvirt] virDomainInterfaceStats why is there a size?
by Stefan de Konink
Another simple question, what is the reasoning about the size field in
this call. I would really be a happy boy if anyone said:
if you put in path == NULL, it will fill your stats structure up to size
interfaces.
...but since this is not the case (yet) what is the reason behind it?
Stefan
16 years
[libvirt] anyone implementing host device enumeration?
by David Lively
Hi -
I'm about to start working on host device enumeration, along the
(HAL-ish) lines of what was discussed back in April:
https://www.redhat.com/archives/libvir-list/2008-April/msg00005.html
I know the xml details haven't been fully fleshed out, but there seems
to be agreement that it will be a fairly direct mapping from (a subset
of the) HAL info to the details that we need in the xml. Doubtless it
will take a while to figure out exactly what subset suffices (and, for
that matter, if everything needed is available via HAL ...), but I think
the work is well-defined for some of the obvious details (discussed in
the above thread) on which there's broad agreement.
Is anyone working on such an implementation?
Thanks,
Dave
16 years, 2 months
[libvirt] Live migration sanity checks
by Chris Lalancette
All,
One thing that oVirt would like to have (and that might be useful for other
users) is a call that would do some basic sanity checking for live migration.
This call would go over to the remote libvirtd, do some checks, and
return whether we think migration is likely to succeed. Note that I say
"likely to succeed", because there are certainly things that can cause migration
to fail after we've made checks, but anything is better than what we have today
("try it and pray").
Now, in order for this call to be widely useful, I think we would have to allow
the caller to specify *which* of the available checks they would like to
perform, and then have some sort of return value that indicated if there are
show-stopper problems, or just problems that may cause things to be sub-optimal
on the remote side. The caller could then decide what action it wants to take.
There is also a corollary to the "is it sane for me to migrate", which is, given
two hosts A and B, what's the lowest common denominator I need to run my guest
at so that migration will likely be successful between them. This could also be
used by management apps to make sure things are configured properly for the
guest before ever starting it.
The biggest problem with implementing these calls, however, is that there is no
comprehensive list of things we should check. This e-mail is an attempt to
write down some of the more obvious things we need to check, and to garner
discussion of things I might have missed. Once I have a proper list, I'll add
it to the TODO page on the libvirt Wiki so it's at least somewhere permanent.
Note that we don't have to implement *all* of these as a first go at this; if we
leave it open enough, we can add more checks as we go along without breaking
compatibility.
MIGRATION CRITERIA:
0) Matching hypervisors - seems obvious, but I'm not sure if we have these
checks today. Make sure we don't try to migrate Xen to KVM or vice-versa. We
also might want to think of at least warning the caller if you try to migrate
from a "newer" hypervisor (say, Xen 3.2) to an "older" hypervisor (say, Xen
3.1). That should, in theory, work, but maybe the caller would prefer not to do
that if possible. Rich has pointed out that KVM and Xen are accidentally
incompatible in libvirt, but we should make it explicit.
1) Matching CPU architectures - also obvious, but as far as I know today,
there's no checking for this (well, at least in Xen; I don't know about
libvirt). So you can happily attempt to migrate from i386 -> ia64, and watch
the fireworks. We also need to make sure you can't migrate x86_64 -> i386. I
believe i386 -> x86_64 should work, but this might be hypervisor dependent.
2) Matching CPU vendors - this one isn't a hard requirement; given the things
below, we may still be likely to succeed even if we go from AMD to Intel or
vice-versa. It still might be useful information for the caller to know.
3) CPU flags - the CPU flags of the destination *must* be a superset of the CPU
flags that were presented to the guest at startup. Many OS's and application
check for CPU flags once at startup to choose optimized routines, and then never
check again; if they happened to select sse3, and sse3 is not there on the
destination, then they will (eventually) crash.
This is where the CPU masking technology and the lowest common denominator
libvirt call can make a big difference. If you make sure to mask some of the
CPU flags off of the guest when you are first creating it, then the destination
host just needs a superset of the flags that were presented to the guest at
bootup, which makes the problem easier.
4) Number of CPUs - generally, you want the destination to have at least one
physical CPU for each virtual CPU assigned to the guest. However, I can see use
cases where this might not be the case (temporary or emergency migrations). So
this would probably be a warning, and the caller can make the choice of whether
to proceed.
5a) Memory - non-NUMA -> non-NUMA - fairly straightforward. The destination
must have enough memory to fit the guest memory. We might want to do some
"extra" checking on the destination to make sure we aren't going to OOM the
destination as soon as we arrive.
5b) Memory - non-NUMA -> NUMA - A little trickier. There are no cpusets we
have to worry about, since we are coming from non-NUMA, but for absolute best
performance, we should try to fit the whole guest into a single NUMA node. Of
course, if that node is overloaded, that may be a bad idea. NUMA placement
problem, basically.
5c) Memory - NUMA -> non-NUMA - Less tricky. On the destination, all memory is
"equally" far away, so no need to worry about cpusets. Just have to make sure
that there is enough memory on the destination for the guest.
5d) Memory - NUMA -> NUMA - Tricky, just like case 5b). Need to determine if
there is enough memory in the machine first, then check if we can fit the guest
in a single node, and also check if we can match the cpuset from the source on
the destination.
6a) Networks - at the very least, the destination must have the same bridges
configured as the source side. Whether those bridges are hooked to the same
physical networks as the source or not is another question, and may be outside
the bounds of what we can/should check.
6b) Networks - we need to make sure that the device model on the remote side
supports the same devices as the source side. That is, if you have a e1000 nic
on the source side, but your destination doesn't support it, you are going to
fail the migration.
7a) Disks - we have to make sure that all of the disks on the source side are
available on the destination side, at the same paths. To be entirely clear, we
have to make sure that the file on the destination side is the *same* file as on
the source side, not just a file with the same name. For traditional
file-based, the best we can do may be path names. For device names (like LVM,
actual disk partitions, etc.), we might be able to take advantage of device
enumaration API's and validate that the device info is the same (UUID matching,
etc.).
7b) Disks - Additionally, we need to make sure that the device model on the
remote side supports the same devices as the source side. That is, if you have
a virtio drive on the source side, but your destination host doesn't support
virtio on the backend, you are going to fail. (virtio might be a bad example,
but there might be further things in the device model in the future that we
might not necessarily have on both ends).
------ That's the absolute basic criteria. More esoteric/less thought-out
criteria follow:
8) Time skew - this is less thought out at the moment, but if you calibrated
your lpj at boot time, and now you migrate to a host with a different clock
frequency, your time will run either fast or slow compared to what you expect.
Also synchronized vs. unsynchronized TSC could cause issues, etc.
9) PCI-passthrough - this is actually a check on the *source* side. If the
guest is using a PCI passthrough device, it *usually* doesn't make sense to
live migrate it. On the other hand, it looks like various groups are trying to
make this work (with the bonding of a PV NIC to a PCI-passthrough NIC), so we
need to keep that in mind, and not necessarily make this a hard failure.
10) MSR's?? - I've thought about this one before, but I'm not sure what the
answer is. Unfortunately, MSR's in virtualization are sort of done hodge-podge.
That is, some MSR's are emulated for the guests, some MSR's guests have direct
control over, and some aren't emulated at all. This one can get ugly fast; it's
probably something we want to leave until later.
11) CPUID?? - Not entirely sure about this one; there is a lot of
model-specific information encoded in the various CPUID calls (things like cache
size, cache line size, etc. etc). However, I don't know if CPUID instructions
are trapped-n-emulated under the different hypervisors, or if they are done
right on the processor itself. I guess if an OS or application called this at
startup, cached the information, and then checked again later it might get
upset, but it seems somewhat unlikely.
Things that I've missed?
Thanks,
Chris Lalancette
16 years, 2 months
[libvirt] [PATCH] kvm: maxVCPU runtime detection
by Guido Günther
Hi,
with recent linux kernels we can detect the maximum number of virtual
cpus at runtime via an ioctl. Possible patch attached. It does this on
every call to qemudGetMaxVCPUs. Would you prefer something that does
this only once in qemudStartup()?
Cheers,
-- Guido
16 years, 3 months
[libvirt] LXC: making the private root filesystem more secure
by Daniel P. Berrange
When I wrote the private root filesystem stuff for LXC (which I just
committed) I noted that we couldn't actually make this secure, because
someone inside the chroot can just 'mknod' and access the host devices.
What I completely forgot was that cgroups as of 2.6.26 has device ACLs
If we place every container in a cgroup (which was planned anyway), then
we can trivially prevent containers accessing host devices
One time setup
mount -t cgroups /dev/cgroups
mkdir /dev/cgroups/libvirt
mkdir /dev/cgroups/libvirt/lxc
For each new container 'NAME'
mkdir /dev/cgroups/libvirt/lxc/{NAME}
echo "a" > /dev/cgroups/libvirt/lxc/{NAME}/devices.deny
echo "c 1:3 rwm" > /dev/cgroups/libvirt/lxc/{NAME}/devices.allow
echo "c 1:5 rwm" > /dev/cgroups/libvirt/lxc/{NAME}/devices.allow
echo "c 1:7 rwm" > /dev/cgroups/libvirt/lxc/{NAME}/devices.allow
echo "c 5:1 rwm" > /dev/cgroups/libvirt/lxc/{NAME}/devices.allow
echo "c 1:8 rwm" > /dev/cgroups/libvirt/lxc/{NAME}/devices.allow
echo "c 1:9 rwm" > /dev/cgroups/libvirt/lxc/{NAME}/devices.allow
This denies all devices, and then allows null, zero, full, console, random
and urandom. Allowing use of 'random' is debatable.
The 'devpts' namespace stuff is also needed to provide private PTYs.
The 'user' namespace stuff is needed to prevent an unprivileged user
in the host OS from killing off processes with same UID inside the
container. There looks to be active patchsets for both of these being
discussed, so we're getting close to having a genuinely useful
container based virt driver with LXC
Daniel
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
16 years, 3 months
[libvirt] [PATCH] fix a error message and coding-style cleanup
by Nguyen Anh Quynh
Hi,
This patch fixes a "copy&paste" error message in MemoryPeek() function
of qemu driver.
And while I am at it, this patch does some clean-up on coding style.
Without this, my vim goes crazy while browsing the source.
Please enforce the coding style (more or less similar to GNU style?)
when merging.
Thanks,
Quynh
# diffstat fix5.patch
qemu_driver.c | 261 ++++++++++++++++++++++++++++++++++++++--------------------
1 file changed, 175 insertions(+), 86 deletions(-)
16 years, 3 months
[libvirt] [PATCH] Use gcc style for structure fields declaration
by Nguyen Anh Quynh
Hi,
This patch uses gcc style to declare fields in virDriver structures.
This also makes it easier to spot bugs.
$ diffstat fix3.patch
lxc_driver.c | 118 ++++++++++++++++++++++++++--------------------------
openvz_driver.c | 118 ++++++++++++++++++++++++++--------------------------
qemu_driver.c | 126 ++++++++++++++++++++++++++++----------------------------
test.c | 118 ++++++++++++++++++++++++++--------------------------
4 files changed, 240 insertions(+), 240 deletions(-)
Thanks,
Quynh
16 years, 3 months
[libvirt] [PATCH] Implement vol delete for disk pools
by Cole Robinson
The patch below implements virStorageVolDelete for volumes
on a disk pool.
The only interesting thing here is that parted wants a
partition number to delete, so we need to peel off the
end of the volume's target path which will be of the form
'/dev/sda1' or similar (I assume. If not, it's still
better than having nothing implemented).
Thanks,
Cole
16 years, 3 months
[libvirt] [PATCH]Fix minor issues in logical storage backend
by Jim Fehlig
Hi All!
I came across some problems trying to create a new LVM-based storage
pool using this config
<pool type="logical">
<name>test_vg</name>
<source>
<device path="/dev/sdb1"/>
</source>
<target>
<path>/dev/test_vg</path>
</target>
</pool>
Volume group did not previously exist so I did
virsh pool-define <above.xml>
virsh pool-build test_vg
pool-build failed since the backend logical storage driver does not have
VIR_STORAGE_BACKEND_POOL_SOURCE_DEVICE set in flags. Without this flag
set, the device element is never parsed in virStoragePoolDefParseDoc()
(storage_conf.c), causing pvcreate to fail since no physical volume is
specified.
After this problem was memory corruption cause by miscalculating the
size of vgcreate command line :-).
This patch fixes both issues.
Regards,
Jim
16 years, 3 months
[libvirt] PATCH: Switch openvz driver to domain APIs
by Daniel P. Berrange
This patch is the minimum effort port of the OpenVZ driver over to the
new generic domain XML routines. It basically removes all the existing
config format stuff from openvz_conf, defines a set of openvz capabilities
and implements the DumpXML method too. This is enough to get all the core
libvirt functions working. The biggest flaw I see currently is that the
openvz driver doesn't load the existing device config for networks or
filesystems of existing VMs, so you can't see that info in the XML dump
Daniel
diff -r e270be59a80f src/openvz_conf.c
--- a/src/openvz_conf.c Wed Aug 27 17:03:25 2008 +0100
+++ b/src/openvz_conf.c Wed Aug 27 17:26:08 2008 +0100
@@ -40,39 +40,29 @@
#include <limits.h>
#include <errno.h>
#include <string.h>
-
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/xpath.h>
-#include <libxml/uri.h>
-
-#include "internal.h"
-
-#include "openvz_driver.h"
+#include <sys/utsname.h>
+
#include "openvz_conf.h"
#include "uuid.h"
#include "buf.h"
#include "memory.h"
#include "util.h"
-#include "xml.h"
-#include "domain_conf.h"
static char *openvzLocateConfDir(void);
-static struct openvz_vm_def *openvzParseXML(virConnectPtr conn, xmlDocPtr xml);
static int openvzGetVPSUUID(int vpsid, char *uuidstr);
-static int openvzSetUUID(int vpsid);
static int openvzLocateConfFile(int vpsid, char *conffile, int maxlen);
+static int openvzAssignUUIDs(void);
void
openvzError (virConnectPtr conn, virErrorNumber code, const char *fmt, ...)
{
va_list args;
- char errorMessage[OPENVZ_MAX_ERROR_LEN];
+ char errorMessage[1024];
const char *errmsg;
if (fmt) {
va_start(args, fmt);
- vsnprintf(errorMessage, OPENVZ_MAX_ERROR_LEN-1, fmt, args);
+ vsnprintf(errorMessage, sizeof(errorMessage)-1, fmt, args);
va_end(args);
} else {
errorMessage[0] = '\0';
@@ -84,46 +74,6 @@ openvzError (virConnectPtr conn, virErro
errmsg, errorMessage);
}
-struct openvz_vm
-*openvzFindVMByID(const struct openvz_driver *driver, int id) {
- struct openvz_vm *vm = driver->vms;
-
- while (vm) {
- if (vm->vpsid == id)
- return vm;
- vm = vm->next;
- }
-
- return NULL;
-}
-
-struct openvz_vm
-*openvzFindVMByUUID(const struct openvz_driver *driver,
- const unsigned char *uuid) {
- struct openvz_vm *vm = driver->vms;
-
- while (vm) {
- if (!memcmp(vm->vmdef->uuid, uuid, VIR_UUID_BUFLEN))
- return vm;
- vm = vm->next;
- }
-
- return NULL;
-}
-
-struct openvz_vm
-*openvzFindVMByName(const struct openvz_driver *driver,
- const char *name) {
- struct openvz_vm *vm = driver->vms;
-
- while (vm) {
- if (STREQ(vm->vmdef->name, name))
- return vm;
- vm = vm->next;
- }
-
- return NULL;
-}
int
strtoI(const char *str)
@@ -135,6 +85,43 @@ strtoI(const char *str)
return val;
}
+
+virCapsPtr openvzCapsInit(void)
+{
+ struct utsname utsname;
+ virCapsPtr caps;
+ virCapsGuestPtr guest;
+
+ uname(&utsname);
+
+ if ((caps = virCapabilitiesNew(utsname.machine,
+ 0, 0)) == NULL)
+ goto no_memory;
+
+ if ((guest = virCapabilitiesAddGuest(caps,
+ "exe",
+ utsname.machine,
+ sizeof(int) == 4 ? 32 : 8,
+ NULL,
+ NULL,
+ 0,
+ NULL)) == NULL)
+ goto no_memory;
+
+ if (virCapabilitiesAddGuestDomain(guest,
+ "openvz",
+ NULL,
+ NULL,
+ 0,
+ NULL) == NULL)
+ goto no_memory;
+ return caps;
+
+no_memory:
+ virCapabilitiesFree(caps);
+ return NULL;
+}
+
/* function checks MAC address is empty
return 0 - empty
@@ -164,438 +151,105 @@ char *openvzMacToString(const unsigned c
return strdup(str);
}
-void
-openvzRemoveInactiveVM(struct openvz_driver *driver, struct openvz_vm *vm)
-{
- driver->num_inactive--;
- openvzFreeVM(driver, vm, 1);
-}
-
-/* Free all memory associated with a openvz_vm_def structure */
-void
-openvzFreeVMDef(struct openvz_vm_def *def)
-{
- if (def) {
- virDomainNetDefFree(def->net);
- }
-}
-
-/* Free all memory associated with a openvz_vm structure
- * @checkCallee == 0 then openvzFreeDriver() is callee else some other function
- */
-void
-openvzFreeVM(struct openvz_driver *driver, struct openvz_vm *vm,
- int checkCallee)
-{
- struct openvz_vm *vms;
-
- if (!vm && !driver)
- return;
- vms = driver->vms;
- if (checkCallee) {
- if (vms == vm)
- driver->vms = vm->next;
- else {
- while (vms) {
- struct openvz_vm *prev = vms;
-
- vms = vms->next;
- if (vms == vm) {
- prev->next = vms->next;
- break;
- }
- }
- }
- }
- if (vms) {
- openvzFreeVMDef(vm->vmdef);
- VIR_FREE(vm);
- }
-}
-
/* Free all memory associated with a openvz_driver structure */
void
openvzFreeDriver(struct openvz_driver *driver)
{
- struct openvz_vm *next;
-
+ virDomainObjPtr dom;
+
if (!driver)
return;
- if (driver->vms)
- for(next = driver->vms->next; driver->vms; driver->vms = next)
- openvzFreeVM(driver, driver->vms, 0);
- VIR_FREE(driver);
-}
-
-struct openvz_vm *
-openvzAssignVMDef(virConnectPtr conn,
- struct openvz_driver *driver, struct openvz_vm_def *def)
-{
- struct openvz_vm *vm = NULL;
-
- if (!driver || !def)
- return NULL;
-
- if ((vm = openvzFindVMByName(driver, def->name))) {
- if (!openvzIsActiveVM(vm)) {
- openvzFreeVMDef(vm->vmdef);
- vm->vmdef = def;
- }
- else
- {
- openvzLog(OPENVZ_ERR,
- _("Error already an active OPENVZ VM having id '%s'"),
- def->name);
- openvzFreeVMDef(def);
- return NULL; /* can't redefine an active domain */
- }
-
- return vm;
- }
-
- if (VIR_ALLOC(vm) < 0) {
- openvzFreeVMDef(def);
- openvzError(conn, VIR_ERR_NO_MEMORY, _("vm"));
- return NULL;
- }
-
- vm->vpsid = -1; /* -1 needed for to represent inactiveness of domain before 'start' */
- vm->status = VIR_DOMAIN_SHUTOFF;
- vm->vmdef = def;
- vm->next = driver->vms;
-
- driver->vms = vm;
- driver->num_inactive++;
-
- return vm;
-}
-
-struct openvz_vm_def
-*openvzParseVMDef(virConnectPtr conn,
- const char *xmlStr, const char *displayName)
-{
- xmlDocPtr xml;
- struct openvz_vm_def *def = NULL;
-
- xml = xmlReadDoc(BAD_CAST xmlStr, displayName ? displayName : "domain.xml", NULL,
- XML_PARSE_NOENT | XML_PARSE_NONET | XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
- if (!xml) {
- openvzError(conn, VIR_ERR_XML_ERROR, NULL);
- return NULL;
- }
-
- def = openvzParseXML(conn, xml);
- xmlFreeDoc(xml);
-
- return def;
-}
-
-/* Parse filesystem section
-Sample:
-<filesystem type="template">
- <source name="fedora-core-5-i386"/>
- <quota type="size" max="10000"/>
- <quota type="inodes" max="100"/>
-</filesystem>
-*/
-static int openvzParseDomainFS(virConnectPtr conn,
- struct openvz_fs_def *fs,
- xmlXPathContextPtr ctxt)
-{
- xmlNodePtr cur, obj;
- char *type = NULL;
- int n;
- xmlNodePtr *nodes = NULL;
-
-
- if ((n = virXPathNodeSet(conn, "/domain/devices/filesystem",
- ctxt, &nodes)) < 0) {
- openvzError(conn, VIR_ERR_INTERNAL_ERROR,
- _("missing filesystem tag"));
- goto error;
- }
-
- if (n > 1) {
- openvzError(conn, VIR_ERR_INTERNAL_ERROR,
- _("There should be only one filesystem tag"));
- goto error;
- }
-
- obj = nodes[0];
-
- /*check template type*/
- type = virXMLPropString(obj, "type");
- if (type == NULL) {
- openvzError(conn, VIR_ERR_INTERNAL_ERROR,
- _("missing type attribute"));
- goto error;
- }
-
- if (STRNEQ(type, "template")) {
- openvzError(conn, VIR_ERR_INTERNAL_ERROR,
- _("Unknown type attribute %s"), type);
- goto error;
- }
- VIR_FREE(type);
-
- cur = obj->children;
- while(cur != NULL)
- {
- if (cur->type == XML_ELEMENT_NODE) {
- if (xmlStrEqual(cur->name, BAD_CAST "source")) {
- char * name = virXMLPropString(cur, "name");
-
- if (name != NULL) {
- strncpy(fs->tmpl, name,sizeof(fs->tmpl));
- fs->tmpl[sizeof(fs->tmpl) - 1] = '\0';
- }
- VIR_FREE(name);
- } else if (xmlStrEqual(cur->name, BAD_CAST "quota")) {
- char * qtype = virXMLPropString(cur, "type");
- char * max = virXMLPropString(cur, "max");
-
- if (qtype != NULL && STREQ(qtype, "size") && max != NULL)
- fs->disksize = strtoI(max);
- else if (qtype != NULL && STREQ(qtype, "inodes") && max != NULL)
- fs->diskinodes = strtoI(max);
- VIR_FREE(qtype);
- VIR_FREE(max);
- }
- }
- cur = cur->next;
- }
- VIR_FREE(nodes);
-
- return 0;
-
- error:
- VIR_FREE(nodes);
- VIR_FREE(type);
-
- return -1;
-}
-
-
-/*
- * Parses a libvirt XML definition of a guest, and populates the
- * the openvz_vm struct with matching data about the guests config
- */
-static struct openvz_vm_def
-*openvzParseXML(virConnectPtr conn,
- xmlDocPtr xml) {
- xmlNodePtr root = NULL;
- char *prop = NULL;
- xmlXPathContextPtr ctxt = NULL;
- xmlXPathObjectPtr obj = NULL;
- struct openvz_vm_def *def = NULL;
- xmlNodePtr *nodes = NULL;
- int i, n;
-
- if (VIR_ALLOC(def) < 0) {
- openvzError(conn, VIR_ERR_NO_MEMORY, _("xmlXPathContext"));
- return NULL;
- }
-
- /* Prepare parser / xpath context */
- root = xmlDocGetRootElement(xml);
- if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "domain"))) {
- openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("incorrect root element"));
- goto bail_out;
- }
-
- ctxt = xmlXPathNewContext(xml);
- if (ctxt == NULL) {
- openvzError(conn, VIR_ERR_NO_MEMORY, _("xmlXPathContext"));
- goto bail_out;
- }
- ctxt->node = root;
-
- /* Find out what type of OPENVZ virtualization to use */
- if (!(prop = virXMLPropString(root, "type"))) {
- openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("missing domain type attribute"));
- goto bail_out;
- }
-
- if (STRNEQ(prop, "openvz")){
- openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("invalid domain type attribute"));
- goto bail_out;
- }
- VIR_FREE(prop);
-
- /* Extract domain name */
- obj = xmlXPathEval(BAD_CAST "string(/domain/name[1])", ctxt);
- if ((obj == NULL) || (obj->type != XPATH_STRING) ||
- (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
- openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("invalid domain name"));
- goto bail_out;
- }
-
- /* rejecting VPS ID <= OPENVZ_RSRV_VM_LIMIT for they are reserved */
- if (strtoI((const char *) obj->stringval) <= OPENVZ_RSRV_VM_LIMIT) {
- openvzError(conn, VIR_ERR_INTERNAL_ERROR,
- _("VPS ID Error (must be an integer greater than 100"));
- goto bail_out;
- }
- strncpy(def->name, (const char *) obj->stringval, OPENVZ_NAME_MAX);
- xmlXPathFreeObject(obj);
- obj = NULL;
-
- /* Extract domain uuid */
- prop = virXPathString(conn, "string(./uuid[1])", ctxt);
- if (!prop) {
- int err;
- if ((err = virUUIDGenerate(def->uuid))) {
- openvzError(conn, VIR_ERR_INTERNAL_ERROR,
- _("Failed to generate UUID: %s"),
- strerror(err));
- goto bail_out;
- }
- } else {
- if (virUUIDParse(prop, def->uuid) < 0) {
- openvzError(conn, VIR_ERR_INTERNAL_ERROR,
- _("malformed uuid element"));
- goto bail_out;
- }
- VIR_FREE(prop);
- }
-
- /* extract virtual CPUs */
- if (virXPathULong(conn, "string(./vcpu[1])", ctxt, &def->vcpus) < 0)
- def->vcpus = 0; //use default CPUs count
-
- /* Extract filesystem info */
- if (openvzParseDomainFS(conn, &(def->fs), ctxt)) {
- openvzError(conn, VIR_ERR_INTERNAL_ERROR,
- _("malformed filesystem tag"));
- goto bail_out;
- }
-
- /* analysis of the network devices */
- if ((n = virXPathNodeSet(conn, "/domain/devices/interface",
- ctxt, &nodes)) < 0) {
- openvzError(conn, VIR_ERR_INTERNAL_ERROR,
- "%s", _("cannot extract network devices"));
- goto bail_out;
- }
-
- for (i = n - 1 ; i >= 0 ; i--) {
- virDomainNetDefPtr net = virDomainNetDefParseXML(conn,
- nodes[i]);
- if (!net)
- goto bail_out;
-
- net->next = def->net;
- def->net = net;
- }
- VIR_FREE(nodes);
-
- xmlXPathFreeContext(ctxt);
- return def;
-
- bail_out:
- VIR_FREE(prop);
- xmlXPathFreeObject(obj);
- xmlXPathFreeContext(ctxt);
- openvzFreeVMDef(def);
-
- return NULL;
-}
-
-struct openvz_vm *
-openvzGetVPSInfo(virConnectPtr conn) {
+
+ dom = driver->domains;
+ while (dom) {
+ virDomainObjPtr tmp = dom->next;
+ virDomainObjFree(dom);
+ dom = tmp;
+ }
+
+ virCapabilitiesFree(driver->caps);
+}
+
+
+
+int openvzLoadDomains(struct openvz_driver *driver) {
FILE *fp;
int veid, ret;
char status[16];
char uuidstr[VIR_UUID_STRING_BUFLEN];
- struct openvz_vm *vm;
- struct openvz_vm **pnext;
- struct openvz_driver *driver;
- struct openvz_vm_def *vmdef;
- char temp[124];
-
- vm = NULL;
- driver = conn->privateData;
- driver->num_active = 0;
- driver->num_inactive = 0;
-
- if((fp = popen(VZLIST " -a -ovpsid,status -H 2>/dev/null", "r")) == NULL) {
- openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("popen failed"));
- return NULL;
- }
- pnext = &vm;
+ virDomainObjPtr dom = NULL, prev = NULL;
+
+ if (openvzAssignUUIDs() < 0)
+ return -1;
+
+ if ((fp = popen(VZLIST " -a -ovpsid,status -H 2>/dev/null", "r")) == NULL) {
+ openvzError(NULL, VIR_ERR_INTERNAL_ERROR, _("popen failed"));
+ return -1;
+ }
+
while(!feof(fp)) {
- if (VIR_ALLOC(*pnext) < 0) {
- openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("calloc failed"));
- goto error;
- }
-
- if(!vm)
- vm = *pnext;
-
if (fscanf(fp, "%d %s\n", &veid, status) != 2) {
if (feof(fp))
break;
-
- openvzError(conn, VIR_ERR_INTERNAL_ERROR,
- _("Failed to parse vzlist output"));
- goto error;
- }
- if(STRNEQ(status, "stopped")) {
- (*pnext)->status = VIR_DOMAIN_RUNNING;
- driver->num_active ++;
- (*pnext)->vpsid = veid;
- }
- else {
- (*pnext)->status = VIR_DOMAIN_SHUTOFF;
- driver->num_inactive ++;
- /*
- * inactive domains don't have their ID set in libvirt,
- * thought this doesn't make sense for OpenVZ
- */
- (*pnext)->vpsid = -1;
- }
-
- if (VIR_ALLOC(vmdef) < 0) {
- openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("calloc failed"));
- goto error;
- }
-
- snprintf(vmdef->name, OPENVZ_NAME_MAX, "%i", veid);
+
+ openvzError(NULL, VIR_ERR_INTERNAL_ERROR,
+ _("Failed to parse vzlist output"));
+ goto cleanup;
+ }
+
+ if (VIR_ALLOC(dom) < 0 ||
+ VIR_ALLOC(dom->def) < 0)
+ goto no_memory;
+
+ if (STRNEQ(status, "stopped"))
+ dom->state = VIR_DOMAIN_RUNNING;
+ else
+ dom->state = VIR_DOMAIN_SHUTOFF;
+
+ dom->pid = veid;
+ dom->def->id = dom->state == VIR_DOMAIN_SHUTOFF ? -1 : veid;
+
+ if (asprintf(&dom->def->name, "%i", veid) < 0) {
+ dom->def->name = NULL;
+ goto no_memory;
+ }
+
openvzGetVPSUUID(veid, uuidstr);
- ret = virUUIDParse(uuidstr, vmdef->uuid);
-
- if(ret == -1) {
- openvzError(conn, VIR_ERR_INTERNAL_ERROR,
- _("UUID in config file malformed"));
- VIR_FREE(vmdef);
- goto error;
- }
-
- /*get VCPU*/
- ret = openvzReadConfigParam(veid, "CPUS", temp, sizeof(temp));
- if (ret < 0) {
- openvzError(conn, VIR_ERR_INTERNAL_ERROR,
- _("Cound not read config for container %d"), veid);
- goto error;
- } else if (ret > 0) {
- vmdef->vcpus = strtoI(temp);
- }
-
-
- (*pnext)->vmdef = vmdef;
- pnext = &(*pnext)->next;
- }
- return vm;
-error:
- while (vm != NULL) {
- struct openvz_vm *next;
-
- next = vm->next;
- VIR_FREE(vm->vmdef);
- VIR_FREE(vm);
- vm = next;
- }
- return NULL;
+ ret = virUUIDParse(uuidstr, dom->def->uuid);
+
+ if (ret == -1) {
+ openvzError(NULL, VIR_ERR_INTERNAL_ERROR,
+ _("UUID in config file malformed"));
+ goto cleanup;
+ }
+
+ dom->def->vcpus = 1;
+ if (!(dom->def->os.type = strdup("exe")))
+ goto no_memory;
+ if (!(dom->def->os.init = strdup("/sbin/init")))
+ goto no_memory;
+
+ /* XXX load rest of VM config data .... */
+
+ if (prev) {
+ prev->next = dom;
+ } else {
+ driver->domains = dom;
+ }
+ prev = dom;
+ }
+
+ fclose(fp);
+
+ return 0;
+
+ no_memory:
+ openvzError(NULL, VIR_ERR_NO_MEMORY, NULL);
+
+ cleanup:
+ fclose(fp);
+ virDomainObjFree(dom);
+ return -1;
}
/*
@@ -797,7 +451,7 @@ openvzSetUUID(int vpsid){
*
*/
-int openvzAssignUUIDs(void)
+static int openvzAssignUUIDs(void)
{
DIR *dp;
struct dirent *dent;
diff -r e270be59a80f src/openvz_conf.h
--- a/src/openvz_conf.h Wed Aug 27 17:03:25 2008 +0100
+++ b/src/openvz_conf.h Wed Aug 27 17:03:45 2008 +0100
@@ -28,94 +28,35 @@
#ifndef OPENVZ_CONF_H
#define OPENVZ_CONF_H
-#include "openvz_driver.h"
+#include "internal.h"
#include "domain_conf.h"
enum { OPENVZ_WARN, OPENVZ_ERR };
-#define OPENVZ_NAME_MAX 8
-#define OPENVZ_TMPL_MAX 256
-#define OPENVZ_UNAME_MAX 32
-#define OPENVZ_IP_MAX 16
-#define OPENVZ_HOSTNAME_MAX 256
-#define OPENVZ_PROFILE_MAX 256
-#define OPENVZ_MAX_ERROR_LEN 1024
-#define OPENVZ_MAX_XML_LEN 4096
-#define OPENVZ_MAX_QUOTA 8
-#define OPENVZ_MAX_XPathEval_LEN 256
-#define OPENVZ_RSRV_VM_LIMIT 100
+#define openvzLog(level, msg...) { if(level == OPENVZ_WARN) \
+ fprintf(stderr, "\nWARNING: ");\
+ else \
+ fprintf(stderr, "\nERROR: ");\
+ fprintf(stderr, "\n\t");\
+ fprintf(stderr, msg);\
+ fprintf(stderr, "\n"); }
-enum openvz_quota{
- VM_LEVEL = 0,
- USER_LEVEL = 1,
+/* OpenVZ commands - Replace with wrapper scripts later? */
+#define VZLIST "vzlist"
+#define VZCTL "vzctl"
+
+struct openvz_driver {
+ virCapsPtr caps;
+ virDomainObjPtr domains;
};
-
-/* TODO Add more properties here */
-struct vps_props {
- int kmemsize; /* currently held */
- int kmemsize_m; /* max held */
- int kmemsize_b; /* barrier */
- int kmemsize_l; /* limit */
- int kmemsize_f; /* fail count */
-
-};
-
-struct openvz_fs_def {
- char tmpl[OPENVZ_TMPL_MAX];
- long int disksize, diskinodes;
-};
-
-struct openvz_vm_def {
- char name[OPENVZ_NAME_MAX];
- unsigned char uuid[VIR_UUID_BUFLEN];
- char profile[OPENVZ_PROFILE_MAX];
- unsigned long vcpus;
- struct openvz_fs_def fs;
- virDomainNetDefPtr net;
-};
-
-struct ovz_quota {
- enum openvz_quota type;
- unsigned int size;
- char uname[OPENVZ_UNAME_MAX];
- struct ovz_quota *next;
-};
-
-struct openvz_vm {
- int vpsid;
- int status;
- struct openvz_vm_def *vmdef;
- struct openvz_vm *next;
-};
-
-static inline int
-openvzIsActiveVM(struct openvz_vm *vm)
-{
- return vm->vpsid != -1;
-}
void openvzError (virConnectPtr conn, virErrorNumber code, const char *fmt, ...)
ATTRIBUTE_FORMAT(printf, 3, 4);
int openvz_readline(int fd, char *ptr, int maxlen);
int openvzReadConfigParam(int vpsid ,const char * param, char *value, int maxlen);
-struct openvz_vm *openvzFindVMByID(const struct openvz_driver *driver, int id);
-struct openvz_vm *openvzFindVMByUUID(const struct openvz_driver *driver,
- const unsigned char *uuid);
-
-struct openvz_vm *openvzFindVMByName(const struct openvz_driver *driver, const char *name);
-struct openvz_vm_def *openvzParseVMDef(virConnectPtr conn, const char *xmlStr,
- const char *displayName);
-
-struct openvz_vm *openvzAssignVMDef(virConnectPtr conn, struct openvz_driver *driver,
- struct openvz_vm_def *def);
-
-struct openvz_vm *openvzGetVPSInfo(virConnectPtr conn);
-void openvzGenerateUUID(unsigned char *uuid);
-int openvzAssignUUIDs(void);
-void openvzRemoveInactiveVM(struct openvz_driver *driver, struct openvz_vm *vm);
+virCapsPtr openvzCapsInit(void);
+int openvzLoadDomains(struct openvz_driver *driver);
void openvzFreeDriver(struct openvz_driver *driver);
-void openvzFreeVM(struct openvz_driver *driver, struct openvz_vm *vm, int checkCallee);
-void openvzFreeVMDef(struct openvz_vm_def *def);
int strtoI(const char *str);
int openvzCheckEmptyMac(const unsigned char *mac);
char *openvzMacToString(const unsigned char *mac);
diff -r e270be59a80f src/openvz_driver.c
--- a/src/openvz_driver.c Wed Aug 27 17:03:25 2008 +0100
+++ b/src/openvz_driver.c Wed Aug 27 17:29:40 2008 +0100
@@ -60,33 +60,6 @@
#define CMDBUF_LEN 1488
#define CMDOP_LEN 288
-static virDomainPtr openvzDomainLookupByID(virConnectPtr conn, int id);
-static char *openvzGetOSType(virDomainPtr dom);
-static int openvzGetNodeInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo);
-static virDomainPtr openvzDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid);
-static virDomainPtr openvzDomainLookupByName(virConnectPtr conn, const char *name);
-static int openvzDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info);
-static int openvzDomainShutdown(virDomainPtr dom);
-static int openvzDomainReboot(virDomainPtr dom, unsigned int flags);
-static int openvzDomainCreate(virDomainPtr dom);
-static virDrvOpenStatus openvzOpen(virConnectPtr conn,
- xmlURIPtr uri,
- virConnectAuthPtr auth ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED);
-static int openvzClose(virConnectPtr conn);
-static const char *openvzGetType(virConnectPtr conn ATTRIBUTE_UNUSED);
-static int openvzListDomains(virConnectPtr conn, int *ids, int nids);
-static int openvzNumDomains(virConnectPtr conn);
-static int openvzListDefinedDomains(virConnectPtr conn, char **const names, int nnames);
-static int openvzNumDefinedDomains(virConnectPtr conn);
-
-static virDomainPtr openvzDomainDefineXML(virConnectPtr conn, const char *xml);
-static virDomainPtr openvzDomainCreateLinux(virConnectPtr conn, const char *xml,
- unsigned int flags ATTRIBUTE_UNUSED);
-
-static int openvzDomainUndefine(virDomainPtr dom);
-static void cmdExecFree(const char *cmdExec[]);
-
static int openvzGetProcessInfo(unsigned long long *cpuTime, int vpsid);
static int openvzGetMaxVCPUs(virConnectPtr conn, const char *type);
static int openvzDomainGetMaxVcpus(virDomainPtr dom);
@@ -110,7 +83,7 @@ static int openvzDomainDefineCmd(virConn
static int openvzDomainDefineCmd(virConnectPtr conn,
const char *args[],
int maxarg,
- struct openvz_vm_def *vmdef)
+ virDomainDefPtr vmdef)
{
int narg;
@@ -143,15 +116,29 @@ static int openvzDomainDefineCmd(virConn
ADD_ARG_LIT("--quiet");
ADD_ARG_LIT("create");
ADD_ARG_LIT(vmdef->name);
-
- if ((vmdef->fs.tmpl && *(vmdef->fs.tmpl))) {
+
+ if (vmdef->fss) {
+ if (vmdef->fss->type != VIR_DOMAIN_FS_TYPE_TEMPLATE) {
+ openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("only filesystem templates are supported"));
+ return -1;
+ }
+
+ if (vmdef->fss->next) {
+ openvzError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("only one filesystem supported"));
+ return -1;
+ }
+
ADD_ARG_LIT("--ostemplate");
- ADD_ARG_LIT(vmdef->fs.tmpl);
- }
+ ADD_ARG_LIT(vmdef->fss->src);
+ }
+#if 0
if ((vmdef->profile && *(vmdef->profile))) {
ADD_ARG_LIT("--config");
ADD_ARG_LIT(vmdef->profile);
}
+#endif
ADD_ARG(NULL);
return 0;
@@ -165,39 +152,43 @@ static int openvzDomainDefineCmd(virConn
static virDomainPtr openvzDomainLookupByID(virConnectPtr conn,
- int id) {
+ int id) {
struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
- struct openvz_vm *vm;
+ virDomainObjPtr vm;
virDomainPtr dom;
- vm = openvzFindVMByID(driver, id);
+ vm = virDomainFindByID(driver->domains, id);
if (!vm) {
openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
return NULL;
}
- dom = virGetDomain(conn, vm->vmdef->name, vm->vmdef->uuid);
- if (!dom) {
- openvzError(conn, VIR_ERR_NO_MEMORY, _("virDomainPtr"));
- return NULL;
- }
-
- dom->id = vm->vpsid;
+ dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
+ if (!dom)
+ return NULL;
+
+ dom->id = vm->def->id;
return dom;
}
-static char *openvzGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED)
-{
- /* OpenVZ runs on Linux and runs only Linux */
- return strdup("linux");
+static char *openvzGetOSType(virDomainPtr dom)
+{
+ struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
+ char *ret = strdup(vm->def->os.type);
+
+ if (!ret)
+ openvzError(dom->conn, VIR_ERR_NO_MEMORY, NULL);
+
+ return ret;
}
static virDomainPtr openvzDomainLookupByUUID(virConnectPtr conn,
- const unsigned char *uuid) {
+ const unsigned char *uuid) {
struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
- struct openvz_vm *vm = openvzFindVMByUUID(driver, uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, uuid);
virDomainPtr dom;
if (!vm) {
@@ -205,20 +196,18 @@ static virDomainPtr openvzDomainLookupBy
return NULL;
}
- dom = virGetDomain(conn, vm->vmdef->name, vm->vmdef->uuid);
- if (!dom) {
- openvzError(conn, VIR_ERR_NO_MEMORY, _("virDomainPtr"));
- return NULL;
- }
-
- dom->id = vm->vpsid;
+ dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
+ if (!dom)
+ return NULL;
+
+ dom->id = vm->def->id;
return dom;
}
static virDomainPtr openvzDomainLookupByName(virConnectPtr conn,
const char *name) {
struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
- struct openvz_vm *vm = openvzFindVMByName(driver, name);
+ virDomainObjPtr vm = virDomainFindByName(driver->domains, name);
virDomainPtr dom;
if (!vm) {
@@ -226,74 +215,83 @@ static virDomainPtr openvzDomainLookupBy
return NULL;
}
- dom = virGetDomain(conn, vm->vmdef->name, vm->vmdef->uuid);
- if (!dom) {
- openvzError(conn, VIR_ERR_NO_MEMORY, _("virDomainPtr"));
- return NULL;
- }
-
- dom->id = vm->vpsid;
+ dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
+ if (!dom)
+ return NULL;
+
+ dom->id = vm->def->id;
return dom;
}
static int openvzDomainGetInfo(virDomainPtr dom,
- virDomainInfoPtr info) {
+ virDomainInfoPtr info) {
struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
- struct openvz_vm *vm = openvzFindVMByUUID(driver, dom->uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
if (!vm) {
openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
- _("no domain with matching uuid"));
- return -1;
- }
-
- info->state = vm->status;
-
- if (!openvzIsActiveVM(vm)) {
+ _("no domain with matching uuid"));
+ return -1;
+ }
+
+ info->state = vm->state;
+
+ if (!virDomainIsActive(vm)) {
info->cpuTime = 0;
} else {
if (openvzGetProcessInfo(&(info->cpuTime), dom->id) < 0) {
openvzError(dom->conn, VIR_ERR_OPERATION_FAILED,
- _("cannot read cputime for domain %d"), dom->id);
+ _("cannot read cputime for domain %d"), dom->id);
return -1;
}
}
/* TODO These need to be calculated differently for OpenVZ */
//info->cpuTime =
- //info->maxMem = vm->def->maxmem;
- //info->memory = vm->def->memory;
- info->nrVirtCpu = vm->vmdef->vcpus;
- return 0;
-}
+ info->maxMem = vm->def->maxmem;
+ info->memory = vm->def->memory;
+ info->nrVirtCpu = vm->def->vcpus;
+ return 0;
+}
+
+
+static char *openvzDomainDumpXML(virDomainPtr dom, int flags) {
+ struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
+
+ if (!vm) {
+ openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
+ _("no domain with matching uuid"));
+ return NULL;
+ }
+
+ return virDomainDefFormat(dom->conn, vm->def, flags);
+}
+
+
static int openvzDomainShutdown(virDomainPtr dom) {
struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
- struct openvz_vm *vm = openvzFindVMByUUID(driver, dom->uuid);
- const char *prog[] = {VZCTL, "--quiet", "stop", vm->vmdef->name, NULL};
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
+ const char *prog[] = {VZCTL, "--quiet", "stop", vm->def->name, NULL};
if (!vm) {
openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
- _("no domain with matching id"));
- return -1;
- }
-
- if (vm->status != VIR_DOMAIN_RUNNING) {
- openvzError(dom->conn, VIR_ERR_OPERATION_DENIED,
- _("domain is not in running state"));
- return -1;
- }
-
- if (virRun(dom->conn, prog, NULL) < 0) {
+ _("no domain with matching uuid"));
+ return -1;
+ }
+
+ if (vm->state != VIR_DOMAIN_RUNNING) {
openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
- _("Could not exec %s"), VZCTL);
- return -1;
- }
-
- vm->vpsid = -1;
- vm->status = VIR_DOMAIN_SHUTOFF;
- ovz_driver.num_inactive ++;
- ovz_driver.num_active --;
+ _("domain is not in running state"));
+ return -1;
+ }
+
+ if (virRun(dom->conn, prog, NULL) < 0)
+ return -1;
+
+ vm->def->id = -1;
+ vm->state = VIR_DOMAIN_SHUTOFF;
return 0;
}
@@ -301,26 +299,23 @@ static int openvzDomainReboot(virDomainP
static int openvzDomainReboot(virDomainPtr dom,
unsigned int flags ATTRIBUTE_UNUSED) {
struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
- struct openvz_vm *vm = openvzFindVMByUUID(driver, dom->uuid);
- const char *prog[] = {VZCTL, "--quiet", "restart", vm->vmdef->name, NULL};
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
+ const char *prog[] = {VZCTL, "--quiet", "restart", vm->def->name, NULL};
if (!vm) {
openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
- _("no domain with matching id"));
- return -1;
- }
-
- if (vm->status != VIR_DOMAIN_RUNNING) {
- openvzError(dom->conn, VIR_ERR_OPERATION_DENIED,
- _("domain is not in running state"));
- return -1;
- }
-
- if (virRun(dom->conn, prog, NULL) < 0) {
+ _("no domain with matching uuid"));
+ return -1;
+ }
+
+ if (vm->state != VIR_DOMAIN_RUNNING) {
openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
- _("Could not exec %s"), VZCTL);
- return -1;
- }
+ _("domain is not in running state"));
+ return -1;
+ }
+
+ if (virRun(dom->conn, prog, NULL) < 0)
+ return -1;
return 0;
}
@@ -421,24 +416,31 @@ openvzDomainDefineXML(virConnectPtr conn
openvzDomainDefineXML(virConnectPtr conn, const char *xml)
{
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
- struct openvz_vm_def *vmdef = NULL;
- struct openvz_vm *vm = NULL;
+ virDomainDefPtr vmdef = NULL;
+ virDomainObjPtr vm = NULL;
virDomainPtr dom = NULL;
const char *prog[OPENVZ_MAX_ARG];
prog[0] = NULL;
- if ((vmdef = openvzParseVMDef(conn, xml, NULL)) == NULL)
- return NULL;
-
- vm = openvzFindVMByName(driver, vmdef->name);
+ if ((vmdef = virDomainDefParseString(conn, driver->caps, xml)) == NULL)
+ return NULL;
+
+ if (vmdef->os.init == NULL &&
+ !(vmdef->os.init = strdup("/sbin/init"))) {
+ virDomainDefFree(vmdef);
+ return NULL;
+ }
+
+ vm = virDomainFindByName(driver->domains, vmdef->name);
if (vm) {
+ virDomainDefFree(vmdef);
openvzLog(OPENVZ_ERR, _("Already an OPENVZ VM active with the id '%s'"),
vmdef->name);
return NULL;
}
- if (!(vm = openvzAssignVMDef(conn, driver, vmdef))) {
- openvzFreeVMDef(vmdef);
- openvzLog(OPENVZ_ERR, "%s", _("Error creating OPENVZ VM"));
+ if (!(vm = virDomainAssignDef(conn, &driver->domains, vmdef))) {
+ virDomainDefFree(vmdef);
+ return NULL;
}
if (openvzDomainDefineCmd(conn, prog, OPENVZ_MAX_ARG, vmdef) < 0) {
@@ -461,11 +463,11 @@ openvzDomainDefineXML(virConnectPtr conn
goto exit;
}
- dom = virGetDomain(conn, vm->vmdef->name, vm->vmdef->uuid);
+ dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
if (dom)
- dom->id = vm->vpsid;
-
- if (openvzDomainSetNetwork(conn, vmdef->name, vmdef->net) < 0) {
+ dom->id = -1;
+
+ if (openvzDomainSetNetwork(conn, vmdef->name, vmdef->nets) < 0) {
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
_("Could not configure network"));
goto exit;
@@ -488,27 +490,33 @@ openvzDomainCreateLinux(virConnectPtr co
openvzDomainCreateLinux(virConnectPtr conn, const char *xml,
unsigned int flags ATTRIBUTE_UNUSED)
{
- struct openvz_vm_def *vmdef = NULL;
- struct openvz_vm *vm = NULL;
+ virDomainDefPtr vmdef = NULL;
+ virDomainObjPtr vm = NULL;
virDomainPtr dom = NULL;
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
const char *progstart[] = {VZCTL, "--quiet", "start", NULL, NULL};
const char *progcreate[OPENVZ_MAX_ARG];
progcreate[0] = NULL;
- if (!(vmdef = openvzParseVMDef(conn, xml, NULL)))
- return NULL;
-
- vm = openvzFindVMByName(driver, vmdef->name);
+ if ((vmdef = virDomainDefParseString(conn, driver->caps, xml)) == NULL)
+ return NULL;
+
+ if (vmdef->os.init == NULL &&
+ !(vmdef->os.init = strdup("/sbin/init"))) {
+ virDomainDefFree(vmdef);
+ return NULL;
+ }
+
+ vm = virDomainFindByName(driver->domains, vmdef->name);
if (vm) {
- openvzFreeVMDef(vmdef);
+ virDomainDefFree(vmdef);
openvzLog(OPENVZ_ERR,
_("Already an OPENVZ VM defined with the id '%d'"),
strtoI(vmdef->name));
return NULL;
}
- if (!(vm = openvzAssignVMDef(conn, driver, vmdef))) {
- openvzLog(OPENVZ_ERR, "%s", _("Error creating OPENVZ VM"));
+ if (!(vm = virDomainAssignDef(conn, &driver->domains, vmdef))) {
+ virDomainDefFree(vmdef);
return NULL;
}
@@ -530,7 +538,7 @@ openvzDomainCreateLinux(virConnectPtr co
goto exit;
}
- if (openvzDomainSetNetwork(conn, vmdef->name, vmdef->net) < 0) {
+ if (openvzDomainSetNetwork(conn, vmdef->name, vmdef->nets) < 0) {
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
_("Could not configure network"));
goto exit;
@@ -544,20 +552,19 @@ openvzDomainCreateLinux(virConnectPtr co
goto exit;
}
- vm->vpsid = strtoI(vmdef->name);
- vm->status = VIR_DOMAIN_RUNNING;
- ovz_driver.num_inactive--;
- ovz_driver.num_active++;
-
- dom = virGetDomain(conn, vm->vmdef->name, vm->vmdef->uuid);
+ vm->pid = strtoI(vmdef->name);
+ vm->def->id = vm->pid;
+ vm->state = VIR_DOMAIN_RUNNING;
+
+ dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
if (dom)
- dom->id = vm->vpsid;
+ dom->id = vm->def->id;
if (vmdef->vcpus > 0) {
if (openvzDomainSetVcpus(dom, vmdef->vcpus) < 0) {
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
- _("Could not set number of virtual cpu"));
- goto exit;
+ _("Could not set number of virtual cpu"));
+ goto exit;
}
}
@@ -570,8 +577,8 @@ openvzDomainCreate(virDomainPtr dom)
openvzDomainCreate(virDomainPtr dom)
{
struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
- struct openvz_vm *vm = openvzFindVMByName(driver, dom->name);
- const char *prog[] = {VZCTL, "--quiet", "start", vm->vmdef->name, NULL };
+ virDomainObjPtr vm = virDomainFindByName(driver->domains, dom->name);
+ const char *prog[] = {VZCTL, "--quiet", "start", vm->def->name, NULL };
if (!vm) {
openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
@@ -579,7 +586,7 @@ openvzDomainCreate(virDomainPtr dom)
return -1;
}
- if (vm->status != VIR_DOMAIN_SHUTOFF) {
+ if (vm->state != VIR_DOMAIN_SHUTOFF) {
openvzError(dom->conn, VIR_ERR_OPERATION_DENIED,
_("domain is not in shutoff state"));
return -1;
@@ -591,10 +598,9 @@ openvzDomainCreate(virDomainPtr dom)
return -1;
}
- vm->vpsid = strtoI(vm->vmdef->name);
- vm->status = VIR_DOMAIN_RUNNING;
- ovz_driver.num_inactive --;
- ovz_driver.num_active ++;
+ vm->pid = strtoI(vm->def->name);
+ vm->def->id = vm->pid;
+ vm->state = VIR_DOMAIN_RUNNING;
return 0;
}
@@ -604,15 +610,15 @@ openvzDomainUndefine(virDomainPtr dom)
{
virConnectPtr conn= dom->conn;
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
- struct openvz_vm *vm = openvzFindVMByUUID(driver, dom->uuid);
- const char *prog[] = { VZCTL, "--quiet", "destroy", vm->vmdef->name, NULL };
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
+ const char *prog[] = { VZCTL, "--quiet", "destroy", vm->def->name, NULL };
if (!vm) {
openvzError(conn, VIR_ERR_INVALID_DOMAIN, _("no domain with matching uuid"));
return -1;
}
- if (openvzIsActiveVM(vm)) {
+ if (virDomainIsActive(vm)) {
openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("cannot delete active domain"));
return -1;
}
@@ -623,7 +629,8 @@ openvzDomainUndefine(virDomainPtr dom)
return -1;
}
- openvzRemoveInactiveVM(driver, vm);
+ virDomainRemoveInactive(&driver->domains, vm);
+
return 0;
}
@@ -632,8 +639,8 @@ openvzDomainSetAutostart(virDomainPtr do
{
virConnectPtr conn= dom->conn;
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
- struct openvz_vm *vm = openvzFindVMByUUID(driver, dom->uuid);
- const char *prog[] = { VZCTL, "--quiet", "set", vm->vmdef->name,
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
+ const char *prog[] = { VZCTL, "--quiet", "set", vm->def->name,
"--onboot", autostart ? "yes" : "no",
"--save", NULL };
@@ -655,7 +662,7 @@ openvzDomainGetAutostart(virDomainPtr do
{
virConnectPtr conn= dom->conn;
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
- struct openvz_vm *vm = openvzFindVMByUUID(driver, dom->uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
char value[1024];
if (!vm) {
@@ -663,7 +670,7 @@ openvzDomainGetAutostart(virDomainPtr do
return -1;
}
- if (openvzReadConfigParam(strtoI(vm->vmdef->name), "ONBOOT", value, sizeof(value)) < 0) {
+ if (openvzReadConfigParam(strtoI(vm->def->name), "ONBOOT", value, sizeof(value)) < 0) {
openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("Could not read container config"));
return -1;
}
@@ -692,32 +699,32 @@ static int openvzDomainSetVcpus(virDomai
static int openvzDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
virConnectPtr conn= dom->conn;
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
- struct openvz_vm *vm = openvzFindVMByUUID(driver, dom->uuid);
+ virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
char str_vcpus[32];
- const char *prog[] = { VZCTL, "--quiet", "set", vm->vmdef->name,
+ const char *prog[] = { VZCTL, "--quiet", "set", vm->def->name,
"--cpus", str_vcpus, "--save", NULL };
snprintf(str_vcpus, 31, "%d", nvcpus);
str_vcpus[31] = '\0';
if (nvcpus <= 0) {
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
- _("VCPUs should be >= 1"));
+ _("VCPUs should be >= 1"));
return -1;
}
if (!vm) {
openvzError(conn, VIR_ERR_INVALID_DOMAIN,
- _("no domain with matching uuid"));
+ _("no domain with matching uuid"));
return -1;
}
if (virRun(conn, prog, NULL) < 0) {
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
- _("Could not exec %s"), VZCTL);
- return -1;
- }
-
- vm->vmdef->vcpus = nvcpus;
+ _("Could not exec %s"), VZCTL);
+ return -1;
+ }
+
+ vm->def->vcpus = nvcpus;
return 0;
}
@@ -735,51 +742,48 @@ static virDrvOpenStatus openvzOpen(virCo
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
int flags ATTRIBUTE_UNUSED)
{
- struct openvz_vm *vms;
-
+ struct openvz_driver *driver;
/*Just check if the user is root. Nothing really to open for OpenVZ */
- if (getuid()) { // OpenVZ tools can only be used by r00t
- return VIR_DRV_OPEN_DECLINED;
- } else {
- if (uri == NULL || uri->scheme == NULL || uri->path == NULL)
- return VIR_DRV_OPEN_DECLINED;
- if (STRNEQ (uri->scheme, "openvz"))
- return VIR_DRV_OPEN_DECLINED;
- if (STRNEQ (uri->path, "/system"))
- return VIR_DRV_OPEN_DECLINED;
- }
+ if (getuid()) { // OpenVZ tools can only be used by r00t
+ return VIR_DRV_OPEN_DECLINED;
+ } else {
+ if (uri == NULL || uri->scheme == NULL || uri->path == NULL)
+ return VIR_DRV_OPEN_DECLINED;
+ if (STRNEQ (uri->scheme, "openvz"))
+ return VIR_DRV_OPEN_DECLINED;
+ if (STRNEQ (uri->path, "/system"))
+ return VIR_DRV_OPEN_DECLINED;
+ }
/* See if we are running an OpenVZ enabled kernel */
- if(access("/proc/vz/veinfo", F_OK) == -1 ||
- access("/proc/user_beancounters", F_OK) == -1) {
- return VIR_DRV_OPEN_DECLINED;
- }
-
- conn->privateData = &ovz_driver;
-
- openvzAssignUUIDs();
-
- vms = openvzGetVPSInfo(conn);
- ovz_driver.vms = vms;
-
- return VIR_DRV_OPEN_SUCCESS;
+ if(access("/proc/vz/veinfo", F_OK) == -1 ||
+ access("/proc/user_beancounters", F_OK) == -1) {
+ return VIR_DRV_OPEN_DECLINED;
+ }
+
+ if (VIR_ALLOC(driver) < 0) {
+ openvzError(conn, VIR_ERR_NO_MEMORY, NULL);
+ return VIR_DRV_OPEN_ERROR;
+ }
+
+ if (!(driver->caps = openvzCapsInit()))
+ goto cleanup;
+
+ if (openvzLoadDomains(driver) < 0)
+ goto cleanup;
+
+ conn->privateData = driver;
+
+ return VIR_DRV_OPEN_SUCCESS;
+
+cleanup:
+ openvzFreeDriver(driver);
+ return VIR_DRV_OPEN_ERROR;
};
static int openvzClose(virConnectPtr conn) {
-
struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
- struct openvz_vm *vm = driver->vms;
-
- while(vm) {
- openvzFreeVMDef(vm->vmdef);
- vm = vm->next;
- }
- vm = driver->vms;
- while (vm) {
- struct openvz_vm *prev = vm;
- vm = vm->next;
- free(prev);
- }
-
+
+ openvzFreeDriver(driver);
conn->privateData = NULL;
return 0;
@@ -792,6 +796,12 @@ static int openvzGetNodeInfo(virConnectP
static int openvzGetNodeInfo(virConnectPtr conn,
virNodeInfoPtr nodeinfo) {
return virNodeInfoPopulate(conn, nodeinfo);
+}
+
+static char *openvzGetCapabilities(virConnectPtr conn) {
+ struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
+
+ return virCapabilitiesFormatXML(driver->caps);
}
static int openvzListDomains(virConnectPtr conn, int *ids, int nids) {
@@ -829,14 +839,22 @@ static int openvzListDomains(virConnectP
}
static int openvzNumDomains(virConnectPtr conn ATTRIBUTE_UNUSED) {
- return ovz_driver.num_active;
+ struct openvz_driver *driver = conn->privateData;
+ int nactive = 0;
+ virDomainObjPtr vm = driver->domains;
+ while (vm) {
+ if (virDomainIsActive(vm))
+ nactive++;
+ vm = vm->next;
+ }
+ return nactive;
}
static int openvzListDefinedDomains(virConnectPtr conn,
- char **const names, int nnames) {
+ char **const names, int nnames) {
int got = 0;
int veid, pid, outfd = -1, errfd = -1, ret;
- char vpsname[OPENVZ_NAME_MAX];
+ char vpsname[32];
char buf[32];
char *endptr;
const char *cmd[] = {VZLIST, "-ovpsid", "-H", "-S", NULL};
@@ -858,7 +876,7 @@ static int openvzListDefinedDomains(virC
_("Could not parse VPS ID %s"), buf);
continue;
}
- sprintf(vpsname, "%d", veid);
+ snprintf(vpsname, sizeof(vpsname), "%d", veid);
names[got] = strdup(vpsname);
got ++;
}
@@ -911,8 +929,16 @@ Version: 2.2
return 0;
}
-static int openvzNumDefinedDomains(virConnectPtr conn ATTRIBUTE_UNUSED) {
- return ovz_driver.num_inactive;
+static int openvzNumDefinedDomains(virConnectPtr conn) {
+ struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
+ int ninactive = 0;
+ virDomainObjPtr vm = driver->domains;
+ while (vm) {
+ if (!virDomainIsActive(vm))
+ ninactive++;
+ vm = vm->next;
+ }
+ return ninactive;
}
static virDriver openvzDriver = {
@@ -929,7 +955,7 @@ static virDriver openvzDriver = {
NULL, /* uri */
openvzGetMaxVCPUs, /* getMaxVcpus */
openvzGetNodeInfo, /* nodeGetInfo */
- NULL, /* getCapabilities */
+ openvzGetCapabilities, /* getCapabilities */
openvzListDomains, /* listDomains */
openvzNumDomains, /* numOfDomains */
openvzDomainCreateLinux, /* domainCreateLinux */
@@ -953,7 +979,7 @@ static virDriver openvzDriver = {
NULL, /* domainPinVcpu */
NULL, /* domainGetVcpus */
openvzDomainGetMaxVcpus, /* domainGetMaxVcpus */
- NULL, /* domainDumpXML */
+ openvzDomainDumpXML, /* domainDumpXML */
openvzListDefinedDomains, /* listDomains */
openvzNumDefinedDomains, /* numOfDomains */
openvzDomainCreate, /* domainCreate */
diff -r e270be59a80f src/openvz_driver.h
--- a/src/openvz_driver.h Wed Aug 27 17:03:25 2008 +0100
+++ b/src/openvz_driver.h Wed Aug 27 17:03:45 2008 +0100
@@ -31,24 +31,6 @@
#include "internal.h"
-/* OpenVZ commands - Replace with wrapper scripts later? */
-#define VZLIST "vzlist"
-#define VZCTL "vzctl"
-
-struct openvz_driver {
- struct openvz_vm *vms;
- int num_active;
- int num_inactive;
-};
-
int openvzRegister(void);
-#define openvzLog(level, msg...) { if(level == OPENVZ_WARN) \
- fprintf(stderr, "\nWARNING: ");\
- else \
- fprintf(stderr, "\nERROR: ");\
- fprintf(stderr, "\n\t");\
- fprintf(stderr, msg);\
- fprintf(stderr, "\n"); }
-
#endif
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
16 years, 3 months