Tony Asleson
2014-09-04 21:54:44 UTC
The library expects and now enforces 32 character lower case hex
representation for vpd 0x83.
Added:
C: lsm_volume_vpd83_verify
Py: Volume.vpd83_verify
To allow a user the ability to validate the vpd.
Signed-off-by: Tony Asleson <***@redhat.com>
---
.../include/libstoragemgmt/libstoragemgmt_common.h | 8 +++++++
c_binding/lsm_datatypes.cpp | 15 +++++++++---
c_binding/lsm_mgmt.cpp | 18 +++++++++++++++
python_binding/lsm/_data.py | 21 +++++++++++++----
test/plugin_test.py | 14 +++++++++++
test/tester.c | 27 ++++++++++++++++++++++
6 files changed, 96 insertions(+), 7 deletions(-)
diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_common.h b/c_binding/include/libstoragemgmt/libstoragemgmt_common.h
index 360b49a..64404bb 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_common.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_common.h
@@ -121,6 +121,14 @@ int LSM_DLL_EXPORT lsm_string_list_delete(lsm_string_list *sl, uint32_t index);
int LSM_DLL_EXPORT lsm_initiator_id_verify( const char *init_id,
lsm_access_group_init_type *init_type);
+
+/**
+ * Checks to see if volume vpd83 is valid
+ * @param vpd83 VPD string to check
+ * @return LSM_ERR_OK if vpd is OK, else LSM_INVALID_ARGUMENT
+ */
+int LSM_DLL_EXPORT lsm_volume_vpd83_verify( const char *vpd83 );
+
#ifdef __cplusplus
}
#endif
diff --git a/c_binding/lsm_datatypes.cpp b/c_binding/lsm_datatypes.cpp
index c8475e6..4826a6b 100644
--- a/c_binding/lsm_datatypes.cpp
+++ b/c_binding/lsm_datatypes.cpp
@@ -644,14 +644,23 @@ CREATE_ALLOC_ARRAY_FUNC(lsm_volume_record_array_alloc, lsm_volume *)
lsm_volume * lsm_volume_record_alloc(const char *id, const char *name,
const char *vpd83, uint64_t blockSize,
uint64_t numberOfBlocks,
- uint32_t status, const char *system_id, const char *pool_id, const char* plugin_data)
+ uint32_t status, const char *system_id, const char *pool_id,
+ const char* plugin_data)
{
+ if( vpd83 && (LSM_ERR_OK != lsm_volume_vpd83_verify(vpd83)) ) {
+ return NULL;
+ }
+
lsm_volume *rc = (lsm_volume *)calloc(1, sizeof(lsm_volume));
if (rc) {
rc->magic = LSM_VOL_MAGIC;
rc->id = strdup(id);
rc->name = strdup(name);
- rc->vpd83 = strdup(vpd83);
+
+ if( vpd83 ) {
+ rc->vpd83 = strdup(vpd83);
+ }
+
rc->block_size = blockSize;
rc->number_of_blocks = numberOfBlocks;
rc->admin_state = status;
@@ -662,7 +671,7 @@ lsm_volume * lsm_volume_record_alloc(const char *id, const char *name,
rc->plugin_data = strdup(plugin_data);
}
- if( !rc->id || !rc->name || !rc->vpd83 || !rc->system_id ||
+ if( !rc->id || !rc->name || (vpd83 && !rc->vpd83) || !rc->system_id ||
!rc->pool_id ||
(plugin_data && !rc->plugin_data)) {
lsm_volume_record_free(rc);
diff --git a/c_binding/lsm_mgmt.cpp b/c_binding/lsm_mgmt.cpp
index 36f616d..37faed4 100644
--- a/c_binding/lsm_mgmt.cpp
+++ b/c_binding/lsm_mgmt.cpp
@@ -113,6 +113,24 @@ int lsm_initiator_id_verify(const char *init_id,
return rc;
}
+int lsm_volume_vpd83_verify( const char *vpd83 )
+{
+ int rc = LSM_ERR_INVALID_ARGUMENT;
+ int i;
+
+ if( vpd83 && strlen(vpd83) == 32 ) {
+ for(i = 0; i < 32; ++i) {
+ char v = vpd83[i];
+ // 0-9 || a-f is OK
+ if( !((v >= 48 && v <= 57) || (v >= 97 && v <= 102)) ) {
+ return rc;
+ }
+ }
+ rc = LSM_ERR_OK;
+ }
+ return rc;
+}
+
static int verify_initiator_id(const char *id, lsm_access_group_init_type t,
Value &initiator)
{
diff --git a/python_binding/lsm/_data.py b/python_binding/lsm/_data.py
index 41597d1..2fb1d1f 100644
--- a/python_binding/lsm/_data.py
+++ b/python_binding/lsm/_data.py
@@ -222,6 +222,11 @@ class Disk(IData):
return self.name
+# Lets do this once outside of the class to minimize the number of
+# times it needs to be compiled.
+_vol_regex_vpd83 = re.compile('^[0-9a-f]{32}$')
+
+
@default_property('id', doc="Unique identifier")
@default_property('name', doc="User given name")
@default_property('vpd83', doc="Vital product page 0x83 identifier")
@@ -254,15 +259,14 @@ class Volume(IData):
ADMIN_STATE_DISABLED = 0
ADMIN_STATE_ENABLED = 1
- _regex_vpd83_str = re.compile(r"""^[0-9a-f]{32}$""")
-
def __init__(self, _id, _name, _vpd83, _block_size, _num_of_blocks,
_admin_state, _system_id, _pool_id, _plugin_data=None):
self._id = _id # Identifier
self._name = _name # Human recognisable name
- if _vpd83 and not Volume._regex_vpd83_str.match(_vpd83):
+ if _vpd83 and not Volume.vpd83_verify(_vpd83):
raise LsmError(ErrorNumber.INVALID_ARGUMENT,
- "Incorrect format of VPD 0x83 string: '%s'" %
+ "Incorrect format of VPD 0x83 string: '%s', "
+ "expecting 32 lower case hex characters" %
_vpd83)
self._vpd83 = _vpd83 # SCSI page 83 unique ID
self._block_size = _block_size # Block size
@@ -282,6 +286,15 @@ class Volume(IData):
def __str__(self):
return self.name
+ @staticmethod
+ def vpd83_verify(vpd):
+ """
+ Returns True if string is valid vpd 0x83 representation
+ """
+ if vpd and _vol_regex_vpd83.match(vpd):
+ return True
+ return False
+
@default_property('id', doc="Unique identifier")
@default_property('name', doc="User defined system name")
diff --git a/test/plugin_test.py b/test/plugin_test.py
index 8679e54..eb09b23 100755
--- a/test/plugin_test.py
+++ b/test/plugin_test.py
@@ -975,6 +975,20 @@ class TestPlugin(unittest.TestCase):
self.c.access_group_delete(ag)
+ def test_volume_vpd83_verify(self):
+
+ failing = [None,
+ "012345678901234567890123456789AB",
+ "012345678901234567890123456789ax",
+ "012345678901234567890123456789ag",
+ "1234567890123456789012345abcdef",
+ "01234567890123456789012345abcdefa"]
+
+ for f in failing:
+ self.assertFalse(lsm.Volume.vpd83_verify(f))
+
+ self.assertTrue(
+ lsm.Volume.vpd83_verify("01234567890123456789012345abcdef"))
def dump_results():
diff --git a/test/tester.c b/test/tester.c
index 01a8513..4cf2f28 100644
--- a/test/tester.c
+++ b/test/tester.c
@@ -66,6 +66,17 @@ fail_unless( LSM_ERR_OK == variable, "call:%s rc = %d %s (which %d)", #func, \
variable, error(lsm_error_last_get(c)), which_plugin);
/**
+ * Macro for calls which we expect failure.
+ * @param variable Where the result of the call is placed
+ * @param func Name of function
+ * @param ... Function parameters
+ */
+#define F(variable, func, ...) \
+variable = func(__VA_ARGS__); \
+fail_unless( LSM_ERR_OK != variable, "call:%s rc = %d %s (which %d)", #func, \
+ variable, error(lsm_error_last_get(c)), which_plugin);
+
+/**
* Generates a random string in the buffer with specified length.
* Note: This function should not produce repeating sequences or duplicates
* regardless if it's used repeatedly in the same function in the same process
@@ -2827,6 +2838,21 @@ START_TEST(test_initiator_id_verification)
}
END_TEST
+START_TEST(test_volume_vpd_check)
+{
+ int rc;
+
+ F(rc, lsm_volume_vpd83_verify, NULL );
+ F(rc, lsm_volume_vpd83_verify, "012345678901234567890123456789AB");
+ F(rc, lsm_volume_vpd83_verify, "012345678901234567890123456789ax");
+ F(rc, lsm_volume_vpd83_verify, "012345678901234567890123456789ag");
+ F(rc, lsm_volume_vpd83_verify, "1234567890123456789012345abcdef");
+ F(rc, lsm_volume_vpd83_verify, "01234567890123456789012345abcdefa");
+
+ G(rc, lsm_volume_vpd83_verify, "01234567890123456789012345abcdef");
+}
+END_TEST
+
Suite * lsm_suite(void)
{
Suite *s = suite_create("libStorageMgmt");
@@ -2834,6 +2860,7 @@ Suite * lsm_suite(void)
TCase *basic = tcase_create("Basic");
tcase_add_checked_fixture (basic, setup, teardown);
+ tcase_add_test(basic, test_volume_vpd_check);
tcase_add_test(basic, test_initiator_id_verification);
tcase_add_test(basic, test_target_ports);
tcase_add_test(basic, test_search_fs);
representation for vpd 0x83.
Added:
C: lsm_volume_vpd83_verify
Py: Volume.vpd83_verify
To allow a user the ability to validate the vpd.
Signed-off-by: Tony Asleson <***@redhat.com>
---
.../include/libstoragemgmt/libstoragemgmt_common.h | 8 +++++++
c_binding/lsm_datatypes.cpp | 15 +++++++++---
c_binding/lsm_mgmt.cpp | 18 +++++++++++++++
python_binding/lsm/_data.py | 21 +++++++++++++----
test/plugin_test.py | 14 +++++++++++
test/tester.c | 27 ++++++++++++++++++++++
6 files changed, 96 insertions(+), 7 deletions(-)
diff --git a/c_binding/include/libstoragemgmt/libstoragemgmt_common.h b/c_binding/include/libstoragemgmt/libstoragemgmt_common.h
index 360b49a..64404bb 100644
--- a/c_binding/include/libstoragemgmt/libstoragemgmt_common.h
+++ b/c_binding/include/libstoragemgmt/libstoragemgmt_common.h
@@ -121,6 +121,14 @@ int LSM_DLL_EXPORT lsm_string_list_delete(lsm_string_list *sl, uint32_t index);
int LSM_DLL_EXPORT lsm_initiator_id_verify( const char *init_id,
lsm_access_group_init_type *init_type);
+
+/**
+ * Checks to see if volume vpd83 is valid
+ * @param vpd83 VPD string to check
+ * @return LSM_ERR_OK if vpd is OK, else LSM_INVALID_ARGUMENT
+ */
+int LSM_DLL_EXPORT lsm_volume_vpd83_verify( const char *vpd83 );
+
#ifdef __cplusplus
}
#endif
diff --git a/c_binding/lsm_datatypes.cpp b/c_binding/lsm_datatypes.cpp
index c8475e6..4826a6b 100644
--- a/c_binding/lsm_datatypes.cpp
+++ b/c_binding/lsm_datatypes.cpp
@@ -644,14 +644,23 @@ CREATE_ALLOC_ARRAY_FUNC(lsm_volume_record_array_alloc, lsm_volume *)
lsm_volume * lsm_volume_record_alloc(const char *id, const char *name,
const char *vpd83, uint64_t blockSize,
uint64_t numberOfBlocks,
- uint32_t status, const char *system_id, const char *pool_id, const char* plugin_data)
+ uint32_t status, const char *system_id, const char *pool_id,
+ const char* plugin_data)
{
+ if( vpd83 && (LSM_ERR_OK != lsm_volume_vpd83_verify(vpd83)) ) {
+ return NULL;
+ }
+
lsm_volume *rc = (lsm_volume *)calloc(1, sizeof(lsm_volume));
if (rc) {
rc->magic = LSM_VOL_MAGIC;
rc->id = strdup(id);
rc->name = strdup(name);
- rc->vpd83 = strdup(vpd83);
+
+ if( vpd83 ) {
+ rc->vpd83 = strdup(vpd83);
+ }
+
rc->block_size = blockSize;
rc->number_of_blocks = numberOfBlocks;
rc->admin_state = status;
@@ -662,7 +671,7 @@ lsm_volume * lsm_volume_record_alloc(const char *id, const char *name,
rc->plugin_data = strdup(plugin_data);
}
- if( !rc->id || !rc->name || !rc->vpd83 || !rc->system_id ||
+ if( !rc->id || !rc->name || (vpd83 && !rc->vpd83) || !rc->system_id ||
!rc->pool_id ||
(plugin_data && !rc->plugin_data)) {
lsm_volume_record_free(rc);
diff --git a/c_binding/lsm_mgmt.cpp b/c_binding/lsm_mgmt.cpp
index 36f616d..37faed4 100644
--- a/c_binding/lsm_mgmt.cpp
+++ b/c_binding/lsm_mgmt.cpp
@@ -113,6 +113,24 @@ int lsm_initiator_id_verify(const char *init_id,
return rc;
}
+int lsm_volume_vpd83_verify( const char *vpd83 )
+{
+ int rc = LSM_ERR_INVALID_ARGUMENT;
+ int i;
+
+ if( vpd83 && strlen(vpd83) == 32 ) {
+ for(i = 0; i < 32; ++i) {
+ char v = vpd83[i];
+ // 0-9 || a-f is OK
+ if( !((v >= 48 && v <= 57) || (v >= 97 && v <= 102)) ) {
+ return rc;
+ }
+ }
+ rc = LSM_ERR_OK;
+ }
+ return rc;
+}
+
static int verify_initiator_id(const char *id, lsm_access_group_init_type t,
Value &initiator)
{
diff --git a/python_binding/lsm/_data.py b/python_binding/lsm/_data.py
index 41597d1..2fb1d1f 100644
--- a/python_binding/lsm/_data.py
+++ b/python_binding/lsm/_data.py
@@ -222,6 +222,11 @@ class Disk(IData):
return self.name
+# Lets do this once outside of the class to minimize the number of
+# times it needs to be compiled.
+_vol_regex_vpd83 = re.compile('^[0-9a-f]{32}$')
+
+
@default_property('id', doc="Unique identifier")
@default_property('name', doc="User given name")
@default_property('vpd83', doc="Vital product page 0x83 identifier")
@@ -254,15 +259,14 @@ class Volume(IData):
ADMIN_STATE_DISABLED = 0
ADMIN_STATE_ENABLED = 1
- _regex_vpd83_str = re.compile(r"""^[0-9a-f]{32}$""")
-
def __init__(self, _id, _name, _vpd83, _block_size, _num_of_blocks,
_admin_state, _system_id, _pool_id, _plugin_data=None):
self._id = _id # Identifier
self._name = _name # Human recognisable name
- if _vpd83 and not Volume._regex_vpd83_str.match(_vpd83):
+ if _vpd83 and not Volume.vpd83_verify(_vpd83):
raise LsmError(ErrorNumber.INVALID_ARGUMENT,
- "Incorrect format of VPD 0x83 string: '%s'" %
+ "Incorrect format of VPD 0x83 string: '%s', "
+ "expecting 32 lower case hex characters" %
_vpd83)
self._vpd83 = _vpd83 # SCSI page 83 unique ID
self._block_size = _block_size # Block size
@@ -282,6 +286,15 @@ class Volume(IData):
def __str__(self):
return self.name
+ @staticmethod
+ def vpd83_verify(vpd):
+ """
+ Returns True if string is valid vpd 0x83 representation
+ """
+ if vpd and _vol_regex_vpd83.match(vpd):
+ return True
+ return False
+
@default_property('id', doc="Unique identifier")
@default_property('name', doc="User defined system name")
diff --git a/test/plugin_test.py b/test/plugin_test.py
index 8679e54..eb09b23 100755
--- a/test/plugin_test.py
+++ b/test/plugin_test.py
@@ -975,6 +975,20 @@ class TestPlugin(unittest.TestCase):
self.c.access_group_delete(ag)
+ def test_volume_vpd83_verify(self):
+
+ failing = [None,
+ "012345678901234567890123456789AB",
+ "012345678901234567890123456789ax",
+ "012345678901234567890123456789ag",
+ "1234567890123456789012345abcdef",
+ "01234567890123456789012345abcdefa"]
+
+ for f in failing:
+ self.assertFalse(lsm.Volume.vpd83_verify(f))
+
+ self.assertTrue(
+ lsm.Volume.vpd83_verify("01234567890123456789012345abcdef"))
def dump_results():
diff --git a/test/tester.c b/test/tester.c
index 01a8513..4cf2f28 100644
--- a/test/tester.c
+++ b/test/tester.c
@@ -66,6 +66,17 @@ fail_unless( LSM_ERR_OK == variable, "call:%s rc = %d %s (which %d)", #func, \
variable, error(lsm_error_last_get(c)), which_plugin);
/**
+ * Macro for calls which we expect failure.
+ * @param variable Where the result of the call is placed
+ * @param func Name of function
+ * @param ... Function parameters
+ */
+#define F(variable, func, ...) \
+variable = func(__VA_ARGS__); \
+fail_unless( LSM_ERR_OK != variable, "call:%s rc = %d %s (which %d)", #func, \
+ variable, error(lsm_error_last_get(c)), which_plugin);
+
+/**
* Generates a random string in the buffer with specified length.
* Note: This function should not produce repeating sequences or duplicates
* regardless if it's used repeatedly in the same function in the same process
@@ -2827,6 +2838,21 @@ START_TEST(test_initiator_id_verification)
}
END_TEST
+START_TEST(test_volume_vpd_check)
+{
+ int rc;
+
+ F(rc, lsm_volume_vpd83_verify, NULL );
+ F(rc, lsm_volume_vpd83_verify, "012345678901234567890123456789AB");
+ F(rc, lsm_volume_vpd83_verify, "012345678901234567890123456789ax");
+ F(rc, lsm_volume_vpd83_verify, "012345678901234567890123456789ag");
+ F(rc, lsm_volume_vpd83_verify, "1234567890123456789012345abcdef");
+ F(rc, lsm_volume_vpd83_verify, "01234567890123456789012345abcdefa");
+
+ G(rc, lsm_volume_vpd83_verify, "01234567890123456789012345abcdef");
+}
+END_TEST
+
Suite * lsm_suite(void)
{
Suite *s = suite_create("libStorageMgmt");
@@ -2834,6 +2860,7 @@ Suite * lsm_suite(void)
TCase *basic = tcase_create("Basic");
tcase_add_checked_fixture (basic, setup, teardown);
+ tcase_add_test(basic, test_volume_vpd_check);
tcase_add_test(basic, test_initiator_id_verification);
tcase_add_test(basic, test_target_ports);
tcase_add_test(basic, test_search_fs);
--
1.8.2.1
1.8.2.1