Discussion:
[Libstoragemgmt-devel] [PATCH 1/4] simc_lsmplugin.c: Change pools storage to hash
Tony Asleson
2014-03-25 23:02:19 UTC
Permalink
Signed-off-by: Tony Asleson <***@redhat.com>
---
plugin/simc_lsmplugin.c | 145 +++++++++++++++++++++++-------------------------
1 file changed, 68 insertions(+), 77 deletions(-)

diff --git a/plugin/simc_lsmplugin.c b/plugin/simc_lsmplugin.c
index bf64c92..c309ef0 100644
--- a/plugin/simc_lsmplugin.c
+++ b/plugin/simc_lsmplugin.c
@@ -40,7 +40,6 @@ static char sys_id[] = "sim-01";

#define BS 512
#define MAX_SYSTEMS 1
-#define MAX_POOLS 4
#define MAX_VOLUMES 128
#define MAX_FS 32
#define MAX_EXPORT 32
@@ -109,9 +108,6 @@ struct plugin_data {
uint32_t num_systems;
lsmSystem *system[MAX_SYSTEMS];

- uint32_t num_pools;
- lsmPool *pool[MAX_POOLS];
-
uint32_t num_volumes;
struct allocated_volume volume[MAX_VOLUMES];

@@ -120,6 +116,8 @@ struct plugin_data {
GHashTable *fs;

GHashTable *jobs;
+
+ GHashTable *pools;
};

struct allocated_job {
@@ -204,6 +202,13 @@ void free_allocated_ag(void *v)
}
}

+void free_pool_record(void *p)
+{
+ if( p ) {
+ lsmPoolRecordFree((lsmPool*)p);
+ }
+}
+
void free_fs_record(struct allocated_fs *fs)
{
if( fs ) {
@@ -421,30 +426,31 @@ static int list_pools(lsmPluginPtr c, lsmPool **poolArray[],
{
int rc = LSM_ERR_OK;
struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);
+ *count = g_hash_table_size(pd->pools);

- if(pd) {
- *count = pd->num_pools;
- *poolArray = lsmPoolRecordArrayAlloc( pd->num_pools );
-
+ if( *count ) {
+ *poolArray = lsmPoolRecordArrayAlloc( *count );
if( *poolArray ) {
uint32_t i = 0;
- for( i = 0; i < pd->num_pools; ++i ) {
- (*poolArray)[i] = lsmPoolRecordCopy(pd->pool[i]);
+ char *k = NULL;
+ lsmPool *p = NULL;
+ GHashTableIter iter;
+ g_hash_table_iter_init(&iter, pd->pools);
+ while(g_hash_table_iter_next(&iter,(gpointer) &k,(gpointer)&p)) {
+ (*poolArray)[i] = lsmPoolRecordCopy(p);
if( !(*poolArray)[i] ) {
rc = LSM_ERR_NO_MEMORY;
lsmPoolRecordArrayFree(*poolArray, i);
- *poolArray = NULL;
*count = 0;
+ *poolArray = NULL;
break;
}
+ ++i;
}
} else {
- rc = LSM_ERR_NO_MEMORY;
+ rc = lsmLogErrorBasic(c, LSM_ERR_NO_MEMORY, "ENOMEM");
}
- } else {
- rc = LSM_ERR_INVALID_PLUGIN;
}
-
return rc;
}

@@ -706,17 +712,9 @@ void pool_deallocate(lsmPool *p, uint64_t size)
lsmPoolFreeSpaceSet(p, free_space);
}

-static int find_pool(struct plugin_data *pd, const char* pool_id)
+static lsmPool *find_pool(struct plugin_data *pd, const char* pool_id)
{
- if( pd ) {
- int i;
- for( i = 0; i < pd->num_pools; ++i ) {
- if( strcmp(lsmPoolIdGet(pd->pool[i]), pool_id) == 0) {
- return i;
- }
- }
- }
- return -1;
+ return (lsmPool*) g_hash_table_lookup(pd->pools, pool_id);
}

static int find_volume_name(struct plugin_data *pd, const char *name)
@@ -740,12 +738,11 @@ static int volume_create(lsmPluginPtr c, lsmPool *pool,
int rc = LSM_ERR_OK;

struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);
- int pool_index = find_pool(pd, lsmPoolIdGet(pool));
+ lsmPool *p = find_pool(pd, lsmPoolIdGet(pool));

- if( pool_index >= 0 ) {
+ if( p ) {
if( -1 == find_volume_name(pd, volumeName) ) {
if ( pd->num_volumes < MAX_VOLUMES ) {
- lsmPool *p = pd->pool[pool_index];
uint64_t allocated_size = pool_allocate(p, size);
if( allocated_size ) {
char *id = md5(volumeName);
@@ -791,41 +788,30 @@ static int volume_replicate(lsmPluginPtr c, lsmPool *pool,
char **job, lsmFlag_t flags)
{
int rc = LSM_ERR_OK;
- int pi = 0;
int vi;
- lsmPool *pool_to_use = pool;
+ lsmPool *pool_to_use = NULL;

struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);

- /* If the user didn't pass us a pool to use, we will use the same one
- that the source pool is contained on */
- if( pool_to_use ) {
- pi = find_pool(pd, lsmPoolIdGet(pool));
+ if( pool ) {
+ pool_to_use = find_pool(pd, lsmPoolIdGet(pool));
} else {
- int pool_index = find_pool(pd, lsmVolumePoolIdGet(volumeSrc));
-
- if( pool_index >= 0 )
- pool_to_use = pd->pool[pool_index];
+ pool_to_use = find_pool(pd, lsmVolumePoolIdGet(volumeSrc));
}

- vi = find_volume_name(pd, lsmVolumeNameGet(volumeSrc));
-
- if( pool_to_use && pi > -1 && vi > -1 ) {
- rc = volume_create(c, pool_to_use, name,
+ if( !pool_to_use ) {
+ rc = lsmLogErrorBasic(c, LSM_ERR_NOT_FOUND_POOL,
+ "Pool not found!");
+ } else {
+ vi = find_volume_name(pd, lsmVolumeNameGet(volumeSrc));
+ if( vi > -1 ) {
+ rc = volume_create(c, pool_to_use, name,
lsmVolumeNumberOfBlocksGet(volumeSrc)*BS,
LSM_PROVISION_DEFAULT, newReplicant, job, flags);
-
-
- } else {
- if ( -1 == vi ) {
+ } else {
rc = lsmLogErrorBasic(c, LSM_ERR_NOT_FOUND_VOLUME,
"Volume not found!");
}
-
- if( -1 == pi ) {
- rc = lsmLogErrorBasic(c, LSM_ERR_NOT_FOUND_POOL,
- "Pool not found!");
- }
}
return rc;
}
@@ -1685,11 +1671,10 @@ static int fs_create(lsmPluginPtr c, lsmPool *pool, const char *name,
int rc = LSM_ERR_OK;
struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);

- int pi = find_pool(pd, lsmPoolIdGet(pool));
+ lsmPool *p = find_pool(pd, lsmPoolIdGet(pool));


- if( -1 != pi && !g_hash_table_lookup(pd->fs, md5(name)) ) {
- lsmPool *p = pd->pool[pi];
+ if( p && !g_hash_table_lookup(pd->fs, md5(name)) ) {
uint64_t allocated_size = pool_allocate(p, size_bytes);
if( allocated_size ) {
char *id = md5(name);
@@ -1724,7 +1709,7 @@ static int fs_create(lsmPluginPtr c, lsmPool *pool, const char *name,
"Insufficient space in pool");
}
} else {
- if( -1 == pi ) {
+ if( p == NULL ) {
rc = lsmLogErrorBasic(c, LSM_ERR_NOT_FOUND_POOL, "Pool not found!");
} else {
rc = lsmLogErrorBasic(c, LSM_ERR_EXISTS_NAME,
@@ -2189,6 +2174,8 @@ int load( lsmPluginPtr c, xmlURIPtr uri, const char *password,
struct plugin_data *data = (struct plugin_data *)
malloc(sizeof(struct plugin_data));
int rc = LSM_ERR_NO_MEMORY;
+ int i;
+ lsmPool *p;
if( data ) {
memset(data, 0, sizeof(struct plugin_data));

@@ -2197,20 +2184,31 @@ int load( lsmPluginPtr c, xmlURIPtr uri, const char *password,
"LSM simulated storage plug-in",
LSM_SYSTEM_STATUS_OK);

- data->num_pools = MAX_POOLS;
- data->pool[0] = lsmPoolRecordAlloc("POOL_0", "POOL_ZERO", UINT64_MAX,
- UINT64_MAX, LSM_POOL_STATUS_OK,
- sys_id);
- data->pool[1] = lsmPoolRecordAlloc("POOL_1", "POOL_ONE", UINT64_MAX,
- UINT64_MAX, LSM_POOL_STATUS_OK,
- sys_id);
- data->pool[2] = lsmPoolRecordAlloc("POOL_2", "POOL_TWO", UINT64_MAX,
- UINT64_MAX, LSM_POOL_STATUS_OK,
- sys_id);
- data->pool[3] = lsmPoolRecordAlloc("POOL_3", "lsm_test_aggr",
+ p = lsmPoolRecordAlloc("POOL_3", "lsm_test_aggr",
UINT64_MAX, UINT64_MAX,
LSM_POOL_STATUS_OK,
sys_id);
+ if( p ) {
+ data->pools = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+ free_pool_record);
+
+ g_hash_table_insert(data->pools, lsmPoolIdGet(p), p);
+
+ for( i = 0; i < 3; ++i ) {
+ char name[32];
+ snprintf(name, sizeof(name), "POOL_%d", i);
+
+ p = lsmPoolRecordAlloc(name, name, UINT64_MAX,
+ UINT64_MAX, LSM_POOL_STATUS_OK, sys_id);
+
+ if( p ) {
+ g_hash_table_insert(data->pools, lsmPoolIdGet(p), p);
+ } else {
+ g_hash_table_destroy(data->pools);
+ data->pools = NULL;
+ }
+ }
+ }

data->access_groups = g_hash_table_new_full(g_str_hash, g_str_equal,
free, free_allocated_ag);
@@ -2226,8 +2224,7 @@ int load( lsmPluginPtr c, xmlURIPtr uri, const char *password,
data->jobs = g_hash_table_new_full(g_str_hash, g_str_equal, free,
free_allocated_job);

- if( !data->system[0] || !data->pool[0] || !data->pool[1] ||
- !data->pool[2] || !data->pool[3] || !data->access_groups ||
+ if( !data->system[0] || !data->pools || !data->access_groups ||
!data->group_grant || !data->fs || !data->jobs ) {
rc = LSM_ERR_NO_MEMORY; /* We need to free data and everything else */

@@ -2239,10 +2236,8 @@ int load( lsmPluginPtr c, xmlURIPtr uri, const char *password,
g_hash_table_destroy(data->group_grant);
if( data->access_groups )
g_hash_table_destroy(data->access_groups);
- lsmPoolRecordFree(data->pool[3]);
- lsmPoolRecordFree(data->pool[2]);
- lsmPoolRecordFree(data->pool[1]);
- lsmPoolRecordFree(data->pool[0]);
+ if( data->pools )
+ g_hash_table_destroy(data->pools);
lsmSystemRecordFree(data->system[0]);
memset(data, 0xAA, sizeof(struct plugin_data));
free(data);
@@ -2280,11 +2275,7 @@ int unload( lsmPluginPtr c, lsmFlag_t flags)
}
pd->num_volumes = 0;

- for( i = 0; i < pd->num_pools; ++i ) {
- lsmPoolRecordFree(pd->pool[i]);
- pd->pool[i]= NULL;
- }
- pd->num_pools = 0;
+ g_hash_table_destroy(pd->pools);

for( i = 0; i < pd->num_systems; ++i ) {
lsmSystemRecordFree(pd->system[i]);
--
1.8.2.1
Tony Asleson
2014-03-25 23:02:22 UTC
Permalink
Signed-off-by: Tony Asleson <***@redhat.com>
---
lsm/lsm/_common.py | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/lsm/lsm/_common.py b/lsm/lsm/_common.py
index 745fd9e..5b63a3c 100644
--- a/lsm/lsm/_common.py
+++ b/lsm/lsm/_common.py
@@ -423,7 +423,8 @@ class ErrorNumber(object):
EXISTS_NAME = 53
FS_NOT_EXPORTED = 54
INITIATOR_NOT_IN_ACCESS_GROUP = 55
- EXISTS_VOLUME = 56
+ EXISTS_POOL = 56
+ EXISTS_VOLUME = 57

INVALID_ACCESS_GROUP = 100
INVALID_ARGUMENT = 101
@@ -446,6 +447,7 @@ class ErrorNumber(object):
INVALID_IQN = 118
INVALID_DISK = 119
INVALID_OPTIONAL_DATA = 120
+ INVALID_BLOCK_RANGE = 121

IS_MAPPED = 125

@@ -462,6 +464,8 @@ class ErrorNumber(object):
NOT_FOUND_VOLUME = 205
NOT_FOUND_NFS_EXPORT = 206
NOT_FOUND_INITIATOR = 207
+ NOT_FOUND_SYSTEM = 208
+ NOT_FOUND_DISK = 209

NOT_IMPLEMENTED = 225
NOT_LICENSED = 226
--
1.8.2.1
Tony Asleson
2014-03-25 23:02:21 UTC
Permalink
Signed-off-by: Tony Asleson <***@redhat.com>
---
include/libstoragemgmt/libstoragemgmt.h | 16 +
.../libstoragemgmt/libstoragemgmt_capabilities.h | 62 ++--
include/libstoragemgmt/libstoragemgmt_error.h | 9 +-
.../libstoragemgmt/libstoragemgmt_plug_interface.h | 81 +++++
lsm/lsm/_common.py | 1 +
lsm/lsm/simarray.py | 8 +-
plugin/simc_lsmplugin.c | 353 +++++++++++++++++--
src/lsm_mgmt.cpp | 36 +-
src/lsm_plugin_ipc.cpp | 230 +++++++++++--
test/tester.c | 382 +++++++++++++++++++--
10 files changed, 1059 insertions(+), 119 deletions(-)

diff --git a/include/libstoragemgmt/libstoragemgmt.h b/include/libstoragemgmt/libstoragemgmt.h
index 69fddf2..84b96ba 100644
--- a/include/libstoragemgmt/libstoragemgmt.h
+++ b/include/libstoragemgmt/libstoragemgmt.h
@@ -136,6 +136,22 @@ extern "C" {
lsmFlag_t flags);

/**
+ * Check on the status of a job and return the pool information when
+ * complete
+ * @param[in] conn Valid connection pointer
+ * @param[in] job_id Job to check status on
+ * @param[out] status What is the job status
+ * @param[out] percentComplete Domain 0..100
+ * @param[out] pool lsmPool for completed operation
+ * @param[in] flags Reserved for future use, must be zero
+ * @return LSM_ERR_OK on success, else error reason.
+ */
+ int LSM_DLL_EXPORT lsmJobStatusPoolGet(lsmConnect *conn,
+ const char *job_id, lsmJobStatus *status,
+ uint8_t *percentComplete, lsmPool **pool,
+ lsmFlag_t flags);
+
+ /**
* Check on the status of a job and returns the volume information when
* complete.
* @param[in] conn Valid connection pointer.
diff --git a/include/libstoragemgmt/libstoragemgmt_capabilities.h b/include/libstoragemgmt/libstoragemgmt_capabilities.h
index f34464f..44056be 100644
--- a/include/libstoragemgmt/libstoragemgmt_capabilities.h
+++ b/include/libstoragemgmt/libstoragemgmt_capabilities.h
@@ -109,31 +109,43 @@ typedef enum {
LSM_CAP_EXPORT_CUSTOM_PATH = 124, /**< Plug-in allows user to define custome export path */

LSM_CAP_POOL_CREATE = 130, /**< Pool create support */
- LSM_CAP_POOL_CREATE_THIN = 131, /**< Pool create that support thin prov. */
- LSM_CAP_POOL_CREATE_THICK = 132, /**< Pool create that supports thick prov. */
- LSM_CAP_POOL_CREATE_RAID_TYPE = 133, /**< Pool create supports user defined RAID type */
- LSM_CAP_POOL_CREATE_VIA_MEMBER_COUNT = 134, /**< Pool create supports member count param */
- LSM_CAP_POOL_CREATE_VIA_MEMBER_IDS = 135, /**< Pool create specifing member IDs */
- LSM_CAP_POOL_CREATE_MEMBER_TYPE_DISK = 136, /**< Pool create member is disk */
- LSM_CAP_POOL_CREATE_MEMBER_TYPE_POOL = 137, /**< Pool create member is pool */
- LSM_CAP_POOL_CREATE_MEMBER_TYPE_VOL = 138, /**< Pool create member is volume */
-
- LSM_CAP_POOL_CREATE_RAID_0 = 140, /**< Pool create supports RAID N */
- LSM_CAP_POOL_CREATE_RAID_1 = 141,
- LSM_CAP_POOL_CREATE_RAID_JBOD = 142,
- LSM_CAP_POOL_CREATE_RAID_3 = 143,
- LSM_CAP_POOL_CREATE_RAID_4 = 144,
- LSM_CAP_POOL_CREATE_RAID_5 = 145,
- LSM_CAP_POOL_CREATE_RAID_6 = 146,
- LSM_CAP_POOL_POOL_CREATE_RAID_10 = 147,
- LSM_CAP_POOL_POOL_CREATE_RAID_50 = 148,
- LSM_CAP_POOL_POOL_CREATE_RAID_51 = 149,
- LSM_CAP_POOL_POOL_CREATE_RAID_60 = 150,
- LSM_CAP_POOL_POOL_CREATE_RAID_61 = 151,
- LSM_CAP_POOL_POOL_CREATE_RAID_15 = 152,
- LSM_CAP_POOL_POOL_CREATE_RAID_16 = 153,
-
- LSM_CAP_POOL_DELETE = 160 /**< Pool delete support */
+ LSM_CAP_POOL_CREATE_FROM_DISKS = 131, /**< Pool create from disks */
+ LSM_CAP_POOL_CREATE_FROM_VOLUMES = 132, /**< Pool create from volumes */
+ LSM_CAP_POOL_CREATE_FROM_POOL = 133, /**< Pool create from pool */
+
+ LSM_CAP_POOL_CREATE_DISK_RAID_0 = 140,
+ LSM_CAP_POOL_CREATE_DISK_RAID_1 = 141,
+ LSM_CAP_POOL_CREATE_DISK_RAID_JBOD = 142,
+ LSM_CAP_POOL_CREATE_DISK_RAID_3 = 143,
+ LSM_CAP_POOL_CREATE_DISK_RAID_4 = 144,
+ LSM_CAP_POOL_CREATE_DISK_RAID_5 = 145,
+ LSM_CAP_POOL_CREATE_DISK_RAID_6 = 146,
+ LSM_CAP_POOL_CREATE_DISK_RAID_10 = 147,
+ LSM_CAP_POOL_CREATE_DISK_RAID_50 = 148,
+ LSM_CAP_POOL_CREATE_DISK_RAID_51 = 149,
+ LSM_CAP_POOL_CREATE_DISK_RAID_60 = 150,
+ LSM_CAP_POOL_CREATE_DISK_RAID_61 = 151,
+ LSM_CAP_POOL_CREATE_DISK_RAID_15 = 152,
+ LSM_CAP_POOL_CREATE_DISK_RAID_16 = 153,
+ LSM_CAP_POOL_CREATE_DISK_RAID_NOT_APPLICABLE = 154,
+
+ LSM_CAP_POOL_CREATE_VOLUME_RAID_0 = 160,
+ LSM_CAP_POOL_CREATE_VOLUME_RAID_1 = 161,
+ LSM_CAP_POOL_CREATE_VOLUME_RAID_JBOD = 162,
+ LSM_CAP_POOL_CREATE_VOLUME_RAID_3 = 163,
+ LSM_CAP_POOL_CREATE_VOLUME_RAID_4 = 164,
+ LSM_CAP_POOL_CREATE_VOLUME_RAID_5 = 165,
+ LSM_CAP_POOL_CREATE_VOLUME_RAID_6 = 166,
+ LSM_CAP_POOL_CREATE_VOLUME_RAID_10 = 167,
+ LSM_CAP_POOL_CREATE_VOLUME_RAID_50 = 168,
+ LSM_CAP_POOL_CREATE_VOLUME_RAID_51 = 169,
+ LSM_CAP_POOL_CREATE_VOLUME_RAID_60 = 170,
+ LSM_CAP_POOL_CREATE_VOLUME_RAID_61 = 171,
+ LSM_CAP_POOL_CREATE_VOLUME_RAID_15 = 172,
+ LSM_CAP_POOL_CREATE_VOLUME_RAID_16 = 173,
+ LSM_CAP_POOL_CREATE_VOLUME_RAID_NOT_APPLICABLE = 174,
+
+ LSM_CAP_POOL_DELETE = 200 /**< Pool delete support */
} lsmCapabilityType;

/**
diff --git a/include/libstoragemgmt/libstoragemgmt_error.h b/include/libstoragemgmt/libstoragemgmt_error.h
index 8527e1f..d2ea12a 100644
--- a/include/libstoragemgmt/libstoragemgmt_error.h
+++ b/include/libstoragemgmt/libstoragemgmt_error.h
@@ -57,6 +57,8 @@ typedef enum {
LSM_ERR_EXISTS_NAME = 53, /**< Named item already exists */
LSM_ERR_FS_NOT_EXPORTED = 54, /**< FS not nfs exported */
LSM_ERR_INITIATOR_NOT_IN_ACCESS_GROUP = 55, /**< Initiator not in access group */
+ LSM_ERR_EXISTS_POOL = 56, /**< Pool exists */
+ LSM_ERR_EXISTS_VOLUME = 57, /**< Volume exists */

LSM_ERR_INVALID_ACCESS_GROUP = 100, /**< Invalid access group */
LSM_ERR_INVALID_ARGUMENT = 101, /**< Precondition checks failed */
@@ -96,6 +98,8 @@ typedef enum {
LSM_ERR_NOT_FOUND_VOLUME = 205, /**< Specified volume not found */
LSM_ERR_NOT_FOUND_NFS_EXPORT = 206, /**< NFS export not found */
LSM_ERR_NOT_FOUND_INITIATOR = 207, /**< Initiator not found */
+ LSM_ERR_NOT_FOUND_SYSTEM = 208, /**< System not found */
+ LSM_ERR_NOT_FOUND_DISK = 209, /**< Disk not found */

LSM_ERR_NOT_IMPLEMENTED = 225, /**< Feature not implemented */
LSM_ERR_NOT_LICENSED = 226, /**< Need license for feature */
@@ -128,7 +132,10 @@ typedef enum {

LSM_ERR_UNSUPPORTED_INITIATOR_TYPE = 450, /**< Unsupported initiator type */
LSM_ERR_UNSUPPORTED_PROVISIONING = 451, /**< Unsupported provisioning */
- LSM_ERR_UNSUPPORTED_REPLICATION_TYPE = 452 /**< Unsupported replication type */
+ LSM_ERR_UNSUPPORTED_REPLICATION_TYPE = 452, /**< Unsupported replication type */
+
+ LSM_ERR_DISK_BUSY = 500, /* Disk already in use */
+ LSM_ERR_VOLUME_BUSY = 501 /* Volume already in use */

} lsmErrorNumber;

diff --git a/include/libstoragemgmt/libstoragemgmt_plug_interface.h b/include/libstoragemgmt/libstoragemgmt_plug_interface.h
index f51c96a..c6d7022 100644
--- a/include/libstoragemgmt/libstoragemgmt_plug_interface.h
+++ b/include/libstoragemgmt/libstoragemgmt_plug_interface.h
@@ -216,6 +216,82 @@ typedef int (*lsmPlugListDisks)( lsmPluginPtr c, lsmDisk **diskArray[],
uint32_t *count, lsmFlag_t flags);

/**
+ * Create a pool.
+ * @param[in] c Valid lsm plug-in pointer
+ * @param[in] system_id System id
+ * @param[in] pool_name Human name of pool
+ * @param[in] size_bytes Desired size of pool
+ * @param[in] raid_type Raid type for pool
+ * @param[in] member_type Type of individual members eg. SAS/FC/SSD etc.
+ * @param[out] pool Newly create pool if done sync.
+ * @param[out] job Job id if execution is async.
+ * @return LSM_ERR_OK, else error reason
+ */
+typedef int (*lsmPlugPoolCreate)( lsmPluginPtr c, const char* system_id,
+ const char *pool_name, uint64_t size_bytes,
+ lsmPoolRaidType raid_type, lsmPoolMemberType member_type,
+ lsmPool **pool, char **job, lsmFlag_t flags);
+
+/**
+ * Create a pool and specifying disks to use.
+ * @param[in] c Valid lsm plug-in pointer
+ * @param[in] system_id System id
+ * @param[in] pool_name Human name of pool
+ * @param[in] member_ids List of disk IDs to create pool from
+ * @param[in] raid_type Raid type for pool
+ * @param[out] pool Newly create pool if done sync.
+ * @param[out] job Job id if execution is async.
+ * @return LSM_ERR_OK, else error reason
+ */
+typedef int (*lsmPlugPoolCreateFromDisks)( lsmPluginPtr c, const char *system_id,
+ const char *pool_name, lsmStringList *member_ids,
+ lsmPoolRaidType raid_type, lsmPool **pool, char **job,
+ lsmFlag_t flags);
+
+/**
+ * Create a pool and specifying volumes to use.
+ * @param[in] c Valid lsm plug-in pointer
+ * @param[in] system_id System id
+ * @param[in] pool_name Human name of pool
+ * @param[in] member_ids List of volume IDs to create pool from
+ * @param[in] raid_type Raid type for pool
+ * @param[out] pool Newly create pool if done sync.
+ * @param[out] job Job id if execution is async.
+ * @return LSM_ERR_OK, else error reason
+ */
+typedef int (*lsmPlugPoolCreateFromVolumes)( lsmPluginPtr c, const char *system_id,
+ const char *pool_name, lsmStringList *member_ids,
+ lsmPoolRaidType raid_type, lsmPool** pool, char **job,
+ lsmFlag_t flags);
+
+/**
+ * Create a pool and specifying pool to use.
+ * @param[in] c Valid lsm plug-in pointer
+ * @param[in] system_id System id
+ * @param[in] pool_name Human name of pool
+ * @param[in] member_id ID of pool to create pool from
+ * @param[in] size_bytes Size of pool
+ * @param[out] pool Newly create pool if done sync.
+ * @param[out] job Job id if execution is async.
+ * @return LSM_ERR_OK, else error reason
+ */
+typedef int (*lsmPlugPoolCreateFromPool)( lsmPluginPtr c, const char *system_id,
+ const char *pool_name, const char *member_id,
+ uint64_t size_bytes, lsmPool **pool, char **job,
+ lsmFlag_t flags );
+
+
+/**
+ * Delete a pool.
+ * @param[in] c Valid lsm plug-in pointer
+ * @param[in] pool Pool to delete
+ * @param[out] job Job pointer if job is async
+ * @return LSM_ERR_OK, else error reason
+ */
+typedef int (*lsmPlugPoolDelete)( lsmPluginPtr c, lsmPool *pool, char **job,
+ lsmFlag_t flags);
+
+/**
* Creates a volume, callback function signature
* @param[in] c Valid lsm plug-in pointer
* @param[in] pool Pool to allocated storage from
@@ -797,6 +873,11 @@ struct lsmSanOpsV1 {
lsmPlugListInits init_get; /**< retrieving initiators */
lsmPlugListVolumes vol_get; /**< retrieving volumes */
lsmPlugListDisks disk_get; /**< retrieve disks */
+ lsmPlugPoolCreate pool_create; /**< Pool create */
+ lsmPlugPoolCreateFromDisks pool_create_from_disks; /**< Pool create from disks */
+ lsmPlugPoolCreateFromVolumes pool_create_from_volumes; /**< Pool create using volumes */
+ lsmPlugPoolCreateFromPool pool_create_from_pool; /**< Pool creation from pool */
+ lsmPlugPoolDelete pool_delete; /**< Delete a pool */
lsmPlugVolumeCreate vol_create; /**< creating a lun */
lsmPlugVolumeReplicate vol_replicate; /**< replicating lun */
lsmPlugVolumeReplicateRangeBlockSize vol_rep_range_bs; /**< volume replication range block size */
diff --git a/lsm/lsm/_common.py b/lsm/lsm/_common.py
index c5a315f..745fd9e 100644
--- a/lsm/lsm/_common.py
+++ b/lsm/lsm/_common.py
@@ -423,6 +423,7 @@ class ErrorNumber(object):
EXISTS_NAME = 53
FS_NOT_EXPORTED = 54
INITIATOR_NOT_IN_ACCESS_GROUP = 55
+ EXISTS_VOLUME = 56

INVALID_ACCESS_GROUP = 100
INVALID_ARGUMENT = 101
diff --git a/lsm/lsm/simarray.py b/lsm/lsm/simarray.py
index eddabfa..e5fe45f 100644
--- a/lsm/lsm/simarray.py
+++ b/lsm/lsm/simarray.py
@@ -818,7 +818,7 @@ class SimData(object):
SimData.SIM_DATA_BLK_SIZE

def job_create(self, returned_item):
- if True:
+ if False:
#if random.randint(0,5) == 1:
self.job_num += 1
job_id = "JOB_%s" % self.job_num
@@ -2073,5 +2073,11 @@ class SimData(object):
raise LsmError(ErrorNumber.INVALID_POOL,
"Pool not found: %s" % pool_id)

+ volumes = self.volumes()
+ for v in volumes:
+ if v['pool_id'] == pool_id:
+ raise LsmError(ErrorNumber.EXISTS_VOLUME,
+ "Volumes exist on pool")
+
del(self.pool_dict[pool_id])
return None
diff --git a/plugin/simc_lsmplugin.c b/plugin/simc_lsmplugin.c
index 73d87d5..f4b57e3 100644
--- a/plugin/simc_lsmplugin.c
+++ b/plugin/simc_lsmplugin.c
@@ -29,6 +29,7 @@
#include <time.h>

#include "libstoragemgmt/libstoragemgmt_optionaldata.h"
+#include "libstoragemgmt/libstoragemgmt_disk.h"

#ifdef __cplusplus
extern "C" {
@@ -110,11 +111,10 @@ struct plugin_data {
GHashTable *access_groups;
GHashTable *group_grant;
GHashTable *fs;
-
GHashTable *jobs;
-
GHashTable *pools;
GHashTable *volumes;
+ GHashTable *disks;
};

struct allocated_job {
@@ -654,34 +654,34 @@ static int list_volumes(lsmPluginPtr c, lsmVolume **vols[],
static int list_disks(lsmPluginPtr c, lsmDisk **disks[], uint32_t *count,
lsmFlag_t flags)
{
- int i;
int rc = LSM_ERR_OK;
- char name[17];
- char sn[32];
struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);
- lsmOptionalData *od = lsmOptionalDataRecordAlloc();
-
- if(pd && od) {
- // For now we are going to make up some disks to return. Later we will
- // try to make a simulated array that makes sense.
- *count = 10;
-
- *disks = lsmDiskRecordArrayAlloc(*count);
- for( i = 0; i < *count; ++i ) {
- snprintf(name, sizeof(name), "Sim C disk %d", i);
- snprintf(sn, sizeof(sn), "SIMDISKSN00000%04d\n", i);
+ *count = g_hash_table_size(pd->disks);

- lsmOptionalDataStringSet(od, "sn", sn);

- (*disks)[i] = lsmDiskRecordAlloc(md5(name), name, LSM_DISK_TYPE_SOP, 512,
- 0x8000000000000, LSM_DISK_STATUS_OK, od, sys_id);
+ if( *count ) {
+ *disks = lsmDiskRecordArrayAlloc( *count );
+ if( *disks ) {
+ uint32_t i = 0;
+ char *k = NULL;
+ lsmDisk *disk;
+ GHashTableIter iter;
+ g_hash_table_iter_init(&iter, pd->disks);
+ while(g_hash_table_iter_next(&iter,(gpointer) &k,(gpointer)&disk)) {
+ (*disks)[i] = lsmDiskRecordCopy(disk);
+ if( !(*disks)[i] ) {
+ rc = LSM_ERR_NO_MEMORY;
+ lsmDiskRecordArrayFree(*disks, i);
+ *count = 0;
+ *disks = NULL;
+ break;
+ }
+ ++i;
+ }
+ } else {
+ rc = lsmLogErrorBasic(c, LSM_ERR_NO_MEMORY, "ENOMEM");
}
-
- } else {
- rc = LSM_ERR_INVALID_PLUGIN;
}
-
- lsmOptionalDataRecordFree(od);
return rc;
}

@@ -714,6 +714,25 @@ static lsmPool *find_pool(struct plugin_data *pd, const char* pool_id)
return (lsmPool*) g_hash_table_lookup(pd->pools, pool_id);
}

+static lsmPool * find_pool_name(struct plugin_data *pd, const char *name)
+{
+ char *k = NULL;
+ GHashTableIter iter;
+ lsmPool *pool = NULL;
+ g_hash_table_iter_init(&iter, pd->pools);
+ while(g_hash_table_iter_next(&iter,(gpointer) &k,(gpointer)&pool)) {
+ if( strcmp(lsmPoolNameGet(pool), name) == 0 ) {
+ return pool;
+ }
+ }
+ return NULL;
+}
+
+static lsmDisk * find_disk(struct plugin_data *pd, const char* disk_id)
+{
+ return (lsmDisk*) g_hash_table_lookup(pd->disks, disk_id);
+}
+
static struct allocated_volume *find_volume(struct plugin_data *pd,
const char* vol_id)
{
@@ -914,22 +933,20 @@ static int volume_resize(lsmPluginPtr c, lsmVolume *volume,
return rc;
}

-static int volume_delete(lsmPluginPtr c, lsmVolume *volume,
- char **job, lsmFlag_t flags)
+static int _volume_delete(lsmPluginPtr c, const char *volume_id)
{
int rc = LSM_ERR_OK;
GHashTableIter iter;
char *k = NULL;
GHashTable *v = NULL;
- const char *volume_id = lsmVolumeIdGet(volume);
struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);
+ struct allocated_volume *av = find_volume(pd, volume_id);

- struct allocated_volume *av = find_volume(pd, lsmVolumeIdGet(volume));
if( av ) {
lsmVolume *vp = av->v;
pool_deallocate(av->p, lsmVolumeNumberOfBlocksGet(vp)*BS);

- g_hash_table_remove(pd->volumes, lsmVolumeIdGet(volume));
+ g_hash_table_remove(pd->volumes, volume_id);

g_hash_table_iter_init (&iter, pd->group_grant);
while( g_hash_table_iter_next( &iter, (gpointer)&k, (gpointer)&v) ) {
@@ -938,8 +955,6 @@ static int volume_delete(lsmPluginPtr c, lsmVolume *volume,
}
}

- rc = create_job(pd, job, LSM_DATA_TYPE_NONE, NULL, NULL);
-
} else {
rc = lsmLogErrorBasic(c, LSM_ERR_NOT_FOUND_VOLUME,
"volume not found!");
@@ -947,6 +962,226 @@ static int volume_delete(lsmPluginPtr c, lsmVolume *volume,
return rc;
}

+static int _pool_create(lsmPluginPtr c, const char *system_id,
+ const char *pool_name, uint64_t size_bytes,
+ lsmPool **pool, char **job)
+{
+ int rc = LSM_ERR_OK;
+ struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);
+ lsmPool *new_pool = NULL;
+ lsmPool *pool_to_store = NULL;
+ char *key = NULL;
+
+ /* Verify system id */
+ if( strcmp(system_id, lsmSystemIdGet(pd->system[0])) == 0 ) {
+ /* Verify that we don't already have a pool by that name */
+ new_pool = find_pool_name(pd, pool_name);
+ if( !new_pool ) {
+ /* Create the pool */
+ new_pool = lsmPoolRecordAlloc(md5(pool_name), pool_name, size_bytes,
+ size_bytes, LSM_POOL_STATUS_OK,
+ system_id);
+
+ pool_to_store = lsmPoolRecordCopy(new_pool);
+ key = strdup(lsmPoolIdGet(new_pool));
+ if( new_pool && pool_to_store && key ) {
+ g_hash_table_insert(pd->pools, key, pool_to_store);
+
+ /* Create a job */
+ rc = create_job(pd, job, LSM_DATA_TYPE_POOL, new_pool,
+ (void**)pool);
+ } else {
+ free(key);
+ lsmPoolRecordFree(new_pool);
+ lsmPoolRecordFree(pool_to_store);
+ rc = lsmLogErrorBasic(c, LSM_ERR_NO_MEMORY, "No memory");
+ }
+ } else {
+ rc = lsmLogErrorBasic(c, LSM_ERR_EXISTS_POOL,
+ "Pool with name exists!");
+ }
+ } else {
+ rc = lsmLogErrorBasic(c, LSM_ERR_NOT_FOUND_SYSTEM,
+ "system not found!");
+ }
+ return rc;
+}
+
+
+static int pool_create(lsmPluginPtr c, const char *system_id,
+ const char *pool_name, uint64_t size_bytes,
+ lsmPoolRaidType raid_type,
+ lsmPoolMemberType member_type, lsmPool** pool,
+ char **job, lsmFlag_t flags)
+{
+ return _pool_create(c, system_id, pool_name, size_bytes, pool, job);
+}
+
+static int pool_create_from_disks( lsmPluginPtr c, const char *system_id,
+ const char *pool_name, lsmStringList *member_ids,
+ lsmPoolRaidType raid_type, lsmPool **pool, char **job,
+ lsmFlag_t flags)
+{
+ /* Check that the disks are valid, then call common routine */
+ uint64_t size = 0;
+ int rc = LSM_ERR_OK;
+ int i = 0;
+ int num_disks = lsmStringListSize(member_ids);
+ struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);
+
+ if( num_disks ) {
+ for( i = 0; i < num_disks; ++i ) {
+ lsmDisk *d = find_disk(pd, lsmStringListElemGet(member_ids, i));
+ if( d ) {
+ size += (lsmDiskNumberOfBlocksGet(d) * lsmDiskBlockSizeGet(d));
+ } else {
+ rc = lsmLogErrorBasic(c, LSM_ERR_NOT_FOUND_DISK,
+ "Disk not found");
+ goto bail;
+ }
+ }
+
+ rc = _pool_create(c, system_id, pool_name, size, pool, job);
+ } else {
+ rc = lsmLogErrorBasic(c, LSM_ERR_INVALID_ARGUMENT, "No disks provided");
+ }
+bail:
+ return rc;
+}
+
+static int pool_create_from_volumes( lsmPluginPtr c, const char *system_id,
+ const char *pool_name, lsmStringList *member_ids,
+ lsmPoolRaidType raid_type, lsmPool **pool, char **job,
+ lsmFlag_t flags)
+{
+ /* Check that the disks are valid, then call common routine */
+ uint64_t size = 0;
+ int rc = LSM_ERR_OK;
+ int i = 0;
+ int num_volumes = lsmStringListSize(member_ids);
+ struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);
+
+ if( num_volumes ) {
+ for( i = 0; i < num_volumes; ++i ) {
+ struct allocated_volume *v =
+ find_volume(pd, lsmStringListElemGet(member_ids, i));
+ if( v ) {
+ size += (lsmVolumeNumberOfBlocksGet(v->v) *
+ lsmVolumeNumberOfBlocksGet(v->v));
+ } else {
+ rc = lsmLogErrorBasic(c, LSM_ERR_NOT_FOUND_VOLUME,
+ "Volume not found");
+ goto bail;
+ }
+ }
+
+ rc = _pool_create(c, system_id, pool_name, size, pool, job);
+ } else {
+ rc = lsmLogErrorBasic(c, LSM_ERR_INVALID_ARGUMENT, "No disks provided");
+ }
+bail:
+ return rc;
+}
+
+static int pool_create_from_pool(lsmPluginPtr c, const char *system_id,
+ const char *pool_name, const char *member_id,
+ uint64_t size_bytes, lsmPool **pool, char **job,
+ lsmFlag_t flags )
+{
+ /* Check that the disks are valid, then call common routine */
+ int rc = LSM_ERR_OK;
+ struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);
+ lsmPool *p = find_pool(pd, member_id);
+
+ if( p ) {
+ rc = _pool_create(c, system_id, pool_name, size_bytes, pool, job);
+ } else {
+ rc = lsmLogErrorBasic(c, LSM_ERR_NOT_FOUND_POOL, "Pool not found");
+ }
+ return rc;
+}
+
+static int pool_delete(lsmPluginPtr c, lsmPool *pool, char **job,
+ lsmFlag_t flags)
+{
+ int rc = LSM_ERR_OK;
+ struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);
+ lsmPool *pool_to_delete = find_pool(pd, lsmPoolIdGet(pool));
+ lsmStringList *vol_delete = lsmStringListAlloc(0);
+
+ if( !vol_delete ) {
+ return LSM_ERR_NO_MEMORY;
+ }
+
+ if( pool_to_delete ) {
+
+ /* Loop through building a list of volumes in this pool */
+ char *k = NULL;
+ struct allocated_volume *vol;
+ GHashTableIter iter;
+ g_hash_table_iter_init(&iter, pd->volumes);
+ while(g_hash_table_iter_next(&iter,(gpointer) &k,(gpointer)&vol)) {
+ if( strcmp(lsmVolumePoolIdGet(vol->v), lsmPoolIdGet(pool)) == 0) {
+ if( LSM_ERR_OK != lsmStringListAppend(vol_delete,
+ lsmVolumeIdGet(vol->v))) {
+ lsmStringListFree(vol_delete);
+ rc = LSM_ERR_NO_MEMORY;
+ goto bail;
+ }
+ }
+ }
+
+ /*
+ * Actual arrays will fail the pool delete if it contains a volume,
+ * so we will fail with an error. If this changes we can enable
+ * the code in the for loop below to delete the volumes, one by one.
+ */
+
+ if (lsmStringListSize(vol_delete)) {
+ rc = lsmLogErrorBasic(c, LSM_ERR_EXISTS_VOLUME,
+ "volumes exist on pool");
+
+ vol_delete = NULL;
+ goto bail;
+ }
+
+ /*
+ for( i = 0; i < lsmStringListSize(vol_delete); ++i ) {
+ rc = _volume_delete(c, lsmStringListElemGet(vol_delete, i));
+ if( LSM_ERR_OK != rc ) {
+ rc = lsmLogErrorBasic(c, LSM_ERR_INTERNAL_ERROR,
+ "Error while removing volume from pool");
+ goto bail;
+ }
+ }
+ */
+
+ /* Remove pool from hash */
+ g_hash_table_remove(pd->pools, lsmPoolIdGet(pool));
+
+ rc = create_job(pd, job, LSM_DATA_TYPE_NONE, NULL, NULL);
+
+ } else {
+ rc = lsmLogErrorBasic(c, LSM_ERR_NOT_FOUND_POOL,
+ "pool not found!");
+ }
+bail:
+ lsmStringListFree(vol_delete);
+ return rc;
+}
+
+static int volume_delete(lsmPluginPtr c, lsmVolume *volume,
+ char **job, lsmFlag_t flags)
+{
+ struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);
+ int rc = _volume_delete(c, lsmVolumeIdGet(volume));
+
+ if( LSM_ERR_OK == rc ) {
+ rc = create_job(pd, job, LSM_DATA_TYPE_NONE, NULL, NULL);
+ }
+ return rc;
+}
+
static int volume_online_offline(lsmPluginPtr c, lsmVolume *v,
lsmFlag_t flags)
{
@@ -1621,10 +1856,11 @@ static struct lsmSanOpsV1 sanOps = {
list_initiators,
list_volumes,
list_disks,
- NULL,
- NULL,
- NULL,
- NULL,
+ pool_create,
+ pool_create_from_disks,
+ pool_create_from_volumes,
+ pool_create_from_pool,
+ pool_delete,
volume_create,
volume_replicate,
volume_replicate_range_bs,
@@ -2188,6 +2424,11 @@ void free_allocated_fs(void *v)
free_fs_record((struct allocated_fs*)v);
}

+void free_disk(void *d)
+{
+ lsmDiskRecordFree((lsmDisk *)d);
+}
+
void free_allocated_volume(void *v)
{
if( v ) {
@@ -2258,8 +2499,44 @@ int load( lsmPluginPtr c, xmlURIPtr uri, const char *password,
data->jobs = g_hash_table_new_full(g_str_hash, g_str_equal, free,
free_allocated_job);

+ data->disks = g_hash_table_new_full(g_str_hash, g_str_equal, free,
+ free_disk);
+
+ /* Create disks */
+ lsmOptionalData *od = lsmOptionalDataRecordAlloc();
+ if( od ) {
+ for( i = 0; i < 10; ++i ) {
+ lsmDisk *d = NULL;
+ char name[17];
+ char sn[32];
+ char *key = NULL;
+
+
+ snprintf(name, sizeof(name), "Sim C disk %d", i);
+ snprintf(sn, sizeof(sn), "SIMDISKSN00000%04d\n", i);
+
+ lsmOptionalDataStringSet(od, "sn", sn);
+
+ d = lsmDiskRecordAlloc(md5(name), name, LSM_DISK_TYPE_SOP, 512,
+ 0x8000000000000, LSM_DISK_STATUS_OK, od, sys_id);
+
+ key = strdup(lsmDiskIdGet(d));
+
+ if( !key ) {
+ g_hash_table_destroy(data->disks);
+ data->disks = NULL;
+ break;
+ }
+
+ g_hash_table_insert(data->disks, key, d);
+ d = NULL;
+ }
+ lsmOptionalDataRecordFree(od);
+ }
+
+
if( !data->system[0] || !data->volumes || !data->pools || !data->access_groups ||
- !data->group_grant || !data->fs || !data->jobs ) {
+ !data->group_grant || !data->fs || !data->jobs || !data->disks ) {
rc = LSM_ERR_NO_MEMORY; /* We need to free data and everything else */

if( data->jobs )
@@ -2272,8 +2549,10 @@ int load( lsmPluginPtr c, xmlURIPtr uri, const char *password,
g_hash_table_destroy(data->access_groups);
if( data->pools )
g_hash_table_destroy(data->pools);
- if ( data->volumes )
+ if( data->volumes )
g_hash_table_destroy(data->volumes);
+ if( data->disks )
+ g_hash_table_destroy(data->disks);

lsmSystemRecordFree(data->system[0]);
memset(data, 0xAA, sizeof(struct plugin_data));
diff --git a/src/lsm_mgmt.cpp b/src/lsm_mgmt.cpp
index 3d0520b..4954184 100644
--- a/src/lsm_mgmt.cpp
+++ b/src/lsm_mgmt.cpp
@@ -444,6 +444,38 @@ int lsmJobStatusGet(lsmConnect *c, const char *job_id,
return jobStatus(c, job_id, status, percentComplete, rv, flags);
}

+int lsmJobStatusPoolGet(lsmConnect *c,
+ const char *job, lsmJobStatus *status,
+ uint8_t *percentComplete, lsmPool **pool,
+ lsmFlag_t flags)
+{
+ Value rv;
+ int rc = LSM_ERR_OK;
+
+ CONN_SETUP(c);
+
+ if( CHECK_RP(pool) || LSM_FLAG_UNUSED_CHECK(flags) ) {
+ return LSM_ERR_INVALID_ARGUMENT;
+ }
+
+ try {
+
+ rc = jobStatus(c, job, status, percentComplete, rv, flags);
+
+ if( LSM_ERR_OK == rc ) {
+ if( Value::object_t == rv.valueType() ) {
+ *pool = valueToPool(rv);
+ } else {
+ *pool = NULL;
+ }
+ }
+ } catch( const ValueException &ve ) {
+ rc = logException(c, LSM_ERR_INTERNAL_ERROR, "Unexpected type",
+ ve.what());
+ }
+ return rc;
+}
+
int lsmJobStatusVolumeGet( lsmConnect *c, const char *job,
lsmJobStatus *status, uint8_t *percentComplete,
lsmVolume **vol, lsmFlag_t flags)
@@ -958,7 +990,7 @@ int LSM_DLL_EXPORT lsmPoolCreateFromDisks(lsmConnect *c,
lsmPool** pool, char **job, lsmFlag_t flags)
{
return lsm_pool_create_from(c, system_id, pool_name, member_ids, raid_type,
- pool, job, flags, "lsm_pool_create_from_disks");
+ pool, job, flags, "pool_create_from_disks");
}

int LSM_DLL_EXPORT lsmPoolCreateFromVolumes(lsmConnect *c,
@@ -968,7 +1000,7 @@ int LSM_DLL_EXPORT lsmPoolCreateFromVolumes(lsmConnect *c,
{
return lsm_pool_create_from(c, system_id, pool_name, member_ids, raid_type,
pool, job, flags,
- "lsm_pool_create_from_volumes");
+ "pool_create_from_volumes");
}


diff --git a/src/lsm_plugin_ipc.cpp b/src/lsm_plugin_ipc.cpp
index 01493c5..968fd52 100644
--- a/src/lsm_plugin_ipc.cpp
+++ b/src/lsm_plugin_ipc.cpp
@@ -99,6 +99,14 @@ void * lsmDataTypeCopy(lsmDataType t, void *item)
return rc;
}

+static Value job_handle(const Value &val, char *job)
+{
+ std::vector<Value> r;
+ r.push_back(Value(job));
+ r.push_back(val);
+ return Value(r);
+}
+
int lsmRegisterPluginV1(lsmPluginPtr plug,
void *private_data, struct lsmMgmtOpsV1 *mgmOps,
struct lsmSanOpsV1 *sanOp, struct lsmFsOpsV1 *fsOp,
@@ -354,6 +362,10 @@ static int handle_job_status( lsmPluginPtr p, Value &params, Value &response)
LSM_IS_SS((lsmSs *)value)) {
result.push_back(ssToValue((lsmSs *)value));
lsmSsRecordFree((lsmSs *)value);
+ } else if( LSM_DATA_TYPE_POOL == t &&
+ LSM_IS_POOL((lsmPool *)value)) {
+ result.push_back(poolToValue((lsmPool *)value));
+ lsmPoolRecordFree((lsmPool *)value);
} else {
rc = LSM_ERR_PLUGIN_ERROR;
}
@@ -453,6 +465,190 @@ static int handle_pools(lsmPluginPtr p, Value &params, Value &response)
return rc;
}

+static int handle_pool_create(lsmPluginPtr p, Value &params, Value &response)
+{
+ int rc = LSM_ERR_NO_SUPPORT;
+ if( p && p->sanOps && p->sanOps->pool_create ) {
+
+ Value v_sys_id = params["system_id"];
+ Value v_pool_name = params["pool_name"];
+ Value v_size = params["size_bytes"];
+ Value v_raid_t = params["raid_type"];
+ Value v_member_t = params["member_type"];
+
+ if( Value::string_t == v_sys_id.valueType() &&
+ Value::string_t == v_pool_name.valueType() &&
+ Value::numeric_t == v_size.valueType() &&
+ Value::numeric_t == v_raid_t.valueType() &&
+ Value::numeric_t == v_member_t.valueType() &&
+ LSM_FLAG_EXPECTED_TYPE(params)) {
+
+ const char *sys_id = v_sys_id.asC_str();
+ const char *pool_name = v_pool_name.asC_str();
+ uint64_t size = v_size.asUint64_t();
+ lsmPoolRaidType raid_type = (lsmPoolRaidType)v_raid_t.asInt32_t();
+ lsmPoolMemberType member_type = (lsmPoolMemberType)v_member_t.asInt32_t();
+ lsmPool *pool = NULL;
+ char *job = NULL;
+
+ rc = p->sanOps->pool_create(p, sys_id, pool_name, size, raid_type,
+ member_type, &pool, &job,
+ LSM_FLAG_GET_VALUE(params));
+
+ Value p = poolToValue(pool);
+ response = job_handle(p, job);
+ lsmPoolRecordFree(pool);
+ free(job);
+ } else {
+ rc = LSM_ERR_TRANSPORT_INVALID_ARG;
+ }
+ }
+ return rc;
+}
+
+typedef int (*lsmPlugPoolCreateFrom)( lsmPluginPtr c,
+ const char *system_id,
+ const char *pool_name, lsmStringList *member_ids,
+ lsmPoolRaidType raid_type, lsmPool** pool, char **job,
+ lsmFlag_t flags);
+
+
+static int handle_pool_create_from( lsmPluginPtr p, Value &params,
+ Value &response,
+ lsmPlugPoolCreate
Tony Asleson
2014-03-25 23:02:20 UTC
Permalink
Signed-off-by: Tony Asleson <***@redhat.com>
---
plugin/simc_lsmplugin.c | 236 +++++++++++++++++++++++++++---------------------
1 file changed, 134 insertions(+), 102 deletions(-)

diff --git a/plugin/simc_lsmplugin.c b/plugin/simc_lsmplugin.c
index c309ef0..73d87d5 100644
--- a/plugin/simc_lsmplugin.c
+++ b/plugin/simc_lsmplugin.c
@@ -40,7 +40,6 @@ static char sys_id[] = "sim-01";

#define BS 512
#define MAX_SYSTEMS 1
-#define MAX_VOLUMES 128
#define MAX_FS 32
#define MAX_EXPORT 32

@@ -108,9 +107,6 @@ struct plugin_data {
uint32_t num_systems;
lsmSystem *system[MAX_SYSTEMS];

- uint32_t num_volumes;
- struct allocated_volume volume[MAX_VOLUMES];
-
GHashTable *access_groups;
GHashTable *group_grant;
GHashTable *fs;
@@ -118,6 +114,7 @@ struct plugin_data {
GHashTable *jobs;

GHashTable *pools;
+ GHashTable *volumes;
};

struct allocated_job {
@@ -625,32 +622,32 @@ static int list_volumes(lsmPluginPtr c, lsmVolume **vols[],
{
int rc = LSM_ERR_OK;
struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);
+ *count = g_hash_table_size(pd->volumes);

- if(pd) {
- *count = pd->num_volumes;

- if( *count ) {
- *vols = lsmVolumeRecordArrayAlloc( pd->num_volumes );
- if( *vols ) {
- uint32_t i = 0;
- for( i = 0; i < pd->num_volumes; ++i ) {
- (*vols)[i] = lsmVolumeRecordCopy(pd->volume[i].v);
- if( !(*vols)[i] ) {
- rc = LSM_ERR_NO_MEMORY;
- lsmVolumeRecordArrayFree(*vols, i);
- *vols = NULL;
- *count = 0;
- break;
- }
+ if( *count ) {
+ *vols = lsmVolumeRecordArrayAlloc( *count );
+ if( *vols ) {
+ uint32_t i = 0;
+ char *k = NULL;
+ struct allocated_volume *vol;
+ GHashTableIter iter;
+ g_hash_table_iter_init(&iter, pd->volumes);
+ while(g_hash_table_iter_next(&iter,(gpointer) &k,(gpointer)&vol)) {
+ (*vols)[i] = lsmVolumeRecordCopy(vol->v);
+ if( !(*vols)[i] ) {
+ rc = LSM_ERR_NO_MEMORY;
+ lsmVolumeRecordArrayFree(*vols, i);
+ *count = 0;
+ *vols = NULL;
+ break;
}
- } else {
- rc = LSM_ERR_NO_MEMORY;
+ ++i;
}
+ } else {
+ rc = lsmLogErrorBasic(c, LSM_ERR_NO_MEMORY, "ENOMEM");
}
- } else {
- rc = LSM_ERR_INVALID_PLUGIN;
}
-
return rc;
}

@@ -717,17 +714,28 @@ static lsmPool *find_pool(struct plugin_data *pd, const char* pool_id)
return (lsmPool*) g_hash_table_lookup(pd->pools, pool_id);
}

-static int find_volume_name(struct plugin_data *pd, const char *name)
+static struct allocated_volume *find_volume(struct plugin_data *pd,
+ const char* vol_id)
{
- if( pd ) {
- int i;
- for( i = 0; i < pd->num_volumes; ++i ) {
- if( strcmp(lsmVolumeNameGet(pd->volume[i].v), name) == 0) {
- return i;
- }
+ struct allocated_volume *rc = g_hash_table_lookup(pd->volumes, vol_id);
+ return rc;
+}
+
+static struct allocated_volume * find_volume_name(struct plugin_data *pd,
+ const char *name)
+{
+ struct allocated_volume *found = NULL;
+ char *k = NULL;
+ struct allocated_volume *vol;
+ GHashTableIter iter;
+ g_hash_table_iter_init(&iter, pd->volumes);
+ while(g_hash_table_iter_next(&iter,(gpointer) &k,(gpointer)&vol)) {
+ if( strcmp(lsmVolumeNameGet(vol->v), name) == 0 ) {
+ found = vol;
+ break;
}
}
- return -1;
+ return found;
}

static int volume_create(lsmPluginPtr c, lsmPool *pool,
@@ -741,37 +749,48 @@ static int volume_create(lsmPluginPtr c, lsmPool *pool,
lsmPool *p = find_pool(pd, lsmPoolIdGet(pool));

if( p ) {
- if( -1 == find_volume_name(pd, volumeName) ) {
- if ( pd->num_volumes < MAX_VOLUMES ) {
- uint64_t allocated_size = pool_allocate(p, size);
- if( allocated_size ) {
- char *id = md5(volumeName);
+ if( !find_volume_name(pd, volumeName) ) {
+ uint64_t allocated_size = pool_allocate(p, size);
+ if( allocated_size ) {
+ char *id = md5(volumeName);

- lsmVolume *v = lsmVolumeRecordAlloc(id, volumeName,
- "VPD", BS, allocated_size/BS, 0, sys_id,
- lsmPoolIdGet(pool));
+ /* We create one to return and a copy to store in memory */

- if( v ) {
- pd->volume[pd->num_volumes].v = lsmVolumeRecordCopy(v);
- pd->volume[pd->num_volumes].p = p;
- pd->num_volumes +=1;
+ lsmVolume *v = lsmVolumeRecordAlloc(id, volumeName,
+ "VPD", BS, allocated_size/BS, 0, sys_id,
+ lsmPoolIdGet(pool));

- rc = create_job(pd, job, LSM_DATA_TYPE_VOLUME, v,
- (void**)newVolume);
+ lsmVolume *to_store = lsmVolumeRecordCopy(v);
+ struct allocated_volume *av = malloc(sizeof(struct allocated_volume));

- } else {
- rc = lsmLogErrorBasic(c, LSM_ERR_NO_MEMORY,
- "Check for leaks");
- }
+ if( v && av && to_store) {
+ av->v = to_store;
+ av->p = p;
+
+ /*
+ * Make a copy of the key, as we may replace the volume,
+ * but leave the key.
+ */
+ g_hash_table_insert(pd->volumes,
+ (gpointer)strdup(lsmVolumeIdGet(to_store)),
+ (gpointer)av);
+
+ rc = create_job(pd, job, LSM_DATA_TYPE_VOLUME, v,
+ (void**)newVolume);

} else {
- rc = lsmLogErrorBasic(c, LSM_ERR_SIZE_INSUFFICIENT_SPACE,
- "Insufficient space in pool");
+ free(av);
+ lsmVolumeRecordFree(v);
+ lsmVolumeRecordFree(to_store);
+ rc = lsmLogErrorBasic(c, LSM_ERR_NO_MEMORY,
+ "Check for leaks");
}
+
} else {
- rc = lsmLogErrorBasic(c, LSM_ERR_SIZE_LIMIT_REACHED,
- "Number of volumes limit reached");
+ rc = lsmLogErrorBasic(c, LSM_ERR_SIZE_INSUFFICIENT_SPACE,
+ "Insufficient space in pool");
}
+
} else {
rc = lsmLogErrorBasic(c, LSM_ERR_EXISTS_NAME, "Existing volume "
"with name");
@@ -788,7 +807,6 @@ static int volume_replicate(lsmPluginPtr c, lsmPool *pool,
char **job, lsmFlag_t flags)
{
int rc = LSM_ERR_OK;
- int vi;
lsmPool *pool_to_use = NULL;

struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);
@@ -803,8 +821,7 @@ static int volume_replicate(lsmPluginPtr c, lsmPool *pool,
rc = lsmLogErrorBasic(c, LSM_ERR_NOT_FOUND_POOL,
"Pool not found!");
} else {
- vi = find_volume_name(pd, lsmVolumeNameGet(volumeSrc));
- if( vi > -1 ) {
+ if( find_volume(pd, lsmVolumeIdGet(volumeSrc) )) {
rc = volume_create(c, pool_to_use, name,
lsmVolumeNumberOfBlocksGet(volumeSrc)*BS,
LSM_PROVISION_DEFAULT, newReplicant, job, flags);
@@ -835,10 +852,10 @@ static int volume_replicate_range(lsmPluginPtr c,
int rc = LSM_ERR_OK;
struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);

- int src_v = find_volume_name(pd, lsmVolumeNameGet(source));
- int dest_v = find_volume_name(pd, lsmVolumeNameGet(dest));
+ struct allocated_volume *src_v = find_volume(pd, lsmVolumeIdGet(source));
+ struct allocated_volume *dest_v = find_volume(pd, lsmVolumeIdGet(dest));

- if( -1 == src_v || -1 == dest_v ) {
+ if( !src_v || !dest_v ) {
rc = lsmLogErrorBasic(c, LSM_ERR_NOT_FOUND_VOLUME,
"Src or dest volumes not found!");
} else {
@@ -853,14 +870,12 @@ static int volume_resize(lsmPluginPtr c, lsmVolume *volume,
char **job, lsmFlag_t flags)
{
int rc = LSM_ERR_OK;
- int vi;
struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);
+ struct allocated_volume *av = find_volume(pd, lsmVolumeIdGet(volume));

- vi = find_volume_name(pd, lsmVolumeNameGet(volume));
-
- if( -1 != vi ) {
- lsmVolume *v = pd->volume[vi].v;
- lsmPool *p = pd->volume[vi].p;
+ if( av ) {
+ lsmVolume *v = av->v;
+ lsmPool *p = av->p;
uint64_t curr_size = lsmVolumeNumberOfBlocksGet(v) * BS;

pool_deallocate(p, curr_size);
@@ -872,8 +887,9 @@ static int volume_resize(lsmPluginPtr c, lsmVolume *volume,
lsmVolumeBlockSizeGet(v),
resized_size/BS, 0, sys_id,
lsmVolumePoolIdGet(volume));
+
if( vp ) {
- pd->volume[vi].v = vp;
+ av->v = vp;
lsmVolumeRecordFree(v);
rc = create_job(pd, job, LSM_DATA_TYPE_VOLUME,
lsmVolumeRecordCopy(vp),
@@ -907,15 +923,13 @@ static int volume_delete(lsmPluginPtr c, lsmVolume *volume,
GHashTable *v = NULL;
const char *volume_id = lsmVolumeIdGet(volume);
struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);
- int vi = find_volume_name(pd, lsmVolumeNameGet(volume));
- if( -1 != vi ) {
- lsmVolume *vp = pd->volume[vi].v;
- pool_deallocate(pd->volume[vi].p, lsmVolumeNumberOfBlocksGet(vp)*BS);

- lsmVolumeRecordFree(vp);
- remove_item(pd->volume, vi, pd->num_volumes,
- sizeof(struct allocated_volume));
- pd->num_volumes -= 1;
+ struct allocated_volume *av = find_volume(pd, lsmVolumeIdGet(volume));
+ if( av ) {
+ lsmVolume *vp = av->v;
+ pool_deallocate(av->p, lsmVolumeNumberOfBlocksGet(vp)*BS);
+
+ g_hash_table_remove(pd->volumes, lsmVolumeIdGet(volume));

g_hash_table_iter_init (&iter, pd->group_grant);
while( g_hash_table_iter_next( &iter, (gpointer)&k, (gpointer)&v) ) {
@@ -938,9 +952,9 @@ static int volume_online_offline(lsmPluginPtr c, lsmVolume *v,
{
int rc = LSM_ERR_OK;
struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);
+ struct allocated_volume *av = find_volume(pd, lsmVolumeIdGet(v));

- int vi = find_volume_name(pd, lsmVolumeNameGet(v));
- if( -1 == vi ) {
+ if( !av) {
rc = lsmLogErrorBasic(c, LSM_ERR_NOT_FOUND_VOLUME,
"volume not found!");
}
@@ -1133,9 +1147,9 @@ static int access_group_grant(lsmPluginPtr c,
g_hash_table_lookup(pd->access_groups,
lsmAccessGroupIdGet(group));

- int vi = find_volume_name(pd, lsmVolumeNameGet(volume));
+ struct allocated_volume *av = find_volume(pd, lsmVolumeIdGet(volume));

- if( find && (-1 != vi) ) {
+ if( find && av ) {
GHashTable *grants = g_hash_table_lookup(pd->group_grant,
lsmAccessGroupIdGet(find->ag));
if( !grants ) {
@@ -1186,7 +1200,7 @@ static int access_group_grant(lsmPluginPtr c,
}
}
} else {
- if( -1 == vi ) {
+ if( !av ) {
rc = lsmLogErrorBasic(c, LSM_ERR_NOT_FOUND_VOLUME,
"volume not found");
} else {
@@ -1209,9 +1223,9 @@ static int access_group_revoke(lsmPluginPtr c,
g_hash_table_lookup(pd->access_groups,
lsmAccessGroupIdGet(group));

- int vi = find_volume_name(pd, lsmVolumeNameGet(volume));
+ struct allocated_volume *av = find_volume(pd, lsmVolumeIdGet(volume));

- if( find && (-1 != vi) ) {
+ if( find && av ) {
GHashTable *grants = g_hash_table_lookup(pd->group_grant,
lsmAccessGroupIdGet(find->ag));

@@ -1221,7 +1235,7 @@ static int access_group_revoke(lsmPluginPtr c,
}

} else {
- if( -1 == vi ) {
+ if( !av ) {
rc = lsmLogErrorBasic(c, LSM_ERR_NOT_FOUND_VOLUME,
"volume not found");
} else {
@@ -1234,11 +1248,9 @@ static int access_group_revoke(lsmPluginPtr c,

static lsmVolume *get_volume_by_id(struct plugin_data *pd, const char *id)
{
- int i = 0;
- for( i = 0; i < pd->num_volumes; ++i ) {
- if( 0 == strcmp(id, lsmVolumeIdGet(pd->volume[i].v))) {
- return pd->volume[i].v;
- }
+ struct allocated_volume *av = find_volume(pd, id);
+ if( av ) {
+ return av->v;
}
return NULL;
}
@@ -1364,9 +1376,9 @@ int static volume_dependency(lsmPluginPtr c,
uint8_t *yes, lsmFlag_t flags)
{
struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);
- int vi = find_volume_name(pd, lsmVolumeNameGet(volume));
+ struct allocated_volume *av = find_volume(pd, lsmVolumeIdGet(volume));

- if( -1 != vi ) {
+ if( av ) {
*yes = 0;
return LSM_ERR_OK;
} else {
@@ -1379,9 +1391,9 @@ int static volume_dependency_rm(lsmPluginPtr c,
char **job, lsmFlag_t flags)
{
struct plugin_data *pd = (struct plugin_data*)lsmPrivateDataGet(c);
- int vi = find_volume_name(pd, lsmVolumeNameGet(volume));
+ struct allocated_volume *av = find_volume(pd, lsmVolumeIdGet(volume));

- if( -1 != vi ) {
+ if( av ) {
return create_job(pd, job, LSM_DATA_TYPE_NONE, NULL, NULL);
} else {
return LSM_ERR_NOT_FOUND_VOLUME;
@@ -1569,10 +1581,14 @@ static int vol_accessible_by_init(lsmPluginPtr c,
*volumes = lsmVolumeRecordArrayAlloc( *count );
if( *volumes ) {
/* Walk through each volume and see if we should include it*/
- uint32_t i = 0;
+
uint32_t alloc_count = 0;
- for( i = 0; i < pd->num_volumes; ++i ) {
- lsmVolume *tv = pd->volume[i].v;
+ char *k = NULL;
+ struct allocated_volume *vol;
+ GHashTableIter iter;
+ g_hash_table_iter_init(&iter, pd->volumes);
+ while(g_hash_table_iter_next(&iter,(gpointer) &k,(gpointer)&vol)) {
+ lsmVolume *tv = vol->v;

if( g_hash_table_lookup(tmp_vols, lsmVolumeIdGet(tv))) {
(*volumes)[alloc_count] = lsmVolumeRecordCopy(tv);
@@ -1605,6 +1621,10 @@ static struct lsmSanOpsV1 sanOps = {
list_initiators,
list_volumes,
list_disks,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
volume_create,
volume_replicate,
volume_replicate_range_bs,
@@ -2168,6 +2188,17 @@ void free_allocated_fs(void *v)
free_fs_record((struct allocated_fs*)v);
}

+void free_allocated_volume(void *v)
+{
+ if( v ) {
+ struct allocated_volume *av = (struct allocated_volume *)v;
+ lsmVolumeRecordFree(av->v);
+ av->v = NULL;
+ av->p = NULL; /* Pool takes care of itself */
+ free(av);
+ }
+}
+
int load( lsmPluginPtr c, xmlURIPtr uri, const char *password,
uint32_t timeout, lsmFlag_t flags)
{
@@ -2210,6 +2241,9 @@ int load( lsmPluginPtr c, xmlURIPtr uri, const char *password,
}
}

+ data->volumes = g_hash_table_new_full(g_str_hash, g_str_equal, free,
+ free_allocated_volume);
+
data->access_groups = g_hash_table_new_full(g_str_hash, g_str_equal,
free, free_allocated_ag);

@@ -2224,7 +2258,7 @@ int load( lsmPluginPtr c, xmlURIPtr uri, const char *password,
data->jobs = g_hash_table_new_full(g_str_hash, g_str_equal, free,
free_allocated_job);

- if( !data->system[0] || !data->pools || !data->access_groups ||
+ if( !data->system[0] || !data->volumes || !data->pools || !data->access_groups ||
!data->group_grant || !data->fs || !data->jobs ) {
rc = LSM_ERR_NO_MEMORY; /* We need to free data and everything else */

@@ -2238,6 +2272,9 @@ int load( lsmPluginPtr c, xmlURIPtr uri, const char *password,
g_hash_table_destroy(data->access_groups);
if( data->pools )
g_hash_table_destroy(data->pools);
+ if ( data->volumes )
+ g_hash_table_destroy(data->volumes);
+
lsmSystemRecordFree(data->system[0]);
memset(data, 0xAA, sizeof(struct plugin_data));
free(data);
@@ -2268,12 +2305,7 @@ int unload( lsmPluginPtr c, lsmFlag_t flags)

g_hash_table_destroy(pd->access_groups);

- for( i = 0; i < pd->num_volumes; ++i ) {
- lsmVolumeRecordFree(pd->volume[i].v);
- pd->volume[i].v = NULL;
- pd->volume[i].p = NULL;
- }
- pd->num_volumes = 0;
+ g_hash_table_destroy(pd->volumes);

g_hash_table_destroy(pd->pools);
--
1.8.2.1
Loading...