mgmt_acsls.c revision cee0fb94c0d4227de0a00efc162fb2739844b641
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <netdb.h>
#include <procfs.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dlfcn.h>
#include "mgmt_acsls.h"
#include "mgmt_library.h"
#include "mgmt_media.h"
#include "mms_cfg.h"
/*
* This code represents a ACS client application and communicates with the ACS
* library via the ACSAPI interface. ACSAPI procedures communicate via IPC
* with the SSI process running on this same client machine. Each client app
* can send multiple requests to the ACS Library Manager via this SSI. The SSI
* receives requests from one or more clients, places them on a queue, and sends
* the requests to the CSI to relay them to the ACS Library Manager. Multiple
* heterogeneous clients can communicate and manage the ACSLS Library via the
* same SSI. The SSI also relays the responses back to the appropriate client
* application. The CSI and SSI talk to each other via RPC. The same RPC program
* number is used for all instances of SSI and CSI connections. So there is a
* limitation that a client cannot connect to multiple ACSLS.
*
* The ACSAPI resides on the client machine as a set of three C language library
* object modules to be linked with a client application. These modules are the
* formal interface, and the functions that carry out the IPC for requests and
* responses.
*
*/
static int acs_dlsym(void);
ALIGNED_BYTES) = NULL;
/* Display configuration and status */
static int parse_f_int(char *f, uint32_t *s);
static int parse_f_date(char *f, time_t *t);
static acs_query_cmdresp_t acs_query_cmdresp_tbl[] = {
};
/*
* As ACSLS is a separate product, all functions must be retrieved
*/
static int
acs_dlsym(void)
{
int st = 0;
char buf[2048];
int scf_size = MMS_CFG_MAX_VALUE;
if (st != 0) {
return (st);
}
(void) pthread_mutex_lock(&acs_mutex);
if (!acs_init) {
/* not there, try the normal locations */
(void) pthread_mutex_unlock(&acs_mutex);
return (MMS_MGMT_ACSLS_NOT_FOUND);
}
}
"acs_response");
if ((!dl_acs_display) || (!dl_acs_response)) {
} else {
}
}
(void) pthread_mutex_unlock(&acs_mutex);
return (st);
}
/*
* Interface to control the lifecycle of the SSI process and its children
*
* Any priviledged client of ACSLS can start the SSI process. The same process
* is to be used by all ACS clients on this machine to communicate within the
* ACSLS library. Do not start multiple SSI process.
*
* The envva ACSAPI_SSI_SOCKET is the local port number of the SSI
*/
int
{
int st;
char env_acsport[128];
int status;
int scf_size = MMS_CFG_MAX_VALUE;
char ssibuf[1024];
char sockbuf[1024];
char *cmd[3];
char *bufp;
return (MMS_MGMT_NOARG);
}
if (st != 0) {
return (st);
}
if (!mms_list_empty(&proclist)) {
return (0);
}
}
acshost);
*bufp = '\0';
bufp++;
}
if (!bufp) {
/* use default port */
bufp = "50004";
}
bufp);
if (ssiport) {
"ACSAPI_SSI_SOCKET=%s", ssiport);
} else {
"ACSAPI_SSI_SOCKET=%s", "50004");
}
/* set required envvars */
(void) putenv(env_acshost);
(void) putenv(env_acsport);
if (status != 0) {
"Could not start ACSLS client daemon, exec status = %d",
status);
}
return (status);
}
/*
* get the configuration of the acs library, given the name of the acsls
* hostname and port.
*
* If get_drives is TRUE, get information about drives as well as libraries
*/
int
char *acshost,
)
{
int st;
char location[128];
return (MMS_MGMT_NOARG);
}
/* check if the acsls host is accessible and start if it not */
return (MMS_MGMT_ERR_EXEC_SSI);
}
/* get all the acs-lsm */
if (st != 0) {
return (st);
}
if (get_drives) {
/* get the drives in each library */
&lsm->drive_list);
if (st != 0) {
break;
}
}
}
return (st);
}
static int
int seq,
int (*parse_acs_resp)(void *, mms_list_t *),
{
int ret;
return (MMS_MGMT_NOARG);
}
/*
* call acs_response() repeatedly until the FINAL packet for this
* request has been received
*/
do {
10, /* Block for 10 seconds */
&rseq,
&reqid,
&type,
rbuf);
if (st == STATUS_IPC_FAILURE) {
return (MMS_MGMT_ERR_ACSLS_RSP);
}
rseq);
return (MMS_MGMT_ERR_ACSLS_RSP);
}
if (ret != 0) {
break;
}
}
return (ret);
}
/*
* To get the configuration of the components in an ACSLS library, or their
* status, use the 'display' command to create complex or detailed queries
* using XML as the Query language. The XML request is then sent to the SSI
* using the acs_display() ACSAPI and the responses are awaited and parsed.
*
* The SSI process must be running before this API can be used.
*/
int
int query_type, /* type of query */
char *cmdarg, /* arguments for the XML request */
{
int st = 0;
char *s = "*";
return (MMS_MGMT_NOARG);
}
if (st != 0) {
return (st);
}
s = cmdarg;
}
/* LINTED [E_SEC_PRINTF_VAR_FMT] */
if (len > MAX_XML_DATA_SIZE) {
return (ENAMETOOLONG);
}
/*
* generate a sequence number, this uniquely identifies the response
* with the request. SEQ_NO is defined as a short int.
*/
return (MMS_MGMT_ERR_ACSLS_PARSE);
}
if (st != 0) {
return (st);
} else {
}
return (st);
}
/*
* parse_drive_resp() assumes the format of the data response, the
* following information is expected in the drive data:
* acs, lsm, panel, drive, type, status, state and serial number
*/
static int
void *buf,
{
size_t l;
char junkbuf[1024];
return (MMS_MGMT_NOARG);
}
return (MMS_MGMT_ERR_ACSLS_RSP);
}
};
/*
* <r> marks the start of a drive entry, <f> marks the start of a field
*
* <r>
* <f maxlen="3">acs</f>
* <f maxlen="3">lsm</f>
* <f maxlen="5">panel</f>
* <f maxlen="5">drive</f>
* <f maxlen="9">status</f>
* <f maxlen="10">state</f>
* <f maxlen="6">volume</f>
* <f maxlen="9">type</f>
* <f maxlen="5">lock</f>
* <f maxlen="32">serial_num</f>
* <f maxlen="14">condition</f>
* </r>
*/
if (drive_list->list_size == 0) {
}
return (ENOMEM);
}
/* extract string from <f ....>..</f> */
ptr2 += l;
ptr2 += l;
ptr2 += l;
ptr2 += l;
/* properly convert flags and provide for volume */
/* status */
ptr2 += l;
/* state */
ptr2 += l;
/* volume */
ptr2 += l;
ptr2 += l;
/* lock */
ptr2 += l;
ptr2 += l;
/* condition */
ptr2 += l;
}
}
return (0);
}
/*
* parse_vol_resp() assumes the format of the data response, the
* following information is expected in the volume data:
* vol_id, acs, lsm, panel, row, column, pool, status, media, and type
*/
static int
{
size_t l;
char junkbuf[1024];
return (MMS_MGMT_NOARG);
}
return (MMS_MGMT_ERR_ACSLS_RSP);
}
};
/* only create the list if it's the first time through */
}
return (ENOMEM);
}
/* extract string from <f ....>..</f> */
ptr2 += l;
ptr2 += l;
ptr2 += l;
/* drive */
ptr2 += l;
/* type - cleaning|data */
ptr2 += l;
ptr2 += l;
/* status */
ptr2 += l;
ptr2 += l;
/* advance to the start of the next volume */
/* malformed response */
break;
}
}
}
return (0);
}
/*
* parse_lsm_resp() parses the response data assuming a particular
* format for the data. The following information is expected in the
* response:- acs, lsm, status, state and serial number
*
*/
static int
void *buf,
{
size_t l;
char status[1024];
char state[1024];
return (MMS_MGMT_NOARG);
}
return (MMS_MGMT_ERR_ACSLS_RSP);
}
};
}
return (ENOMEM);
}
ptr2 += l;
ptr2 += l;
/* parse status and state to flags */
ptr2 += l;
ptr2 += l;
ptr2 += l;
ptr2 += l;
/* advance to the start of the next drive */
/* malformed response */
break;
}
}
}
return (0);
}
static int /* return number of characters parsed */
size_t n;
char *ptr;
return (0);
}
*ptr = '\0';
}
n = strlen(f);
return (0);
}
ptr++;
return (n + 4);
}
/* parse just a single char */
static int
parse_f_int(char *f, uint32_t *i)
{
char *ptr;
char *ptr2;
size_t n;
char buf[4];
int j;
if (!f || !i) {
return (0);
}
return (0);
}
ptr++;
for (j = 0; j < 4; j++, ptr++) {
break;
}
}
return (0);
}
n = (++ptr2 - f);
return (n);
}
static int
parse_f_date(char *f, time_t *t)
{
char *ptr;
size_t n;
if (!f || !t) {
return (0);
}
return (0);
}
ptr++;
return (0);
}
ptr += 4;
n = ptr - f;
return (n);
}
/*
* get volumes from an acs library, given the name of the acsls
* hostname and port.
*
* in_vols is optional, allows the requester to ask for only
*
*/
int
char *acshost,
char *in_vols,
)
{
int st;
return (MMS_MGMT_NOARG);
}
/* check if the acsls host is accessible and start if it not */
return (MMS_MGMT_ERR_EXEC_SSI);
}
if (st != 0) {
return (st);
}
return (st);
}