mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-28 19:41:16 +00:00
conf: Add new module node_device_util
There's a lot of stuff going on in src/conf/nodedev_conf which is sometimes not directly related to config and we're not really consistent with putting only parser/formatter related stuff here, e.g. like we do for domains. So, let's start simply by adding a new module node_device_util containing some of the helpers. Unfortunately, even though these helpers tend to open a secondary driver connection and would be much therefore better suited as a nodedev driver module, we can't do that without pulling headers from the driver into conf/ and that's wrong because we want conf/ to stay driver-agnostic. Signed-off-by: Erik Skultety <eskultet@redhat.com> Acked-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
03abfd2a6e
commit
f1e8d2f09a
@ -119,6 +119,8 @@ SECRET_CONF_SOURCES = \
|
|||||||
NODE_DEVICE_CONF_SOURCES = \
|
NODE_DEVICE_CONF_SOURCES = \
|
||||||
conf/node_device_conf.c \
|
conf/node_device_conf.c \
|
||||||
conf/node_device_conf.h \
|
conf/node_device_conf.h \
|
||||||
|
conf/node_device_util.c \
|
||||||
|
conf/node_device_util.h \
|
||||||
conf/virnodedeviceobj.c \
|
conf/virnodedeviceobj.c \
|
||||||
conf/virnodedeviceobj.h \
|
conf/virnodedeviceobj.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
@ -2220,205 +2220,6 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* virNodeDeviceGetParentName
|
|
||||||
* @conn: Connection pointer
|
|
||||||
* @nodedev_name: Node device to lookup
|
|
||||||
*
|
|
||||||
* Lookup the node device by name and return the parent name
|
|
||||||
*
|
|
||||||
* Returns parent name on success, caller is responsible for freeing;
|
|
||||||
* otherwise, returns NULL on failure
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
virNodeDeviceGetParentName(virConnectPtr conn,
|
|
||||||
const char *nodedev_name)
|
|
||||||
{
|
|
||||||
virNodeDevicePtr device = NULL;
|
|
||||||
char *parent;
|
|
||||||
|
|
||||||
if (!(device = virNodeDeviceLookupByName(conn, nodedev_name))) {
|
|
||||||
virReportError(VIR_ERR_XML_ERROR,
|
|
||||||
_("Cannot find '%s' in node device database"),
|
|
||||||
nodedev_name);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ignore_value(VIR_STRDUP(parent, virNodeDeviceGetParent(device)));
|
|
||||||
virObjectUnref(device);
|
|
||||||
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @fchost: Pointer to vHBA adapter
|
|
||||||
*
|
|
||||||
* Create a vHBA for Storage. This code accomplishes this via searching
|
|
||||||
* through the sysfs for scsi_host/fc_host in order to first ensure some
|
|
||||||
* vHBA doesn't already exist for the requested wwnn/wwpn (e.g. an unmanaged
|
|
||||||
* vHBA) and to search for the parent vport capable scsi_host by name,
|
|
||||||
* wwnn/wwpn, or fabric_wwn (if provided). If no parent is provided, then
|
|
||||||
* a vport capable scsi_host will be selected.
|
|
||||||
*
|
|
||||||
* Returns vHBA name on success, NULL on failure with an error message set
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
virNodeDeviceCreateVport(virStorageAdapterFCHostPtr fchost)
|
|
||||||
{
|
|
||||||
unsigned int parent_host;
|
|
||||||
char *name = NULL;
|
|
||||||
char *parent_hoststr = NULL;
|
|
||||||
bool skip_capable_check = false;
|
|
||||||
|
|
||||||
VIR_DEBUG("parent='%s', wwnn='%s' wwpn='%s'",
|
|
||||||
NULLSTR(fchost->parent), fchost->wwnn, fchost->wwpn);
|
|
||||||
|
|
||||||
if (fchost->parent) {
|
|
||||||
if (VIR_STRDUP(parent_hoststr, fchost->parent) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
} else if (fchost->parent_wwnn && fchost->parent_wwpn) {
|
|
||||||
if (!(parent_hoststr = virVHBAGetHostByWWN(NULL, fchost->parent_wwnn,
|
|
||||||
fchost->parent_wwpn))) {
|
|
||||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
||||||
_("cannot find parent using provided wwnn/wwpn"));
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
} else if (fchost->parent_fabric_wwn) {
|
|
||||||
if (!(parent_hoststr =
|
|
||||||
virVHBAGetHostByFabricWWN(NULL, fchost->parent_fabric_wwn))) {
|
|
||||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
||||||
_("cannot find parent using provided fabric_wwn"));
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!(parent_hoststr = virVHBAFindVportHost(NULL))) {
|
|
||||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
||||||
_("'parent' for vHBA not specified, and "
|
|
||||||
"cannot find one on this host"));
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
skip_capable_check = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virSCSIHostGetNumber(parent_hoststr, &parent_host) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
/* NOTE:
|
|
||||||
* We do not save the parent_hoststr in fchost->parent since
|
|
||||||
* we could be writing out the 'def' to the saved XML config.
|
|
||||||
* If we wrote out the name in the XML, then future starts would
|
|
||||||
* always use the same parent rather than finding the "best available"
|
|
||||||
* parent. Besides we have a way to determine the parent based on
|
|
||||||
* the 'name' field.
|
|
||||||
*/
|
|
||||||
if (!skip_capable_check && !virVHBAPathExists(NULL, parent_host)) {
|
|
||||||
virReportError(VIR_ERR_XML_ERROR,
|
|
||||||
_("parent '%s' specified for vHBA does not exist"),
|
|
||||||
parent_hoststr);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virVHBAManageVport(parent_host, fchost->wwpn, fchost->wwnn,
|
|
||||||
VPORT_CREATE) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
/* Let's ensure the device was created */
|
|
||||||
virWaitForDevices();
|
|
||||||
if (!(name = virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn))) {
|
|
||||||
ignore_value(virVHBAManageVport(parent_host, fchost->wwpn, fchost->wwnn,
|
|
||||||
VPORT_DELETE));
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
VIR_FREE(parent_hoststr);
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @conn: Connection pointer
|
|
||||||
* @fchost: Pointer to vHBA adapter
|
|
||||||
*
|
|
||||||
* As long as the vHBA is being managed, search for the scsi_host via the
|
|
||||||
* provided wwnn/wwpn and then find the corresponding parent scsi_host in
|
|
||||||
* order to send the delete request.
|
|
||||||
*
|
|
||||||
* Returns 0 on success, -1 on failure
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
virNodeDeviceDeleteVport(virConnectPtr conn,
|
|
||||||
virStorageAdapterFCHostPtr fchost)
|
|
||||||
{
|
|
||||||
char *name = NULL;
|
|
||||||
char *scsi_host_name = NULL;
|
|
||||||
unsigned int parent_host;
|
|
||||||
char *vhba_parent = NULL;
|
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
VIR_DEBUG("conn=%p parent='%s', managed='%d' wwnn='%s' wwpn='%s'",
|
|
||||||
conn, NULLSTR(fchost->parent), fchost->managed,
|
|
||||||
fchost->wwnn, fchost->wwpn);
|
|
||||||
|
|
||||||
/* If we're not managing the deletion of the vHBA, then just return */
|
|
||||||
if (fchost->managed != VIR_TRISTATE_BOOL_YES)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Find our vHBA by searching the fc_host sysfs tree for our wwnn/wwpn */
|
|
||||||
if (!(name = virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn))) {
|
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
||||||
_("Failed to find fc_host for wwnn='%s' and wwpn='%s'"),
|
|
||||||
fchost->wwnn, fchost->wwpn);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virAsprintf(&scsi_host_name, "scsi_%s", name) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
/* If at startup time we provided a parent, then use that to
|
|
||||||
* get the parent_host value; otherwise, we have to determine
|
|
||||||
* the parent scsi_host which we did not save at startup time
|
|
||||||
*/
|
|
||||||
if (fchost->parent) {
|
|
||||||
/* Someone provided a parent string at startup time that
|
|
||||||
* was the same as the scsi_host - meaning we have a pool
|
|
||||||
* backed to an HBA, so there won't be a vHBA to delete */
|
|
||||||
if (STREQ(scsi_host_name, fchost->parent)) {
|
|
||||||
ret = 0;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virSCSIHostGetNumber(fchost->parent, &parent_host) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
} else {
|
|
||||||
if (!(vhba_parent = virNodeDeviceGetParentName(conn, scsi_host_name)))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
/* If the parent is not a scsi_host, then this is a pool backed
|
|
||||||
* directly to an HBA and there's no vHBA to remove - so we're done */
|
|
||||||
if (!STRPREFIX(vhba_parent, "scsi_host")) {
|
|
||||||
ret = 0;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virSCSIHostGetNumber(vhba_parent, &parent_host) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virVHBAManageVport(parent_host, fchost->wwpn, fchost->wwnn,
|
|
||||||
VPORT_DELETE) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
VIR_FREE(name);
|
|
||||||
VIR_FREE(vhba_parent);
|
|
||||||
VIR_FREE(scsi_host_name);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def)
|
virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def)
|
||||||
{
|
{
|
||||||
|
@ -367,17 +367,6 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps);
|
|||||||
VIR_CONNECT_LIST_NODE_DEVICES_CAP_MDEV | \
|
VIR_CONNECT_LIST_NODE_DEVICES_CAP_MDEV | \
|
||||||
VIR_CONNECT_LIST_NODE_DEVICES_CAP_CCW_DEV)
|
VIR_CONNECT_LIST_NODE_DEVICES_CAP_CCW_DEV)
|
||||||
|
|
||||||
char *
|
|
||||||
virNodeDeviceGetParentName(virConnectPtr conn,
|
|
||||||
const char *nodedev_name);
|
|
||||||
|
|
||||||
char *
|
|
||||||
virNodeDeviceCreateVport(virStorageAdapterFCHostPtr fchost);
|
|
||||||
|
|
||||||
int
|
|
||||||
virNodeDeviceDeleteVport(virConnectPtr conn,
|
|
||||||
virStorageAdapterFCHostPtr fchost);
|
|
||||||
|
|
||||||
int
|
int
|
||||||
virNodeDeviceGetSCSIHostCaps(virNodeDevCapSCSIHostPtr scsi_host);
|
virNodeDeviceGetSCSIHostCaps(virNodeDevCapSCSIHostPtr scsi_host);
|
||||||
|
|
||||||
|
229
src/conf/node_device_util.c
Normal file
229
src/conf/node_device_util.c
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
/*
|
||||||
|
* node_device_util.c: helper functions for the node device driver
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include "node_device_util.h"
|
||||||
|
#include "virlog.h"
|
||||||
|
#include "virscsihost.h"
|
||||||
|
#include "virstring.h"
|
||||||
|
#include "virvhba.h"
|
||||||
|
|
||||||
|
#define VIR_FROM_THIS VIR_FROM_NODEDEV
|
||||||
|
|
||||||
|
VIR_LOG_INIT("node_device.node_device_util");
|
||||||
|
|
||||||
|
/* virNodeDeviceGetParentName
|
||||||
|
* @conn: Connection pointer
|
||||||
|
* @nodedev_name: Node device to lookup
|
||||||
|
*
|
||||||
|
* Lookup the node device by name and return the parent name
|
||||||
|
*
|
||||||
|
* Returns parent name on success, caller is responsible for freeing;
|
||||||
|
* otherwise, returns NULL on failure
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
virNodeDeviceGetParentName(virConnectPtr conn,
|
||||||
|
const char *nodedev_name)
|
||||||
|
{
|
||||||
|
virNodeDevicePtr device = NULL;
|
||||||
|
char *parent;
|
||||||
|
|
||||||
|
if (!(device = virNodeDeviceLookupByName(conn, nodedev_name))) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("Cannot find '%s' in node device database"),
|
||||||
|
nodedev_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ignore_value(VIR_STRDUP(parent, virNodeDeviceGetParent(device)));
|
||||||
|
virObjectUnref(device);
|
||||||
|
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fchost: Pointer to vHBA adapter
|
||||||
|
*
|
||||||
|
* Create a vHBA for Storage. This code accomplishes this via searching
|
||||||
|
* through the sysfs for scsi_host/fc_host in order to first ensure some
|
||||||
|
* vHBA doesn't already exist for the requested wwnn/wwpn (e.g. an unmanaged
|
||||||
|
* vHBA) and to search for the parent vport capable scsi_host by name,
|
||||||
|
* wwnn/wwpn, or fabric_wwn (if provided). If no parent is provided, then
|
||||||
|
* a vport capable scsi_host will be selected.
|
||||||
|
*
|
||||||
|
* Returns vHBA name on success, NULL on failure with an error message set
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
virNodeDeviceCreateVport(virStorageAdapterFCHostPtr fchost)
|
||||||
|
{
|
||||||
|
unsigned int parent_host;
|
||||||
|
char *name = NULL;
|
||||||
|
char *parent_hoststr = NULL;
|
||||||
|
bool skip_capable_check = false;
|
||||||
|
|
||||||
|
VIR_DEBUG("parent='%s', wwnn='%s' wwpn='%s'",
|
||||||
|
NULLSTR(fchost->parent), fchost->wwnn, fchost->wwpn);
|
||||||
|
|
||||||
|
if (fchost->parent) {
|
||||||
|
if (VIR_STRDUP(parent_hoststr, fchost->parent) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
} else if (fchost->parent_wwnn && fchost->parent_wwpn) {
|
||||||
|
if (!(parent_hoststr = virVHBAGetHostByWWN(NULL, fchost->parent_wwnn,
|
||||||
|
fchost->parent_wwpn))) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("cannot find parent using provided wwnn/wwpn"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
} else if (fchost->parent_fabric_wwn) {
|
||||||
|
if (!(parent_hoststr =
|
||||||
|
virVHBAGetHostByFabricWWN(NULL, fchost->parent_fabric_wwn))) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("cannot find parent using provided fabric_wwn"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!(parent_hoststr = virVHBAFindVportHost(NULL))) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
|
_("'parent' for vHBA not specified, and "
|
||||||
|
"cannot find one on this host"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
skip_capable_check = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virSCSIHostGetNumber(parent_hoststr, &parent_host) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* NOTE:
|
||||||
|
* We do not save the parent_hoststr in fchost->parent since
|
||||||
|
* we could be writing out the 'def' to the saved XML config.
|
||||||
|
* If we wrote out the name in the XML, then future starts would
|
||||||
|
* always use the same parent rather than finding the "best available"
|
||||||
|
* parent. Besides we have a way to determine the parent based on
|
||||||
|
* the 'name' field.
|
||||||
|
*/
|
||||||
|
if (!skip_capable_check && !virVHBAPathExists(NULL, parent_host)) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("parent '%s' specified for vHBA does not exist"),
|
||||||
|
parent_hoststr);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virVHBAManageVport(parent_host, fchost->wwpn, fchost->wwnn,
|
||||||
|
VPORT_CREATE) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* Let's ensure the device was created */
|
||||||
|
virWaitForDevices();
|
||||||
|
if (!(name = virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn))) {
|
||||||
|
ignore_value(virVHBAManageVport(parent_host, fchost->wwpn, fchost->wwnn,
|
||||||
|
VPORT_DELETE));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(parent_hoststr);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @conn: Connection pointer
|
||||||
|
* @fchost: Pointer to vHBA adapter
|
||||||
|
*
|
||||||
|
* As long as the vHBA is being managed, search for the scsi_host via the
|
||||||
|
* provided wwnn/wwpn and then find the corresponding parent scsi_host in
|
||||||
|
* order to send the delete request.
|
||||||
|
*
|
||||||
|
* Returns 0 on success, -1 on failure
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
virNodeDeviceDeleteVport(virConnectPtr conn,
|
||||||
|
virStorageAdapterFCHostPtr fchost)
|
||||||
|
{
|
||||||
|
char *name = NULL;
|
||||||
|
char *scsi_host_name = NULL;
|
||||||
|
unsigned int parent_host;
|
||||||
|
char *vhba_parent = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
VIR_DEBUG("conn=%p parent='%s', managed='%d' wwnn='%s' wwpn='%s'",
|
||||||
|
conn, NULLSTR(fchost->parent), fchost->managed,
|
||||||
|
fchost->wwnn, fchost->wwpn);
|
||||||
|
|
||||||
|
/* If we're not managing the deletion of the vHBA, then just return */
|
||||||
|
if (fchost->managed != VIR_TRISTATE_BOOL_YES)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Find our vHBA by searching the fc_host sysfs tree for our wwnn/wwpn */
|
||||||
|
if (!(name = virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn))) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Failed to find fc_host for wwnn='%s' and wwpn='%s'"),
|
||||||
|
fchost->wwnn, fchost->wwpn);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virAsprintf(&scsi_host_name, "scsi_%s", name) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* If at startup time we provided a parent, then use that to
|
||||||
|
* get the parent_host value; otherwise, we have to determine
|
||||||
|
* the parent scsi_host which we did not save at startup time
|
||||||
|
*/
|
||||||
|
if (fchost->parent) {
|
||||||
|
/* Someone provided a parent string at startup time that
|
||||||
|
* was the same as the scsi_host - meaning we have a pool
|
||||||
|
* backed to an HBA, so there won't be a vHBA to delete */
|
||||||
|
if (STREQ(scsi_host_name, fchost->parent)) {
|
||||||
|
ret = 0;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virSCSIHostGetNumber(fchost->parent, &parent_host) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
} else {
|
||||||
|
if (!(vhba_parent = virNodeDeviceGetParentName(conn, scsi_host_name)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* If the parent is not a scsi_host, then this is a pool backed
|
||||||
|
* directly to an HBA and there's no vHBA to remove - so we're done */
|
||||||
|
if (!STRPREFIX(vhba_parent, "scsi_host")) {
|
||||||
|
ret = 0;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virSCSIHostGetNumber(vhba_parent, &parent_host) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virVHBAManageVport(parent_host, fchost->wwpn, fchost->wwnn,
|
||||||
|
VPORT_DELETE) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(name);
|
||||||
|
VIR_FREE(vhba_parent);
|
||||||
|
VIR_FREE(scsi_host_name);
|
||||||
|
return ret;
|
||||||
|
}
|
35
src/conf/node_device_util.h
Normal file
35
src/conf/node_device_util.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* node_device_util.h: utility functions for node device driver
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __VIR_NODE_DEVICE_UTIL_H__
|
||||||
|
# define __VIR_NODE_DEVICE_UTIL_H__
|
||||||
|
|
||||||
|
# include "conf/storage_adapter_conf.h"
|
||||||
|
|
||||||
|
char *
|
||||||
|
virNodeDeviceGetParentName(virConnectPtr conn,
|
||||||
|
const char *nodedev_name);
|
||||||
|
|
||||||
|
char *
|
||||||
|
virNodeDeviceCreateVport(virStorageAdapterFCHostPtr fchost);
|
||||||
|
|
||||||
|
int
|
||||||
|
virNodeDeviceDeleteVport(virConnectPtr conn,
|
||||||
|
virStorageAdapterFCHostPtr fchost);
|
||||||
|
|
||||||
|
#endif /* __VIR_NODE_DEVICE_UTIL_H__ */
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
#include "node_device_conf.h"
|
#include "node_device_conf.h"
|
||||||
|
#include "node_device_util.h"
|
||||||
#include "virstorageobj.h"
|
#include "virstorageobj.h"
|
||||||
|
|
||||||
#include "viralloc.h"
|
#include "viralloc.h"
|
||||||
|
@ -722,14 +722,11 @@ virNodeDevCapsDefFree;
|
|||||||
virNodeDevCapTypeFromString;
|
virNodeDevCapTypeFromString;
|
||||||
virNodeDevCapTypeToString;
|
virNodeDevCapTypeToString;
|
||||||
virNodeDeviceCapsListExport;
|
virNodeDeviceCapsListExport;
|
||||||
virNodeDeviceCreateVport;
|
|
||||||
virNodeDeviceDefFormat;
|
virNodeDeviceDefFormat;
|
||||||
virNodeDeviceDefFree;
|
virNodeDeviceDefFree;
|
||||||
virNodeDeviceDefParseFile;
|
virNodeDeviceDefParseFile;
|
||||||
virNodeDeviceDefParseNode;
|
virNodeDeviceDefParseNode;
|
||||||
virNodeDeviceDefParseString;
|
virNodeDeviceDefParseString;
|
||||||
virNodeDeviceDeleteVport;
|
|
||||||
virNodeDeviceGetParentName;
|
|
||||||
virNodeDeviceGetPCIDynamicCaps;
|
virNodeDeviceGetPCIDynamicCaps;
|
||||||
virNodeDeviceGetSCSIHostCaps;
|
virNodeDeviceGetSCSIHostCaps;
|
||||||
virNodeDeviceGetSCSITargetCaps;
|
virNodeDeviceGetSCSITargetCaps;
|
||||||
@ -742,6 +739,10 @@ virNodeDeviceEventLifecycleNew;
|
|||||||
virNodeDeviceEventStateRegisterID;
|
virNodeDeviceEventStateRegisterID;
|
||||||
virNodeDeviceEventUpdateNew;
|
virNodeDeviceEventUpdateNew;
|
||||||
|
|
||||||
|
# conf/node_device_util.h
|
||||||
|
virNodeDeviceCreateVport;
|
||||||
|
virNodeDeviceDeleteVport;
|
||||||
|
virNodeDeviceGetParentName;
|
||||||
|
|
||||||
# conf/numa_conf.h
|
# conf/numa_conf.h
|
||||||
virDomainMemoryAccessTypeFromString;
|
virDomainMemoryAccessTypeFromString;
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "node_device_event.h"
|
#include "node_device_event.h"
|
||||||
#include "node_device_driver.h"
|
#include "node_device_driver.h"
|
||||||
#include "node_device_hal.h"
|
#include "node_device_hal.h"
|
||||||
|
#include "node_device_util.h"
|
||||||
#include "virvhba.h"
|
#include "virvhba.h"
|
||||||
#include "viraccessapicheck.h"
|
#include "viraccessapicheck.h"
|
||||||
#include "virnetdev.h"
|
#include "virnetdev.h"
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "virstring.h"
|
#include "virstring.h"
|
||||||
#include "storage_util.h"
|
#include "storage_util.h"
|
||||||
#include "node_device_conf.h"
|
#include "node_device_conf.h"
|
||||||
|
#include "node_device_util.h"
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_STORAGE
|
#define VIR_FROM_THIS VIR_FROM_STORAGE
|
||||||
|
Loading…
Reference in New Issue
Block a user