[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v3 4/5] libxl: call hotplug scripts from libxl for vif



As the previous change already introduces most of needed machinery to call
hotplug scripts from libxl, this only adds the necessary bits to call this
scripts for vif interfaces also.

libxl_device_nic_add has been changed to make use of the new event
functionality, and the necessary vif hotplug code has been added. No changes
where needed in the teardown part, since it uses exactly the same code
introduced for vbd.

An exception has been introduced for tap devices, since hotplug scripts
should be called after the device model has been created, so the hotplug
call for those is done in do_domain_create after confirmation of the device
model startup. On the other hand, tap devices don't use teardown scripts,
so add another exception for that.

libxl__device_from_nic was moved to libxl_device.c, so it can be used
in libxl_create.c, and libxl__device_from_disk was also moved to maintain
the symmetry.

libxl__initiate_device_remove has been changed a little, to nuke the frontend
xenstore path before trying to perform device teardown, this allows for
uninitialized devices to be closed gracefully, specially vif interfaces added to
HVM machines and not used.

PV nic devices are set to LIBXL_NIC_TYPE_VIF, since the default value is
LIBXL_NIC_TYPE_IOEMU regardless of the guest type.

A new global option, called disable_vif_scripts has been added to allow the user
decide if he wants to execute the hotplug scripts from xl or from udev. This has
been documented in the xl.conf man page.

Changes since v2:

 * Added fancy functions to fetch tap and vif names, now the prefix of the tap
   device has been saved in a constant, called TAP_DEVICE_PREFIX.

 * Wait for timeout before nuking frontend xenstore entries.

 * Changed disable_vif_scripts to disable_xl_vif_scripts, it's easier to
   understand.

 * Default nic type set by libxl__device_nic_setdefault is VIF now (was IOEMU).

 * Save nic type and udev script exection inside
   /libxl/devices/<domid>/nic/<devid>/ instead of saving it in the backend path.

Changes since v1:

 * Propagated changes from previous patch (disable_udev and libxl_device_nic_add
   switch).

 * Modified udev rules to add the new env variable.

 * Added support for named interfaces.

Signed-off-by: Roger Pau Monne <roger.pau@xxxxxxxxxx>
---
 docs/man/xl.conf.pod.5                |    7 ++
 tools/examples/xl.conf                |    3 +
 tools/hotplug/Linux/xen-backend.rules |    6 +-
 tools/libxl/libxl.c                   |  125 +++++++++++++-----------------
 tools/libxl/libxl.h                   |    3 +-
 tools/libxl/libxl_create.c            |   22 +++++-
 tools/libxl/libxl_device.c            |  122 +++++++++++++++++++++++++++--
 tools/libxl/libxl_dm.c                |    2 +-
 tools/libxl/libxl_internal.h          |   18 ++++-
 tools/libxl/libxl_linux.c             |  137 ++++++++++++++++++++++++++++++++-
 tools/libxl/libxl_types.idl           |    1 +
 tools/libxl/xl.c                      |    4 +
 tools/libxl/xl.h                      |    1 +
 tools/libxl/xl_cmdimpl.c              |    8 ++-
 14 files changed, 369 insertions(+), 90 deletions(-)

diff --git a/docs/man/xl.conf.pod.5 b/docs/man/xl.conf.pod.5
index 8bd45ea..da8f16f 100644
--- a/docs/man/xl.conf.pod.5
+++ b/docs/man/xl.conf.pod.5
@@ -55,6 +55,13 @@ default.
 
 Default: C<1>
 
+=item B<disable_xl_vif_scripts=BOOLEAN>
+
+If enabled xl will not execute nic hotplug scripts itself, and instead
+relegate this task to udev.
+
+Default: C<0>
+
 =item B<lockfile="PATH">
 
 Sets the path to the lock file used by xl to serialise certain
diff --git a/tools/examples/xl.conf b/tools/examples/xl.conf
index 56d3b3b..172ff80 100644
--- a/tools/examples/xl.conf
+++ b/tools/examples/xl.conf
@@ -12,3 +12,6 @@
 
 # default output format used by "xl list -l"
 #output_format="json"
+
+# default caller of hotplug scripts for vif interfaces
+#disable_xl_vif_scripts=0
diff --git a/tools/hotplug/Linux/xen-backend.rules 
b/tools/hotplug/Linux/xen-backend.rules
index 19f3d27..5dca574 100644
--- a/tools/hotplug/Linux/xen-backend.rules
+++ b/tools/hotplug/Linux/xen-backend.rules
@@ -2,8 +2,8 @@ SUBSYSTEM=="xen-backend", KERNEL=="tap*", 
ENV{HOTPLUG_GATE}="/libxl/$env{XENBUS_
 SUBSYSTEM=="xen-backend", KERNEL=="vbd*", 
ENV{HOTPLUG_GATE}="/libxl/$env{XENBUS_PATH}/disable_udev", 
RUN+="/etc/xen/scripts/block $env{ACTION}"
 SUBSYSTEM=="xen-backend", KERNEL=="vtpm*", RUN+="/etc/xen/scripts/vtpm 
$env{ACTION}"
 SUBSYSTEM=="xen-backend", KERNEL=="vif2-*", RUN+="/etc/xen/scripts/vif2 
$env{ACTION}"
-SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ACTION=="online", 
RUN+="/etc/xen/scripts/vif-setup online type_if=vif"
-SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ACTION=="offline", 
RUN+="/etc/xen/scripts/vif-setup offline type_if=vif"
+SUBSYSTEM=="xen-backend", KERNEL=="vif-*", 
ENV{HOTPLUG_GATE}="/libxl/$env{XENBUS_PATH}/disable_udev", ACTION=="online", 
RUN+="/etc/xen/scripts/vif-setup online type_if=vif"
+SUBSYSTEM=="xen-backend", KERNEL=="vif-*", 
ENV{HOTPLUG_GATE}="/libxl/$env{XENBUS_PATH}/disable_udev", ACTION=="offline", 
RUN+="/etc/xen/scripts/vif-setup offline type_if=vif"
 SUBSYSTEM=="xen-backend", KERNEL=="vscsi*", RUN+="/etc/xen/scripts/vscsi 
$env{ACTION}"
 SUBSYSTEM=="xen-backend", ACTION=="remove", 
ENV{HOTPLUG_GATE}="/libxl/$env{XENBUS_PATH}/disable_udev", 
RUN+="/etc/xen/scripts/xen-hotplug-cleanup"
 KERNEL=="evtchn", NAME="xen/%k"
@@ -13,4 +13,4 @@ KERNEL=="blktap-control", NAME="xen/blktap-2/control", 
MODE="0600"
 KERNEL=="gntdev", NAME="xen/%k", MODE="0600"
 KERNEL=="pci_iomul", NAME="xen/%k", MODE="0600"
 KERNEL=="tapdev[a-z]*", NAME="xen/blktap-2/tapdev%m", MODE="0600"
-SUBSYSTEM=="net", KERNEL=="xentap*", ACTION=="add", 
RUN+="/etc/xen/scripts/vif-setup $env{ACTION} type_if=tap"
+SUBSYSTEM=="net", KERNEL=="emu*", ACTION=="add", 
ENV{HOTPLUG_GATE}="/libxl/$env{XENBUS_PATH}/disable_udev", 
RUN+="/etc/xen/scripts/vif-setup $env{ACTION} type_if=tap"
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index eaa3095..11d3b3b 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1277,46 +1277,6 @@ int libxl__device_disk_setdefault(libxl__gc *gc, 
libxl_device_disk *disk)
     return rc;
 }
 
-static int libxl__device_from_disk(libxl__gc *gc, uint32_t domid,
-                                   libxl_device_disk *disk,
-                                   libxl__device *device)
-{
-    libxl_ctx *ctx = libxl__gc_owner(gc);
-    int devid;
-
-    devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
-    if (devid==-1) {
-        LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Invalid or unsupported"
-               " virtual disk identifier %s", disk->vdev);
-        return ERROR_INVAL;
-    }
-
-    device->backend_domid = disk->backend_domid;
-    device->backend_devid = devid;
-
-    switch (disk->backend) {
-        case LIBXL_DISK_BACKEND_PHY:
-            device->backend_kind = LIBXL__DEVICE_KIND_VBD;
-            break;
-        case LIBXL_DISK_BACKEND_TAP:
-            device->backend_kind = LIBXL__DEVICE_KIND_VBD;
-            break;
-        case LIBXL_DISK_BACKEND_QDISK:
-            device->backend_kind = LIBXL__DEVICE_KIND_QDISK;
-            break;
-        default:
-            LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unrecognized disk backend type: 
%d\n",
-                       disk->backend);
-            return ERROR_INVAL;
-    }
-
-    device->domid = domid;
-    device->devid = devid;
-    device->kind  = LIBXL__DEVICE_KIND_VBD;
-
-    return 0;
-}
-
 int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid,
                           libxl_device_disk *disk,
                           const libxl_asyncop_how *ao_how)
@@ -1483,7 +1443,7 @@ int libxl_device_disk_remove(libxl_ctx *ctx, uint32_t 
domid,
     rc = libxl__device_from_disk(gc, domid, disk, &device);
     if (rc != 0) goto out;
 
-    rc = libxl__initiate_device_remove(egc, ao, &device);
+    rc = libxl__initiate_device_remove(egc, ao, &device, 0);
     switch(rc) {
     case 1:
         /* event added */
@@ -1838,29 +1798,17 @@ int libxl__device_nic_setdefault(libxl__gc *gc, 
libxl_device_nic *nic)
                                   libxl_xen_script_dir_path()) < 0 )
         return ERROR_FAIL;
     if (!nic->nictype)
-        nic->nictype = LIBXL_NIC_TYPE_IOEMU;
-    return 0;
-}
-
-static int libxl__device_from_nic(libxl__gc *gc, uint32_t domid,
-                                  libxl_device_nic *nic,
-                                  libxl__device *device)
-{
-    device->backend_devid    = nic->devid;
-    device->backend_domid    = nic->backend_domid;
-    device->backend_kind     = LIBXL__DEVICE_KIND_VIF;
-    device->devid            = nic->devid;
-    device->domid            = domid;
-    device->kind             = LIBXL__DEVICE_KIND_VIF;
-
+        nic->nictype = LIBXL_NIC_TYPE_VIF;
     return 0;
 }
 
-int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
+int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic,
+                         const libxl_asyncop_how *ao_how)
 {
-    GC_INIT(ctx);
+    AO_CREATE(ctx, domid, ao_how);
     flexarray_t *front;
     flexarray_t *back;
+    flexarray_t *private;
     libxl__device device;
     char *dompath, **l;
     unsigned int nb, rc;
@@ -1873,10 +1821,15 @@ int libxl_device_nic_add(libxl_ctx *ctx, uint32_t 
domid, libxl_device_nic *nic)
         rc = ERROR_NOMEM;
         goto out;
     }
-    back = flexarray_make(16, 1);
+    back = flexarray_make(18, 1);
     if (!back) {
         rc = ERROR_NOMEM;
-        goto out_free;
+        goto out_free_f;
+    }
+    private = flexarray_make(4, 1);
+    if (!private) {
+        rc = ERROR_NOMEM;
+        goto out_free_b;
     }
 
     if (nic->devid == -1) {
@@ -1936,19 +1889,53 @@ int libxl_device_nic_add(libxl_ctx *ctx, uint32_t 
domid, libxl_device_nic *nic)
     flexarray_append(front, "mac");
     flexarray_append(front, libxl__sprintf(gc,
                                     LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac)));
+
+    flexarray_append(private, "type");
+    flexarray_append(private, libxl__sprintf(gc, "%s", 
libxl_nic_type_to_string(
+                                                                
nic->nictype)));
+    /* compatibility addon to keep udev rules */
+    if (!nic->disable_xl_vif_script) {
+        flexarray_append(private, "disable_udev");
+        flexarray_append(private, "y");
+    }
+
     libxl__device_generic_add(gc, &device,
-                            libxl__xs_kvs_of_flexarray(gc, back, back->count),
-                            libxl__xs_kvs_of_flexarray(gc, front, 
front->count),
-                            NULL);
+                    libxl__xs_kvs_of_flexarray(gc, back, back->count),
+                    libxl__xs_kvs_of_flexarray(gc, front, front->count),
+                    libxl__xs_kvs_of_flexarray(gc, private, private->count));
+
+    switch(nic->nictype) {
+    case LIBXL_NIC_TYPE_VIF:
+        if (!nic->disable_xl_vif_script) {
+            rc = libxl__initiate_device_add(egc, ao, &device);
+            if (rc) goto out_free;
+        } else {
+            libxl__ao_complete(egc, ao, 0);
+        }
+        break;
+    case LIBXL_NIC_TYPE_IOEMU:
+        /*
+         * Don't execute hotplug scripts for IOEMU interfaces yet,
+         * we need to launch the device model first.
+         * 
+         * This are actually launched from do_domain_create after the
+         * domain model has been started.
+        */
+    default:
+        libxl__ao_complete(egc, ao, 0);
+        break;
+    }
 
-    /* FIXME: wait for plug */
     rc = 0;
 out_free:
+    flexarray_free(private);
+out_free_b:
     flexarray_free(back);
+out_free_f:
     flexarray_free(front);
 out:
-    GC_FREE;
-    return rc;
+    if (rc) return AO_ABORT(rc);
+    return AO_INPROGRESS;
 }
 
 int libxl_device_nic_remove(libxl_ctx *ctx, uint32_t domid,
@@ -1962,7 +1949,7 @@ int libxl_device_nic_remove(libxl_ctx *ctx, uint32_t 
domid,
     rc = libxl__device_from_nic(gc, domid, nic, &device);
     if (rc != 0) goto out;
 
-    rc = libxl__initiate_device_remove(egc, ao, &device);
+    rc = libxl__initiate_device_remove(egc, ao, &device, 0);
     switch(rc) {
     case 1:
         /* event added */
@@ -2322,7 +2309,7 @@ int libxl_device_vkb_remove(libxl_ctx *ctx, uint32_t 
domid,
     rc = libxl__device_from_vkb(gc, domid, vkb, &device);
     if (rc != 0) goto out;
 
-    rc = libxl__initiate_device_remove(egc, ao, &device);
+    rc = libxl__initiate_device_remove(egc, ao, &device, 0);
     switch(rc) {
     case 1:
         /* event added */
@@ -2467,7 +2454,7 @@ int libxl_device_vfb_remove(libxl_ctx *ctx, uint32_t 
domid,
     rc = libxl__device_from_vfb(gc, domid, vfb, &device);
     if (rc != 0) goto out;
 
-    rc = libxl__initiate_device_remove(egc, ao, &device);
+    rc = libxl__initiate_device_remove(egc, ao, &device, 0);
     switch(rc) {
     case 1:
         /* event added */
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 6687e2e..723c3aa 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -629,7 +629,8 @@ char * libxl_device_disk_local_attach(libxl_ctx *ctx, 
libxl_device_disk *disk);
 int libxl_device_disk_local_detach(libxl_ctx *ctx, libxl_device_disk *disk);
 
 /* Network Interfaces */
-int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic 
*nic);
+int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic,
+                         const libxl_asyncop_how *ao_how);
 int libxl_device_nic_remove(libxl_ctx *ctx, uint32_t domid,
                             libxl_device_nic *nic,
                             const libxl_asyncop_how *ao_how);
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index de598ad..023159b 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -607,7 +607,7 @@ static int do_domain_create(libxl__gc *gc, 
libxl_domain_config *d_config,
         }
     }
     for (i = 0; i < d_config->num_vifs; i++) {
-        ret = libxl_device_nic_add(ctx, domid, &d_config->vifs[i]);
+        ret = libxl_device_nic_add(ctx, domid, &d_config->vifs[i], 0);
         if (ret) {
             LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
                        "cannot add nic %d to domain: %d", i, ret);
@@ -685,6 +685,26 @@ static int do_domain_create(libxl__gc *gc, 
libxl_domain_config *d_config,
                        "device model did not start: %d", ret);
             goto error_out;
         }
+        /* 
+         * Execute hotplug scripts for tap devices, this has to be done
+         * after the domain model has been started.
+        */
+        for (i = 0; i < d_config->num_vifs; i++) {
+            if (d_config->vifs[i].nictype == LIBXL_NIC_TYPE_IOEMU &&
+                !d_config->vifs[i].disable_xl_vif_script) {
+                libxl__device device;
+                ret = libxl__device_from_nic(gc, domid, &d_config->vifs[i],
+                                             &device);
+                if (ret < 0) goto error_out;
+                ret = libxl__device_hotplug(gc, &device, CONNECT);
+                if (ret < 0) {
+                    LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
+                               "unable to launch hotplug script for device: "
+                               "%"PRIu32, device.devid);
+                    goto error_out;
+                }
+            }
+        }
     }
 
     for (i = 0; i < d_config->num_pcidevs; i++)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index aa19fab..7514290 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -47,6 +47,34 @@ char *libxl__device_private_path(libxl__gc *gc, 
libxl__device *device)
                           device->domid, device->devid);
 }
 
+char *libxl__device_vif_name(libxl__gc *gc, libxl__device *dev)
+{
+    char *be_path = libxl__device_private_path(gc, dev);
+    char *ifname = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/%s",
+                                                                   be_path,
+                                                                   "vifname"));
+    if (!ifname) {
+        ifname = libxl__sprintf(gc, "vif%u.%d", dev->domid, dev->devid);
+    }
+
+    return ifname;
+}
+
+char *libxl__device_tap_name(libxl__gc *gc, libxl__device *dev)
+{
+    char *be_path = libxl__device_private_path(gc, dev);
+    char *ifname = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/%s",
+                                                                   be_path,
+                                                                   "vifname"));
+    if (!ifname) {
+        ifname = libxl__sprintf(gc, TAP_DEVICE_PREFIX"%u.%d", dev->domid, 
dev->devid);
+    } else {
+        ifname = libxl__sprintf(gc, TAP_DEVICE_PREFIX"-%s", ifname);
+    }
+
+    return ifname;
+}
+
 int libxl__parse_backend_path(libxl__gc *gc,
                               const char *path,
                               libxl__device *dev)
@@ -269,6 +297,60 @@ char 
*libxl__device_disk_string_of_backend(libxl_disk_backend backend)
     }
 }
 
+int libxl__device_from_nic(libxl__gc *gc, uint32_t domid,
+                           libxl_device_nic *nic,
+                           libxl__device *device)
+{
+    device->backend_devid    = nic->devid;
+    device->backend_domid    = nic->backend_domid;
+    device->backend_kind     = LIBXL__DEVICE_KIND_VIF;
+    device->devid            = nic->devid;
+    device->domid            = domid;
+    device->kind             = LIBXL__DEVICE_KIND_VIF;
+
+    return 0;
+}
+
+int libxl__device_from_disk(libxl__gc *gc, uint32_t domid,
+                            libxl_device_disk *disk,
+                            libxl__device *device)
+{
+    libxl_ctx *ctx = libxl__gc_owner(gc);
+    int devid;
+
+    devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
+    if (devid==-1) {
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Invalid or unsupported"
+               " virtual disk identifier %s", disk->vdev);
+        return ERROR_INVAL;
+    }
+
+    device->backend_domid = disk->backend_domid;
+    device->backend_devid = devid;
+
+    switch (disk->backend) {
+        case LIBXL_DISK_BACKEND_PHY:
+            device->backend_kind = LIBXL__DEVICE_KIND_VBD;
+            break;
+        case LIBXL_DISK_BACKEND_TAP:
+            device->backend_kind = LIBXL__DEVICE_KIND_VBD;
+            break;
+        case LIBXL_DISK_BACKEND_QDISK:
+            device->backend_kind = LIBXL__DEVICE_KIND_QDISK;
+            break;
+        default:
+            LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unrecognized disk backend type: 
%d\n",
+                       disk->backend);
+            return ERROR_INVAL;
+    }
+
+    device->domid = domid;
+    device->devid = devid;
+    device->kind  = LIBXL__DEVICE_KIND_VBD;
+
+    return 0;
+}
+
 int libxl__device_physdisk_major_minor(const char *physpath, int *major, int 
*minor)
 {
     struct stat buf;
@@ -380,6 +462,7 @@ typedef struct {
     libxl__ao *ao;
     libxl__ev_devstate ds;
     libxl__device *dev;
+    int force;
 } libxl__ao_device_remove;
 
 typedef struct {
@@ -406,6 +489,16 @@ static void device_remove_callback(libxl__egc *egc, 
libxl__ev_devstate *ds,
     libxl__gc *gc = &aorm->ao->gc;
     libxl_ctx *ctx = libxl__gc_owner(gc);
 
+    if (rc == ERROR_TIMEDOUT && !aorm->force) {
+        LIBXL__LOG(ctx, LIBXL__LOG_WARNING, "unable to remove device %"PRIu32
+                                            ", destroying frontend to force "
+                                            "backend disconnection",
+                                            aorm->dev->devid);
+        libxl__ev_devstate_cancel(gc, &aorm->ds);
+        libxl__initiate_device_remove(egc, aorm->ao, aorm->dev, 1);
+        return;
+    }
+
     rc = libxl__device_hotplug(gc, aorm->dev, DISCONNECT);
     if (rc)
         LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unable to execute hotplug script 
for"
@@ -445,26 +538,34 @@ static void device_add_callback(libxl__egc *egc, 
libxl__ev_devstate *ds,
  * libxl__ao_complete when necessary (if no events are added).
  */
 int libxl__initiate_device_remove(libxl__egc *egc, libxl__ao *ao,
-                                  libxl__device *dev)
+                                  libxl__device *dev, int force)
 {
     AO_GC;
     libxl_ctx *ctx = libxl__gc_owner(gc);
-    xs_transaction_t t;
+    xs_transaction_t t = 0;
     char *be_path = libxl__device_backend_path(gc, dev);
     char *state_path = libxl__sprintf(gc, "%s/state", be_path);
-    char *state = libxl__xs_read(gc, XBT_NULL, state_path);
+    char *state;
     int rc = 0;
     libxl__ao_device_remove *aorm = 0;
 
+    if (force)
+        libxl__xs_path_cleanup(gc, libxl__device_frontend_path(gc, dev));
+        /*
+         * Nuke frontend to force backend teardown
+         * It's not pretty, but it's the only way that seems to work for all
+         * types of backends
+         */
+
+retry_transaction:
+    t = xs_transaction_start(ctx->xsh);
+    state = libxl__xs_read(gc, t, state_path);
     if (!state)
         goto out_ok;
-    if (atoi(state) != 4) {
+    if (atoi(state) == XenbusStateClosed)
         libxl__device_destroy_tapdisk(gc, be_path);
         goto out_ok;
-    }
 
-retry_transaction:
-    t = xs_transaction_start(ctx->xsh);
     xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/online", be_path), "0", 
strlen("0"));
     xs_write(ctx->xsh, t, state_path, "5", strlen("5"));
     if (!xs_transaction_end(ctx->xsh, t, 0)) {
@@ -475,12 +576,15 @@ retry_transaction:
             goto out_fail;
         }
     }
+    /* mark transaction as ended, to prevent double closing it on out_ok */
+    t = 0;
 
     libxl__device_destroy_tapdisk(gc, be_path);
 
     aorm = libxl__zalloc(gc, sizeof(*aorm));
     aorm->ao = ao;
     aorm->dev = dev;
+    aorm->force = force;
     libxl__ev_devstate_init(&aorm->ds);
 
     rc = libxl__ev_devstate_wait(gc, &aorm->ds, device_remove_callback,
@@ -496,8 +600,8 @@ retry_transaction:
     return rc;
 
  out_ok:
+    if (t) xs_transaction_end(ctx->xsh, t, 0);
     rc = libxl__device_hotplug(gc, dev, DISCONNECT);
-    libxl__xs_path_cleanup(gc, libxl__device_frontend_path(gc, dev));
     libxl__xs_path_cleanup(gc, be_path);
     libxl__xs_path_cleanup(gc, libxl__device_private_path(gc, dev));
     return 0;
@@ -596,7 +700,7 @@ int libxl__devices_destroy(libxl__egc *egc, libxl__ao *ao, 
uint32_t domid)
                 dev.domid = domid;
                 dev.kind = kind;
                 dev.devid = atoi(devs[j]);
-                rc = libxl__initiate_device_remove(egc, ao, &dev);
+                rc = libxl__initiate_device_remove(egc, ao, &dev, 0);
                 switch(rc) {
                 case 1:
                     events++;
diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index 4ce58f6..8cf9d9d 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -794,7 +794,7 @@ retry_transaction:
             goto out_free;
     }
     for (i = 0; i < dm_config.num_vifs; i++) {
-        ret = libxl_device_nic_add(ctx, dm_domid, &dm_config.vifs[i]);
+        ret = libxl_device_nic_add(ctx, dm_domid, &dm_config.vifs[i], 0);
         if (ret)
             goto out_free;
     }
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 95d5c40..68c7514 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -84,6 +84,7 @@
 #define STUBDOM_CONSOLE_RESTORE 2
 #define STUBDOM_CONSOLE_SERIAL 3
 #define STUBDOM_SPECIAL_CONSOLES 3
+#define TAP_DEVICE_PREFIX "emu"
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
 
@@ -765,6 +766,12 @@ _hidden int libxl__domain_pvcontrol_write(libxl__gc *gc, 
xs_transaction_t t,
 _hidden char *libxl__device_disk_string_of_backend(libxl_disk_backend backend);
 _hidden char *libxl__device_disk_string_of_format(libxl_disk_format format);
 _hidden int libxl__device_disk_set_backend(libxl__gc*, libxl_device_disk*);
+_hidden int libxl__device_from_nic(libxl__gc *gc, uint32_t domid,
+                                   libxl_device_nic *nic,
+                                   libxl__device *device);
+_hidden int libxl__device_from_disk(libxl__gc *gc, uint32_t domid,
+                                    libxl_device_disk *disk,
+                                    libxl__device *device);
 
 _hidden int libxl__device_physdisk_major_minor(const char *physpath, int 
*major, int *minor);
 _hidden int libxl__device_disk_dev_number(const char *virtpath,
@@ -775,10 +782,13 @@ _hidden int libxl__device_console_add(libxl__gc *gc, 
uint32_t domid,
                                       libxl__domain_build_state *state);
 
 _hidden int libxl__device_generic_add(libxl__gc *gc, libxl__device *device,
-                             char **bents, char **fents, char **private);
+                                      char **bents, char **fents,
+                                      char **private);
 _hidden char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device);
-_hidden char *libxl__device_private_path(libxl__gc *gc, libxl__device *device);
 _hidden char *libxl__device_frontend_path(libxl__gc *gc, libxl__device 
*device);
+_hidden char *libxl__device_private_path(libxl__gc *gc, libxl__device *device);
+_hidden char *libxl__device_vif_name(libxl__gc *gc, libxl__device *dev);
+_hidden char *libxl__device_tap_name(libxl__gc *gc, libxl__device *dev);
 _hidden int libxl__parse_backend_path(libxl__gc *gc, const char *path,
                                       libxl__device *dev);
 _hidden int libxl__device_destroy(libxl__gc *gc, libxl__device *dev);
@@ -803,8 +813,8 @@ _hidden int libxl__wait_for_backend(libxl__gc *gc, char 
*be_path, char *state);
  * this is done, the ao will be completed.  An error
  * return from libxl__initiate_device_remove means that the ao
  * will _not_ be completed and the caller must do so. */
-_hidden int libxl__initiate_device_remove(libxl__egc*, libxl__ao*,
-                                          libxl__device *dev);
+_hidden int libxl__initiate_device_remove(libxl__egc *egc, libxl__ao *ao,
+                                          libxl__device *dev, int force);
 
 /* Arranges that dev will be added to the guest, and the
  * hotplug scripts will be executed (if necessary). When
diff --git a/tools/libxl/libxl_linux.c b/tools/libxl/libxl_linux.c
index 7c107dc..745a11a 100644
--- a/tools/libxl/libxl_linux.c
+++ b/tools/libxl/libxl_linux.c
@@ -27,6 +27,30 @@ int libxl__try_phy_backend(mode_t st_mode)
 }
 
 /* Hotplug scripts helpers */
+
+static libxl_nic_type get_nic_type(libxl__gc *gc, libxl__device *dev)
+{
+    libxl_ctx *ctx = libxl__gc_owner(gc);
+    char *snictype, *pr_path;
+    libxl_nic_type nictype;
+
+    pr_path = libxl__device_private_path(gc, dev);
+    snictype = libxl__xs_read(gc, XBT_NULL,
+                            libxl__sprintf(gc, "%s/%s", pr_path, "type"));
+    if (!snictype) {
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unable to read nictype from %s",
+                                          pr_path);
+        return -1;
+    }
+    if (libxl_nic_type_from_string(snictype, &nictype) < 0) {
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unable to parse nictype from %s",
+                                          pr_path);
+        return -1;
+    }
+
+    return nictype;
+}
+
 static char **get_hotplug_env(libxl__gc *gc, libxl__device *dev)
 {
     libxl_ctx *ctx = libxl__gc_owner(gc);
@@ -44,7 +68,7 @@ static char **get_hotplug_env(libxl__gc *gc, libxl__device 
*dev)
         return NULL;
     }
 
-    f_env = flexarray_make(9, 1);
+    f_env = flexarray_make(13, 1);
     if (!f_env) {
         LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
                    "unable to create environment array");
@@ -63,6 +87,19 @@ static char **get_hotplug_env(libxl__gc *gc, libxl__device 
*dev)
                   dev->domid, dev->devid));
     flexarray_set(f_env, nr++, "XENBUS_BASE_PATH");
     flexarray_set(f_env, nr++, "backend");
+    if (dev->backend_kind == LIBXL__DEVICE_KIND_VIF) {
+        switch (get_nic_type(gc, dev)) {
+        case LIBXL_NIC_TYPE_IOEMU:
+            flexarray_set(f_env, nr++, "INTERFACE");
+            flexarray_set(f_env, nr++, libxl__device_tap_name(gc, dev));
+        case LIBXL_NIC_TYPE_VIF:
+            flexarray_set(f_env, nr++, "vif");
+            flexarray_set(f_env, nr++, libxl__device_vif_name(gc, dev));
+            break;
+        default:
+            return NULL;
+        }
+    }
 
     flexarray_set(f_env, nr++, NULL);
 
@@ -126,6 +163,101 @@ out_free:
     return rc;
 }
 
+static int libxl__hotplug_nic(libxl__gc *gc, libxl__device *dev,
+                              libxl__hotplug_action action)
+{
+    libxl_ctx *ctx = libxl__gc_owner(gc);
+    char *be_path = libxl__device_backend_path(gc, dev);
+    char *what, *script;
+    char **args, **env;
+    int nr = 0, rc = 0;
+    libxl_nic_type nictype;
+    flexarray_t *vif_args, *tap_args;
+
+    script = libxl__xs_read(gc, XBT_NULL,
+                            libxl__sprintf(gc, "%s/%s", be_path, "script"));
+    if (!script) {
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unable to read script from %s",
+                                          be_path);
+        return -1;
+    }
+
+    nictype = get_nic_type(gc, dev);
+    if (nictype < 0) {
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "error when fetching nic type");
+        return -1;
+    }
+
+    env = get_hotplug_env(gc, dev);
+    if (!env)
+        return -1;
+
+    vif_args = flexarray_make(4, 1);
+    if (!vif_args) {
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unable to create arguments array");
+        return -1;
+    }
+    tap_args = flexarray_make(4, 1);
+    if (!tap_args) {
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unable to create arguments array");
+        return -1;
+    }
+
+    switch(nictype) {
+    case LIBXL_NIC_TYPE_IOEMU:
+        flexarray_set(tap_args, nr++, script);
+        flexarray_set(tap_args, nr++, action == CONNECT ? "add" : "remove");
+        flexarray_set(tap_args, nr++, libxl__sprintf(gc, "type_if=tap"));
+        flexarray_set(tap_args, nr++, NULL);
+        args = (char **) flexarray_contents(tap_args);
+        what = libxl__sprintf(gc, "%s %s", args[0],
+                              action == CONNECT ? "connect" : "disconnect");
+        LIBXL__LOG(ctx, LIBXL__LOG_DEBUG,
+                   "Calling hotplug script: %s %s %s",
+                   args[0], args[1], args[2]);
+        rc = libxl__hotplug_exec(gc, args[0], args, env);
+        if (rc) {
+            LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unable execute hotplug scripts "
+                                              "for vif device %"PRIu32,
+                                              dev->devid);
+            goto out;
+        }
+        free(args);
+        nr = 0;
+    case LIBXL_NIC_TYPE_VIF:
+        flexarray_set(vif_args, nr++, script);
+        flexarray_set(vif_args, nr++, action == CONNECT ? "online" : 
"offline");
+        flexarray_set(vif_args, nr++, libxl__sprintf(gc, "type_if=vif"));
+        flexarray_set(vif_args, nr++, NULL);
+        args = (char **) flexarray_contents(vif_args);
+        what = libxl__sprintf(gc, "%s %s", args[0],
+                              action == CONNECT ? "connect" : "disconnect");
+        LIBXL__LOG(ctx, LIBXL__LOG_DEBUG,
+                   "Calling hotplug script: %s %s %s",
+                   args[0], args[1], args[2]);
+        rc = libxl__hotplug_exec(gc, args[0], args, env);
+        if (rc) {
+            LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unable execute hotplug scripts "
+                                              "for vif device %"PRIu32,
+                                              dev->devid);
+            goto out;
+        }
+        break;
+    default:
+        /* Unknown network type */
+        LIBXL__LOG(ctx, LIBXL__LOG_WARNING, "unknown network card type with "
+                                            "id %"PRIu32, dev->devid);
+        return 0;
+    }
+
+    rc = 0;
+
+out:
+    free(env);
+    free(args);
+    return rc;
+}
+
 int libxl__device_hotplug(libxl__gc *gc, libxl__device *dev,
                           libxl__hotplug_action action)
 {
@@ -135,6 +267,9 @@ int libxl__device_hotplug(libxl__gc *gc, libxl__device *dev,
     case LIBXL__DEVICE_KIND_VBD:
         rc = libxl__hotplug_disk(gc, dev, action);
         break;
+    case LIBXL__DEVICE_KIND_VIF:
+        rc = libxl__hotplug_nic(gc, dev, action);
+        break;
     default:
         rc = 0;
         break;
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 5cf9708..0b2c832 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -343,6 +343,7 @@ libxl_device_nic = Struct("device_nic", [
     ("ifname", string),
     ("script", string),
     ("nictype", libxl_nic_type),
+    ("disable_xl_vif_script", integer),
     ])
 
 libxl_device_pci = Struct("device_pci", [
diff --git a/tools/libxl/xl.c b/tools/libxl/xl.c
index a6ffd25..2f96468 100644
--- a/tools/libxl/xl.c
+++ b/tools/libxl/xl.c
@@ -35,6 +35,7 @@
 xentoollog_logger_stdiostream *logger;
 int dryrun_only;
 int autoballoon = 1;
+int disable_xl_vif_scripts = 0;
 char *lockfile;
 char *default_vifscript = NULL;
 char *default_bridge = NULL;
@@ -66,6 +67,9 @@ static void parse_global_config(const char *configfile,
     if (!xlu_cfg_get_long (config, "autoballoon", &l, 0))
         autoballoon = l;
 
+    if (!xlu_cfg_get_long (config, "disable_xl_vif_scripts", &l, 0))
+        disable_xl_vif_scripts = l;
+
     if (!xlu_cfg_get_string (config, "lockfile", &buf, 0))
         lockfile = strdup(buf);
     else {
diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h
index 7e258d5..b60cd12 100644
--- a/tools/libxl/xl.h
+++ b/tools/libxl/xl.h
@@ -109,6 +109,7 @@ void postfork(void);
 
 /* global options */
 extern int autoballoon;
+extern int disable_xl_vif_scripts;
 extern int dryrun_only;
 extern char *lockfile;
 extern char *default_vifscript;
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 0bc3ac2..704d938 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -847,6 +847,12 @@ static void parse_config_data(const char 
*configfile_filename_report,
                 nic->script = strdup(default_vifscript);
             }
 
+            /*
+             * Disable nic network script calling, to allow the user
+             * to attach the nic backend from a different domain.
+             */
+            nic->disable_xl_vif_script = disable_xl_vif_scripts;
+
            if (default_bridge) {
                free(nic->bridge);
                nic->bridge = strdup(default_bridge);
@@ -4916,7 +4922,7 @@ int main_networkattach(int argc, char **argv)
             return 1;
         }
     }
-    if (libxl_device_nic_add(ctx, domid, &nic)) {
+    if (libxl_device_nic_add(ctx, domid, &nic, 0)) {
         fprintf(stderr, "libxl_device_nic_add failed.\n");
         return 1;
     }
-- 
1.7.7.5 (Apple Git-26)


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.