summaryrefslogtreecommitdiffstats
path: root/rpc
diff options
context:
space:
mode:
authorPrasanna Kumar Kalever <prasanna.kalever@redhat.com>2017-02-05 20:23:20 +0530
committerPrasanna Kumar Kalever <prasanna.kalever@redhat.com>2017-02-07 13:29:05 +0530
commit23b12455796ec453ca35e94ab49e7629d7f9aced (patch)
tree0d69ce51ad68b56a753fa8e4a021bec2a3cc5f4a /rpc
parentbbcbaf494ad406ceea4f0175b91cf67966d32a27 (diff)
gluster-block: migrate build to libtoolz and create rpm
Till now we had simple makefile for checking dependencies and building. Using libtoolz will give more control on dependency checks and flexibility. This patch also introduce rpm build feature. Compiling: $ ./autogen.sh $ ./configure $ make -j $ make install Building RPMS: $ make rpms Running: $ systemctl start gluster-blockd.service Using CLI: $ gluster-block help Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Diffstat (limited to 'rpc')
-rw-r--r--rpc/Makefile.am15
-rw-r--r--rpc/block.h21
-rw-r--r--rpc/block_svc.c114
-rw-r--r--rpc/block_svc_routines.c832
-rw-r--r--rpc/glfs-operations.c270
-rw-r--r--rpc/glfs-operations.h61
-rw-r--r--rpc/rpcl/block.x (renamed from rpc/block.x)0
7 files changed, 1201 insertions, 112 deletions
diff --git a/rpc/Makefile.am b/rpc/Makefile.am
new file mode 100644
index 0000000..20ed49d
--- /dev/null
+++ b/rpc/Makefile.am
@@ -0,0 +1,15 @@
+noinst_LTLIBRARIES = libgbxdr.la
+
+libgbxdr_la_SOURCES = block_clnt.c block_xdr.c block_svc.c block_svc_routines.c glfs-operations.c
+
+noinst_HEADERS = block.h glfs-operations.h
+
+libgbxdr_la_CFLAGS = -I$(top_srcdir)/utils/
+
+libgbxdr_la_LIBADD = -lgfapi
+
+libgbxdr_ladir = $(includedir)/gluster-block/rpc
+
+DISTCLEANFILES = Makefile.in
+
+CLEANFILES = *~
diff --git a/rpc/block.h b/rpc/block.h
index 03d0ec4..7122632 100644
--- a/rpc/block.h
+++ b/rpc/block.h
@@ -69,6 +69,27 @@ struct blockResponse {
};
typedef struct blockResponse blockResponse;
+typedef struct blockServerDef {
+ size_t nhosts;
+ char **hosts;
+} blockServerDef;
+typedef blockServerDef *blockServerDefPtr;
+
+typedef enum operations {
+ CREATE_SRV = 1,
+ DELETE_SRV = 2,
+} operations;
+
+void
+gluster_block_cli_1(struct svc_req *rqstp, register SVCXPRT *transp);
+
+void
+gluster_block_1(struct svc_req *rqstp, register SVCXPRT *transp);
+
+
+int
+glusterBlockCallRPC_1(char *host, void *cobj, operations opt, char **out);
+
#define GLUSTER_BLOCK_CLI 212153113
#define GLUSTER_BLOCK_CLI_VERS 1
diff --git a/rpc/block_svc.c b/rpc/block_svc.c
index 3722d51..8c94d30 100644
--- a/rpc/block_svc.c
+++ b/rpc/block_svc.c
@@ -4,23 +4,12 @@
*/
#include "block.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <rpc/pmap_clnt.h>
-#include <string.h>
-#include <memory.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
#ifndef SIG_PF
#define SIG_PF void(*)(int)
#endif
-
-
-static void
+void
gluster_block_cli_1(struct svc_req *rqstp, register SVCXPRT *transp)
{
union {
@@ -82,7 +71,7 @@ gluster_block_cli_1(struct svc_req *rqstp, register SVCXPRT *transp)
return;
}
-static void
+void
gluster_block_1(struct svc_req *rqstp, register SVCXPRT *transp)
{
union {
@@ -129,102 +118,3 @@ gluster_block_1(struct svc_req *rqstp, register SVCXPRT *transp)
}
return;
}
-
-void *
-cli_thread_proc (void *vargp)
-{
- register SVCXPRT *transp;
- struct sockaddr_un saun;
- int sockfd, len;
-
- if ((sockfd = socket(AF_UNIX, SOCK_STREAM, IPPROTO_IP)) < 0) {
- perror("server: socket");
- exit(1);
- }
-
- saun.sun_family = AF_UNIX;
- strcpy(saun.sun_path, ADDRESS);
-
- unlink(ADDRESS);
- len = sizeof(saun.sun_family) + strlen(saun.sun_path);
-
- if (bind(sockfd, (struct sockaddr *) &saun, len) < 0) {
- perror("server: bind");
- exit(1);
- }
-
- transp = svcunix_create(sockfd, 0, 0, ADDRESS);
- if (transp == NULL) {
- fprintf (stderr, "%s", "cannot create tcp service");
- exit(1);
- }
-
- if (!svc_register(transp, GLUSTER_BLOCK_CLI, GLUSTER_BLOCK_CLI_VERS, gluster_block_cli_1, IPPROTO_IP)) {
- fprintf (stderr, "%s", "unable to register (GLUSTER_BLOCK_CLI, GLUSTER_BLOCK_CLI_VERS, unix|local).");
- exit(1);
- }
-
- svc_run ();
-
- return NULL;
-}
-
-void *
-server_thread_proc(void *vargp)
-{
- register SVCXPRT *transp;
- struct sockaddr_in sain;
- int sockfd;
-
- if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
- perror("server: socket");
- exit(1);
- }
-
- sain.sin_family = AF_INET;
- sain.sin_addr.s_addr = INADDR_ANY;
- sain.sin_port = htons(24006);
-
- if (bind(sockfd, (struct sockaddr *) &sain, sizeof (sain)) < 0) {
- perror("server: bind");
- exit(1);
- }
-
- transp = svctcp_create(sockfd, 0, 0);
- if (transp == NULL) {
- fprintf (stderr, "%s", "cannot create tcp service");
- exit(1);
- }
-
- if (!svc_register(transp, GLUSTER_BLOCK, GLUSTER_BLOCK_VERS, gluster_block_1, IPPROTO_TCP)) {
- fprintf (stderr, "%s", "unable to register (GLUSTER_BLOCK, GLUSTER_BLOCK_VERS, tcp).");
- exit(1);
- }
-
- svc_run ();
-
- return NULL;
-}
-
-
-int
-main (int argc, char **argv)
-{
- pthread_t cli_thread;
- pthread_t server_thread;
-
-
- pmap_unset (GLUSTER_BLOCK_CLI, GLUSTER_BLOCK_CLI_VERS);
- pmap_unset (GLUSTER_BLOCK, GLUSTER_BLOCK_VERS);
-
- pthread_create(&cli_thread, NULL, cli_thread_proc , NULL);
- pthread_create(&server_thread, NULL, server_thread_proc , NULL);
-
- pthread_join(cli_thread, NULL);
- pthread_join(server_thread, NULL);
-
-
- fprintf (stderr, "%s", "svc_run returned");
- exit (0);
- /* NOTREACHED */
-}
diff --git a/rpc/block_svc_routines.c b/rpc/block_svc_routines.c
new file mode 100644
index 0000000..91ad630
--- /dev/null
+++ b/rpc/block_svc_routines.c
@@ -0,0 +1,832 @@
+/*
+ Copyright (c) 2016 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of gluster-block.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+
+# include "common.h"
+# include "glfs-operations.h"
+
+# include <netdb.h>
+# include <uuid/uuid.h>
+
+
+# define UUID_BUF_SIZE 38
+
+# define CREATE "create"
+# define DELETE "delete"
+
+# define GLFS_PATH "/backstores/user:glfs"
+# define TARGETCLI_GLFS "targetcli "GLFS_PATH
+# define TARGETCLI_ISCSI "targetcli /iscsi"
+# define TARGETCLI_SAVE "targetcli / saveconfig"
+# define ATTRIBUTES "generate_node_acls=1 demo_mode_write_protect=0"
+# define IQN_PREFIX "iqn.2016-12.org.gluster-block:"
+
+# define MSERVER_DELIMITER ","
+
+
+
+int
+glusterBlockCallRPC_1(char *host, void *cobj,
+ operations opt, char **out)
+{
+ CLIENT *clnt = NULL;
+ int ret = -1;
+ int sockfd;
+ blockResponse *reply;
+ struct hostent *server;
+ struct sockaddr_in sain;
+
+
+ if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+ LOG("mgmt", GB_LOG_ERROR, "socket creation failed (%s)",
+ strerror (errno));
+ goto out;
+ }
+
+ server = gethostbyname(host);
+ if (!server) {
+ LOG("mgmt", GB_LOG_ERROR, "gethostbyname failed (%s)",
+ strerror (errno));
+ goto out;
+ }
+
+ bzero((char *) &sain, sizeof(sain));
+ sain.sin_family = AF_INET;
+ bcopy((char *)server->h_addr, (char *)&sain.sin_addr.s_addr,
+ server->h_length);
+ sain.sin_port = htons(24006);
+
+ if (connect(sockfd, (struct sockaddr *) &sain, sizeof(sain)) < 0) {
+ LOG("mgmt", GB_LOG_ERROR, "connect failed (%s)", strerror (errno));
+ goto out;
+ }
+
+ clnt = clnttcp_create ((struct sockaddr_in *) &sain, GLUSTER_BLOCK,
+ GLUSTER_BLOCK_VERS, &sockfd, 0, 0);
+ if (!clnt) {
+ LOG("mgmt", GB_LOG_ERROR, "%s, inet host %s",
+ clnt_spcreateerror("client create failed"), host);
+ goto out;
+ }
+
+ switch(opt) {
+ case CREATE_SRV:
+ reply = block_create_1((blockCreate *)cobj, clnt);
+ if (!reply) {
+ LOG("mgmt", GB_LOG_ERROR, "%s",
+ clnt_sperror(clnt, "block create failed"));
+ goto out;
+ }
+ break;
+ case DELETE_SRV:
+ reply = block_delete_1((blockDelete *)cobj, clnt);
+ if (!reply) {
+ LOG("mgmt", GB_LOG_ERROR, "%s",
+ clnt_sperror(clnt, "block delete failed"));
+ goto out;
+ }
+ break;
+ }
+
+ if (GB_STRDUP(*out, reply->out) < 0){
+ goto out;
+ }
+ ret = reply->exit;
+
+ out:
+ if (clnt) {
+ if (!reply ||
+ !clnt_freeres(clnt, (xdrproc_t)xdr_blockResponse, (char *)reply)) {
+ LOG("mgmt", GB_LOG_ERROR, "%s",
+ clnt_sperror(clnt, "clnt_freeres failed"));
+
+ clnt_destroy (clnt);
+ }
+ }
+
+ close(sockfd);
+
+ return ret;
+}
+
+
+void
+blockServerDefFree(blockServerDefPtr blkServers)
+{
+ size_t i;
+
+
+ if (!blkServers) {
+ return;
+ }
+
+ for (i = 0; i < blkServers->nhosts; i++) {
+ GB_FREE(blkServers->hosts[i]);
+ }
+ GB_FREE(blkServers->hosts);
+ GB_FREE(blkServers);
+}
+
+
+static blockServerDefPtr
+blockServerParse(char *blkServers)
+{
+ blockServerDefPtr list;
+ char *tmp = blkServers;
+ size_t i = 0;
+
+
+ if (GB_ALLOC(list) < 0) {
+ return NULL;
+ }
+
+ if (!blkServers) {
+ blkServers = "localhost";
+ }
+
+ /* count number of servers */
+ while (*tmp) {
+ if (*tmp == ',') {
+ list->nhosts++;
+ }
+ tmp++;
+ }
+ list->nhosts++;
+ tmp = blkServers; /* reset addr */
+
+
+ if (GB_ALLOC_N(list->hosts, list->nhosts) < 0) {
+ goto fail;
+ }
+
+ for (i = 0; tmp != NULL; i++) {
+ if (GB_STRDUP(list->hosts[i], strsep(&tmp, MSERVER_DELIMITER)) < 0) {
+ goto fail;
+ }
+ }
+
+ return list;
+
+ fail:
+ blockServerDefFree(list);
+ return NULL;
+}
+
+
+static void
+glusterBlockCreateRemote(struct glfs_fd *tgmfd, char *volume,
+ blockCreate *cobj, char *addr, char **reply)
+{
+ int ret;
+ char *out = NULL;
+ char *tmp = *reply;
+
+
+ GB_METAUPDATE_OR_GOTO(tgmfd, cobj->gbid, volume, ret, out,
+ "%s: CONFIGINPROGRESS\n", addr);
+
+ ret = glusterBlockCallRPC_1(addr, cobj, CREATE_SRV, &out);
+ if (ret) {
+ GB_METAUPDATE_OR_GOTO(tgmfd, cobj->gbid, volume, ret, out,
+ "%s: CONFIGFAIL\n", addr);
+ LOG("mgmt", GB_LOG_ERROR, "%s on host: %s", FAILED_CREATE, addr);
+ goto out;
+ }
+
+ GB_METAUPDATE_OR_GOTO(tgmfd, cobj->gbid, volume, ret, out,
+ "%s: CONFIGSUCCESS\n", addr);
+
+ out:
+ asprintf(reply, "%s%s\n", (tmp==NULL?"":tmp), out);
+ GB_FREE(tmp);
+ GB_FREE(out);
+}
+
+
+static int
+glusterBlockAuditRequest(struct glfs *glfs,
+ struct glfs_fd *tgmfd,
+ blockCreateCli *blk,
+ blockCreate *cobj,
+ blockServerDefPtr list,
+ char **reply)
+{
+ int ret = -1;
+ size_t i;
+ size_t successcnt = 0;
+ size_t failcnt = 0;
+ size_t spent;
+ size_t spare;
+ size_t morereq;
+ MetaInfo *info;
+
+
+ if (GB_ALLOC(info) < 0) {
+ goto out;
+ }
+
+ ret = blockGetMetaInfo(glfs, blk->block_name, info);
+ if (ret) {
+ goto out;
+ }
+
+ for (i = 0; i < info->nhosts; i++) {
+ switch (blockMetaStatusEnumParse(info->list[i]->status)) {
+ case GB_CONFIG_SUCCESS:
+ successcnt++;
+ break;
+ case GB_CONFIG_INPROGRESS:
+ case GB_CONFIG_FAIL:
+ failcnt++;
+ }
+ }
+
+ /* check if mpath is satisfied */
+ if (blk->mpath == successcnt) {
+ ret = 0;
+ goto out;
+ } else {
+ spent = successcnt + failcnt; /* total spent */
+ spare = list->nhosts - spent; /* spare after spent */
+ morereq = blk->mpath - successcnt; /* needed nodes to complete req */
+ if (spare == 0) {
+ LOG("mgmt", GB_LOG_WARNING, "%s",
+ "No Spare nodes: rewining the creation of target");
+ ret = -1;
+ goto out;
+ } else if (spare < morereq) {
+ LOG("mgmt", GB_LOG_WARNING, "%s",
+ "Not enough Spare nodes: rewining the creation of target");
+ ret = -1;
+ goto out;
+ } else {
+ /* create on spare */
+ LOG("mgmt", GB_LOG_INFO, "%s",
+ "trying to serve the mpath from spare machines");
+ for (i = spent; i < list->nhosts; i++) {
+ glusterBlockCreateRemote(tgmfd, info->volume, cobj,
+ list->hosts[i], reply);
+ }
+ }
+ }
+
+ ret = glusterBlockAuditRequest(glfs, tgmfd, blk, cobj, list, reply);
+
+ out:
+ blockFreeMetaInfo(info);
+ return ret;
+}
+
+
+static void
+glusterBlockDeleteRemote(struct glfs_fd *tgmfd, MetaInfo *info,
+ blockDelete *cobj, char *addr, char **reply)
+{
+ int ret = -1;
+ char *out = NULL;
+ char *tmp = *reply;
+
+
+ GB_METAUPDATE_OR_GOTO(tgmfd, info->gbid, info->volume, ret, out,
+ "%s: CLEANUPINPROGRES\n", addr);
+ ret = glusterBlockCallRPC_1(addr, cobj, DELETE_SRV, &out);
+ if (ret) {
+ GB_METAUPDATE_OR_GOTO(tgmfd, info->gbid, info->volume, ret, out,
+ "%s: CLEANUPFAIL\n", addr);
+ LOG("mgmt", GB_LOG_ERROR, "%s on host: %s",
+ FAILED_GATHERING_INFO, addr);
+ goto out;
+ }
+ GB_METAUPDATE_OR_GOTO(tgmfd, info->gbid, info->volume, ret, out,
+ "%s: CLEANUPSUCCESS\n", addr);
+
+ out:
+ asprintf(reply, "%s%s\n", (tmp==NULL?"":tmp), out);
+ GB_FREE(tmp);
+ GB_FREE(out);
+}
+
+
+static int
+glusterBlockCleanUp(struct glfs *glfs, char *blockname,
+ bool deleteall, char **reply)
+{
+ int ret = -1;
+ size_t i;
+ static blockDelete cobj;
+ struct glfs_fd *tgmfd = NULL;
+ size_t cleanupsuccess = 0;
+ MetaInfo *info;
+
+
+ if (GB_ALLOC(info) < 0) {
+ goto out;
+ }
+
+ ret = blockGetMetaInfo(glfs, blockname, info);
+ if (ret) {
+ goto out;
+ }
+
+ strcpy(cobj.block_name, blockname);
+ strcpy(cobj.gbid, info->gbid);
+
+ tgmfd = glfs_open(glfs, blockname, O_WRONLY|O_APPEND);
+ if (!tgmfd) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_open: failed");
+ goto out;
+ }
+
+ for (i = 0; i < info->nhosts; i++) {
+ switch (blockMetaStatusEnumParse(info->list[i]->status)) {
+ case GB_CLEANUP_INPROGRES:
+ case GB_CLEANUP_FAIL:
+ case GB_CONFIG_FAIL:
+ case GB_CONFIG_INPROGRESS:
+ glusterBlockDeleteRemote(tgmfd, info, &cobj,
+ info->list[i]->addr, reply);
+ break;
+ }
+ if (deleteall &&
+ blockMetaStatusEnumParse(info->list[i]->status) == GB_CONFIG_SUCCESS) {
+ glusterBlockDeleteRemote(tgmfd, info, &cobj,
+ info->list[i]->addr, reply);
+ }
+ }
+ blockFreeMetaInfo(info);
+
+ if (GB_ALLOC(info) < 0)
+ goto out;
+
+ ret = blockGetMetaInfo(glfs, blockname, info);
+ if (ret)
+ goto out;
+
+ for (i = 0; i < info->nhosts; i++) {
+ if (blockMetaStatusEnumParse(info->list[i]->status) == GB_CLEANUP_SUCCESS) {
+ cleanupsuccess++;
+ }
+ }
+
+ if (cleanupsuccess == info->nhosts) {
+ if (glusterBlockDeleteEntry(info->volume, info->gbid)) {
+ LOG("mgmt", GB_LOG_ERROR, "%s volume: %s host: %s",
+ FAILED_DELETING_FILE, info->volume, "localhost");
+ }
+ ret = glfs_unlink(glfs, blockname);
+ if (ret && errno != ENOENT) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_unlink: failed");
+ goto out;
+ }
+ }
+
+ out:
+ blockFreeMetaInfo(info);
+
+ if (glfs_close(tgmfd) != 0) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed");
+ }
+
+ return ret;
+}
+
+
+blockResponse *
+block_create_cli_1_svc(blockCreateCli *blk, struct svc_req *rqstp)
+{
+ int ret = -1;
+ size_t i;
+ uuid_t uuid;
+ char *savereply = NULL;
+ char gbid[UUID_BUF_SIZE];
+ static blockCreate cobj;
+ static blockResponse *reply;
+ struct glfs *glfs;
+ struct glfs_fd *lkfd = NULL;
+ struct glfs_fd *tgmfd = NULL;
+ blockServerDefPtr list = NULL;
+
+
+ if (GB_ALLOC(reply) < 0) {
+ goto out;
+ }
+
+ list = blockServerParse(blk->block_hosts);
+
+ /* Fail if mpath > list->nhosts */
+ if (blk->mpath > list->nhosts) {
+ LOG("mgmt", GB_LOG_ERROR, "block multipath request:%d is greater "
+ "than provided block-hosts:%s",
+ blk->mpath, blk->block_hosts);
+ asprintf(&reply->out, "multipath req: %d > block-hosts: %s\n",
+ blk->mpath, blk->block_hosts);
+ reply->exit = ENODEV;
+ goto optfail;
+ }
+
+ glfs = glusterBlockVolumeInit(blk->volume, blk->volfileserver);
+ if (!glfs) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed");
+ goto out;
+ }
+
+ lkfd = glusterBlockCreateMetaLockFile(glfs, blk->volume);
+ if (!lkfd) {
+ LOG("mgmt", GB_LOG_ERROR, "%s",
+ "glusterBlockCreateMetaLockFile failed");
+ goto out;
+ }
+
+ GB_METALOCK_OR_GOTO(lkfd, blk->volume, ret, out);
+
+ if (!glfs_access(glfs, blk->block_name, F_OK)) {
+ asprintf(&reply->out, "BLOCK with name: '%s' already EXIST\n",
+ blk->block_name);
+ ret = EEXIST;
+ goto exist;
+ }
+
+ tgmfd = glfs_creat(glfs, blk->block_name, O_RDWR, S_IRUSR | S_IWUSR);
+ if (!tgmfd) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_creat: failed");
+ goto out;
+ }
+
+ uuid_generate(uuid);
+ uuid_unparse(uuid, gbid);
+
+ GB_METAUPDATE_OR_GOTO(tgmfd, blk->block_name, blk->volume, ret, exist,
+ "VOLUME: %s\nGBID: %s\nSIZE: %zu\nHA: %d\n"
+ "ENTRYCREATE: INPROGRESS\n",
+ blk->volume, gbid, blk->size, blk->mpath);
+
+ ret = glusterBlockCreateEntry(blk, gbid);
+ if (ret) {
+ GB_METAUPDATE_OR_GOTO(tgmfd, blk->block_name, blk->volume, ret,
+ exist, "ENTRYCREATE: FAIL\n");
+ LOG("mgmt", GB_LOG_ERROR, "%s volume: %s host: %s",
+ FAILED_CREATING_FILE, blk->volume, blk->volfileserver);
+ goto out;
+ }
+
+ GB_METAUPDATE_OR_GOTO(tgmfd, blk->block_name, blk->volume, ret, exist,
+ "ENTRYCREATE: SUCCESS\n");
+
+ strcpy(cobj.volume, blk->volume);
+ strcpy(cobj.volfileserver, blk->volfileserver);
+ strcpy(cobj.block_name, blk->block_name);
+ cobj.size = blk->size;
+ strcpy(cobj.gbid, gbid);
+
+ for (i = 0; i < blk->mpath; i++) {
+ glusterBlockCreateRemote(tgmfd, blk->volume, &cobj,
+ list->hosts[i], &savereply);
+ }
+
+ /* Check Point */
+ ret = glusterBlockAuditRequest(glfs, tgmfd, blk,
+ &cobj, list, &savereply);
+ if (ret) {
+ LOG("mgmt", GB_LOG_ERROR, "%s",
+ "even spare nodes have exhausted rewinding");
+ ret = glusterBlockCleanUp(glfs,
+ blk->block_name, FALSE, &savereply);
+ }
+
+ out:
+ reply->out = savereply;
+
+ if (glfs_close(tgmfd) != 0)
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed");
+
+ exist:
+ GB_METAUNLOCK(lkfd, blk->volume, ret);
+
+ reply->exit = ret;
+
+ if (glfs_close(lkfd) != 0) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed");
+ }
+
+ glfs_fini(glfs);
+
+ optfail:
+ blockServerDefFree(list);
+
+ return reply;
+}
+
+
+blockResponse *
+block_create_1_svc(blockCreate *blk, struct svc_req *rqstp)
+{
+ FILE *fp;
+ char *backstore;
+ char *iqn;
+ char *lun;
+ char *attr;
+ char *exec;
+ blockResponse *reply = NULL;
+
+
+ asprintf(&backstore, "%s %s %s %zu %s@%s/%s %s", TARGETCLI_GLFS,
+ CREATE, blk->block_name, blk->size, blk->volume,
+ blk->volfileserver, blk->gbid, blk->gbid);
+
+ asprintf(&iqn, "%s %s %s%s", TARGETCLI_ISCSI, CREATE,
+ IQN_PREFIX, blk->gbid);
+
+
+ asprintf(&lun, "%s/%s%s/tpg1/luns %s %s/%s", TARGETCLI_ISCSI,
+ IQN_PREFIX, blk->gbid, CREATE, GLFS_PATH, blk->block_name);
+
+ asprintf(&attr, "%s/%s%s/tpg1 set attribute %s",
+ TARGETCLI_ISCSI, IQN_PREFIX, blk->gbid, ATTRIBUTES);
+
+
+ asprintf(&exec, "%s && %s && %s && %s && %s", backstore, iqn, lun,
+ attr, TARGETCLI_SAVE);
+
+ if (GB_ALLOC(reply) < 0) {
+ goto out;
+ }
+
+ if (GB_ALLOC_N(reply->out, 4096) < 0) {
+ GB_FREE(reply);
+ goto out;
+ }
+
+ fp = popen(exec, "r");
+ if (fp != NULL) {
+ size_t newLen = fread(reply->out, sizeof(char), 4096, fp);
+ if (ferror( fp ) != 0) {
+ LOG("mgmt", GB_LOG_ERROR, "Reading command %s output", exec);
+ } else {
+ reply->out[newLen++] = '\0';
+ }
+ reply->exit = WEXITSTATUS(pclose(fp));
+ }
+
+ out:
+ GB_FREE(exec);
+ GB_FREE(attr);
+ GB_FREE(lun);
+ GB_FREE(iqn);
+ GB_FREE(backstore);
+
+ return reply;
+}
+
+
+blockResponse *
+block_delete_cli_1_svc(blockDeleteCli *blk, struct svc_req *rqstp)
+{
+ int ret = -1;
+ char *savereply = NULL;
+ static blockResponse *reply = NULL;
+ struct glfs *glfs;
+ struct glfs_fd *lkfd;
+
+
+ if (GB_ALLOC(reply) < 0) {
+ return NULL;
+ }
+
+ glfs = glusterBlockVolumeInit(blk->volume, "localhost");
+ if (!glfs) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed");
+ goto out;
+ }
+
+ lkfd = glusterBlockCreateMetaLockFile(glfs, blk->volume);
+ if (!lkfd) {
+ LOG("mgmt", GB_LOG_ERROR, "%s",
+ "glusterBlockCreateMetaLockFile failed");
+ goto out;
+ }
+
+ GB_METALOCK_OR_GOTO(lkfd, blk->volume, ret, out);
+
+ if (glfs_access(glfs, blk->block_name, F_OK)) {
+ GB_STRDUP(reply->out, "BLOCK Doesn't EXIST");
+ reply->exit = ENOENT;
+ goto out;
+ }
+
+ ret = glusterBlockCleanUp(glfs, blk->block_name, TRUE, &savereply);
+
+ out:
+ reply->out = savereply;
+
+ GB_METAUNLOCK(lkfd, blk->volume, ret);
+
+ reply->exit = ret;
+
+ if (glfs_close(lkfd) != 0)
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed");
+
+ glfs_fini(glfs);
+
+ return reply;
+}
+
+
+blockResponse *
+block_delete_1_svc(blockDelete *blk, struct svc_req *rqstp)
+{
+ FILE *fp;
+ char *iqn;
+ char *backstore;
+ char *exec;
+ blockResponse *reply = NULL;
+
+
+ asprintf(&iqn, "%s %s %s%s", TARGETCLI_ISCSI, DELETE,
+ IQN_PREFIX, blk->gbid);
+
+ asprintf(&backstore, "%s %s %s", TARGETCLI_GLFS,
+ DELETE, blk->block_name);
+
+ asprintf(&exec, "%s && %s && %s", backstore, iqn, TARGETCLI_SAVE);
+
+ if (GB_ALLOC(reply) < 0) {
+ goto out;
+ }
+
+ if (GB_ALLOC_N(reply->out, 4096) < 0) {
+ GB_FREE(reply);
+ goto out;
+ }
+
+ fp = popen(exec, "r");
+ if (fp != NULL) {
+ size_t newLen = fread(reply->out, sizeof(char), 4096, fp);
+ if (ferror( fp ) != 0) {
+ LOG("mgmt", GB_LOG_ERROR, "reading command %s output", exec);
+ } else {
+ reply->out[newLen++] = '\0';
+ }
+ reply->exit = WEXITSTATUS(pclose(fp));
+ }
+
+ out:
+ GB_FREE(exec);
+ GB_FREE(backstore);
+ GB_FREE(iqn);
+
+ return reply;
+}
+
+
+blockResponse *
+block_list_cli_1_svc(blockListCli *blk, struct svc_req *rqstp)
+{
+ blockResponse *reply;
+ struct glfs *glfs;
+ struct glfs_fd *lkfd = NULL;
+ struct glfs_fd *tgmfd = NULL;
+ struct dirent *entry;
+ char *tmp = NULL;
+ char *filelist = NULL;
+ int ret = -1;
+
+
+ glfs = glusterBlockVolumeInit(blk->volume, "localhost");
+ if (!glfs) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed");
+ goto out;
+ }
+
+ lkfd = glusterBlockCreateMetaLockFile(glfs, blk->volume);
+ if (!lkfd) {
+ LOG("mgmt", GB_LOG_ERROR, "%s",
+ "glusterBlockCreateMetaLockFile failed");
+ goto out;
+ }
+
+ GB_METALOCK_OR_GOTO(lkfd, blk->volume, ret, out);
+
+ tgmfd = glfs_opendir (glfs, "/block-meta");
+ if (!tgmfd) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed");
+ goto out;
+ }
+
+ while ((entry = glfs_readdir (tgmfd))) {
+ if (strcmp(entry->d_name, ".") &&
+ strcmp(entry->d_name, "..") &&
+ strcmp(entry->d_name, "meta.lock")) {
+ asprintf(&filelist, "%s%s\n", (tmp==NULL?"":tmp), entry->d_name);
+ GB_FREE(tmp);
+ tmp = filelist;
+ }
+ }
+
+ ret = 0;
+
+ out:
+ if (GB_ALLOC(reply) < 0) {
+ return NULL;
+ }
+
+ reply->out = filelist? filelist:strdup("*Nil*\n");
+
+ glfs_closedir (tgmfd);
+
+ GB_METAUNLOCK(lkfd, blk->volume, ret);
+
+ reply->exit = ret;
+
+ if (glfs_close(lkfd) != 0) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed");
+ }
+
+ glfs_fini(glfs);
+
+ return reply;
+}
+
+
+blockResponse *
+block_info_cli_1_svc(blockInfoCli *blk, struct svc_req *rqstp)
+{
+ blockResponse *reply;
+ char *out = NULL;
+ char *tmp = NULL;
+ struct glfs *glfs;
+ struct glfs_fd *lkfd = NULL;
+ MetaInfo *info = NULL;
+ int ret = -1;
+ size_t i;
+
+
+ glfs = glusterBlockVolumeInit(blk->volume, "localhost");
+ if (!glfs) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glusterBlockVolumeInit failed");
+ goto out;
+ }
+
+ lkfd = glusterBlockCreateMetaLockFile(glfs, blk->volume);
+ if (!lkfd) {
+ LOG("mgmt", GB_LOG_ERROR, "%s",
+ "glusterBlockCreateMetaLockFile failed");
+ goto out;
+ }
+
+ GB_METALOCK_OR_GOTO(lkfd, blk->volume, ret, out);
+
+ if (GB_ALLOC(info) < 0) {
+ goto out;
+ }
+
+ ret = blockGetMetaInfo(glfs, blk->block_name, info);
+ if (ret) {
+ goto out;
+ }
+
+ asprintf(&tmp, "NAME: %s\nVOLUME: %s\nGBID: %s\nSIZE: %zu\n"
+ "MULTIPATH: %zu\nBLOCK CONFIG NODE(S):",
+ blk->block_name, info->volume, info->gbid,
+ info->size, info->mpath);
+ for (i = 0; i < info->nhosts; i++) {
+ if (blockMetaStatusEnumParse(info->list[i]->status) == GB_CONFIG_SUCCESS) {
+ asprintf(&out, "%s %s", (tmp==NULL?"":tmp), info->list[i]->addr);
+ GB_FREE(tmp);
+ tmp = out;
+ }
+ }
+ asprintf(&out, "%s\n", tmp);
+ ret = 0;
+
+ out:
+ if (GB_ALLOC(reply) < 0) {
+ return NULL;
+ }
+
+ if (!out) {
+ asprintf(&out, "No Block with name %s", blk->block_name);
+ }
+
+ reply->out = out;
+
+ GB_METAUNLOCK(lkfd, blk->volume, ret);
+
+ reply->exit = ret;
+
+ if (glfs_close(lkfd) != 0) {
+ LOG("mgmt", GB_LOG_ERROR, "%s", "glfs_close: failed");
+ }
+
+ glfs_fini(glfs);
+
+ blockFreeMetaInfo(info);
+
+ return reply;
+}
diff --git a/rpc/glfs-operations.c b/rpc/glfs-operations.c
new file mode 100644
index 0000000..9712f64
--- /dev/null
+++ b/rpc/glfs-operations.c
@@ -0,0 +1,270 @@
+/*
+ Copyright (c) 2016 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of gluster-block.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+
+# include "common.h"
+# include "glfs-operations.h"
+
+# define METADIR "/block-meta"
+# define TXLOCKFILE "meta.lock"
+
+
+
+struct glfs *
+glusterBlockVolumeInit(char *volume, char *volfileserver)
+{
+ struct glfs *glfs;
+ int ret;
+
+
+ glfs = glfs_new(volume);
+ if (!glfs) {
+ LOG("gfapi", GB_LOG_ERROR, "glfs_new(%s) from %s failed[%s]", volume,
+ volfileserver, strerror(errno));
+ return NULL;
+ }
+
+ ret = glfs_set_volfile_server(glfs, "tcp", volfileserver, 24007);
+ if (ret) {
+ LOG("gfapi", GB_LOG_ERROR, "glfs_set_volfile_server(%s) of %s "
+ "failed[%s]", volfileserver, volume, strerror(errno));
+ goto out;
+ }
+
+ ret = glfs_set_logging(glfs, GFAPI_LOG_FILE, GFAPI_LOG_LEVEL);
+ if (ret) {
+ LOG("gfapi", GB_LOG_ERROR, "glfs_set_logging(%s, %d) on %s failed[%s]",
+ GFAPI_LOG_FILE, GFAPI_LOG_LEVEL, volume, strerror(errno));
+ goto out;
+ }
+
+ ret = glfs_init(glfs);
+ if (ret) {
+ LOG("gfapi", GB_LOG_ERROR, "glfs_init() on %s failed[%s]", volume,
+ strerror(errno) );
+ goto out;
+ }
+
+ return glfs;
+
+ out:
+ glfs_fini(glfs);
+
+ return NULL;
+}
+
+
+int
+glusterBlockCreateEntry(blockCreateCli *blk, char *gbid)
+{
+ struct glfs *glfs;
+ struct glfs_fd *tgfd;
+ int ret = -1;
+
+
+ glfs = glusterBlockVolumeInit(blk->volume, blk->volfileserver);
+ if (!glfs) {
+ LOG("gfapi", GB_LOG_ERROR, "glusterBlockVolumeInit(%s): failed",
+ blk->volume);
+ goto out;
+ }
+
+ tgfd = glfs_creat(glfs, gbid,
+ O_WRONLY | O_CREAT | O_EXCL,
+ S_IRUSR | S_IWUSR);
+ if (!tgfd) {
+ LOG("gfapi", GB_LOG_ERROR, "glfs_creat(%s) on volume %s failed[%s]",
+ gbid, blk->volume, strerror(errno));
+ } else {
+ ret = glfs_ftruncate(tgfd, blk->size);
+ if (ret) {
+ LOG("gfapi", GB_LOG_ERROR, "glfs_ftruncate(%s): on volume %s "
+ "of size %zu failed[%s]", gbid, blk->volume, blk->size,
+ strerror(errno));
+ goto out;
+ }
+
+ if (glfs_close(tgfd) != 0) {
+ LOG("gfapi", GB_LOG_ERROR, "glfs_close(%s): on volume %s failed[%s]",
+ gbid, blk->volume, strerror(errno));
+ goto out;
+ }
+ }
+
+ out:
+ glfs_fini(glfs);
+ return ret;
+}
+
+
+int
+glusterBlockDeleteEntry(char *volume, char *gbid)
+{
+ struct glfs *glfs;
+ int ret = -1;
+
+
+ glfs = glusterBlockVolumeInit(volume, "localhost");
+ if (!glfs) {
+ LOG("gfapi", GB_LOG_ERROR, "glusterBlockVolumeInit(%s): failed",
+ volume);
+ goto out;
+ }
+
+ ret = glfs_unlink(glfs, gbid);
+ if (ret) {
+ LOG("gfapi", GB_LOG_ERROR, "glfs_unlink(%s) on volume %s failed[%s]",
+ gbid, volume, strerror(errno));
+ goto out;
+ }
+
+ out:
+ glfs_fini(glfs);
+ return ret;
+}
+
+
+struct glfs_fd *
+glusterBlockCreateMetaLockFile(struct glfs *glfs, char *volume)
+{
+ struct glfs_fd *lkfd;
+ int ret;
+
+
+ ret = glfs_mkdir (glfs, METADIR, 0);
+ if (ret && errno != EEXIST) {
+ LOG("gfapi", GB_LOG_ERROR, "glfs_mkdir(%s) on volume %s failed[%s]",
+ METADIR, volume, strerror(errno));
+ goto out;
+ }
+
+ ret = glfs_chdir (glfs, METADIR);
+ if (ret) {
+ LOG("gfapi", GB_LOG_ERROR, "glfs_chdir(%s) on volume %s failed[%s]",
+ METADIR, volume, strerror(errno));
+ goto out;
+ }
+
+ lkfd = glfs_creat(glfs, TXLOCKFILE, O_RDWR, S_IRUSR | S_IWUSR);
+ if (!lkfd) {
+ LOG("gfapi", GB_LOG_ERROR, "glfs_creat(%s) on volume %s failed[%s]",
+ TXLOCKFILE, volume, strerror(errno));
+ goto out;
+ }
+
+ return lkfd;
+
+ out:
+ return NULL;
+}
+
+
+void
+blockFreeMetaInfo(MetaInfo *info)
+{
+ int i;
+
+
+ if (!info)
+ return;
+
+ for (i = 0; i < info->nhosts; i++)
+ GB_FREE(info->list[i]);
+
+ GB_FREE(info->list);
+ GB_FREE(info);
+}
+
+
+static void
+blockStuffMetaInfo(MetaInfo *info, char *line)
+{
+ char* tmp = strdup(line);
+ char* opt = strtok(tmp,":");
+ int Flag = 0;
+ size_t i;
+
+
+ switch (blockMetaKeyEnumParse(opt)) {
+ case GB_META_VOLUME:
+ strcpy(info->volume, strchr(line, ' ')+1);
+ break;
+ case GB_META_GBID:
+ strcpy(info->gbid, strchr(line, ' ')+1);
+ break;
+ case GB_META_SIZE:
+ sscanf(strchr(line, ' ')+1, "%zu", &info->size);
+ break;
+ case GB_META_HA:
+ sscanf(strchr(line, ' ')+1, "%zu", &info->mpath);
+ break;
+ case GB_META_ENTRYCREATE:
+ strcpy(info->entry, strchr(line, ' ')+1);
+ break;
+
+ default:
+ if(!info->list) {
+ if(GB_ALLOC(info->list) < 0)
+ return;
+ if(GB_ALLOC(info->list[0]) < 0)
+ return;
+ strcpy(info->list[0]->addr, opt);
+ strcpy(info->list[0]->status, strchr(line, ' ')+1);
+ info->nhosts = 1;
+ } else {
+ for (i = 0; i < info->nhosts; i++) {
+ if(!strcmp(info->list[i]->addr, opt)) {
+ strcpy(info->list[i]->status, strchr(line, ' ')+1);
+ Flag = 1;
+ break;
+ }
+ }
+ if (!Flag) {
+ if(GB_ALLOC(info->list[info->nhosts]) < 0)
+ return;
+ strcpy(info->list[info->nhosts]->addr, opt);
+ strcpy(info->list[info->nhosts]->status, strchr(line, ' ')+1);
+ info->nhosts++;
+ }
+ }
+ break;
+ }
+
+ GB_FREE(tmp);
+}
+
+
+int
+blockGetMetaInfo(struct glfs* glfs, char* metafile, MetaInfo *info)
+{
+ size_t count = 0;
+ struct glfs_fd *tgmfd;
+ char line[1024];
+ char *tmp;
+
+
+ tgmfd = glfs_open(glfs, metafile, O_RDONLY);
+ if (!tgmfd) {
+ LOG("gfapi", GB_LOG_ERROR, "glfs_open(%s) on volume %s failed[%s]",
+ metafile, info->volume, strerror(errno));
+ return -1;
+ }
+
+ while (glfs_read (tgmfd, line, sizeof(line), 0) > 0) {
+ tmp = strtok(line,"\n");
+ count += strlen(tmp) + 1;
+ blockStuffMetaInfo(info, tmp);
+ glfs_lseek(tgmfd, count, SEEK_SET);
+ }
+
+ glfs_close(tgmfd);
+
+ return 0;
+}
diff --git a/rpc/glfs-operations.h b/rpc/glfs-operations.h
new file mode 100644
index 0000000..8ba12f5
--- /dev/null
+++ b/rpc/glfs-operations.h
@@ -0,0 +1,61 @@
+/*
+ Copyright (c) 2016 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of gluster-block.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+
+# ifndef _GLFS_OPERATIONS_H
+# define _GLFS_OPERATIONS_H 1
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <stdbool.h>
+# include <errno.h>
+
+# include <glusterfs/api/glfs.h>
+
+# include "block.h"
+
+
+
+typedef struct NodeInfo {
+ char addr[255];
+ char status[16];
+} NodeInfo;
+
+typedef struct MetaInfo {
+ char volume[255];
+ char gbid[38];
+ size_t size;
+ size_t mpath;
+ char entry[16];
+
+ size_t nhosts;
+ NodeInfo **list;
+} MetaInfo;
+
+
+struct glfs *
+glusterBlockVolumeInit(char *volume, char *volfileserver);
+
+int
+glusterBlockCreateEntry(blockCreateCli *blk, char *gbid);
+
+int
+glusterBlockDeleteEntry(char *volume, char *gbid);
+
+struct glfs_fd *
+glusterBlockCreateMetaLockFile(struct glfs *glfs, char *volume);
+
+int
+blockGetMetaInfo(struct glfs *glfs, char *metafile, MetaInfo *info);
+
+void
+blockFreeMetaInfo(MetaInfo *info);
+
+#endif /* _GLFS_OPERATIONS_H */
diff --git a/rpc/block.x b/rpc/rpcl/block.x
index 0bc988c..0bc988c 100644
--- a/rpc/block.x
+++ b/rpc/rpcl/block.x