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(a)redhat.com>
---
src/conf/Makefile.inc.am | 2 +
src/conf/node_device_conf.c | 199 -----------------------
src/conf/node_device_conf.h | 11 --
src/conf/node_device_util.c | 229 +++++++++++++++++++++++++++
src/conf/node_device_util.h | 35 ++++
src/conf/virstorageobj.c | 1 +
src/libvirt_private.syms | 7 +-
src/node_device/node_device_driver.c | 1 +
src/storage/storage_backend_scsi.c | 1 +
9 files changed, 273 insertions(+), 213 deletions(-)
create mode 100644 src/conf/node_device_util.c
create mode 100644 src/conf/node_device_util.h
diff --git a/src/conf/Makefile.inc.am b/src/conf/Makefile.inc.am
index af23810640..219ff350d7 100644
--- a/src/conf/Makefile.inc.am
+++ b/src/conf/Makefile.inc.am
@@ -119,6 +119,8 @@ SECRET_CONF_SOURCES = \
NODE_DEVICE_CONF_SOURCES = \
conf/node_device_conf.c \
conf/node_device_conf.h \
+ conf/node_device_util.c \
+ conf/node_device_util.h \
conf/virnodedeviceobj.c \
conf/virnodedeviceobj.h \
$(NULL)
diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c
index 03bd794dc0..74a7bc3933 100644
--- a/src/conf/node_device_conf.c
+++ b/src/conf/node_device_conf.c
@@ -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
virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def)
{
diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h
index 685ae30347..fde239183d 100644
--- a/src/conf/node_device_conf.h
+++ b/src/conf/node_device_conf.h
@@ -367,17 +367,6 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps);
VIR_CONNECT_LIST_NODE_DEVICES_CAP_MDEV | \
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
virNodeDeviceGetSCSIHostCaps(virNodeDevCapSCSIHostPtr scsi_host);
diff --git a/src/conf/node_device_util.c b/src/conf/node_device_util.c
new file mode 100644
index 0000000000..d1d9c3ee49
--- /dev/null
+++ b/src/conf/node_device_util.c
@@ -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;
+}
diff --git a/src/conf/node_device_util.h b/src/conf/node_device_util.h
new file mode 100644
index 0000000000..5cb225d03e
--- /dev/null
+++ b/src/conf/node_device_util.h
@@ -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__ */
diff --git a/src/conf/virstorageobj.c b/src/conf/virstorageobj.c
index 0b3ba84af2..30aabb2b37 100644
--- a/src/conf/virstorageobj.c
+++ b/src/conf/virstorageobj.c
@@ -22,6 +22,7 @@
#include "datatypes.h"
#include "node_device_conf.h"
+#include "node_device_util.h"
#include "virstorageobj.h"
#include "viralloc.h"
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 335210c31d..2343a757c1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -722,14 +722,11 @@ virNodeDevCapsDefFree;
virNodeDevCapTypeFromString;
virNodeDevCapTypeToString;
virNodeDeviceCapsListExport;
-virNodeDeviceCreateVport;
virNodeDeviceDefFormat;
virNodeDeviceDefFree;
virNodeDeviceDefParseFile;
virNodeDeviceDefParseNode;
virNodeDeviceDefParseString;
-virNodeDeviceDeleteVport;
-virNodeDeviceGetParentName;
virNodeDeviceGetPCIDynamicCaps;
virNodeDeviceGetSCSIHostCaps;
virNodeDeviceGetSCSITargetCaps;
@@ -742,6 +739,10 @@ virNodeDeviceEventLifecycleNew;
virNodeDeviceEventStateRegisterID;
virNodeDeviceEventUpdateNew;
+# conf/node_device_util.h
+virNodeDeviceCreateVport;
+virNodeDeviceDeleteVport;
+virNodeDeviceGetParentName;
# conf/numa_conf.h
virDomainMemoryAccessTypeFromString;
diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c
index c46d0fbe12..0bcb3de053 100644
--- a/src/node_device/node_device_driver.c
+++ b/src/node_device/node_device_driver.c
@@ -37,6 +37,7 @@
#include "node_device_event.h"
#include "node_device_driver.h"
#include "node_device_hal.h"
+#include "node_device_util.h"
#include "virvhba.h"
#include "viraccessapicheck.h"
#include "virnetdev.h"
diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backend_scsi.c
index 7c927c4d95..fe3a1e36ac 100644
--- a/src/storage/storage_backend_scsi.c
+++ b/src/storage/storage_backend_scsi.c
@@ -35,6 +35,7 @@
#include "virstring.h"
#include "storage_util.h"
#include "node_device_conf.h"
+#include "node_device_util.h"
#include "driver.h"
#define VIR_FROM_THIS VIR_FROM_STORAGE
--
2.19.1