|
|
99cbc7 |
From 0fffd7d7d2767d8f03407c2c61da6baf0ac181c5 Mon Sep 17 00:00:00 2001
|
|
|
99cbc7 |
Message-Id: <0fffd7d7d2767d8f03407c2c61da6baf0ac181c5@dist-git>
|
|
|
99cbc7 |
From: John Ferlan <jferlan@redhat.com>
|
|
|
99cbc7 |
Date: Tue, 12 Mar 2019 13:55:58 -0400
|
|
|
99cbc7 |
Subject: [PATCH] util: Introduce virStorageFileGetNPIVKey
|
|
|
99cbc7 |
MIME-Version: 1.0
|
|
|
99cbc7 |
Content-Type: text/plain; charset=UTF-8
|
|
|
99cbc7 |
Content-Transfer-Encoding: 8bit
|
|
|
99cbc7 |
|
|
|
99cbc7 |
https://bugzilla.redhat.com/show_bug.cgi?id=1687715 (7.6.z)
|
|
|
99cbc7 |
https://bugzilla.redhat.com/show_bug.cgi?id=1657468 (7.7.0)
|
|
|
99cbc7 |
|
|
|
99cbc7 |
The vHBA/NPIV LUNs created via the udev processing of the
|
|
|
99cbc7 |
VPORT_CREATE command end up using the same serial value
|
|
|
99cbc7 |
as seen/generated by the /lib/udev/scsi_id as returned
|
|
|
99cbc7 |
during virStorageFileGetSCSIKey. Therefore, in order to
|
|
|
99cbc7 |
generate a unique enough key to be used when adding the
|
|
|
99cbc7 |
LUN as a volume during virStoragePoolObjAddVol a more
|
|
|
99cbc7 |
unique key needs to be generated for an NPIV volume.
|
|
|
99cbc7 |
|
|
|
99cbc7 |
The problem is illustrated by the following example, where
|
|
|
99cbc7 |
scsi_host5 is a vHBA used with the following LUNs:
|
|
|
99cbc7 |
|
|
|
99cbc7 |
$ lsscsi -tg
|
|
|
99cbc7 |
...
|
|
|
99cbc7 |
[5:0:4:0] disk fc:0x5006016844602198,0x101f00 /dev/sdh /dev/sg23
|
|
|
99cbc7 |
[5:0:5:0] disk fc:0x5006016044602198,0x102000 /dev/sdi /dev/sg24
|
|
|
99cbc7 |
...
|
|
|
99cbc7 |
|
|
|
99cbc7 |
Calling virStorageFileGetSCSIKey would return:
|
|
|
99cbc7 |
|
|
|
99cbc7 |
/lib/udev/scsi_id --device /dev/sdh --whitelisted --replace-whitespace /dev/sdh
|
|
|
99cbc7 |
350060160c460219850060160c4602198
|
|
|
99cbc7 |
/lib/udev/scsi_id --device /dev/sdh --whitelisted --replace-whitespace /dev/sdi
|
|
|
99cbc7 |
350060160c460219850060160c4602198
|
|
|
99cbc7 |
|
|
|
99cbc7 |
Note that althrough /dev/sdh and /dev/sdi are separate LUNs, they
|
|
|
99cbc7 |
end up with the same serial number used for the vol->key value.
|
|
|
99cbc7 |
When virStoragePoolFCRefreshThread calls virStoragePoolObjAddVol
|
|
|
99cbc7 |
the second LUN fails to be added with the following message
|
|
|
99cbc7 |
getting logged:
|
|
|
99cbc7 |
|
|
|
99cbc7 |
virHashAddOrUpdateEntry:341 : internal error: Duplicate key
|
|
|
99cbc7 |
|
|
|
99cbc7 |
To resolve this, virStorageFileGetNPIVKey will use a similar call
|
|
|
99cbc7 |
sequence as virStorageFileGetSCSIKey, except that it will add the
|
|
|
99cbc7 |
"--export" option to the call. This results in more detailed output
|
|
|
99cbc7 |
which needs to be parsed in order to formulate a unique enough key
|
|
|
99cbc7 |
to be used. In order to be unique enough, the returned value will
|
|
|
99cbc7 |
concatenate the target port as returned in the "ID_TARGET_PORT"
|
|
|
99cbc7 |
field from the command to the "ID_SERIAL" value.
|
|
|
99cbc7 |
|
|
|
99cbc7 |
Signed-off-by: John Ferlan <jferlan@redhat.com>
|
|
|
99cbc7 |
ACKed-by: Michal Privoznik <mprivozn@redhat.com>
|
|
|
99cbc7 |
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
|
99cbc7 |
(cherry picked from commit 5f9e211c9319311fc296cb91ca8e330917ac9494)
|
|
|
99cbc7 |
|
|
|
99cbc7 |
Handled build failure of not having VIR_AUTOFREE in the next-7.6 sources,
|
|
|
99cbc7 |
by not using VIR_AUTOFREE and using VIR_FREE(outbuf) explicitly.
|
|
|
99cbc7 |
|
|
|
99cbc7 |
Signed-off-by: John Ferlan <jferlan@redhat.com>
|
|
|
99cbc7 |
Message-Id: <20190312175559.13583-4-jferlan@redhat.com>
|
|
|
99cbc7 |
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
|
99cbc7 |
---
|
|
|
99cbc7 |
src/libvirt_private.syms | 1 +
|
|
|
99cbc7 |
src/util/virstoragefile.c | 80 +++++++++++++++++++++++++++++++++++++++
|
|
|
99cbc7 |
src/util/virstoragefile.h | 2 +
|
|
|
99cbc7 |
3 files changed, 83 insertions(+)
|
|
|
99cbc7 |
|
|
|
99cbc7 |
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
|
|
|
99cbc7 |
index 86846f3b08..636891eabd 100644
|
|
|
99cbc7 |
--- a/src/libvirt_private.syms
|
|
|
99cbc7 |
+++ b/src/libvirt_private.syms
|
|
|
99cbc7 |
@@ -2820,6 +2820,7 @@ virStorageFileGetMetadata;
|
|
|
99cbc7 |
virStorageFileGetMetadataFromBuf;
|
|
|
99cbc7 |
virStorageFileGetMetadataFromFD;
|
|
|
99cbc7 |
virStorageFileGetMetadataInternal;
|
|
|
99cbc7 |
+virStorageFileGetNPIVKey;
|
|
|
99cbc7 |
virStorageFileGetRelativeBackingPath;
|
|
|
99cbc7 |
virStorageFileGetSCSIKey;
|
|
|
99cbc7 |
virStorageFileGetUniqueIdentifier;
|
|
|
99cbc7 |
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
|
|
|
99cbc7 |
index 56d38b467e..52c9dc0e1a 100644
|
|
|
99cbc7 |
--- a/src/util/virstoragefile.c
|
|
|
99cbc7 |
+++ b/src/util/virstoragefile.c
|
|
|
99cbc7 |
@@ -1503,6 +1503,86 @@ int virStorageFileGetSCSIKey(const char *path,
|
|
|
99cbc7 |
#endif
|
|
|
99cbc7 |
|
|
|
99cbc7 |
|
|
|
99cbc7 |
+#ifdef WITH_UDEV
|
|
|
99cbc7 |
+/* virStorageFileGetNPIVKey
|
|
|
99cbc7 |
+ * @path: Path to the NPIV device
|
|
|
99cbc7 |
+ * @key: Unique key to be returned
|
|
|
99cbc7 |
+ *
|
|
|
99cbc7 |
+ * Using a udev specific function, query the @path to get and return a
|
|
|
99cbc7 |
+ * unique @key for the caller to use. Unlike the GetSCSIKey method, an
|
|
|
99cbc7 |
+ * NPIV LUN is uniquely identified by its ID_TARGET_PORT value.
|
|
|
99cbc7 |
+ *
|
|
|
99cbc7 |
+ * Returns:
|
|
|
99cbc7 |
+ * 0 On success, with the @key filled in or @key=NULL if the
|
|
|
99cbc7 |
+ * returned output string didn't have the data we need to
|
|
|
99cbc7 |
+ * formulate a unique key value
|
|
|
99cbc7 |
+ * -1 When WITH_UDEV is undefined and a system error is reported
|
|
|
99cbc7 |
+ * -2 When WITH_UDEV is defined, but calling virCommandRun fails
|
|
|
99cbc7 |
+ */
|
|
|
99cbc7 |
+# define ID_SERIAL "ID_SERIAL="
|
|
|
99cbc7 |
+# define ID_TARGET_PORT "ID_TARGET_PORT="
|
|
|
99cbc7 |
+int
|
|
|
99cbc7 |
+virStorageFileGetNPIVKey(const char *path,
|
|
|
99cbc7 |
+ char **key)
|
|
|
99cbc7 |
+{
|
|
|
99cbc7 |
+ int status;
|
|
|
99cbc7 |
+ char *outbuf = NULL;
|
|
|
99cbc7 |
+ const char *serial;
|
|
|
99cbc7 |
+ const char *port;
|
|
|
99cbc7 |
+ virCommandPtr cmd = virCommandNewArgList("/lib/udev/scsi_id",
|
|
|
99cbc7 |
+ "--replace-whitespace",
|
|
|
99cbc7 |
+ "--whitelisted",
|
|
|
99cbc7 |
+ "--export",
|
|
|
99cbc7 |
+ "--device", path,
|
|
|
99cbc7 |
+ NULL
|
|
|
99cbc7 |
+ );
|
|
|
99cbc7 |
+ int ret = -2;
|
|
|
99cbc7 |
+
|
|
|
99cbc7 |
+ *key = NULL;
|
|
|
99cbc7 |
+
|
|
|
99cbc7 |
+ /* Run the program and capture its output */
|
|
|
99cbc7 |
+ virCommandSetOutputBuffer(cmd, &outbuf);
|
|
|
99cbc7 |
+ if (virCommandRun(cmd, &status) < 0)
|
|
|
99cbc7 |
+ goto cleanup;
|
|
|
99cbc7 |
+
|
|
|
99cbc7 |
+ /* Explicitly check status == 0, rather than passing NULL
|
|
|
99cbc7 |
+ * to virCommandRun because we don't want to raise an actual
|
|
|
99cbc7 |
+ * error in this scenario, just return a NULL key.
|
|
|
99cbc7 |
+ */
|
|
|
99cbc7 |
+ if (status == 0 && *outbuf &&
|
|
|
99cbc7 |
+ (serial = strstr(outbuf, ID_SERIAL)) &&
|
|
|
99cbc7 |
+ (port = strstr(outbuf, ID_TARGET_PORT))) {
|
|
|
99cbc7 |
+ char *tmp;
|
|
|
99cbc7 |
+
|
|
|
99cbc7 |
+ serial += strlen(ID_SERIAL);
|
|
|
99cbc7 |
+ port += strlen(ID_TARGET_PORT);
|
|
|
99cbc7 |
+
|
|
|
99cbc7 |
+ if ((tmp = strchr(serial, '\n')))
|
|
|
99cbc7 |
+ *tmp = '\0';
|
|
|
99cbc7 |
+
|
|
|
99cbc7 |
+ if ((tmp = strchr(port, '\n')))
|
|
|
99cbc7 |
+ *tmp = '\0';
|
|
|
99cbc7 |
+
|
|
|
99cbc7 |
+ if (*serial != '\0' && *port != '\0')
|
|
|
99cbc7 |
+ ignore_value(virAsprintf(key, "%s_PORT%s", serial, port));
|
|
|
99cbc7 |
+ }
|
|
|
99cbc7 |
+
|
|
|
99cbc7 |
+ ret = 0;
|
|
|
99cbc7 |
+
|
|
|
99cbc7 |
+ cleanup:
|
|
|
99cbc7 |
+ virCommandFree(cmd);
|
|
|
99cbc7 |
+ VIR_FREE(outbuf);
|
|
|
99cbc7 |
+
|
|
|
99cbc7 |
+ return ret;
|
|
|
99cbc7 |
+}
|
|
|
99cbc7 |
+#else
|
|
|
99cbc7 |
+int virStorageFileGetNPIVKey(const char *path,
|
|
|
99cbc7 |
+ char **key ATTRIBUTE_UNUSED)
|
|
|
99cbc7 |
+{
|
|
|
99cbc7 |
+ return -1;
|
|
|
99cbc7 |
+}
|
|
|
99cbc7 |
+#endif
|
|
|
99cbc7 |
+
|
|
|
99cbc7 |
/**
|
|
|
99cbc7 |
* virStorageFileParseBackingStoreStr:
|
|
|
99cbc7 |
* @str: backing store specifier string to parse
|
|
|
99cbc7 |
diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h
|
|
|
99cbc7 |
index bbb0b8b3c1..7d28dcfe65 100644
|
|
|
99cbc7 |
--- a/src/util/virstoragefile.h
|
|
|
99cbc7 |
+++ b/src/util/virstoragefile.h
|
|
|
99cbc7 |
@@ -386,6 +386,8 @@ int virStorageFileGetLVMKey(const char *path,
|
|
|
99cbc7 |
int virStorageFileGetSCSIKey(const char *path,
|
|
|
99cbc7 |
char **key,
|
|
|
99cbc7 |
bool ignoreError);
|
|
|
99cbc7 |
+int virStorageFileGetNPIVKey(const char *path,
|
|
|
99cbc7 |
+ char **key);
|
|
|
99cbc7 |
|
|
|
99cbc7 |
void virStorageAuthDefFree(virStorageAuthDefPtr def);
|
|
|
99cbc7 |
virStorageAuthDefPtr virStorageAuthDefCopy(const virStorageAuthDef *src);
|
|
|
99cbc7 |
--
|
|
|
99cbc7 |
2.21.0
|
|
|
99cbc7 |
|