"Fossies" - the Fresh Open Source Software archive 
Member "evms-2.5.5/plugins/csm/options.c" of archive evms-2.5.5.tar.gz:
/*
*
* (C) Copyright IBM Corp. 2001, 2003
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Module: libcsm.so
*
* File: segoptions.c
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <plugin.h>
#include "csm_plugin.h"
static int allocate_assign_option_descriptors( task_context_t * context )
{
int i, rc = 0;
const char *my_nodeid_name=NULL;
const node_list_t *node_name_list=NULL;
LOG_ENTRY();
REQUIRE(context != NULL);
context->option_descriptors->count = CSM_ASSIGN_OPTION_COUNT;
// My Node Id
rc = EngFncs->nodeid_to_string(&csm_nodeid, &my_nodeid_name);
if (rc) {
LOG_EXIT_INT(rc);
return rc;
}
// List of Node Ids
rc = EngFncs->get_node_list( 0, &node_name_list);
if (rc) {
rc = ENOMEM;
LOG_EXIT_INT(rc);
return rc;
}
else if (node_name_list->count == 0) {
rc = ENOMEM;
LOG_EXIT_INT(rc);
return rc;
}
LOG_DEBUG("Node Name List ...\n");
LOG_DEBUG(" count = %d\n", node_name_list->count);
LOG_DEBUG(" ... Start\n");
for ( i=0; i<node_name_list->count; i++ ) {
LOG_DEBUG(" name = %s\n", node_name_list->node_info[i].node_name);
}
LOG_DEBUG(" ... Done\n");
context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].flags = EVMS_OPTION_FLAGS_INACTIVE;
context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].constraint.list =
EngFncs->engine_alloc( sizeof(value_list_t) + (sizeof(value_t) * node_name_list->count) );
if (context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].constraint.list) {
for ( i=0; i<node_name_list->count; i++ ) {
context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].constraint.list->value[i].s =
EngFncs->engine_strdup( node_name_list->node_info[i].node_name );
}
context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].constraint.list->count = node_name_list->count;
}
else {
rc = ENOMEM;
LOG_EXIT_INT(rc);
return rc;
}
context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].constraint_type = EVMS_Collection_List;
context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].help = NULL;
context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].name =
EngFncs->engine_strdup( CSM_ASSIGN_OPTION_NODE_ID_STRING );
context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].min_len = 1;
context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].max_len = NODEID_STRING_SIZE;
context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].tip =
EngFncs->engine_strdup( _("Clustering requires that you specify a node that will owner this storage object.") );
context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].title = EngFncs->engine_strdup( _("Node") );
context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].type = EVMS_Type_String;
context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].unit = EVMS_Unit_None;
context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].value.s = EngFncs->engine_alloc(NODEID_STRING_SIZE+1);
if (context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].value.s) {
rc = 0;
}
else {
rc = ENOMEM;
LOG_EXIT_INT(rc);
return rc;
}
// Storage Type Option
context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].flags = EVMS_OPTION_FLAGS_INACTIVE;
context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].constraint.list =
EngFncs->engine_alloc( sizeof(value_list_t) + (sizeof(value_t) * 3) );
if (context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].constraint.list) {
context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].constraint.list->value[0].s =
EngFncs->engine_strdup( _("private") );
context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].constraint.list->value[1].s =
EngFncs->engine_strdup( _("shared") );
context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].constraint.list->value[2].s =
EngFncs->engine_strdup( _("deported") );
context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].constraint.list->count = 3;
}
else {
rc = ENOMEM;
LOG_EXIT_INT(rc);
return rc;
}
context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].constraint_type = EVMS_Collection_List;
context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].help = NULL;
context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].name =
EngFncs->engine_strdup( CSM_ASSIGN_OPTION_TYPE_STRING );
context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].min_len = 1;
context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].max_len = EVMS_NAME_SIZE+1;
context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].tip =
EngFncs->engine_strdup( _("Clustering requires that you specify that the storage will be either shared by all or else private to a node.") );
context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].title = EngFncs->engine_strdup( _("Type") );
context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].type = EVMS_Type_String;
context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].unit = EVMS_Unit_None;
context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].value.s = EngFncs->engine_alloc(EVMS_NAME_SIZE+1);
if (context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].value.s) {
rc = 0;
}
else {
rc = ENOMEM;
LOG_EXIT_INT(rc);
return rc;
}
// Container Name
context->option_descriptors->option[CSM_ASSIGN_OPTION_CONTAINER_NAME_INDEX].flags = EVMS_OPTION_FLAGS_INACTIVE ;
context->option_descriptors->option[CSM_ASSIGN_OPTION_CONTAINER_NAME_INDEX].constraint.list = NULL;
context->option_descriptors->option[CSM_ASSIGN_OPTION_CONTAINER_NAME_INDEX].constraint_type = EVMS_Collection_None;
context->option_descriptors->option[CSM_ASSIGN_OPTION_CONTAINER_NAME_INDEX].help = NULL;
context->option_descriptors->option[CSM_ASSIGN_OPTION_CONTAINER_NAME_INDEX].name =
EngFncs->engine_strdup( CSM_ASSIGN_OPTION_CONTAINER_NAME_STRING );
context->option_descriptors->option[CSM_ASSIGN_OPTION_CONTAINER_NAME_INDEX].min_len = 1;
context->option_descriptors->option[CSM_ASSIGN_OPTION_CONTAINER_NAME_INDEX].max_len = EVMS_NAME_SIZE;
context->option_descriptors->option[CSM_ASSIGN_OPTION_CONTAINER_NAME_INDEX].tip =
EngFncs->engine_strdup( _("Clustering requires that you choose a container in which to place cluster segments.") );
context->option_descriptors->option[CSM_ASSIGN_OPTION_CONTAINER_NAME_INDEX].title = EngFncs->engine_strdup( _("Name") );
context->option_descriptors->option[CSM_ASSIGN_OPTION_CONTAINER_NAME_INDEX].type = EVMS_Type_String;
context->option_descriptors->option[CSM_ASSIGN_OPTION_CONTAINER_NAME_INDEX].unit = EVMS_Unit_None;
context->option_descriptors->option[CSM_ASSIGN_OPTION_CONTAINER_NAME_INDEX].value.s = EngFncs->engine_alloc(EVMS_NAME_SIZE+1);
if (context->option_descriptors->option[CSM_ASSIGN_OPTION_CONTAINER_NAME_INDEX].value.s) {
rc = 0;
}
else {
rc = ENOMEM;
LOG_EXIT_INT(rc);
return rc;
}
LOG_EXIT_INT(rc);
return rc;
}
static int initialize_assign_option_descriptors( task_context_t * context)
{
int rc;
const char *node_string;
LOG_ENTRY();
REQUIRE(context != NULL);
REQUIRE(context->option_descriptors->count == CSM_ASSIGN_OPTION_COUNT);
// Node ID
rc = EngFncs->nodeid_to_string(&csm_nodeid, &node_string);
if (rc) {
LOG_EXIT_INT(rc);
return rc;
}
context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].flags = 0;
strncpy (context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].value.s,
node_string,
NODEID_STRING_SIZE );
// Storage Type
context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].flags = 0;
strncpy (context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].value.s,
_("private"),
EVMS_NAME_SIZE );
// Cluster Container Name
context->option_descriptors->option[CSM_ASSIGN_OPTION_CONTAINER_NAME_INDEX].flags = EVMS_OPTION_FLAGS_NO_INITIAL_VALUE ;
strncpy (context->option_descriptors->option[CSM_ASSIGN_OPTION_CONTAINER_NAME_INDEX].value.s,
"",
EVMS_NAME_SIZE );
rc = 0;
LOG_EXIT_INT(rc);
return rc;
}
static int allocate_container_setinfo_option_descriptors( task_context_t *context )
{
int rc = 0;
LOG_ENTRY();
REQUIRE(context != NULL);
context->option_descriptors->count = CONTAINER_SETINFO_COUNT;
// Node ID
context->option_descriptors->option[CONTAINER_SETINFO_NODE_ID_INDEX].flags = EVMS_OPTION_FLAGS_INACTIVE ;
context->option_descriptors->option[CONTAINER_SETINFO_NODE_ID_INDEX].constraint.list = NULL;
context->option_descriptors->option[CONTAINER_SETINFO_NODE_ID_INDEX].constraint_type = EVMS_Collection_None;
context->option_descriptors->option[CONTAINER_SETINFO_NODE_ID_INDEX].help = NULL;
context->option_descriptors->option[CONTAINER_SETINFO_NODE_ID_INDEX].name =
EngFncs->engine_strdup( CONTAINER_SETINFO_NODE_ID_STRING );
context->option_descriptors->option[CONTAINER_SETINFO_NODE_ID_INDEX].min_len = 1;
context->option_descriptors->option[CONTAINER_SETINFO_NODE_ID_INDEX].max_len = NODEID_STRING_SIZE;
context->option_descriptors->option[CONTAINER_SETINFO_NODE_ID_INDEX].tip =
EngFncs->engine_strdup( _("You can change the owner of a container (disk group) by changing the node id.") );
context->option_descriptors->option[CONTAINER_SETINFO_NODE_ID_INDEX].title = EngFncs->engine_strdup( _("Node") );
context->option_descriptors->option[CONTAINER_SETINFO_NODE_ID_INDEX].type = EVMS_Type_String;
context->option_descriptors->option[CONTAINER_SETINFO_NODE_ID_INDEX].unit = EVMS_Unit_None;
context->option_descriptors->option[CONTAINER_SETINFO_NODE_ID_INDEX].value.s = EngFncs->engine_alloc(NODEID_STRING_SIZE+1);
if (context->option_descriptors->option[CONTAINER_SETINFO_NODE_ID_INDEX].value.s) {
rc = 0;
}
else {
rc = ENOMEM;
LOG_EXIT_INT(rc);
return rc;
}
// Storage Type
context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].flags = EVMS_OPTION_FLAGS_INACTIVE ;
context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].constraint.list = NULL;
context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].constraint_type = EVMS_Collection_List;
context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].help = NULL;
context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].name =
EngFncs->engine_strdup( CONTAINER_SETINFO_TYPE_STRING );
context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].min_len = 1;
context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].max_len = EVMS_NAME_SIZE;
context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].tip =
EngFncs->engine_strdup( _("You can change the storage type of the container (disk group) to private, shared or deported.") );
context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].title = EngFncs->engine_strdup( _("Type") );
context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].type = EVMS_Type_String;
context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].unit = EVMS_Unit_None;
context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].value.s = EngFncs->engine_alloc(EVMS_NAME_SIZE+1);
if (context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].value.s) {
rc = 0;
}
else {
rc = ENOMEM;
LOG_EXIT_INT(rc);
return rc;
}
// Container Name
context->option_descriptors->option[CONTAINER_SETINFO_NAME_INDEX].flags = EVMS_OPTION_FLAGS_INACTIVE ;
context->option_descriptors->option[CONTAINER_SETINFO_NAME_INDEX].constraint.list = NULL;
context->option_descriptors->option[CONTAINER_SETINFO_NAME_INDEX].constraint_type = EVMS_Collection_None;
context->option_descriptors->option[CONTAINER_SETINFO_NAME_INDEX].help = NULL;
context->option_descriptors->option[CONTAINER_SETINFO_NAME_INDEX].name =
EngFncs->engine_strdup( CONTAINER_SETINFO_NAME_STRING );
context->option_descriptors->option[CONTAINER_SETINFO_NAME_INDEX].min_len = 1;
context->option_descriptors->option[CONTAINER_SETINFO_NAME_INDEX].max_len = EVMS_NAME_SIZE;
context->option_descriptors->option[CONTAINER_SETINFO_NAME_INDEX].tip =
EngFncs->engine_strdup( _("You can change the name of the container (disk group) in which to place cluster segments.") );
context->option_descriptors->option[CONTAINER_SETINFO_NAME_INDEX].title = EngFncs->engine_strdup( _("Name") );
context->option_descriptors->option[CONTAINER_SETINFO_NAME_INDEX].type = EVMS_Type_String;
context->option_descriptors->option[CONTAINER_SETINFO_NAME_INDEX].unit = EVMS_Unit_None;
context->option_descriptors->option[CONTAINER_SETINFO_NAME_INDEX].value.s = EngFncs->engine_alloc(EVMS_NAME_SIZE+1);
if (context->option_descriptors->option[CONTAINER_SETINFO_NAME_INDEX].value.s) {
rc = 0;
}
else {
rc = ENOMEM;
LOG_EXIT_INT(rc);
return rc;
}
LOG_EXIT_INT(rc);
return rc;
}
static int initialize_container_setinfo_option_descriptors( task_context_t * context )
{
int rc;
const char *node_string;
storage_container_t *container=NULL;
container_private_data_t *c_pdata;
value_list_t * constraint_list;
const node_list_t * node_list;
LOG_ENTRY();
REQUIRE(context != NULL);
REQUIRE(context->container != NULL);
REQUIRE(context->option_descriptors->count == CONTAINER_SETINFO_COUNT);
REQUIRE(isa_cluster_container(context->container)==TRUE);
container = (storage_container_t *) context->container;
c_pdata = (container_private_data_t *) container->private_data;
// Node ID
rc = EngFncs->get_node_list(ACTIVE_NODES_ONLY, &node_list);
if (!rc) {
constraint_list = EngFncs->engine_alloc(sizeof(value_list_t) * node_list->count * sizeof(value_t));
if (constraint_list != NULL) {
int i;
constraint_list->count = node_list->count;
for (i = 0; i < node_list->count; i++) {
constraint_list->value[i].s = EngFncs->engine_strdup(node_list->node_info[i].node_name);
}
context->option_descriptors->option[CONTAINER_SETINFO_NODE_ID_INDEX].constraint.list = constraint_list;
context->option_descriptors->option[CONTAINER_SETINFO_NODE_ID_INDEX].constraint_type = EVMS_Collection_List;
}
}
rc = EngFncs->nodeid_to_string(&c_pdata->nodeid, &node_string);
if (rc) {
LOG_EXIT_INT(rc);
return rc;
}
context->option_descriptors->option[CONTAINER_SETINFO_NODE_ID_INDEX].flags = EVMS_OPTION_FLAGS_NOT_REQUIRED;
strncpy (context->option_descriptors->option[CONTAINER_SETINFO_NODE_ID_INDEX].value.s,
node_string,
sizeof(ece_nodeid_t) );
// Type
constraint_list = EngFncs->engine_alloc(sizeof(value_list_t) + 3 * sizeof(value_t));
if (constraint_list != NULL) {
constraint_list->count = 3;
constraint_list->value[0].s = EngFncs->engine_strdup(_("private"));
constraint_list->value[1].s = EngFncs->engine_strdup(_("shared"));
constraint_list->value[2].s = EngFncs->engine_strdup(_("deported"));
context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].constraint.list = constraint_list;
}
context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].flags = EVMS_OPTION_FLAGS_NOT_REQUIRED;
if (container->flags & SCFLAG_CLUSTER_PRIVATE) {
strncpy ( context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].value.s,
_("private"),
EVMS_NAME_SIZE );
}
else if (container->flags & SCFLAG_CLUSTER_SHARED) {
strncpy ( context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].value.s,
_("shared"),
EVMS_NAME_SIZE );
}
else if (container->flags & SCFLAG_CLUSTER_DEPORTED) {
strncpy ( context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].value.s,
_("deported"),
EVMS_NAME_SIZE );
}
else {
strncpy ( context->option_descriptors->option[CONTAINER_SETINFO_TYPE_INDEX].value.s,
_("private"),
EVMS_NAME_SIZE );
}
// Cluster Container Name
context->option_descriptors->option[CONTAINER_SETINFO_NAME_INDEX].flags = EVMS_OPTION_FLAGS_NOT_REQUIRED;
strncpy (context->option_descriptors->option[CONTAINER_SETINFO_NAME_INDEX].value.s,
container->name,
EVMS_NAME_SIZE );
rc = 0;
LOG_EXIT_INT(rc);
return rc;
}
static int set_assign_object( task_context_t * context,
list_anchor_t declined_objects,
task_effect_t * effect )
{
int rc=EINVAL;
storage_object_t *obj;
int found_good_object = FALSE;
declined_object_t *declined_object=NULL;
list_element_t iter, e;
LOG_ENTRY();
REQUIRE(context != NULL);
REQUIRE(context->selected_objects != NULL);
REQUIRE(EngFncs->list_count(context->selected_objects) != 0);
LIST_FOR_EACH( context->selected_objects, iter, obj ) {
if ( ( found_good_object == FALSE) &&
( obj->object_type == DISK || obj->object_type == SEGMENT ) &&
( obj->volume == NULL ) &&
( EngFncs->list_count(obj->parent_objects) == 0 ) ) {
found_good_object = TRUE;
rc = initialize_assign_option_descriptors(context);
if (rc == 0) {
*effect |= EVMS_Effect_Reload_Options;
}
}
else {
declined_object = EngFncs->engine_alloc( sizeof(declined_object_t));
if (declined_object) {
declined_object->object = obj;
declined_object->reason = rc; // REMINDER ... need to pickup reason codes the UI understands
e=EngFncs->insert_thing( declined_objects,
declined_object,
INSERT_AFTER,
NULL );
if (e!=NULL) {
rc=0;
*effect |= EVMS_Effect_Reload_Objects;
}
else {
rc = ENOMEM;
EngFncs->engine_free(declined_object);
}
}
else {
LOG_ERROR("error, unable to malloc a declined object struct\n");
rc = ENOMEM;
}
}
}
LOG_EXIT_INT(rc);
return rc;
}
static int set_container_assign_object( task_context_t * context,
list_anchor_t declined_objects,
task_effect_t * effect )
{
int rc=0;
storage_object_t *obj;
declined_object_t *declined_object=NULL;
boolean init_done=FALSE;
list_element_t iter, e;
LOG_ENTRY();
REQUIRE(context != NULL);
REQUIRE(context->selected_objects != NULL);
REQUIRE(EngFncs->list_count(context->selected_objects) != 0);
LIST_FOR_EACH( context->selected_objects, iter, obj ) {
if ( ( obj->object_type == DISK || obj->object_type == SEGMENT ) &&
( EngFncs->list_count(obj->parent_objects)==0) &&
( obj->volume == NULL ) ) {
if (init_done == FALSE) {
init_done = TRUE;
rc = initialize_assign_option_descriptors(context);
if (!rc) {
*effect |= EVMS_Effect_Reload_Options;
}
}
}
else {
declined_object = EngFncs->engine_alloc( sizeof(declined_object_t));
if (declined_object) {
declined_object->object = obj;
declined_object->reason = rc;
e = EngFncs->insert_thing( declined_objects,
declined_object,
INSERT_AFTER,
NULL );
if (e!=NULL) {
rc=0;
*effect |= EVMS_Effect_Reload_Objects;
}
else {
rc = ENOMEM;
EngFncs->engine_free(declined_object);
}
}
else {
LOG_ERROR("error, unable to malloc a declined object struct\n");
rc = ENOMEM;
}
}
}
LOG_EXIT_INT(rc);
return rc;
}
void prune_acceptable_disks( list_anchor_t list )
{
storage_object_t *obj;
seg_private_data_t *pdata=NULL;
list_element_t iter,iter2;
boolean prune;
LIST_FOR_EACH_SAFE( list, iter, iter2, obj ) {
prune = TRUE;
if ( obj->plugin != csm_plugin_record_ptr ) {
if (obj->object_type == DISK) {
prune = FALSE;
}
else if (obj->object_type == SEGMENT) {
pdata = (seg_private_data_t *)obj->private_data;
if ( !(pdata->cflags & SEG_CFLAG_TOP_SEGMENT) ) {
// only accept segments from 390 dasd driver
if ( strncmp(obj->name, "dasd", 4) == 0 ) {
prune = FALSE;
}
}
}
}
if (prune) EngFncs->delete_element(iter);
}
}
static int get_acceptable_assign_objects( task_context_t * context )
{
int rc;
list_anchor_t temp_list = context->acceptable_objects;
LOG_ENTRY();
REQUIRE(context != NULL);
REQUIRE(EngFncs->list_count(context->acceptable_objects) == 0);
rc = EngFncs->get_object_list( DISK, //| SEGMENT,
DATA_TYPE,
NULL,
NULL,
TOPMOST,
&context->acceptable_objects );
if (rc == 0) {
// Destroy the original acceptable objects list anchor.
EngFncs->destroy_list(temp_list);
if ( EngFncs->list_count(context->acceptable_objects) > 0) {
prune_acceptable_disks(context->acceptable_objects);
}
else {
LOG_DEBUG("no storage objects returned by get_object_list call\n");
}
rc = 0;
}
LOG_EXIT_INT(rc);
return rc;
}
int csm_init_task(task_context_t * context)
{
int rc = EINVAL;
list_element_t iter;
storage_object_t * ld;
LOG_ENTRY();
REQUIRE(context != NULL);
REQUIRE(csm_has_quorum == TRUE || csm_admin_mode == TRUE);
if (context) {
switch (context->action) {
case EVMS_Task_Assign_Plugin:
context->min_selected_objects = 1;
context->max_selected_objects = 1;
rc = allocate_assign_option_descriptors( context );
if (rc == 0) {
rc = get_acceptable_assign_objects( context );
}
break;
case EVMS_Task_Create_Container:
context->min_selected_objects = 1;
context->max_selected_objects = 1024;
rc = allocate_assign_option_descriptors( context );
if (rc == 0) {
rc = get_acceptable_assign_objects( context );
}
break;
case EVMS_Task_Set_Container_Info:
context->min_selected_objects = 0;
context->max_selected_objects = 0;
rc = allocate_container_setinfo_option_descriptors( context );
if (rc == 0) {
rc = initialize_container_setinfo_option_descriptors( context );
}
break;
case EVMS_Task_Expand:
if (!context->container) {
rc = ENOSYS;
break;
}
// anthing acceptable for assign is also acceptable for expand.
rc = get_acceptable_assign_objects( context );
context->min_selected_objects = 1;
context->max_selected_objects = EngFncs->list_count(context->acceptable_objects);
break;
case EVMS_Task_Shrink:
if (!context->container) {
rc = ENOSYS;
break;
}
LIST_FOR_EACH(context->container->objects_consumed, iter, ld) {
if (csm_can_unassign(ld) == 0) {
EngFncs->insert_thing(context->acceptable_objects,
ld,
INSERT_AFTER,
NULL);
}
}
context->min_selected_objects = 1;
context->max_selected_objects = EngFncs->list_count(context->acceptable_objects);
rc = 0;
break;
default:
rc = ENOSYS;
LOG_ERROR("unsupported task ... context->action = %d\n", context->action);
break;
}
}
LOG_EXIT_INT(rc);
return rc;
}
int csm_set_objects( task_context_t * context,
list_anchor_t declined_objects,
task_effect_t * effect )
{
int rc = EINVAL;
LOG_ENTRY();
if (context) {
switch (context->action) {
case EVMS_Task_Assign_Plugin:
rc = set_assign_object( context, declined_objects, effect );
break;
case EVMS_Task_Create_Container:
rc = set_container_assign_object(context,declined_objects,effect );
break;
case EVMS_Task_Expand:
if (context->container) {
rc = 0;
} else {
rc = ENOSYS;
}
break;
case EVMS_Task_Shrink:
if (context->container) {
rc = 0;
} else {
rc = ENOSYS;
}
break;
default:
rc = ENOSYS;
LOG_ERROR("context->action is unknown or unsupported\n");
break;
}
}
LOG_EXIT_INT(rc);
return rc;
}
static int csm_set_assign_option( task_context_t * context,
u_int32_t index,
value_t * value,
task_effect_t * effect )
{
int rc=EINVAL, i;
storage_container_t *container=NULL;
container_private_data_t *c_pdata;
const char *node_string;
LOG_ENTRY();
REQUIRE(index >= 0 && index < CSM_ASSIGN_OPTION_COUNT);
switch (index) {
case CSM_ASSIGN_OPTION_NODE_ID_INDEX:
if ( strlen(value->s) > 0 ) {
strncpy( context->option_descriptors->option[index].value.s,
value->s,
NODEID_STRING_SIZE );
context->option_descriptors->option[index].flags = 0;
rc = 0;
}
else {
rc = EINVAL;
}
break;
case CSM_ASSIGN_OPTION_TYPE_INDEX:
if ( strlen(value->s) > 0 ) {
strncpy( context->option_descriptors->option[index].value.s,
value->s,
EVMS_NAME_SIZE );
context->option_descriptors->option[index].flags = 0;
rc = 0;
}
else {
rc = EINVAL;
}
break;
case CSM_ASSIGN_OPTION_CONTAINER_NAME_INDEX:
if ( strlen(value->s) > 0 ) {
for (i=0,rc=0; rc==0 && i<strlen(value->s); i++) {
if ( value->s[i] == '/' ) {
rc = EINVAL;
}
}
if (!rc) {
strncpy( context->option_descriptors->option[index].value.s,
value->s,
EVMS_NAME_SIZE );
context->option_descriptors->option[index].flags = 0;
}
}
else {
rc = EINVAL;
}
break;
default:
rc = EINVAL;
break;
}
if (!rc) {
if (strlen(context->option_descriptors->option[CSM_ASSIGN_OPTION_CONTAINER_NAME_INDEX].value.s)>0) {
rc = csm_find_container( context->option_descriptors->option[CSM_ASSIGN_OPTION_CONTAINER_NAME_INDEX].value.s,
&container );
if (!rc) {
c_pdata = (container_private_data_t *) container->private_data;
rc = EngFncs->nodeid_to_string(&c_pdata->nodeid, &node_string);
if (!rc) {
strncpy( context->option_descriptors->option[CSM_ASSIGN_OPTION_NODE_ID_INDEX].value.s,
node_string,
NODEID_STRING_SIZE );
}
if (container->flags & SCFLAG_CLUSTER_PRIVATE) {
strcpy( context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].value.s,
_("private") );
}
else if (container->flags & SCFLAG_CLUSTER_SHARED) {
strcpy( context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].value.s,
_("shared") );
}
else if (container->flags & SCFLAG_CLUSTER_DEPORTED) {
strcpy( context->option_descriptors->option[CSM_ASSIGN_OPTION_TYPE_INDEX].value.s,
_("deported") );
}
}
rc = 0;
}
}
LOG_EXIT_INT(rc);
return rc;
}
static int csm_set_container_option( task_context_t * context,
u_int32_t index,
value_t * value,
task_effect_t * effect )
{
int rc=EINVAL, i;
const node_list_t *node_name_list=NULL;
int flag;
char name[EVMS_NAME_SIZE+1];
LOG_ENTRY();
REQUIRE(index >= 0 && index < CONTAINER_SETINFO_COUNT);
switch (index) {
case CONTAINER_SETINFO_NODE_ID_INDEX:
if ( strlen(value->s) > 0 ) {
// get list of node ids
rc = EngFncs->get_node_list( 0, &node_name_list);
if (rc) {
LOG_ERROR("unable to get cluster node list to validate options\n");
rc = ENOMEM;
LOG_EXIT_INT(rc);
return rc;
}
// must be configured nodeid
for ( i=0,flag=-1; flag!=0 && i<node_name_list->count; i++ ) {
flag = strncmp( node_name_list->node_info[i].node_name,
value->s,
NODEID_STRING_SIZE );
}
if (!flag) {
strncpy( context->option_descriptors->option[index].value.s,
value->s,
NODEID_STRING_SIZE );
context->option_descriptors->option[index].flags = 0;
rc = 0;
}
else {
rc = EINVAL;
}
}
else {
rc = EINVAL;
}
break;
case CONTAINER_SETINFO_TYPE_INDEX:
rc = EINVAL;
if ( strlen(value->s) > 0 ) {
strncpy(name,value->s,EVMS_NAME_SIZE);
string_to_upper_case(name);
if (strcasecmp(name,_("private"))==0) {
strcpy(name, _("private"));
rc = 0;
}
else if (strcasecmp(name,_("shared"))==0) {
strcpy(name,_("shared"));
rc = 0;
}
else if (strcasecmp(name,_("deported"))==0) {
strcpy(name,_("deported"));
rc = 0;
}
if (!rc) {
strncpy( context->option_descriptors->option[index].value.s,
name,
EVMS_NAME_SIZE );
context->option_descriptors->option[index].flags = 0;
}
}
break;
case CONTAINER_SETINFO_NAME_INDEX:
if ( strlen(value->s) > 0 ) {
for (i=0,rc=0; rc==0 && i<strlen(value->s); i++) {
if ( value->s[i] == '/' ) {
rc = EINVAL;
}
}
if (!rc) {
rc = EngFncs->validate_name(value->s);
if (!rc) {
strncpy( context->option_descriptors->option[index].value.s,
value->s,
EVMS_NAME_SIZE );
context->option_descriptors->option[index].flags = 0;
}
else {
LOG_DEBUG("container name is already in use.\n");
rc = EINVAL;
}
}
}
else {
rc = EINVAL;
}
break;
default:
rc = EINVAL;
break;
}
LOG_EXIT_INT(rc);
return rc;
}
int csm_get_option_count(task_context_t * task)
{
int count=0;
LOG_ENTRY();
REQUIRE(task != NULL);
switch (task->action) {
case EVMS_Task_Assign_Plugin:
case EVMS_Task_Create_Container:
count = CSM_ASSIGN_OPTION_COUNT;
break;
case EVMS_Task_Expand:
count = CSM_EXPAND_CONTAINER_OPTION_COUNT;
break;
case EVMS_Task_Shrink:
count = CSM_SHRINK_CONTAINER_OPTION_COUNT;
break;
case EVMS_Task_Set_Container_Info:
count = CONTAINER_SETINFO_COUNT;
break;
default:
LOG_DEBUG("unsupported task ... task->action = %d\n", task->action);
count = 0;
break;
}
LOG_EXIT_INT(count);
return count;
}
int csm_set_option( task_context_t * context,
u_int32_t index,
value_t * value,
task_effect_t * effect )
{
int rc;
LOG_ENTRY();
REQUIRE(context != NULL);
REQUIRE(value != NULL);
REQUIRE(effect != NULL);
switch (context->action) {
case EVMS_Task_Assign_Plugin:
case EVMS_Task_Create_Container:
rc = csm_set_assign_option(context,index,value,effect);
break;
case EVMS_Task_Set_Container_Info:
rc = csm_set_container_option(context,index,value,effect);
break;
case EVMS_Task_Expand:
case EVMS_Task_Shrink:
if (context->container) {
rc = 0;
} else {
rc = ENOSYS;
}
break;
default:
rc = ENOSYS;
LOG_ERROR("error, unknown task ... context->action = %d\n", context->action);
break;
}
LOG_EXIT_INT(rc);
return rc;
}
/*
* Returns segment specific information
*/
int csm_get_segment_info( storage_object_t * object, extended_info_array_t * * info)
{
int rc = EINVAL;
extended_info_array_t *Info;
LOG_ENTRY();
rc = ENOMEM; // init to failed calloc
*info = NULL; // init to no info returned
Info = EngFncs->engine_alloc( sizeof(extended_info_array_t) + ( SEG_INFO_COUNT * sizeof(extended_info_t) ) );
if (Info) {
Info->count = SEG_INFO_COUNT;
Info->info[SEG_INFO_NAME_INDEX].name = EngFncs->engine_strdup( "Name" );
Info->info[SEG_INFO_NAME_INDEX].title = EngFncs->engine_strdup( _("Name") );
Info->info[SEG_INFO_NAME_INDEX].desc = EngFncs->engine_strdup( _("This is the partition name. It must be unique on the system.") );
Info->info[SEG_INFO_NAME_INDEX].type = EVMS_Type_String;
Info->info[SEG_INFO_NAME_INDEX].unit = EVMS_Unit_None;
Info->info[SEG_INFO_NAME_INDEX].value.s = EngFncs->engine_strdup( object->name );
Info->info[SEG_INFO_NAME_INDEX].collection_type = EVMS_Collection_None;
memset( &Info->info[SEG_INFO_NAME_INDEX].group, 0, sizeof(group_info_t));
Info->info[SEG_INFO_SIZE_INDEX].name = EngFncs->engine_strdup( "Size" );
Info->info[SEG_INFO_SIZE_INDEX].title = EngFncs->engine_strdup( _("Size") );
Info->info[SEG_INFO_SIZE_INDEX].desc = EngFncs->engine_strdup( _("This is the size of the partition in sectors.") );
Info->info[SEG_INFO_SIZE_INDEX].type = EVMS_Type_Unsigned_Int64;
Info->info[SEG_INFO_SIZE_INDEX].unit = EVMS_Unit_Sectors;
Info->info[SEG_INFO_SIZE_INDEX].value.ui64 = object->size;
Info->info[SEG_INFO_SIZE_INDEX].format = EVMS_Format_Normal;
Info->info[SEG_INFO_SIZE_INDEX].collection_type = EVMS_Collection_None;
memset( &Info->info[SEG_INFO_SIZE_INDEX].group, 0, sizeof(group_info_t));
Info->info[SEG_INFO_SIZE_INDEX].flags |= EVMS_EINFO_FLAGS_NO_UNIT_CONVERSION;
Info->info[SEG_INFO_START_INDEX].name = EngFncs->engine_strdup( "Start" );
Info->info[SEG_INFO_START_INDEX].title = EngFncs->engine_strdup( _("Start Logical Blcok Address") );
Info->info[SEG_INFO_START_INDEX].desc = EngFncs->engine_strdup( _("This is the sector offset of the partition on the disk, i.e., the logical block address of the first sector of the partition.") );
Info->info[SEG_INFO_START_INDEX].type = EVMS_Type_Unsigned_Int64;
Info->info[SEG_INFO_START_INDEX].unit = EVMS_Unit_None;
Info->info[SEG_INFO_START_INDEX].value.ui64 = object->start;
Info->info[SEG_INFO_START_INDEX].format = EVMS_Format_Normal;
Info->info[SEG_INFO_START_INDEX].collection_type = EVMS_Collection_None;
memset( &Info->info[SEG_INFO_START_INDEX].group, 0, sizeof(group_info_t));
Info->info[SEG_INFO_TYPE_INDEX].name = EngFncs->engine_strdup( "Type" );
Info->info[SEG_INFO_TYPE_INDEX].title = EngFncs->engine_strdup( _("Type") );
Info->info[SEG_INFO_TYPE_INDEX].desc = EngFncs->engine_strdup( _("Partition type - data, metadata, free.") );
Info->info[SEG_INFO_TYPE_INDEX].type = EVMS_Type_String;
Info->info[SEG_INFO_TYPE_INDEX].unit = EVMS_Unit_None;
Info->info[SEG_INFO_TYPE_INDEX].collection_type = EVMS_Collection_None;
memset( &Info->info[SEG_INFO_TYPE_INDEX].group, 0, sizeof(group_info_t));
if ( object->data_type == DATA_TYPE ) {
Info->info[SEG_INFO_TYPE_INDEX].value.s = EngFncs->engine_strdup( _("data") );
}
else if ( object->data_type == META_DATA_TYPE ) {
Info->info[SEG_INFO_TYPE_INDEX].value.s = EngFncs->engine_strdup( _("metadata") );
Info->info[SEG_INFO_TYPE_INDEX].flags = EVMS_EINFO_FLAGS_MORE_INFO_AVAILABLE;
}
else {
Info->info[SEG_INFO_TYPE_INDEX].value.s = EngFncs->engine_strdup( _("unknown") );
}
*info = Info;
rc = 0;
}
else {
LOG_ERROR("unable to malloc memory for extended info array\n");
}
LOG_EXIT_INT(rc);
return rc;
}
/*
* Returns Cluster Metadata specific information
*/
int csm_get_metadata_info(storage_object_t * object, extended_info_array_t **info)
{
int rc = EINVAL;
extended_info_array_t *Info;
csm_header_t *hdr = ((seg_private_data_t *)object->private_data)->hdr;
char *guid_string=NULL;
const char *node_string=NULL;
LOG_ENTRY();
rc = ENOMEM; // init to failed calloc
*info = NULL; // init to no info returned
Info = EngFncs->engine_alloc( sizeof(extended_info_array_t) + ( HEADER_INFO_COUNT * sizeof(extended_info_t) ) );
if (Info) {
Info->count = HEADER_INFO_COUNT;
Info->info[HEADER_INFO_HDRSIZE_INDEX].name = EngFncs->engine_strdup( "Size" );
Info->info[HEADER_INFO_HDRSIZE_INDEX].title = EngFncs->engine_strdup( _("Header Size") );
Info->info[HEADER_INFO_HDRSIZE_INDEX].desc = EngFncs->engine_strdup( _("This is the size of header in bytes.") );
Info->info[HEADER_INFO_HDRSIZE_INDEX].type = EVMS_Type_Unsigned_Int32;
Info->info[HEADER_INFO_HDRSIZE_INDEX].unit = EVMS_Unit_Bytes;
Info->info[HEADER_INFO_HDRSIZE_INDEX].value.ui32 = hdr->size;
Info->info[HEADER_INFO_HDRSIZE_INDEX].format = EVMS_Format_Normal;
Info->info[HEADER_INFO_HDRSIZE_INDEX].collection_type = EVMS_Collection_None;
memset( &Info->info[HEADER_INFO_HDRSIZE_INDEX].group, 0, sizeof(group_info_t));
Info->info[HEADER_INFO_ALTLBA_INDEX].name = EngFncs->engine_strdup( "Alternate LBA" );
Info->info[HEADER_INFO_ALTLBA_INDEX].title = EngFncs->engine_strdup( _("Alternate Logical Block Address") );
Info->info[HEADER_INFO_ALTLBA_INDEX].desc = EngFncs->engine_strdup( _("Logical Block Address of the alternate header.") );
Info->info[HEADER_INFO_ALTLBA_INDEX].type = EVMS_Type_Unsigned_Int64;
Info->info[HEADER_INFO_ALTLBA_INDEX].unit = EVMS_Unit_None;
Info->info[HEADER_INFO_ALTLBA_INDEX].value.ui64 = hdr->alternate_lba;
Info->info[HEADER_INFO_ALTLBA_INDEX].format = EVMS_Format_Normal;
Info->info[HEADER_INFO_ALTLBA_INDEX].collection_type = EVMS_Collection_None;
memset( &Info->info[HEADER_INFO_ALTLBA_INDEX].group, 0, sizeof(group_info_t));
Info->info[HEADER_INFO_START_INDEX].name = EngFncs->engine_strdup( "Useable Start" );
Info->info[HEADER_INFO_START_INDEX].title = EngFncs->engine_strdup( _("Useable Start") );
Info->info[HEADER_INFO_START_INDEX].desc = EngFncs->engine_strdup( _("Logical Block Address of the start of useable space on the disk.") );
Info->info[HEADER_INFO_START_INDEX].type = EVMS_Type_Unsigned_Int64;
Info->info[HEADER_INFO_START_INDEX].unit = EVMS_Unit_None;
Info->info[HEADER_INFO_START_INDEX].value.ui64 = hdr->start_useable;
Info->info[HEADER_INFO_START_INDEX].format = EVMS_Format_Normal;
Info->info[HEADER_INFO_START_INDEX].collection_type = EVMS_Collection_None;
memset( &Info->info[HEADER_INFO_START_INDEX].group, 0, sizeof(group_info_t));
Info->info[HEADER_INFO_END_INDEX].name = EngFncs->engine_strdup( "Useable End" );
Info->info[HEADER_INFO_END_INDEX].title = EngFncs->engine_strdup( _("Useable End") );
Info->info[HEADER_INFO_END_INDEX].desc = EngFncs->engine_strdup( _("Logical Block Address of the end of useable space on the disk.") );
Info->info[HEADER_INFO_END_INDEX].type = EVMS_Type_Unsigned_Int64;
Info->info[HEADER_INFO_END_INDEX].unit = EVMS_Unit_None;
Info->info[HEADER_INFO_END_INDEX].value.ui64 = hdr->end_useable;
Info->info[HEADER_INFO_END_INDEX].format = EVMS_Format_Normal;
Info->info[HEADER_INFO_END_INDEX].collection_type = EVMS_Collection_None;
memset( &Info->info[HEADER_INFO_END_INDEX].group, 0, sizeof(group_info_t));
guid_string = guid_to_string( &hdr->disk_id );
if (guid_string) {
Info->info[HEADER_INFO_DISK_GUID_INDEX].name = EngFncs->engine_strdup( "Disk - GUID" );
Info->info[HEADER_INFO_DISK_GUID_INDEX].title = EngFncs->engine_strdup( _("Disk - GUID") );
Info->info[HEADER_INFO_DISK_GUID_INDEX].desc = EngFncs->engine_strdup( _("This is the disk globally unique identifier.") );
Info->info[HEADER_INFO_DISK_GUID_INDEX].type = EVMS_Type_String;
Info->info[HEADER_INFO_DISK_GUID_INDEX].unit = EVMS_Unit_None;
Info->info[HEADER_INFO_DISK_GUID_INDEX].value.s = EngFncs->engine_strdup( guid_string );
Info->info[HEADER_INFO_DISK_GUID_INDEX].collection_type = EVMS_Collection_None;
memset( &Info->info[HEADER_INFO_DISK_GUID_INDEX].group, 0, sizeof(group_info_t));
free(guid_string);
}
else {
EngFncs->engine_free( Info );
rc = ENOMEM;
LOG_EXIT_INT(rc);
return rc;
}
EngFncs->nodeid_to_string(&hdr->nodeid, &node_string);
if (node_string) {
Info->info[HEADER_INFO_NODE_CUID_INDEX].name = EngFncs->engine_strdup( "Node ID" );
Info->info[HEADER_INFO_NODE_CUID_INDEX].title = EngFncs->engine_strdup( _("Node ID") );
Info->info[HEADER_INFO_NODE_CUID_INDEX].desc = EngFncs->engine_strdup( _("This is the cluster node ID."));
Info->info[HEADER_INFO_NODE_CUID_INDEX].type = EVMS_Type_String;
Info->info[HEADER_INFO_NODE_CUID_INDEX].unit = EVMS_Unit_None;
Info->info[HEADER_INFO_NODE_CUID_INDEX].value.s = EngFncs->engine_strdup( node_string );
Info->info[HEADER_INFO_NODE_CUID_INDEX].collection_type = EVMS_Collection_None;
memset( &Info->info[HEADER_INFO_NODE_CUID_INDEX].group, 0, sizeof(group_info_t));
}
else {
EngFncs->engine_free( Info );
rc = ENOMEM;
LOG_EXIT_INT(rc);
return rc;
}
*info = Info;
rc = 0;
}
else {
LOG_ERROR("unable to malloc memory for extended info array\n");
}
LOG_EXIT_INT(rc);
return rc;
}
/*
* Returns plugin specific information
*/
int csm_get_plugin_info( char * descriptor_name, extended_info_array_t * * info )
{
int rc = EINVAL;
extended_info_array_t *Info;
char version_string[64];
char required_engine_api_version_string[64];
char required_plugin_api_version_string[64];
LOG_ENTRY();
// a measure of protection ...
if (info == NULL) {
LOG_EXIT_INT(rc);
return rc;
}
rc = ENOMEM; // init to failed calloc
*info = NULL; // init to no info returned
Info = EngFncs->engine_alloc( sizeof(extended_info_array_t) + (PLUGIN_INFO_COUNT*sizeof(extended_info_t)) );
if (Info) {
Info->count = PLUGIN_INFO_COUNT;
sprintf(version_string, "%d.%d.%d",
MAJOR_VERSION,
MINOR_VERSION,
PATCH_LEVEL );
sprintf(required_engine_api_version_string, "%d.%d.%d",
csm_plugin_record_ptr->required_engine_api_version.major,
csm_plugin_record_ptr->required_engine_api_version.minor,
csm_plugin_record_ptr->required_engine_api_version.patchlevel );
sprintf(required_plugin_api_version_string, "%d.%d.%d",
csm_plugin_record_ptr->required_plugin_api_version.plugin.major,
csm_plugin_record_ptr->required_plugin_api_version.plugin.minor,
csm_plugin_record_ptr->required_plugin_api_version.plugin.patchlevel );
Info->info[PLUGIN_INFO_SNAME_INDEX].name = EngFncs->engine_strdup( "ShortName" );
Info->info[PLUGIN_INFO_SNAME_INDEX].title = EngFncs->engine_strdup( _("Short Name") );
Info->info[PLUGIN_INFO_SNAME_INDEX].desc = EngFncs->engine_strdup( _("A short name given to this plug-in") );
Info->info[PLUGIN_INFO_SNAME_INDEX].type = EVMS_Type_String;
Info->info[PLUGIN_INFO_SNAME_INDEX].unit = EVMS_Unit_None;
Info->info[PLUGIN_INFO_SNAME_INDEX].value.s = EngFncs->engine_strdup( csm_plugin_record_ptr->short_name );
Info->info[PLUGIN_INFO_SNAME_INDEX].collection_type = EVMS_Collection_None;
memset( &Info->info[PLUGIN_INFO_SNAME_INDEX].group, 0, sizeof(group_info_t));
Info->info[PLUGIN_INFO_LNAME_INDEX].name = EngFncs->engine_strdup( "LongName" );
Info->info[PLUGIN_INFO_LNAME_INDEX].title = EngFncs->engine_strdup( _("Long Name") );
Info->info[PLUGIN_INFO_LNAME_INDEX].desc = EngFncs->engine_strdup( _("A longer, more descriptive name for this plug-in") );
Info->info[PLUGIN_INFO_LNAME_INDEX].type = EVMS_Type_String;
Info->info[PLUGIN_INFO_LNAME_INDEX].unit = EVMS_Unit_None;
Info->info[PLUGIN_INFO_LNAME_INDEX].value.s = EngFncs->engine_strdup( csm_plugin_record_ptr->long_name );
Info->info[PLUGIN_INFO_LNAME_INDEX].collection_type = EVMS_Collection_None;
memset( &Info->info[PLUGIN_INFO_LNAME_INDEX].group, 0, sizeof(group_info_t));
Info->info[PLUGIN_INFO_TYPE_INDEX].name = EngFncs->engine_strdup( "Type" );
Info->info[PLUGIN_INFO_TYPE_INDEX].title = EngFncs->engine_strdup( _("Plug-in Type") );
Info->info[PLUGIN_INFO_TYPE_INDEX].desc = EngFncs->engine_strdup( _("There are various types of plug-ins, each responsible for some kind of storage object or logical volume.") );
Info->info[PLUGIN_INFO_TYPE_INDEX].type = EVMS_Type_String;
Info->info[PLUGIN_INFO_TYPE_INDEX].unit = EVMS_Unit_None;
Info->info[PLUGIN_INFO_TYPE_INDEX].value.s = EngFncs->engine_strdup( _("Segment Manager") );
Info->info[PLUGIN_INFO_TYPE_INDEX].collection_type = EVMS_Collection_None;
memset( &Info->info[PLUGIN_INFO_TYPE_INDEX].group, 0, sizeof(group_info_t));
Info->info[PLUGIN_INFO_VERSION_INDEX].name = EngFncs->engine_strdup( "Version" );
Info->info[PLUGIN_INFO_VERSION_INDEX].title = EngFncs->engine_strdup( _("Plug-in Version") );
Info->info[PLUGIN_INFO_VERSION_INDEX].desc = EngFncs->engine_strdup( _("This is the version number of the plugin.") );
Info->info[PLUGIN_INFO_VERSION_INDEX].type = EVMS_Type_String;
Info->info[PLUGIN_INFO_VERSION_INDEX].unit = EVMS_Unit_None;
Info->info[PLUGIN_INFO_VERSION_INDEX].value.s = EngFncs->engine_strdup( version_string );
Info->info[PLUGIN_INFO_VERSION_INDEX].collection_type = EVMS_Collection_None;
memset( &Info->info[PLUGIN_INFO_VERSION_INDEX].group, 0, sizeof(group_info_t));
Info->info[PLUGIN_INFO_REQENGSVCVERSION_INDEX].name = EngFncs->engine_strdup( "Required Engine Services Version" );
Info->info[PLUGIN_INFO_REQENGSVCVERSION_INDEX].title = EngFncs->engine_strdup( _("Required Engine Services Version") );
Info->info[PLUGIN_INFO_REQENGSVCVERSION_INDEX].desc = EngFncs->engine_strdup( _("This is the version of the Engine services that this plugin requires. "
"It will not run on older versions of the Engine services.") );
Info->info[PLUGIN_INFO_REQENGSVCVERSION_INDEX].type = EVMS_Type_String;
Info->info[PLUGIN_INFO_REQENGSVCVERSION_INDEX].unit = EVMS_Unit_None;
Info->info[PLUGIN_INFO_REQENGSVCVERSION_INDEX].value.s = EngFncs->engine_strdup( required_engine_api_version_string );
Info->info[PLUGIN_INFO_REQENGSVCVERSION_INDEX].collection_type = EVMS_Collection_None;
memset( &Info->info[PLUGIN_INFO_REQENGSVCVERSION_INDEX].group, 0, sizeof(group_info_t));
Info->info[PLUGIN_INFO_REQPLUGAPIVERSION_INDEX].name = EngFncs->engine_strdup( "Required Engine Plug-in API Version" );
Info->info[PLUGIN_INFO_REQPLUGAPIVERSION_INDEX].title = EngFncs->engine_strdup( _("Required Engine Plug-in API Version") );
Info->info[PLUGIN_INFO_REQPLUGAPIVERSION_INDEX].desc = EngFncs->engine_strdup( _("This is the version of the Engine plug-in API that this plugin requires. "
"It will not run on older versions of the Engine plug-in API.") );
Info->info[PLUGIN_INFO_REQPLUGAPIVERSION_INDEX].type = EVMS_Type_String;
Info->info[PLUGIN_INFO_REQPLUGAPIVERSION_INDEX].unit = EVMS_Unit_None;
Info->info[PLUGIN_INFO_REQPLUGAPIVERSION_INDEX].value.s = EngFncs->engine_strdup( required_plugin_api_version_string );
Info->info[PLUGIN_INFO_REQPLUGAPIVERSION_INDEX].collection_type = EVMS_Collection_None;
memset( &Info->info[PLUGIN_INFO_REQPLUGAPIVERSION_INDEX].group, 0, sizeof(group_info_t));
*info = Info;
rc = 0;
}
LOG_EXIT_INT(rc);
return rc;
}