[DEMO 1/2] Demo: API for querying scsi disk name from VPD83 ID.
by Gris Ge
C(using libudev):
int lsm_scsi_disk_name_list_of_vpd83(const char *vpd83,
const char ***sd_name_list,
uint32_t *sd_name_count);
void lsm_scsi_disk_name_list_free(const char **sd_name_list,
uint32_t sd_count);
Python(using pyudev):
lsm.SCSI.disk_name_of_vpd83(vpd83)
Signed-off-by: Gris Ge <fge(a)redhat.com>
---
c_binding/Makefile.am | 9 +-
c_binding/include/libstoragemgmt/libstoragemgmt.h | 21 +++
c_binding/lsm_scsi.c | 168 ++++++++++++++++++++++
c_binding/ptr_list.c | 143 ++++++++++++++++++
c_binding/ptr_list.h | 44 ++++++
configure.ac | 2 +
python_binding/Makefile.am | 1 +
python_binding/lsm/__init__.py | 2 +
python_binding/lsm/_scsi.py | 49 +++++++
9 files changed, 436 insertions(+), 3 deletions(-)
create mode 100644 c_binding/lsm_scsi.c
create mode 100644 c_binding/ptr_list.c
create mode 100644 c_binding/ptr_list.h
create mode 100644 python_binding/lsm/_scsi.py
diff --git a/c_binding/Makefile.am b/c_binding/Makefile.am
index e4b8e1b..9fe283b 100644
--- a/c_binding/Makefile.am
+++ b/c_binding/Makefile.am
@@ -3,13 +3,16 @@ SUBDIRS = include
AM_CPPFLAGS = -I$(top_srcdir)/c_binding/include \
-I$(top_builddir)/c_binding/include \
-I@srcdir@/c_binding/include \
- $(LIBXML_CFLAGS) $(LIBGLIB_CFLAGS)
+ $(LIBXML_CFLAGS) $(LIBGLIB_CFLAGS) \
+ $(LIBUDEV_CFLAGS)
lib_LTLIBRARIES = libstoragemgmt.la
-libstoragemgmt_la_LIBADD=$(LIBXML_LIBS) $(YAJL_LIBS) $(LIBGLIB_LIBS)
+libstoragemgmt_la_LIBADD=$(LIBXML_LIBS) $(YAJL_LIBS) $(LIBGLIB_LIBS) \
+ $(LIBUDEV_LIBS)
libstoragemgmt_la_LDFLAGS= -version-info $(LIBSM_LIBTOOL_VERSION)
libstoragemgmt_la_SOURCES= \
lsm_mgmt.cpp lsm_datatypes.hpp lsm_datatypes.cpp lsm_convert.hpp \
lsm_convert.cpp lsm_ipc.hpp lsm_ipc.cpp lsm_plugin_ipc.hpp \
- lsm_plugin_ipc.cpp util/qparams.c util/qparams.h
+ lsm_plugin_ipc.cpp util/qparams.c util/qparams.h lsm_scsi.c \
+ ptr_list.c ptr_list.h
diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt.h b/c_binding/include/libstoragemgmt/libstoragemgmt.h
index b902bd8..24829aa 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt.h
@@ -1005,6 +1005,27 @@ int LSM_DLL_EXPORT lsm_volume_raid_create(lsm_connect *c,
lsm_volume **new_volume,
lsm_flag flags);
+/**
+ * Find out the scsi disk names of given VPD83 ID.
+ * New in version 1.3
+ * @param[in] vpd83 String. The VPD83 ID retrieved from LSM volume or disk.
+ * for supported strip sizes.
+ * @param[out] sd_name_list.
+ * Pointer of array of char *. The sting format is 'sdz'. NULL
+ * if not found. Returned memory require manual free.
+ * @param[out] sd_name_count.
+ * Pointer of uint32_t. The count of scsi disk names.
+ * @return LSM_ERR_OK on success or LSM_ERR_INVALID_ARGUMENT when vpd83 or
+ * sd_name pointer is NULL or LSM_ERR_NO_MEMORY when no memory or
+ * LSM_ERR_PLUGIN_BUG when something unexpected happens.
+ */
+int LSM_DLL_EXPORT lsm_scsi_disk_name_list_of_vpd83(const char *vpd83,
+ const char ***sd_name_list,
+ uint32_t *sd_name_count);
+
+void LSM_DLL_EXPORT lsm_scsi_disk_name_list_free(const char **sd_name_list,
+ uint32_t sd_count);
+
#ifdef __cplusplus
}
#endif
diff --git a/c_binding/lsm_scsi.c b/c_binding/lsm_scsi.c
new file mode 100644
index 0000000..7f95025
--- /dev/null
+++ b/c_binding/lsm_scsi.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ * 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 3 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/>.
+ *
+ * Author: Gris Ge <fge(a)redhat.com>
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <libudev.h>
+
+#include "libstoragemgmt/libstoragemgmt.h"
+#include "libstoragemgmt/libstoragemgmt_error.h"
+#include "ptr_list.h"
+
+/*
+ * Using ID_WWN_WITH_EXTENSION udev property to match given VPD83.
+ */
+int lsm_scsi_disk_name_list_of_vpd83(const char *vpd83,
+ const char ***sd_name_list,
+ uint32_t *sd_name_count)
+{
+ struct udev *udev = NULL;
+ struct udev_enumerate *enumerate_sd = NULL;
+ struct udev_list_entry *sd_udevices = NULL;
+ struct udev_list_entry *sd_udev_list = NULL;
+ struct udev_list_entry *sd_udev_list_entry = NULL;
+ struct udev_device *sd_udev = NULL;
+ const char *sd_udev_path = NULL;
+ const char *sd_path = NULL;
+ const char *sd_name = NULL;
+ char *wwn = NULL;
+ int rc = LSM_ERR_OK;
+ uint32_t i = 0;
+ struct pointer_list *all_sd_names = NULL;
+ const char *dev_type = NULL;
+
+ if ((vpd83 == NULL) || (sd_name_list == NULL) || (sd_name_count == NULL))
+ return LSM_ERR_INVALID_ARGUMENT;
+
+ *sd_name_list = NULL;
+ *sd_name_count = 0;
+
+ wwn = (char *) malloc(sizeof(char) *
+ (strlen(vpd83) + strlen("0x") + 1 /* tailing \0 */));
+
+ if (wwn == NULL) {
+ rc = LSM_ERR_NO_MEMORY;
+ goto out;
+ }
+
+ sprintf(wwn, "0x%s", vpd83);
+
+ udev = udev_new();
+ if (udev == NULL) {
+ rc = LSM_ERR_NO_MEMORY;
+ goto out;
+ }
+
+ enumerate_sd = udev_enumerate_new(udev);
+ if (enumerate_sd == NULL) {
+ rc = LSM_ERR_NO_MEMORY;
+ goto out;
+ }
+
+ if (udev_enumerate_add_match_subsystem(enumerate_sd, "block") != 0) {
+ rc = LSM_ERR_PLUGIN_BUG;
+ goto out;
+ }
+
+ if (udev_enumerate_add_match_property(enumerate_sd, "ID_WWN_WITH_EXTENSION",
+ wwn) != 0) {
+ rc = LSM_ERR_PLUGIN_BUG;
+ goto out;
+ }
+
+ if (udev_enumerate_scan_devices(enumerate_sd) != 0) {
+ rc = LSM_ERR_PLUGIN_BUG;
+ goto out;
+ }
+
+ all_sd_names = ptr_list_new();
+ sd_udevices = udev_enumerate_get_list_entry(enumerate_sd);
+ udev_list_entry_foreach(sd_udev_list_entry, sd_udevices) {
+ sd_udev_path = udev_list_entry_get_name(sd_udev_list_entry);
+ if (sd_udev_path == NULL)
+ continue;
+
+ sd_udev = udev_device_new_from_syspath(udev, sd_udev_path);
+ if (sd_udev == NULL) {
+ rc = LSM_ERR_PLUGIN_BUG;
+ goto out;
+ }
+
+ dev_type = udev_device_get_property_value(sd_udev, "DEVTYPE");
+ if ((dev_type == NULL) || (strcmp(dev_type, "disk") != 0)) {
+ udev_device_unref(sd_udev);
+ continue;
+ }
+
+ sd_path = udev_device_get_devnode(sd_udev);
+ if ((sd_path == NULL) ||
+ (strncmp(sd_path, "/dev/sd", strlen("/dev/sd")) != 0)) {
+ udev_device_unref(sd_udev);
+ continue;
+ }
+ sd_name = strdup(sd_path + strlen("/dev/"));
+ if (sd_name == NULL) {
+ rc = LSM_ERR_NO_MEMORY;
+ goto out;
+ }
+ ptr_list_add(all_sd_names, (char *) sd_name);
+ }
+
+ ptr_list_2_array(all_sd_names, (void ***) sd_name_list, sd_name_count);
+
+ out:
+ if (udev != NULL) {
+ udev_unref(udev);
+ }
+ if (enumerate_sd != NULL) {
+ udev_enumerate_unref(enumerate_sd);
+ }
+
+ if (wwn != NULL)
+ free(wwn);
+
+ if (rc != LSM_ERR_OK) {
+ ptr_list_for_each(all_sd_names, i, sd_name) {
+ if (sd_name != NULL)
+ free((char *) sd_name);
+ }
+ *sd_name_list = NULL;
+ *sd_name_count = 0;
+ }
+
+ if (all_sd_names != NULL)
+ ptr_list_free(all_sd_names);
+
+ return rc;
+}
+
+void lsm_scsi_disk_name_list_free(const char **sd_name_list, uint32_t sd_count)
+{
+ uint32_t i = 0;
+
+ if ((sd_name_list == NULL) || (sd_count == 0))
+ return;
+
+ for (; i < sd_count; ++i) {
+ if (sd_name_list[i] != NULL)
+ free((char *) sd_name_list[i]);
+ }
+ free(sd_name_list);
+}
diff --git a/c_binding/ptr_list.c b/c_binding/ptr_list.c
new file mode 100644
index 0000000..ac2d4f5
--- /dev/null
+++ b/c_binding/ptr_list.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ * 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 3 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/>.
+ *
+ * Author: Gris Ge <fge(a)redhat.com>
+ *
+ */
+
+#include "ptr_list.h"
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+struct _list_node {
+ void *data;
+ void *next;
+};
+
+struct pointer_list {
+ struct _list_node *first_node;
+ uint32_t len;
+ struct _list_node *last_node;
+};
+
+struct pointer_list *ptr_list_new(void)
+{
+ struct pointer_list *ptr_list = NULL;
+ ptr_list = (struct pointer_list *) malloc(sizeof(struct pointer_list));
+ if (ptr_list == NULL)
+ exit(EXIT_FAILURE);
+
+ ptr_list->len = 0;
+ ptr_list->first_node = NULL;
+ ptr_list->last_node = NULL;
+ return ptr_list;
+}
+
+void ptr_list_add(struct pointer_list *ptr_list, void *data)
+{
+ struct _list_node *node = NULL;
+
+ if (ptr_list == NULL)
+ return;
+
+ node = (struct _list_node *) malloc(sizeof(struct _list_node));
+ if (node == NULL)
+ exit(EXIT_FAILURE);
+
+ node->data = data;
+ node->next = NULL;
+
+ if (ptr_list->first_node == NULL) {
+ ptr_list->first_node = node;
+ } else {
+ ptr_list->last_node->next = node;
+ }
+ ptr_list->last_node = node;
+ ++(ptr_list->len);
+}
+
+uint32_t ptr_list_len(struct pointer_list *ptr_list)
+{
+ if (ptr_list == NULL)
+ return 0;
+ return ptr_list->len;
+}
+
+void *ptr_list_index(struct pointer_list *ptr_list, uint32_t index)
+{
+ uint32_t i = 0;
+ struct _list_node *node;
+
+ if ((ptr_list == NULL) || (ptr_list->len == 0) || (ptr_list->len <= index))
+ return NULL;
+
+ if (index == ptr_list->len - 1)
+ return ptr_list->last_node->data;
+
+ node = ptr_list->first_node;
+ while((i < index) && (node != NULL)) {
+ node = (struct _list_node *) node->next;
+ ++i;
+ }
+ if (i == index)
+ return node->data;
+ return NULL;
+}
+
+void ptr_list_free(struct pointer_list *ptr_list)
+{
+ struct _list_node *node = NULL;
+ struct _list_node *tmp_node = NULL;
+ uint32_t i;
+
+ if (ptr_list == NULL)
+ return;
+
+ node = ptr_list->first_node;
+
+ while(node != NULL) {
+ tmp_node = node;
+ node = (struct _list_node *) node->next;
+ free(tmp_node);
+ }
+
+ free(ptr_list);
+}
+
+void ptr_list_2_array(struct pointer_list *ptr_list, void ***array,
+ uint32_t *count)
+{
+ uint32_t i = 0;
+ void *data = NULL;
+
+ if ((ptr_list == NULL) || (array == NULL) || (count == NULL))
+ return;
+
+ *array = NULL;
+ *count = ptr_list_len(ptr_list);
+ if (*count == 0)
+ return;
+
+ *array = (void **) malloc(sizeof(void *) * (*count));
+ if (*array == NULL)
+ exit(EXIT_FAILURE);
+
+ ptr_list_for_each(ptr_list, i, data) {
+ (*array)[i] = data;
+ }
+ return;
+}
diff --git a/c_binding/ptr_list.h b/c_binding/ptr_list.h
new file mode 100644
index 0000000..566fded
--- /dev/null
+++ b/c_binding/ptr_list.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ * 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 3 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/>.
+ *
+ * Author: Gris Ge <fge(a)redhat.com>
+ */
+
+#ifndef _PTR_LIST_H_
+#define _PTR_LIST_H_
+
+#include <stdint.h>
+
+struct pointer_list;
+
+struct pointer_list *ptr_list_new(void);
+
+void ptr_list_add(struct pointer_list *ptr_list, void *data);
+
+uint32_t ptr_list_len(struct pointer_list *ptr_list);
+
+void *ptr_list_index(struct pointer_list *ptr_list, uint32_t index);
+
+void ptr_list_free(struct pointer_list *ptr_list);
+
+void ptr_list_2_array(struct pointer_list *ptr_list, void ***array,
+ uint32_t *count);
+
+#define ptr_list_for_each(l, i, d) \
+ for ((i) = 0; \
+ (l) && (i) < ptr_list_len((l)) && ((d) = ptr_list_index((l), (i))); \
+ ++(i))
+
+#endif /* End of _PTR_LIST_H_ */
diff --git a/configure.ac b/configure.ac
index beae390..53acb41 100644
--- a/configure.ac
+++ b/configure.ac
@@ -162,6 +162,8 @@ AM_PATH_PYTHON([2.6], [], AC_MSG_ERROR([Python interpreter 2.6 or 2.7 required])
AC_PYTHON_MODULE([pywbem], [Required])
AC_PYTHON_MODULE([M2Crypto], [Required])
AC_PYTHON_MODULE([argparse], [Required])
+AC_PYTHON_MODULE([pyudev], [Required])
+PKG_CHECK_MODULES([LIBUDEV], [libudev])
dnl ==========================================================================
dnl Check for libmicrohttpd and json-c as it is needed for REST API daemon
diff --git a/python_binding/Makefile.am b/python_binding/Makefile.am
index 8b0581a..0fe1a6d 100644
--- a/python_binding/Makefile.am
+++ b/python_binding/Makefile.am
@@ -10,6 +10,7 @@ lsm_PYTHON = \
lsm/_transport.py \
lsm/version.py \
lsm/_iplugin.py \
+ lsm/_scsi.py \
lsm/_pluginrunner.py
external_PYTHON = \
diff --git a/python_binding/lsm/__init__.py b/python_binding/lsm/__init__.py
index fb1cdbd..f85f072 100644
--- a/python_binding/lsm/__init__.py
+++ b/python_binding/lsm/__init__.py
@@ -13,3 +13,5 @@
from _client import Client
from _pluginrunner import PluginRunner, search_property
+
+from _scsi import SCSI
diff --git a/python_binding/lsm/_scsi.py b/python_binding/lsm/_scsi.py
new file mode 100644
index 0000000..90ac482
--- /dev/null
+++ b/python_binding/lsm/_scsi.py
@@ -0,0 +1,49 @@
+# Copyright (C) 2015 Red Hat, Inc.
+# 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 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/>.
+#
+# Author: Gris Ge <fge(a)redhat.com>
+
+import pyudev
+
+class SCSI(object):
+ @staticmethod
+ def disk_name_of_vpd83(vpd83):
+ """
+ Version:
+ 1.3
+ Usage:
+ Find out the sdX name for given VPD83 ID.
+ Parameters:
+ vpd83 (string)
+ Pool to query
+ Returns:
+ sd_name (list of string)
+ Empty list is not found. The string format if 'sdz'
+
+ SpecialExceptions:
+ N/A
+ Capability:
+ N/A
+ No capability required from plugin as this is a library level
+ method.
+ """
+ rc = []
+ context = pyudev.Context()
+ wwn = '0x%s' % vpd83
+ for dev in context.list_devices(subsystem='block',
+ ID_WWN_WITH_EXTENSION=wwn):
+ sd_path = str(dev.device_node)
+ if sd_path.startswith("/dev/sd") and dev['DEVTYPE'] == "disk":
+ rc.append(sd_path[len("/dev/"):])
+ return rc
--
1.8.3.1
8 years, 5 months
[PATCH 0/3] Fixes for MegaRAID disks.
by Gris Ge
Three fixes for MegaRAID plugin on disk querying:
* Remove check on 'Other Error Count' which is not documented and incorrect on
disk status.
* Fix incorrect disk status on JBOD disk.
* Fix incorrect disk status query.
Gris Ge (3):
MegaRAID Plugin: Fix incorrect disk status.
MegaRAID Plugin: Fix the JBOD disk status
MegaRAID Plugin: Remove 'Other Error Count' check on disk status.
plugin/megaraid/megaraid.py | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
--
1.8.3.1
8 years, 6 months
Supporting JBOD/HBA disks in libstoragemgmt.
by Gris Ge
Hi Team,
I would like to share the possible approaches on supporting JBOD/HBA
disks:
Background:
HP SmartArray:
Only configured to HBA mode, all RAIDed volume will be purged,
all physical disks are exposed to OS directly without
any configure. User has to convert back to RAID mode before
making any config changes to the card.
LSI MegaRAID:
JBOD mode only expose 'unconfigred good' disks to OS, existing
RAIDed volumes are still functional. In JBOD mode, user
can still convert JBOD disks back to hidden RAIDed disk.
Only in JBOD mode, can user expose disks directly to OS.
LibstorageMgmt:
* Explicitly documented Volume can only came from Pool.
* Assuming(not documented) only volumes is OS accessible.
* I am intend to introduce new plugin -- SES to support SCSI
enclosure and new methods like 'disk_locate_led_on()',
'lsm.Client.fans()', 'lsm.Client.sensors()' and etc for
JBOD disk system which Ceph is using.
Options:
A):
`lsm.System.mode == lsm.System.MODE_HBA` indicate besides
checking lsm.Volume, lsm.Disk might also OS accessible.
Add `lsm.Disk.STATUS_HBA` to indicate disks are exposed to OS
directly.
Pros:
Minimum code required for HBA/JBOD disks.
Cons:
API user needs to do extra check on lsm.System.mode
and call lsm.Client.disks() also to check OS
accessible volume/disk.
B):
Create psudo lsm.Pool and lsm.Volume for each HBA/JBOD disk.
Pros:
No workflow change required no API user side.
Cons:
Need extra code to create psudo pool/volume.
I personally prefer option A).
Please kindly let me know you ideas.
Thank you very much.
Best regards.
--
Gris Ge
8 years, 6 months
[PATCH 0/8] Adding new system property: system mode.
by Gris Ge
Adding new system property: lsm.System.mode and lsm_system_mode_get().
Please check patch for detail.
TODO: Need HP's help on hpsa plugin, the original HP patch[1] does not works
works on my system.
[1]: https://github.com/libstorage/libstoragemgmt/pull/52
Gris Ge (8):
C API: New system property: system mode.
Python API: New system property: lsm.System.mode
Simulator Plugin: Add system mode support.
Simulator C Plugin: Add system mode support.
SmartArray Plugin: Add system mode support.
MegaRAID Plugin: Add system mode support.
lsmcli: Add system mode support.
Test cases: New test case for system mode.
.../libstoragemgmt/libstoragemgmt_capabilities.h | 2 ++
.../libstoragemgmt/libstoragemgmt_plug_interface.h | 9 +++++++
.../libstoragemgmt/libstoragemgmt_systems.h | 24 +++++++++++++++++
.../include/libstoragemgmt/libstoragemgmt_types.h | 6 +++++
c_binding/lsm_convert.cpp | 11 ++++++++
c_binding/lsm_datatypes.cpp | 26 ++++++++++++++++++
c_binding/lsm_datatypes.hpp | 1 +
plugin/hpsa/hpsa.py | 21 ++++++++++++++-
plugin/megaraid/megaraid.py | 7 ++++-
plugin/sim/simarray.py | 4 ++-
plugin/simc/simc_lsmplugin.c | 1 +
python_binding/lsm/_data.py | 31 +++++++++++++++++++++-
test/plugin_test.py | 8 ++++++
test/tester.c | 30 +++++++++++++++++++++
tools/lsmcli/data_display.py | 12 +++++++++
15 files changed, 189 insertions(+), 4 deletions(-)
--
1.8.3.1
8 years, 6 months