From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dmitry Mishin Date: Fri, 10 Dec 2010 12:00:12 +0300 Subject: [Cluster-devel] [PATCH 7/8] Added 'failoverdomain' object manipulations In-Reply-To: <1291971613-13076-1-git-send-email-dim@parallels.com> References: <1291971613-13076-1-git-send-email-dim@parallels.com> Message-ID: <1291971613-13076-8-git-send-email-dim@parallels.com> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Signed-off-by: Dmitry Mishin --- config/tools/ccs_tool/ccs_tool.c | 21 +++- config/tools/ccs_tool/editconf.c | 292 +++++++++++++++++++++++++++++++++++++- config/tools/ccs_tool/editconf.h | 2 + 3 files changed, 305 insertions(+), 10 deletions(-) diff --git a/config/tools/ccs_tool/ccs_tool.c b/config/tools/ccs_tool/ccs_tool.c index dfe5610..e1dc3cc 100644 --- a/config/tools/ccs_tool/ccs_tool.c +++ b/config/tools/ccs_tool/ccs_tool.c @@ -259,6 +259,14 @@ static int tool_main(int argc, char *argv[]) del_node(argc-1, argv+1); exit(EXIT_SUCCESS); } + else if(!strcmp(argv[optind], "addfdomain")){ + add_fdomain(argc-1, argv+1); + exit(EXIT_SUCCESS); + } + else if(!strcmp(argv[optind], "delfdomain")){ + del_node(argc-1, argv+1); + exit(EXIT_SUCCESS); + } else if(!strcmp(argv[optind], "addfence")){ add_fence(argc-1, argv+1); exit(EXIT_SUCCESS); @@ -291,6 +299,10 @@ static int tool_main(int argc, char *argv[]) list_fs(argc-1, argv+1); exit(EXIT_SUCCESS); } + else if(!strcmp(argv[optind], "lsfdomains")){ + list_fdomains(argc-1, argv+1); + exit(EXIT_SUCCESS); + } else if(!strcmp(argv[optind], "create")){ create_skeleton(argc-1, argv+1); exit(EXIT_SUCCESS); @@ -341,9 +353,12 @@ static void tool_print_usage(FILE *stream){ " addip Add an IP address resource\n" " delip Delete an IP address resource\n" " lsip List IP address resources\n" - " addfs Add an IP address resource\n" - " delfs Delete an IP address resource\n" - " lsfs List IP address resources\n" + " addfs Add an filesystem resource\n" + " delfs Delete an filesystem resource\n" + " lsfs List filesystem resources\n" + " addfdomain Add an failover domain\n" + " delfdomain Delete an failover domain\n" + " lsfdomains List failover domains\n" " create Create a skeleton config file\n" " addnodeids Assign node ID numbers to all nodes\n" "\n"); diff --git a/config/tools/ccs_tool/editconf.c b/config/tools/ccs_tool/editconf.c index aa6c7cd..aae1095 100644 --- a/config/tools/ccs_tool/editconf.c +++ b/config/tools/ccs_tool/editconf.c @@ -27,6 +27,12 @@ do { \ } while (0) +#define INT_TO_CHAR(x, str) \ + if (str && atoi((const char *)str)) \ + x = '*'; \ + else \ + x = ' '; + struct option_info { const char *name; @@ -47,10 +53,13 @@ struct option_info const char *options; const char *configfile; const char *outputfile; + const char **failover_nodes; int do_delete; int force_fsck; int force_unmount; int self_fence; + int ordered; + int restricted; int tell_ccsd; int force_ccsd; }; @@ -172,6 +181,20 @@ static void addfs_usage(const char *name) exit(0); } +static void addfdomain_usage(const char *name) +{ + fprintf(stderr, "Usage: %s %s [options] ... \n", + prog_name, name); + fprintf(stderr, " -p --ordered Allows you to specify a preference order\n"); + fprintf(stderr, " among the members of a failover domain\n"); + fprintf(stderr, " -r --restricted Allows you to restrict the members that can\n"); + fprintf(stderr, " run a particular cluster service.\n"); + config_usage(1); + help_usage(); + + exit(0); +} + static void addnodeid_usage(const char *name) { fprintf(stderr, "Add node IDs to all nodes in the config file that don't have them.\n"); @@ -456,7 +479,7 @@ static xmlNode *do_find_node(xmlNode *root, const char *nodename, strcmp((char *)cur_node->name, elem_name) == 0) { xmlChar *name = xmlGetProp(cur_node, BAD_CAST attrib_name); - if (strcmp((char *)name, nodename) == 0) + if (name && strcmp((char *)name, nodename) == 0) return cur_node; } } @@ -498,6 +521,11 @@ static xmlNode *find_fs_resource(xmlNode *root, const char *name) return do_find_node(root, name, "fs", "name"); } +static xmlNode *find_fdomain_resource(xmlNode *root, const char *name) +{ + return do_find_node(root, name, "failoverdomain", "name"); +} + static xmlNode *find_script_resource(xmlNode *root, const char *name) { return do_find_node(root, name, "script", "name"); @@ -523,6 +551,24 @@ static xmlNode *find_fs_ref(xmlNode *root, const char *name) return do_find_resource_ref(root, name, "fs"); } +static xmlNode *find_fdomain_ref(xmlNode *root, const char *name) +{ + xmlNode *cur_node; + + for (cur_node = root->children; cur_node; cur_node = cur_node->next) + { + if (cur_node->type == XML_ELEMENT_NODE && + strcmp((char *)cur_node->name, "service") == 0) + { + xmlChar *domain = xmlGetProp(cur_node, BAD_CAST "domain"); + if (domain && strcmp(name, (char *)domain) == 0) + return cur_node; + } + } + + return NULL; +} + /* Print name=value pairs for a (n XML) node. * "ignore" is a string to ignore if present as a property (probably already printed on the main line) */ @@ -750,6 +796,56 @@ static void add_clusterfs(xmlNode *root_element, struct option_info *ninfo, xmlAddChild(rs, node); } +static void add_clusterfdomain(xmlNode *root_element, struct option_info *ninfo, + int argc, char **argv, int optindex) +{ + xmlNode *rm; + xmlNode *fdomains; + xmlNode *node; + xmlNode *cn; + int i = 0; + + rm = findnode(root_element, "rm"); + if (!rm) + die("Can't find \"rm\" in %s\n", ninfo->configfile); + + fdomains = findnode(rm, "failoverdomains"); + if (!fdomains) + die("Can't find \"failoverdomains\" %s\n", ninfo->configfile); + + cn = findnode(root_element, "clusternodes"); + if (!cn) + die("Can't find \"clusternodes\" in %s\n", ninfo->configfile); + + /* Check it doesn't already exist */ + if (find_fdomain_resource(fdomains, ninfo->name)) + die("failover domain %s already exists\n", ninfo->name); + + /* Check that nodes are defined */ + while (ninfo->failover_nodes[i]) { + if (!find_node(cn, ninfo->failover_nodes[i])) + die("Can't find node %s in %s.\n", + ninfo->failover_nodes[i], ninfo->configfile); + i++; + } + + /* Add the new failover domain */ + node = xmlNewNode(NULL, BAD_CAST "failoverdomain"); + xmlSetProp(node, BAD_CAST "name", BAD_CAST ninfo->name); + _xmlSetIntProp(node, "ordered", ninfo->ordered); + _xmlSetIntProp(node, "restricted", ninfo->restricted); + + i = 0; + while (ninfo->failover_nodes[i]) { + xmlNode *fnode = xmlNewNode(NULL, BAD_CAST "failoverdomainnode"); + xmlSetProp(fnode, BAD_CAST "name", BAD_CAST ninfo->failover_nodes[i]); + _xmlSetIntProp(fnode, "priority", i + 1); + xmlAddChild(node, fnode); + i++; + } + xmlAddChild(fdomains, node); +} + static xmlDoc *open_configfile(struct option_info *ninfo) { xmlDoc *doc; @@ -933,6 +1029,45 @@ static void del_clusterfs(xmlNode *root_element, struct option_info *ninfo) xmlUnlinkNode(node); } +static void del_clusterfdomain(xmlNode *root_element, struct option_info *ninfo) +{ + xmlNode *rm, *fdomains; + xmlNode *node; + + rm = findnode(root_element, "rm"); + if (!rm) + { + fprintf(stderr, "Can't find \"rm\" in %s\n", ninfo->configfile); + exit(1); + } + + fdomains = findnode(rm, "failoverdomains"); + if (!fdomains) + { + fprintf(stderr, "Can't find \"failoverdomains\" in %s\n", ninfo->configfile); + exit(1); + } + + /* Check that not used */ + node = find_fdomain_ref(rm, ninfo->name); + if (node) + { + fprintf(stderr, "failover domain %s is referenced in service in %s," + " please remove reference first.\n", ninfo->name, + ninfo->configfile); + exit(1); + } + + node = find_fdomain_resource(fdomains, ninfo->name); + if (!node) + { + fprintf(stderr, "failover domain %s does not exist in %s\n", ninfo->name, ninfo->configfile); + exit(1); + } + + xmlUnlinkNode(node); +} + struct option addnode_options[] = { { "votes", required_argument, NULL, 'v'}, @@ -960,6 +1095,17 @@ struct option addfs_options[] = { NULL, 0, NULL, 0 }, }; +struct option addfdomain_options[] = +{ + { "outputfile", required_argument, NULL, 'o'}, + { "configfile", required_argument, NULL, 'c'}, + { "no_ccs", no_argument, NULL, 'C'}, + { "force_ccs", no_argument, NULL, 'F'}, + { "ordered", no_argument, NULL, 'p'}, + { "restricted", no_argument, NULL, 'r'}, + { NULL, 0, NULL, 0 }, +}; + struct option commonw_options[] = { { "outputfile", required_argument, NULL, 'o'}, @@ -1307,6 +1453,8 @@ void del_node(int argc, char **argv) del_clusterip(root_element, &ninfo); else if (!strcmp(argv[0], "delfs")) del_clusterfs(root_element, &ninfo); + else if (!strcmp(argv[0], "delfdomain")) + del_clusterfdomain(root_element, &ninfo); /* Write it out */ save_file(doc, &ninfo); @@ -1721,6 +1869,73 @@ void add_fs(int argc, char **argv) xmlCleanupParser(); } +void add_fdomain(int argc, char **argv) +{ + struct option_info ninfo; + xmlDoc *doc; + xmlNode *root_element; + int opt, i; + + memset(&ninfo, 0, sizeof(ninfo)); + ninfo.tell_ccsd = 1; + + while ( (opt = getopt_long(argc, argv, "pro:c:CFh?", addfdomain_options, NULL)) != EOF) + { + switch(opt) + { + case 'p': + ninfo.ordered = 1; + break; + + case 'r': + ninfo.restricted = 1; + break; + + case 'c': + ninfo.configfile = strdup(optarg); + break; + + case 'o': + ninfo.outputfile = strdup(optarg); + break; + + case 'C': + ninfo.tell_ccsd = 0; + break; + + case 'F': + ninfo.force_ccsd = 1; + break; + + case '?': + default: + addfdomain_usage(argv[0]); + } + } + + if (optind < argc - 1) { + ninfo.name = strdup(argv[optind]); + ninfo.failover_nodes = (const char **)malloc(sizeof(char *) * (argc - optind)); + for (i = 0; i < argc - optind - 1; i++) + ninfo.failover_nodes[i] = strdup(argv[i + optind + 1]); + ninfo.failover_nodes[i] = NULL; + } else + addfdomain_usage(argv[0]); + + doc = open_configfile(&ninfo); + + root_element = xmlDocGetRootElement(doc); + + increment_version(root_element); + + add_clusterfdomain(root_element, &ninfo, argc, argv, optind); + + /* Write it out */ + save_file(doc, &ninfo); + /* Shutdown libxml */ + xmlCleanupParser(); +} + void create_skeleton(int argc, char **argv) { xmlNode *root_element; @@ -2095,17 +2310,80 @@ void list_fs(int argc, char **argv) BAD_CAST "mountpoint"); char f, u, s; -#define INT_TO_CHAR(x, str) \ - if (str && atoi((const char *)str)) \ - x = '*'; \ - else \ - x = ' '; INT_TO_CHAR(f, force_fsck) INT_TO_CHAR(u, force_unmount) INT_TO_CHAR(s, self_fence) -#undef INT_TO_CHAR printf("%-16.16s %-5.5s %c%c%c %-19.19s %s\n", name, type, f, u, s, device, mnt); } } } + +void list_fdomains(int argc, char **argv) +{ + xmlNode *cur_node, *fnode; + xmlNode *root_element; + xmlNode *rm, *fdomains; + xmlDocPtr doc; + struct option_info ninfo; + int opt; + int verbose=0; + + memset(&ninfo, 0, sizeof(ninfo)); + + while ( (opt = getopt_long(argc, argv, "c:hv?", list_options, NULL)) != EOF) + { + switch(opt) + { + case 'c': + ninfo.configfile = strdup(optarg); + break; + case 'v': + verbose++; + break; + case '?': + default: + list_usage(argv[0]); + } + } + doc = open_configfile(&ninfo); + root_element = xmlDocGetRootElement(doc); + + rm = findnode(root_element, "rm"); + if (!rm) + die("Can't find \"rm\" in %s\n", ninfo.configfile); + + fdomains = findnode(rm, "failoverdomains"); + if (!fdomains) + die("Can't find \"failoverdomains\" in %s\n", ninfo.configfile); + + printf("Name OR Nodes\n"); + for (cur_node = fdomains->children; cur_node; cur_node = cur_node->next) + { + if (cur_node->type == XML_ELEMENT_NODE && + strcmp((char *)cur_node->name, "failoverdomain") == 0) + { + xmlChar *name = xmlGetProp(cur_node, BAD_CAST "name"); + xmlChar *ordered = xmlGetProp(cur_node, BAD_CAST "ordered"); + xmlChar *restricted = xmlGetProp(cur_node, BAD_CAST "restricted"); + char o, r; + int first_node = 1; + + INT_TO_CHAR(o, ordered) + INT_TO_CHAR(r, restricted) + printf("%-16.16s %c%c ", name, o, r); + for (fnode = cur_node->children; fnode; fnode = fnode->next) + if (fnode->type == XML_ELEMENT_NODE && + strcmp((char *)fnode->name, "failoverdomainnode") == 0) + { + xmlChar *fname = xmlGetProp(fnode, BAD_CAST "name"); + if (first_node) { + printf("%s", fname); + first_node = 0; + } else + printf(",%s", fname); + } + printf("\n"); + } + } +} diff --git a/config/tools/ccs_tool/editconf.h b/config/tools/ccs_tool/editconf.h index 3d1f5c2..7edd52f 100644 --- a/config/tools/ccs_tool/editconf.h +++ b/config/tools/ccs_tool/editconf.h @@ -4,6 +4,7 @@ void add_service(int argc, char **argv); void add_script(int argc, char **argv); void add_ip(int argc, char **argv); void add_fs(int argc, char **argv); +void add_fdomain(int argc, char **argv); void add_fence(int argc, char **argv); void del_node(int argc, char **argv); void del_fence(int argc, char **argv); @@ -13,4 +14,5 @@ void list_fences(int argc, char **argv); void list_scripts(int argc, char **argv); void list_ips(int argc, char **argv); void list_fs(int argc, char **argv); +void list_fdomains(int argc, char **argv); void create_skeleton(int argc, char **argv); -- 1.7.1