示例#1
0
static char *nodeDeviceGetParent(virNodeDevicePtr dev)
{
    virDeviceMonitorStatePtr driver = dev->conn->devMonPrivateData;
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

    nodeDeviceLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
    nodeDeviceUnlock(driver);

    if (!obj) {
        virNodeDeviceReportError(VIR_ERR_NO_NODE_DEVICE,
                                 _("no node device with matching name '%s'"),
                                 dev->name);
        goto cleanup;
    }

    if (obj->def->parent) {
        ret = strdup(obj->def->parent);
        if (!ret)
            virReportOOMError();
    } else {
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 "%s", _("no parent for this device"));
    }

cleanup:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}
示例#2
0
static virNodeDeviceDefPtr
virNodeDeviceDefParseXML(xmlXPathContextPtr ctxt, int create)
{
    virNodeDeviceDefPtr def;
    virNodeDevCapsDefPtr *next_cap;
    xmlNodePtr *nodes;
    int n, i;

    if (VIR_ALLOC(def) < 0) {
        virReportOOMError();
        return NULL;
    }

    /* Extract device name */
    if (create == EXISTING_DEVICE) {
        def->name = virXPathString("string(./name[1])", ctxt);

        if (!def->name) {
            virNodeDeviceReportError(VIR_ERR_NO_NAME, NULL);
            goto error;
        }
    } else {
        def->name = strdup("new device");

        if (!def->name) {
            virReportOOMError();
            goto error;
        }
    }

    /* Extract device parent, if any */
    def->parent = virXPathString("string(./parent[1])", ctxt);

    /* Parse device capabilities */
    nodes = NULL;
    if ((n = virXPathNodeSet("./capability", ctxt, &nodes)) <= 0) {
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 _("no device capabilities for '%s'"),
                                 def->name);
        goto error;
    }

    next_cap = &def->caps;
    for (i = 0 ; i < n ; i++) {
        *next_cap = virNodeDevCapsDefParseXML(ctxt, def, nodes[i], create);
        if (!*next_cap) {
            VIR_FREE(nodes);
            goto error;
        }

        next_cap = &(*next_cap)->next;
    }
    VIR_FREE(nodes);

    return def;

 error:
    virNodeDeviceDefFree(def);
    return NULL;
}
示例#3
0
/*
 * Return fc_host dev's WWNN and WWPN
 */
int
virNodeDeviceGetWWNs(virNodeDeviceDefPtr def,
                     char **wwnn,
                     char **wwpn)
{
    virNodeDevCapsDefPtr cap = NULL;
    int ret = 0;

    cap = def->caps;
    while (cap != NULL) {
        if (cap->type == VIR_NODE_DEV_CAP_SCSI_HOST &&
            cap->data.scsi_host.flags & VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST) {
            *wwnn = strdup(cap->data.scsi_host.wwnn);
            *wwpn = strdup(cap->data.scsi_host.wwpn);
            break;
        }

        cap = cap->next;
    }

    if (cap == NULL) {
        virNodeDeviceReportError(VIR_ERR_NO_SUPPORT,
                                 "%s", _("Device is not a fibre channel HBA"));
        ret = -1;
    } else if (*wwnn == NULL || *wwpn == NULL) {
        /* Free the other one, if allocated... */
        VIR_FREE(wwnn);
        VIR_FREE(wwpn);
        ret = -1;
        virReportOOMError();
    }

    return ret;
}
示例#4
0
virNodeDeviceDefPtr
virNodeDeviceDefParseNode(xmlDocPtr xml,
                          xmlNodePtr root,
                          int create)
{
    xmlXPathContextPtr ctxt = NULL;
    virNodeDeviceDefPtr def = NULL;

    if (!xmlStrEqual(root->name, BAD_CAST "device")) {
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 "%s", _("incorrect root element"));
        return NULL;
    }

    ctxt = xmlXPathNewContext(xml);
    if (ctxt == NULL) {
        virReportOOMError();
        goto cleanup;
    }

    ctxt->node = root;
    def = virNodeDeviceDefParseXML(ctxt, create);

cleanup:
    xmlXPathFreeContext(ctxt);
    return def;
}
示例#5
0
static char *nodeDeviceDumpXML(virNodeDevicePtr dev,
                               unsigned int flags ATTRIBUTE_UNUSED)
{
    virDeviceMonitorStatePtr driver = dev->conn->devMonPrivateData;
    virNodeDeviceObjPtr obj;
    char *ret = NULL;

    nodeDeviceLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
    nodeDeviceUnlock(driver);

    if (!obj) {
        virNodeDeviceReportError(VIR_ERR_NO_NODE_DEVICE,
                                 _("no node device with matching name '%s'"),
                                 dev->name);
        goto cleanup;
    }

    update_driver_name(obj);
    update_caps(obj);

    ret = virNodeDeviceDefFormat(obj->def);

cleanup:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}
示例#6
0
static int
virNodeDevCapScsiTargetParseXML(xmlXPathContextPtr ctxt,
                                virNodeDeviceDefPtr def,
                                xmlNodePtr node,
                                union _virNodeDevCapData *data)
{
    xmlNodePtr orignode;
    int ret = -1;

    orignode = ctxt->node;
    ctxt->node = node;

    data->scsi_target.name = virXPathString("string(./name[1])", ctxt);
    if (!data->scsi_target.name) {
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 _("no target name supplied for '%s'"),
                                 def->name);
        goto out;
    }

    ret = 0;

out:
    ctxt->node = orignode;
    return ret;
}
示例#7
0
static int nodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
    virDeviceMonitorStatePtr driver = dev->conn->devMonPrivateData;
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

    nodeDeviceLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
    nodeDeviceUnlock(driver);

    if (!obj) {
        virNodeDeviceReportError(VIR_ERR_NO_NODE_DEVICE,
                                 _("no node device with matching name '%s'"),
                                 dev->name);
        goto cleanup;
    }

    for (caps = obj->def->caps; caps; caps = caps->next)
        ++ncaps;
    ret = ncaps;

cleanup:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}
示例#8
0
static int
nodeDeviceDestroy(virNodeDevicePtr dev)
{
    int ret = -1;
    virDeviceMonitorStatePtr driver = dev->conn->devMonPrivateData;
    virNodeDeviceObjPtr obj = NULL;
    char *parent_name = NULL, *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;

    nodeDeviceLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
    nodeDeviceUnlock(driver);

    if (!obj) {
        virNodeDeviceReportError(VIR_ERR_NO_NODE_DEVICE, NULL);
        goto out;
    }

    if (virNodeDeviceGetWWNs(obj->def, &wwnn, &wwpn) == -1) {
        goto out;
    }

    parent_name = strdup(obj->def->parent);

    /* virNodeDeviceGetParentHost will cause the device object's lock to be
     * taken, so we have to dup the parent's name and drop the lock
     * before calling it.  We don't need the reference to the object
     * any more once we have the parent's name.  */
    virNodeDeviceObjUnlock(obj);
    obj = NULL;

    if (parent_name == NULL) {
        virReportOOMError();
        goto out;
    }

    if (virNodeDeviceGetParentHost(&driver->devs,
                                   dev->name,
                                   parent_name,
                                   &parent_host) == -1) {
        goto out;
    }

    if (nodeDeviceVportCreateDelete(parent_host,
                                    wwpn,
                                    wwnn,
                                    VPORT_DELETE) == -1) {
        goto out;
    }

    ret = 0;
out:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    VIR_FREE(parent_name);
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return ret;
}
示例#9
0
/*
 * Return the NPIV dev's parent device name
 */
int
virNodeDeviceGetParentHost(const virNodeDeviceObjListPtr devs,
                           const char *dev_name,
                           const char *parent_name,
                           int *parent_host)
{
    virNodeDeviceObjPtr parent = NULL;
    virNodeDevCapsDefPtr cap = NULL;
    int ret = 0;

    parent = virNodeDeviceFindByName(devs, parent_name);
    if (parent == NULL) {
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 _("Could not find parent device for '%s'"),
                                 dev_name);
        ret = -1;
        goto out;
    }

    cap = parent->def->caps;
    while (cap != NULL) {
        if (cap->type == VIR_NODE_DEV_CAP_SCSI_HOST &&
            (cap->data.scsi_host.flags &
             VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS)) {
                *parent_host = cap->data.scsi_host.host;
                break;
        }

        cap = cap->next;
    }

    if (cap == NULL) {
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 _("Parent device %s is not capable "
                                   "of vport operations"),
                                 parent->def->name);
        ret = -1;
    }

    virNodeDeviceObjUnlock(parent);

out:
    return ret;
}
示例#10
0
static int
virNodeDevCapSystemParseXML(xmlXPathContextPtr ctxt,
                            virNodeDeviceDefPtr def,
                            xmlNodePtr node,
                            union _virNodeDevCapData *data)
{
    xmlNodePtr orignode;
    int ret = -1;
    char *tmp;

    orignode = ctxt->node;
    ctxt->node = node;

    data->system.product_name = virXPathString("string(./product[1])", ctxt);

    data->system.hardware.vendor_name = virXPathString("string(./hardware/vendor[1])", ctxt);
    data->system.hardware.version     = virXPathString("string(./hardware/version[1])", ctxt);
    data->system.hardware.serial      = virXPathString("string(./hardware/serial[1])", ctxt);

    tmp = virXPathString("string(./hardware/uuid[1])", ctxt);
    if (!tmp) {
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 _("no system UUID supplied for '%s'"), def->name);
        goto out;
    }

    if (virUUIDParse(tmp, data->system.hardware.uuid) < 0) {
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 _("malformed uuid element for '%s'"), def->name);
        VIR_FREE(tmp);
        goto out;
    }
    VIR_FREE(tmp);

    data->system.firmware.vendor_name  = virXPathString("string(./firmware/vendor[1])", ctxt);
    data->system.firmware.version      = virXPathString("string(./firmware/version[1])", ctxt);
    data->system.firmware.release_date = virXPathString("string(./firmware/release_date[1])", ctxt);

    ret = 0;
out:
    ctxt->node = orignode;
    return ret;
}
示例#11
0
static int
virNodeDevCapNetParseXML(xmlXPathContextPtr ctxt,
                         virNodeDeviceDefPtr def,
                         xmlNodePtr node,
                         union _virNodeDevCapData *data)
{
    xmlNodePtr orignode;
    int ret = -1;
    char *tmp;

    orignode = ctxt->node;
    ctxt->node = node;

    data->net.ifname = virXPathString("string(./interface[1])", ctxt);
    if (!data->net.ifname) {
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 _("no network interface supplied for '%s'"),
                                 def->name);
        goto out;
    }

    data->net.address = virXPathString("string(./address[1])", ctxt);

    data->net.subtype = VIR_NODE_DEV_CAP_NET_LAST;

    tmp = virXPathString("string(./capability/@type)", ctxt);
    if (tmp) {
        int val = virNodeDevNetCapTypeFromString(tmp);
        VIR_FREE(tmp);
        if (val < 0) {
            virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                     _("invalid network type supplied for '%s'"),
                                     def->name);
            goto out;
        }
        data->net.subtype = val;
    }

    ret = 0;
out:
    ctxt->node = orignode;
    return ret;
}
示例#12
0
static virNodeDevicePtr
nodeDeviceCreateXML(virConnectPtr conn,
                    const char *xmlDesc,
                    unsigned int flags ATTRIBUTE_UNUSED)
{
    virDeviceMonitorStatePtr driver = conn->devMonPrivateData;
    virNodeDeviceDefPtr def = NULL;
    char *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;
    virNodeDevicePtr dev = NULL;

    nodeDeviceLock(driver);

    def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE);
    if (def == NULL) {
        goto cleanup;
    }

    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) == -1) {
        goto cleanup;
    }

    if (virNodeDeviceGetParentHost(&driver->devs,
                                   def->name,
                                   def->parent,
                                   &parent_host) == -1) {
        goto cleanup;
    }

    if (nodeDeviceVportCreateDelete(parent_host,
                                    wwpn,
                                    wwnn,
                                    VPORT_CREATE) == -1) {
        goto cleanup;
    }

    dev = find_new_device(conn, wwnn, wwpn);
    /* We don't check the return value, because one way or another,
     * we're returning what we get... */

    if (dev == NULL) {
        virNodeDeviceReportError(VIR_ERR_NO_NODE_DEVICE, NULL);
    }

cleanup:
    nodeDeviceUnlock(driver);
    virNodeDeviceDefFree(def);
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return dev;
}
示例#13
0
static int
get_time(time_t *t)
{
    int ret = 0;

    *t = time(NULL);
    if (*t == (time_t)-1) {
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 "%s", _("Could not get current time"));

        *t = 0;
        ret = -1;
    }

    return ret;
}
示例#14
0
static int
virNodeDevCapsDefParseString(const char *xpath,
                             xmlXPathContextPtr ctxt,
                             char **string,
                             virNodeDeviceDefPtr def,
                             const char *missing_error_fmt)
{
    char *s;

    s = virXPathString(xpath, ctxt);
    if (s == NULL) {
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 missing_error_fmt,
                                 def->name);
        return -1;
    }

    *string = s;
    return 0;
}
示例#15
0
static int
nodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
    virDeviceMonitorStatePtr driver = dev->conn->devMonPrivateData;
    virNodeDeviceObjPtr obj;
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
    int ret = -1;

    nodeDeviceLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
    nodeDeviceUnlock(driver);

    if (!obj) {
        virNodeDeviceReportError(VIR_ERR_NO_NODE_DEVICE,
                                 _("no node device with matching name '%s'"),
                                 dev->name);
        goto cleanup;
    }

    for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) {
        names[ncaps] = strdup(virNodeDevCapTypeToString(caps->type));
        if (names[ncaps++] == NULL) {
            virReportOOMError();
            goto cleanup;
        }
    }
    ret = ncaps;

cleanup:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    if (ret == -1) {
        --ncaps;
        while (--ncaps >= 0)
            VIR_FREE(names[ncaps]);
    }
    return ret;
}
示例#16
0
static int
virNodeDevCapsDefParseHexId(const char *xpath,
                            xmlXPathContextPtr ctxt,
                            unsigned *value,
                            virNodeDeviceDefPtr def,
                            const char *missing_error_fmt,
                            const char *invalid_error_fmt)
{
    int ret;
    unsigned long val;

    ret = virXPathULongHex(xpath, ctxt, &val);
    if (ret < 0) {
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 ret == -1 ? missing_error_fmt : invalid_error_fmt,
                                 def->name);
        return -1;
    }

    *value = val;
    return 0;
}
示例#17
0
static virNodeDevicePtr nodeDeviceLookupByName(virConnectPtr conn,
                                               const char *name)
{
    virDeviceMonitorStatePtr driver = conn->devMonPrivateData;
    virNodeDeviceObjPtr obj;
    virNodeDevicePtr ret = NULL;

    nodeDeviceLock(driver);
    obj = virNodeDeviceFindByName(&driver->devs, name);
    nodeDeviceUnlock(driver);

    if (!obj) {
        virNodeDeviceReportError(VIR_ERR_NO_NODE_DEVICE, NULL);
        goto cleanup;
    }

    ret = virGetNodeDevice(conn, name);

cleanup:
    if (obj)
        virNodeDeviceObjUnlock(obj);
    return ret;
}
示例#18
0
virNodeDeviceObjPtr virNodeDeviceAssignDef(virNodeDeviceObjListPtr devs,
                                           const virNodeDeviceDefPtr def)
{
    virNodeDeviceObjPtr device;

    if ((device = virNodeDeviceFindByName(devs, def->name))) {
        virNodeDeviceDefFree(device->def);
        device->def = def;
        return device;
    }

    if (VIR_ALLOC(device) < 0) {
        virReportOOMError();
        return NULL;
    }

    if (virMutexInit(&device->lock) < 0) {
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 "%s", _("cannot initialize mutex"));
        VIR_FREE(device);
        return NULL;
    }
    virNodeDeviceObjLock(device);
    device->def = def;

    if (VIR_REALLOC_N(devs->objs, devs->count+1) < 0) {
        device->def = NULL;
        virNodeDeviceObjUnlock(device);
        virNodeDeviceObjFree(device);
        virReportOOMError();
        return NULL;
    }
    devs->objs[devs->count++] = device;

    return device;

}
示例#19
0
static int
nodeDeviceVportCreateDelete(const int parent_host,
                            const char *wwpn,
                            const char *wwnn,
                            int operation)
{
    int retval = 0;
    char *operation_path = NULL, *vport_name = NULL;
    const char *operation_file = NULL;
    struct stat st;

    switch (operation) {
    case VPORT_CREATE:
        operation_file = LINUX_SYSFS_VPORT_CREATE_POSTFIX;
        break;
    case VPORT_DELETE:
        operation_file = LINUX_SYSFS_VPORT_DELETE_POSTFIX;
        break;
    default:
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 _("Invalid vport operation (%d)"), operation);
        retval = -1;
        goto cleanup;
        break;
    }

    if (virAsprintf(&operation_path,
                    "%shost%d%s",
                    LINUX_SYSFS_FC_HOST_PREFIX,
                    parent_host,
                    operation_file) < 0) {

        virReportOOMError();
        retval = -1;
        goto cleanup;
    }

    if (stat(operation_path, &st) != 0) {
        VIR_FREE(operation_path);
        if (virAsprintf(&operation_path,
                        "%shost%d%s",
                        LINUX_SYSFS_SCSI_HOST_PREFIX,
                        parent_host,
                        operation_file) < 0) {
            virReportOOMError();
            retval = -1;
            goto cleanup;
        }

        if (stat(operation_path, &st) != 0) {
            VIR_ERROR(_("No vport operation path found for host%d"),
                      parent_host);
            retval = -1;
            goto cleanup;
        }
    }

    VIR_DEBUG("Vport operation path is '%s'", operation_path);

    if (virAsprintf(&vport_name,
                    "%s:%s",
                    wwpn,
                    wwnn) < 0) {

        virReportOOMError();
        retval = -1;
        goto cleanup;
    }

    if (virFileWriteStr(operation_path, vport_name, 0) == -1) {
        virReportSystemError(errno,
                             _("Write of '%s' to '%s' during "
                               "vport create/delete failed"),
                             vport_name, operation_path);
        retval = -1;
    }

cleanup:
    VIR_FREE(vport_name);
    VIR_FREE(operation_path);
    VIR_DEBUG("%s", _("Vport operation complete"));
    return retval;
}
示例#20
0
static int
virNodeDevCapScsiHostParseXML(xmlXPathContextPtr ctxt,
                              virNodeDeviceDefPtr def,
                              xmlNodePtr node,
                              union _virNodeDevCapData *data,
                              int create)
{
    xmlNodePtr orignode, *nodes = NULL;
    int ret = -1, n = 0, i;
    char *type = NULL;

    orignode = ctxt->node;
    ctxt->node = node;

    if (create == EXISTING_DEVICE &&
        virNodeDevCapsDefParseULong("number(./host[1])", ctxt,
                                    &data->scsi_host.host, def,
                                    _("no SCSI host ID supplied for '%s'"),
                                    _("invalid SCSI host ID supplied for '%s'")) < 0) {
        goto out;
    }

    if ((n = virXPathNodeSet("./capability", ctxt, &nodes)) < 0) {
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 _("error parsing SCSI host capabilities for '%s'"),
                                 def->name);
        goto out;
    }

    for (i = 0 ; i < n ; i++) {
        type = virXMLPropString(nodes[i], "type");

        if (!type) {
            virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                     _("missing SCSI host capability type for '%s'"),
                                     def->name);
            goto out;
        }

        if (STREQ(type, "vport_ops")) {

            data->scsi_host.flags |= VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS;

        } else if (STREQ(type, "fc_host")) {

            xmlNodePtr orignode2;

            data->scsi_host.flags |= VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST;

            orignode2 = ctxt->node;
            ctxt->node = nodes[i];

            if (virNodeDevCapsDefParseString("string(./wwnn[1])",
                                             ctxt,
                                             &data->scsi_host.wwnn,
                                             def,
                                             _("no WWNN supplied for '%s'")) < 0) {
                goto out;
            }

            if (virNodeDevCapsDefParseString("string(./wwpn[1])",
                                             ctxt,
                                             &data->scsi_host.wwpn,
                                             def,
                                             _("no WWPN supplied for '%s'")) < 0) {
                goto out;
            }

            ctxt->node = orignode2;

        } else {
            virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                     _("unknown SCSI host capability type '%s' for '%s'"),
                                     type, def->name);
            goto out;
        }

        VIR_FREE(type);
    }

    ret = 0;

out:
    VIR_FREE(type);
    ctxt->node = orignode;
    VIR_FREE(nodes);
    return ret;
}
示例#21
0
static virNodeDevCapsDefPtr
virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt,
                          virNodeDeviceDefPtr def,
                          xmlNodePtr node,
                          int create)
{
    virNodeDevCapsDefPtr caps;
    char *tmp;
    int val, ret;

    if (VIR_ALLOC(caps) < 0) {
        virReportOOMError();
        return NULL;
    }

    tmp = virXMLPropString(node, "type");
    if (!tmp) {
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 "%s", _("missing capability type"));
        goto error;
    }

    if ((val = virNodeDevCapTypeFromString(tmp)) < 0) {
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 _("unknown capability type '%s'"), tmp);
        VIR_FREE(tmp);
        goto error;
    }
    caps->type = val;
    VIR_FREE(tmp);

    switch (caps->type) {
    case VIR_NODE_DEV_CAP_SYSTEM:
        ret = virNodeDevCapSystemParseXML(ctxt, def, node, &caps->data);
        break;
    case VIR_NODE_DEV_CAP_PCI_DEV:
        ret = virNodeDevCapPciDevParseXML(ctxt, def, node, &caps->data);
        break;
    case VIR_NODE_DEV_CAP_USB_DEV:
        ret = virNodeDevCapUsbDevParseXML(ctxt, def, node, &caps->data);
        break;
    case VIR_NODE_DEV_CAP_USB_INTERFACE:
        ret = virNodeDevCapUsbInterfaceParseXML(ctxt, def, node, &caps->data);
        break;
    case VIR_NODE_DEV_CAP_NET:
        ret = virNodeDevCapNetParseXML(ctxt, def, node, &caps->data);
        break;
    case VIR_NODE_DEV_CAP_SCSI_HOST:
        ret = virNodeDevCapScsiHostParseXML(ctxt, def, node, &caps->data, create);
        break;
    case VIR_NODE_DEV_CAP_SCSI_TARGET:
        ret = virNodeDevCapScsiTargetParseXML(ctxt, def, node, &caps->data);
        break;
    case VIR_NODE_DEV_CAP_SCSI:
        ret = virNodeDevCapScsiParseXML(ctxt, def, node, &caps->data);
        break;
    case VIR_NODE_DEV_CAP_STORAGE:
        ret = virNodeDevCapStorageParseXML(ctxt, def, node, &caps->data);
        break;
    default:
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 _("unknown capability type '%d' for '%s'"),
                                 caps->type, def->name);
        ret = -1;
        break;
    }

    if (ret < 0)
        goto error;
    return caps;

error:
    virNodeDevCapsDefFree(caps);
    return NULL;
}
示例#22
0
static int
virNodeDevCapStorageParseXML(xmlXPathContextPtr ctxt,
                             virNodeDeviceDefPtr def,
                             xmlNodePtr node,
                             union _virNodeDevCapData *data)
{
    xmlNodePtr orignode, *nodes = NULL;
    int i, n, ret = -1;
    unsigned long long val;

    orignode = ctxt->node;
    ctxt->node = node;

    data->storage.block = virXPathString("string(./block[1])", ctxt);
    if (!data->storage.block) {
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 _("no block device path supplied for '%s'"),
                                 def->name);
        goto out;
    }

    data->storage.bus        = virXPathString("string(./bus[1])", ctxt);
    data->storage.drive_type = virXPathString("string(./drive_type[1])", ctxt);
    data->storage.model      = virXPathString("string(./model[1])", ctxt);
    data->storage.vendor     = virXPathString("string(./vendor[1])", ctxt);
    data->storage.serial     = virXPathString("string(./serial[1])", ctxt);

    if ((n = virXPathNodeSet("./capability", ctxt, &nodes)) < 0) {
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 _("error parsing storage capabilities for '%s'"),
                                 def->name);
        goto out;
    }

    for (i = 0 ; i < n ; i++) {
        char *type = virXMLPropString(nodes[i], "type");

        if (!type) {
            virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                     _("missing storage capability type for '%s'"),
                                     def->name);
            goto out;
        }

        if (STREQ(type, "hotpluggable"))
            data->storage.flags |= VIR_NODE_DEV_CAP_STORAGE_HOTPLUGGABLE;
        else if (STREQ(type, "removable")) {
            xmlNodePtr orignode2;

            data->storage.flags |= VIR_NODE_DEV_CAP_STORAGE_REMOVABLE;

            orignode2 = ctxt->node;
            ctxt->node = nodes[i];

            if (virXPathBoolean("count(./media_available[. = '1']) > 0", ctxt))
                data->storage.flags |= VIR_NODE_DEV_CAP_STORAGE_REMOVABLE_MEDIA_AVAILABLE;

            data->storage.media_label = virXPathString("string(./media_label[1])", ctxt);

            val = 0;
            if (virNodeDevCapsDefParseULongLong("number(./media_size[1])", ctxt, &val, def,
                                                _("no removable media size supplied for '%s'"),
                                                _("invalid removable media size supplied for '%s'")) < 0) {
                ctxt->node = orignode2;
                VIR_FREE(type);
                goto out;
            }
            data->storage.removable_media_size = val;

            ctxt->node = orignode2;
        } else {
            virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                     _("unknown storage capability type '%s' for '%s'"),
                                     type, def->name);
            VIR_FREE(type);
            goto out;
        }

        VIR_FREE(type);
    }

    if (!(data->storage.flags & VIR_NODE_DEV_CAP_STORAGE_REMOVABLE)) {
        val = 0;
        if (virNodeDevCapsDefParseULongLong("number(./size[1])", ctxt, &val, def,
                                            _("no size supplied for '%s'"),
                                            _("invalid size supplied for '%s'")) < 0)
            goto out;
        data->storage.size = val;
    }

    ret = 0;
out:
    VIR_FREE(nodes);
    ctxt->node = orignode;
    return ret;
}