[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] Smi-s ping tool
by Tony Asleson
Basic tool to connect to a provider and check to make sure we can
enumerate instances of CIM_ComputerSystem so we hopefully have
something to test.
Signed-off-by: Tony Asleson <tasleson(a)redhat.com>
---
tools/smisping/smisping.py | 90 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 90 insertions(+), 0 deletions(-)
create mode 100755 tools/smisping/smisping.py
diff --git a/tools/smisping/smisping.py b/tools/smisping/smisping.py
new file mode 100755
index 0000000..80c1ce2
--- /dev/null
+++ b/tools/smisping/smisping.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python2
+
+# Simple tool to see if we have a SMI-S provider talking on the network and
+# if it has any systems we can test.
+#
+# Can use for scripting as exit value will be:
+# 0 if array is online and enumerate systems has some
+# 1 if we can talk to provider, but no systems
+# 2 Wrong credentials (Wrong username or password)
+# 3 Unable to lookup RegisteredName in registered profile (interop support)
+# 4 if we cannot talk to provider (network error, connection refused etc.)
+
+
+from pywbem import Uint16, CIMError
+import pywbem
+import sys
+DEFAULT_NAMESPACE = 'interop'
+INTEROP_NAMESPACES = ['interop', 'root/interop', 'root/PG_Interop']
+
+
+def get_cim_rps(c):
+ cim_rps = []
+ for n in INTEROP_NAMESPACES:
+ try:
+ cim_rps = c.EnumerateInstances('CIM_RegisteredProfile',
+ namespace=n, localonly=False)
+ except CIMError as e:
+ if e[0] == pywbem.CIM_ERR_NOT_SUPPORTED or \
+ e[0] == pywbem.CIM_ERR_INVALID_NAMESPACE or \
+ e[0] == pywbem.CIM_ERR_INVALID_CLASS:
+ pass
+ else:
+ raise
+
+ if len(cim_rps):
+ for cim_rp in cim_rps:
+ if cim_rp['RegisteredOrganization'] == Uint16(11) and \
+ 'Array' == cim_rp['RegisteredName']:
+ return cim_rp
+ return None
+
+
+def systems(url, username, password):
+ # We will support interop so that we don't have to specify namespace
+ rc = 4
+
+ try:
+ try:
+ conn = pywbem.WBEMConnection(
+ url, (username, password), DEFAULT_NAMESPACE,
+ no_verification=True)
+ except Exception as ei:
+ # Some versions of pywbem don't support the parameter
+ # 'no_verification'
+ if 'no_verification' in str(ei):
+ conn = pywbem.WBEMConnection(
+ url, (username, password), DEFAULT_NAMESPACE)
+ else:
+ raise
+
+ if conn:
+ rps = get_cim_rps(conn)
+
+ if rps:
+ cim_systems = conn.Associators(
+ rps.path, ResultClass='CIM_ComputerSystem',
+ AssocClass='CIM_ElementConformsToProfile')
+ if len(cim_systems):
+ print 'Found %d system(s)' % (len(cim_systems))
+ rc = 0
+ else:
+ print 'No systems found!'
+ rc = 1
+ else:
+ rc = 3
+ except Exception as e:
+ if 'Unauthorized' in str(e):
+ rc = 2
+ else:
+ print 'Exception: ', str(e)
+ return rc
+
+
+if __name__ == '__main__':
+ if len(sys.argv) != 4:
+ print "syntax: ./smisping.py <URL> <username> <password>"
+ print " eg. smisping.py https://127.0.0.1:5989 <username> <passwd>"
+ sys.exit(1)
+
+ sys.exit(systems(*(sys.argv[1:])))
--
1.7.1
8 years, 5 months