1204076Spjd/*- 2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3330449Seadler * 4204076Spjd * Copyright (c) 2009-2010 The FreeBSD Foundation 5204076Spjd * All rights reserved. 6204076Spjd * 7204076Spjd * This software was developed by Pawel Jakub Dawidek under sponsorship from 8204076Spjd * the FreeBSD Foundation. 9204076Spjd * 10204076Spjd * Redistribution and use in source and binary forms, with or without 11204076Spjd * modification, are permitted provided that the following conditions 12204076Spjd * are met: 13204076Spjd * 1. Redistributions of source code must retain the above copyright 14204076Spjd * notice, this list of conditions and the following disclaimer. 15204076Spjd * 2. Redistributions in binary form must reproduce the above copyright 16204076Spjd * notice, this list of conditions and the following disclaimer in the 17204076Spjd * documentation and/or other materials provided with the distribution. 18204076Spjd * 19204076Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 20204076Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21204076Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22204076Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 23204076Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24204076Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25204076Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26204076Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27204076Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28204076Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29204076Spjd * SUCH DAMAGE. 30204076Spjd */ 31204076Spjd 32204076Spjd#include <sys/cdefs.h> 33204076Spjd__FBSDID("$FreeBSD: stable/11/sbin/hastctl/hastctl.c 330449 2018-03-05 07:26:05Z eadler $"); 34204076Spjd 35204076Spjd#include <sys/param.h> 36204076Spjd 37204076Spjd#include <err.h> 38219620Strociny#include <libutil.h> 39204076Spjd#include <stdio.h> 40204076Spjd#include <string.h> 41204076Spjd#include <unistd.h> 42204076Spjd 43204076Spjd#include <activemap.h> 44204076Spjd 45204076Spjd#include "hast.h" 46204076Spjd#include "hast_proto.h" 47204076Spjd#include "metadata.h" 48204076Spjd#include "nv.h" 49204076Spjd#include "pjdlog.h" 50204076Spjd#include "proto.h" 51204076Spjd#include "subr.h" 52204076Spjd 53204076Spjd/* Path to configuration file. */ 54204076Spjdstatic const char *cfgpath = HAST_CONFIG; 55204076Spjd/* Hastd configuration. */ 56204076Spjdstatic struct hastd_config *cfg; 57204076Spjd/* Control connection. */ 58204076Spjdstatic struct proto_conn *controlconn; 59204076Spjd 60204076Spjdenum { 61204076Spjd CMD_INVALID, 62204076Spjd CMD_CREATE, 63204076Spjd CMD_ROLE, 64204076Spjd CMD_STATUS, 65248291Smarck CMD_DUMP, 66248291Smarck CMD_LIST 67204076Spjd}; 68204076Spjd 69204076Spjdstatic __dead2 void 70204076Spjdusage(void) 71204076Spjd{ 72204076Spjd 73204076Spjd fprintf(stderr, 74204076Spjd "usage: %s create [-d] [-c config] [-e extentsize] [-k keepdirty]\n" 75204076Spjd "\t\t[-m mediasize] name ...\n", 76204076Spjd getprogname()); 77204076Spjd fprintf(stderr, 78204076Spjd " %s role [-d] [-c config] <init | primary | secondary> all | name ...\n", 79204076Spjd getprogname()); 80204076Spjd fprintf(stderr, 81248291Smarck " %s list [-d] [-c config] [all | name ...]\n", 82248291Smarck getprogname()); 83248291Smarck fprintf(stderr, 84204076Spjd " %s status [-d] [-c config] [all | name ...]\n", 85204076Spjd getprogname()); 86204076Spjd fprintf(stderr, 87204076Spjd " %s dump [-d] [-c config] [all | name ...]\n", 88204076Spjd getprogname()); 89204076Spjd exit(EX_USAGE); 90204076Spjd} 91204076Spjd 92204076Spjdstatic int 93204076Spjdcreate_one(struct hast_resource *res, intmax_t mediasize, intmax_t extentsize, 94204076Spjd intmax_t keepdirty) 95204076Spjd{ 96204076Spjd unsigned char *buf; 97204076Spjd size_t mapsize; 98204076Spjd int ec; 99204076Spjd 100204076Spjd ec = 0; 101204076Spjd pjdlog_prefix_set("[%s] ", res->hr_name); 102204076Spjd 103229945Spjd if (provinfo(res, true) == -1) { 104204076Spjd ec = EX_NOINPUT; 105204076Spjd goto end; 106204076Spjd } 107204076Spjd if (mediasize == 0) 108204076Spjd mediasize = res->hr_local_mediasize; 109204076Spjd else if (mediasize > res->hr_local_mediasize) { 110204076Spjd pjdlog_error("Provided mediasize is larger than provider %s size.", 111204076Spjd res->hr_localpath); 112204076Spjd ec = EX_DATAERR; 113204076Spjd goto end; 114204076Spjd } 115204076Spjd if (!powerof2(res->hr_local_sectorsize)) { 116204076Spjd pjdlog_error("Sector size of provider %s is not power of 2 (%u).", 117204076Spjd res->hr_localpath, res->hr_local_sectorsize); 118204076Spjd ec = EX_DATAERR; 119204076Spjd goto end; 120204076Spjd } 121204076Spjd if (extentsize == 0) 122204076Spjd extentsize = HAST_EXTENTSIZE; 123204076Spjd if (extentsize < res->hr_local_sectorsize) { 124204076Spjd pjdlog_error("Extent size (%jd) is less than sector size (%u).", 125204076Spjd (intmax_t)extentsize, res->hr_local_sectorsize); 126204076Spjd ec = EX_DATAERR; 127204076Spjd goto end; 128204076Spjd } 129204076Spjd if ((extentsize % res->hr_local_sectorsize) != 0) { 130204076Spjd pjdlog_error("Extent size (%jd) is not multiple of sector size (%u).", 131204076Spjd (intmax_t)extentsize, res->hr_local_sectorsize); 132204076Spjd ec = EX_DATAERR; 133204076Spjd goto end; 134204076Spjd } 135204076Spjd mapsize = activemap_calc_ondisk_size(mediasize - METADATA_SIZE, 136204076Spjd extentsize, res->hr_local_sectorsize); 137204076Spjd if (keepdirty == 0) 138204076Spjd keepdirty = HAST_KEEPDIRTY; 139204076Spjd res->hr_datasize = mediasize - METADATA_SIZE - mapsize; 140204076Spjd res->hr_extentsize = extentsize; 141204076Spjd res->hr_keepdirty = keepdirty; 142204076Spjd 143204076Spjd res->hr_localoff = METADATA_SIZE + mapsize; 144204076Spjd 145229945Spjd if (metadata_write(res) == -1) { 146204076Spjd ec = EX_IOERR; 147204076Spjd goto end; 148204076Spjd } 149204076Spjd buf = calloc(1, mapsize); 150204076Spjd if (buf == NULL) { 151204076Spjd pjdlog_error("Unable to allocate %zu bytes of memory for initial bitmap.", 152204076Spjd mapsize); 153204076Spjd ec = EX_TEMPFAIL; 154204076Spjd goto end; 155204076Spjd } 156204076Spjd if (pwrite(res->hr_localfd, buf, mapsize, METADATA_SIZE) != 157204076Spjd (ssize_t)mapsize) { 158204076Spjd pjdlog_errno(LOG_ERR, "Unable to store initial bitmap on %s", 159204076Spjd res->hr_localpath); 160204076Spjd free(buf); 161204076Spjd ec = EX_IOERR; 162204076Spjd goto end; 163204076Spjd } 164204076Spjd free(buf); 165204076Spjdend: 166204076Spjd if (res->hr_localfd >= 0) 167204076Spjd close(res->hr_localfd); 168204076Spjd pjdlog_prefix_set("%s", ""); 169204076Spjd return (ec); 170204076Spjd} 171204076Spjd 172204076Spjdstatic void 173204076Spjdcontrol_create(int argc, char *argv[], intmax_t mediasize, intmax_t extentsize, 174204076Spjd intmax_t keepdirty) 175204076Spjd{ 176204076Spjd struct hast_resource *res; 177204076Spjd int ec, ii, ret; 178204076Spjd 179204076Spjd /* Initialize the given resources. */ 180204076Spjd if (argc < 1) 181204076Spjd usage(); 182204076Spjd ec = 0; 183204076Spjd for (ii = 0; ii < argc; ii++) { 184204076Spjd TAILQ_FOREACH(res, &cfg->hc_resources, hr_next) { 185204076Spjd if (strcmp(argv[ii], res->hr_name) == 0) 186204076Spjd break; 187204076Spjd } 188204076Spjd if (res == NULL) { 189204076Spjd pjdlog_error("Unknown resource %s.", argv[ii]); 190204076Spjd if (ec == 0) 191204076Spjd ec = EX_DATAERR; 192204076Spjd continue; 193204076Spjd } 194204076Spjd ret = create_one(res, mediasize, extentsize, keepdirty); 195204076Spjd if (ret != 0 && ec == 0) 196204076Spjd ec = ret; 197204076Spjd } 198204076Spjd exit(ec); 199204076Spjd} 200204076Spjd 201204076Spjdstatic int 202204076Spjddump_one(struct hast_resource *res) 203204076Spjd{ 204204076Spjd int ret; 205204076Spjd 206204076Spjd ret = metadata_read(res, false); 207204076Spjd if (ret != 0) 208204076Spjd return (ret); 209204076Spjd 210204076Spjd printf("resource: %s\n", res->hr_name); 211219373Spjd printf(" datasize: %ju (%NB)\n", (uintmax_t)res->hr_datasize, 212219373Spjd (intmax_t)res->hr_datasize); 213219373Spjd printf(" extentsize: %d (%NB)\n", res->hr_extentsize, 214219373Spjd (intmax_t)res->hr_extentsize); 215204076Spjd printf(" keepdirty: %d\n", res->hr_keepdirty); 216204076Spjd printf(" localoff: %ju\n", (uintmax_t)res->hr_localoff); 217204076Spjd printf(" resuid: %ju\n", (uintmax_t)res->hr_resuid); 218204076Spjd printf(" localcnt: %ju\n", (uintmax_t)res->hr_primary_localcnt); 219204076Spjd printf(" remotecnt: %ju\n", (uintmax_t)res->hr_primary_remotecnt); 220204076Spjd printf(" prevrole: %s\n", role2str(res->hr_previous_role)); 221204076Spjd 222204076Spjd return (0); 223204076Spjd} 224204076Spjd 225204076Spjdstatic void 226204076Spjdcontrol_dump(int argc, char *argv[]) 227204076Spjd{ 228204076Spjd struct hast_resource *res; 229204076Spjd int ec, ret; 230204076Spjd 231204076Spjd /* Dump metadata of the given resource(s). */ 232204076Spjd 233204076Spjd ec = 0; 234204076Spjd if (argc == 0 || (argc == 1 && strcmp(argv[0], "all") == 0)) { 235204076Spjd TAILQ_FOREACH(res, &cfg->hc_resources, hr_next) { 236204076Spjd ret = dump_one(res); 237204076Spjd if (ret != 0 && ec == 0) 238204076Spjd ec = ret; 239204076Spjd } 240204076Spjd } else { 241204076Spjd int ii; 242204076Spjd 243204076Spjd for (ii = 0; ii < argc; ii++) { 244204076Spjd TAILQ_FOREACH(res, &cfg->hc_resources, hr_next) { 245204076Spjd if (strcmp(argv[ii], res->hr_name) == 0) 246204076Spjd break; 247204076Spjd } 248204076Spjd if (res == NULL) { 249204076Spjd pjdlog_error("Unknown resource %s.", argv[ii]); 250204076Spjd if (ec == 0) 251204076Spjd ec = EX_DATAERR; 252204076Spjd continue; 253204076Spjd } 254204076Spjd ret = dump_one(res); 255204076Spjd if (ret != 0 && ec == 0) 256204076Spjd ec = ret; 257204076Spjd } 258204076Spjd } 259204076Spjd exit(ec); 260204076Spjd} 261204076Spjd 262204076Spjdstatic int 263204076Spjdcontrol_set_role(struct nv *nv, const char *newrole) 264204076Spjd{ 265204076Spjd const char *res, *oldrole; 266204076Spjd unsigned int ii; 267204076Spjd int error, ret; 268204076Spjd 269204076Spjd ret = 0; 270204076Spjd 271204076Spjd for (ii = 0; ; ii++) { 272204076Spjd res = nv_get_string(nv, "resource%u", ii); 273204076Spjd if (res == NULL) 274204076Spjd break; 275204076Spjd pjdlog_prefix_set("[%s] ", res); 276204076Spjd error = nv_get_int16(nv, "error%u", ii); 277204076Spjd if (error != 0) { 278204076Spjd if (ret == 0) 279204076Spjd ret = error; 280204076Spjd pjdlog_warning("Received error %d from hastd.", error); 281204076Spjd continue; 282204076Spjd } 283204076Spjd oldrole = nv_get_string(nv, "role%u", ii); 284204076Spjd if (strcmp(oldrole, newrole) == 0) 285204076Spjd pjdlog_debug(2, "Role unchanged (%s).", oldrole); 286204076Spjd else { 287204076Spjd pjdlog_debug(1, "Role changed from %s to %s.", oldrole, 288204076Spjd newrole); 289204076Spjd } 290204076Spjd } 291204076Spjd pjdlog_prefix_set("%s", ""); 292204076Spjd return (ret); 293204076Spjd} 294204076Spjd 295204076Spjdstatic int 296248291Smarckcontrol_list(struct nv *nv) 297204076Spjd{ 298252472Strociny pid_t pid; 299204076Spjd unsigned int ii; 300204076Spjd const char *str; 301204076Spjd int error, ret; 302204076Spjd 303204076Spjd ret = 0; 304204076Spjd 305204076Spjd for (ii = 0; ; ii++) { 306204076Spjd str = nv_get_string(nv, "resource%u", ii); 307204076Spjd if (str == NULL) 308204076Spjd break; 309204076Spjd printf("%s:\n", str); 310204076Spjd error = nv_get_int16(nv, "error%u", ii); 311204076Spjd if (error != 0) { 312204076Spjd if (ret == 0) 313204076Spjd ret = error; 314204076Spjd printf(" error: %d\n", error); 315204076Spjd continue; 316204076Spjd } 317204076Spjd printf(" role: %s\n", nv_get_string(nv, "role%u", ii)); 318204076Spjd printf(" provname: %s\n", 319204076Spjd nv_get_string(nv, "provname%u", ii)); 320204076Spjd printf(" localpath: %s\n", 321204076Spjd nv_get_string(nv, "localpath%u", ii)); 322219373Spjd printf(" extentsize: %u (%NB)\n", 323219373Spjd (unsigned int)nv_get_uint32(nv, "extentsize%u", ii), 324219373Spjd (intmax_t)nv_get_uint32(nv, "extentsize%u", ii)); 325204076Spjd printf(" keepdirty: %u\n", 326204076Spjd (unsigned int)nv_get_uint32(nv, "keepdirty%u", ii)); 327204076Spjd printf(" remoteaddr: %s\n", 328204076Spjd nv_get_string(nv, "remoteaddr%u", ii)); 329219821Spjd str = nv_get_string(nv, "sourceaddr%u", ii); 330219821Spjd if (str != NULL) 331219821Spjd printf(" sourceaddr: %s\n", str); 332204076Spjd printf(" replication: %s\n", 333204076Spjd nv_get_string(nv, "replication%u", ii)); 334204076Spjd str = nv_get_string(nv, "status%u", ii); 335204076Spjd if (str != NULL) 336204076Spjd printf(" status: %s\n", str); 337252472Strociny pid = nv_get_int32(nv, "workerpid%u", ii); 338252472Strociny if (pid != 0) 339252472Strociny printf(" workerpid: %d\n", pid); 340219373Spjd printf(" dirty: %ju (%NB)\n", 341219373Spjd (uintmax_t)nv_get_uint64(nv, "dirty%u", ii), 342219373Spjd (intmax_t)nv_get_uint64(nv, "dirty%u", ii)); 343222228Spjd printf(" statistics:\n"); 344222228Spjd printf(" reads: %ju\n", 345247345Strociny (uintmax_t)nv_get_uint64(nv, "stat_read%u", ii)); 346222228Spjd printf(" writes: %ju\n", 347247345Strociny (uintmax_t)nv_get_uint64(nv, "stat_write%u", ii)); 348222228Spjd printf(" deletes: %ju\n", 349247345Strociny (uintmax_t)nv_get_uint64(nv, "stat_delete%u", ii)); 350222228Spjd printf(" flushes: %ju\n", 351247345Strociny (uintmax_t)nv_get_uint64(nv, "stat_flush%u", ii)); 352222228Spjd printf(" activemap updates: %ju\n", 353247345Strociny (uintmax_t)nv_get_uint64(nv, "stat_activemap_update%u", ii)); 354247281Strociny printf(" local errors: " 355247281Strociny "read: %ju, write: %ju, delete: %ju, flush: %ju\n", 356247281Strociny (uintmax_t)nv_get_uint64(nv, "stat_read_error%u", ii), 357247281Strociny (uintmax_t)nv_get_uint64(nv, "stat_write_error%u", ii), 358247281Strociny (uintmax_t)nv_get_uint64(nv, "stat_delete_error%u", ii), 359247281Strociny (uintmax_t)nv_get_uint64(nv, "stat_flush_error%u", ii)); 360257155Strociny printf(" queues: " 361257155Strociny "local: %ju, send: %ju, recv: %ju, done: %ju, idle: %ju\n", 362257155Strociny (uintmax_t)nv_get_uint64(nv, "local_queue_size%u", ii), 363257155Strociny (uintmax_t)nv_get_uint64(nv, "send_queue_size%u", ii), 364257155Strociny (uintmax_t)nv_get_uint64(nv, "recv_queue_size%u", ii), 365257155Strociny (uintmax_t)nv_get_uint64(nv, "done_queue_size%u", ii), 366257155Strociny (uintmax_t)nv_get_uint64(nv, "idle_queue_size%u", ii)); 367204076Spjd } 368204076Spjd return (ret); 369204076Spjd} 370204076Spjd 371248291Smarckstatic int 372248291Smarckcontrol_status(struct nv *nv) 373248291Smarck{ 374248291Smarck unsigned int ii; 375248291Smarck const char *str; 376248291Smarck int error, hprinted, ret; 377248291Smarck 378248291Smarck hprinted = 0; 379248291Smarck ret = 0; 380248291Smarck 381248291Smarck for (ii = 0; ; ii++) { 382248291Smarck str = nv_get_string(nv, "resource%u", ii); 383248291Smarck if (str == NULL) 384248291Smarck break; 385248291Smarck if (!hprinted) { 386248291Smarck printf("Name\tStatus\t Role\t\tComponents\n"); 387248291Smarck hprinted = 1; 388248291Smarck } 389248291Smarck printf("%s\t", str); 390248291Smarck error = nv_get_int16(nv, "error%u", ii); 391248291Smarck if (error != 0) { 392248291Smarck if (ret == 0) 393248291Smarck ret = error; 394248291Smarck printf("ERR%d\n", error); 395248291Smarck continue; 396248291Smarck } 397248291Smarck str = nv_get_string(nv, "status%u", ii); 398248291Smarck printf("%-9s", (str != NULL) ? str : "-"); 399248291Smarck printf("%-15s", nv_get_string(nv, "role%u", ii)); 400248291Smarck printf("%s\t", 401248291Smarck nv_get_string(nv, "localpath%u", ii)); 402248291Smarck printf("%s\n", 403248291Smarck nv_get_string(nv, "remoteaddr%u", ii)); 404248291Smarck } 405248291Smarck return (ret); 406248291Smarck} 407248291Smarck 408204076Spjdint 409204076Spjdmain(int argc, char *argv[]) 410204076Spjd{ 411204076Spjd struct nv *nv; 412219620Strociny int64_t mediasize, extentsize, keepdirty; 413204076Spjd int cmd, debug, error, ii; 414204076Spjd const char *optstr; 415204076Spjd 416204076Spjd debug = 0; 417204076Spjd mediasize = extentsize = keepdirty = 0; 418204076Spjd 419204076Spjd if (argc == 1) 420204076Spjd usage(); 421204076Spjd 422204076Spjd if (strcmp(argv[1], "create") == 0) { 423204076Spjd cmd = CMD_CREATE; 424204076Spjd optstr = "c:de:k:m:h"; 425204076Spjd } else if (strcmp(argv[1], "role") == 0) { 426204076Spjd cmd = CMD_ROLE; 427204076Spjd optstr = "c:dh"; 428248291Smarck } else if (strcmp(argv[1], "list") == 0) { 429248291Smarck cmd = CMD_LIST; 430248291Smarck optstr = "c:dh"; 431204076Spjd } else if (strcmp(argv[1], "status") == 0) { 432204076Spjd cmd = CMD_STATUS; 433204076Spjd optstr = "c:dh"; 434204076Spjd } else if (strcmp(argv[1], "dump") == 0) { 435204076Spjd cmd = CMD_DUMP; 436204076Spjd optstr = "c:dh"; 437204076Spjd } else 438204076Spjd usage(); 439204076Spjd 440204076Spjd argc--; 441204076Spjd argv++; 442204076Spjd 443204076Spjd for (;;) { 444204076Spjd int ch; 445204076Spjd 446204076Spjd ch = getopt(argc, argv, optstr); 447204076Spjd if (ch == -1) 448204076Spjd break; 449204076Spjd switch (ch) { 450204076Spjd case 'c': 451204076Spjd cfgpath = optarg; 452204076Spjd break; 453204076Spjd case 'd': 454204076Spjd debug++; 455204076Spjd break; 456204076Spjd case 'e': 457229945Spjd if (expand_number(optarg, &extentsize) == -1) 458223976Strociny errx(EX_USAGE, "Invalid extentsize"); 459204076Spjd break; 460204076Spjd case 'k': 461229945Spjd if (expand_number(optarg, &keepdirty) == -1) 462223976Strociny errx(EX_USAGE, "Invalid keepdirty"); 463204076Spjd break; 464204076Spjd case 'm': 465229945Spjd if (expand_number(optarg, &mediasize) == -1) 466223976Strociny errx(EX_USAGE, "Invalid mediasize"); 467204076Spjd break; 468204076Spjd case 'h': 469204076Spjd default: 470204076Spjd usage(); 471204076Spjd } 472204076Spjd } 473204076Spjd argc -= optind; 474204076Spjd argv += optind; 475204076Spjd 476204076Spjd switch (cmd) { 477204076Spjd case CMD_CREATE: 478204076Spjd case CMD_ROLE: 479204076Spjd if (argc == 0) 480204076Spjd usage(); 481204076Spjd break; 482204076Spjd } 483204076Spjd 484217965Spjd pjdlog_init(PJDLOG_MODE_STD); 485204076Spjd pjdlog_debug_set(debug); 486204076Spjd 487210909Sdougb cfg = yy_config_parse(cfgpath, true); 488225785Spjd PJDLOG_ASSERT(cfg != NULL); 489204076Spjd 490204076Spjd switch (cmd) { 491204076Spjd case CMD_CREATE: 492204076Spjd control_create(argc, argv, mediasize, extentsize, keepdirty); 493204076Spjd /* NOTREACHED */ 494225785Spjd PJDLOG_ABORT("What are we doing here?!"); 495204076Spjd break; 496204076Spjd case CMD_DUMP: 497204076Spjd /* Dump metadata from local component of the given resource. */ 498204076Spjd control_dump(argc, argv); 499204076Spjd /* NOTREACHED */ 500225785Spjd PJDLOG_ABORT("What are we doing here?!"); 501204076Spjd break; 502204076Spjd case CMD_ROLE: 503204076Spjd /* Change role for the given resources. */ 504204076Spjd if (argc < 2) 505204076Spjd usage(); 506204076Spjd nv = nv_alloc(); 507204076Spjd nv_add_uint8(nv, HASTCTL_CMD_SETROLE, "cmd"); 508204076Spjd if (strcmp(argv[0], "init") == 0) 509204076Spjd nv_add_uint8(nv, HAST_ROLE_INIT, "role"); 510204076Spjd else if (strcmp(argv[0], "primary") == 0) 511204076Spjd nv_add_uint8(nv, HAST_ROLE_PRIMARY, "role"); 512204076Spjd else if (strcmp(argv[0], "secondary") == 0) 513204076Spjd nv_add_uint8(nv, HAST_ROLE_SECONDARY, "role"); 514204076Spjd else 515204076Spjd usage(); 516204076Spjd for (ii = 0; ii < argc - 1; ii++) 517204076Spjd nv_add_string(nv, argv[ii + 1], "resource%d", ii); 518204076Spjd break; 519248291Smarck case CMD_LIST: 520204076Spjd case CMD_STATUS: 521249741Strociny /* Obtain status of the given resources. */ 522204076Spjd nv = nv_alloc(); 523204076Spjd nv_add_uint8(nv, HASTCTL_CMD_STATUS, "cmd"); 524204076Spjd if (argc == 0) 525204076Spjd nv_add_string(nv, "all", "resource%d", 0); 526204076Spjd else { 527204076Spjd for (ii = 0; ii < argc; ii++) 528204076Spjd nv_add_string(nv, argv[ii], "resource%d", ii); 529204076Spjd } 530204076Spjd break; 531204076Spjd default: 532225785Spjd PJDLOG_ABORT("Impossible command!"); 533204076Spjd } 534204076Spjd 535204076Spjd /* Setup control connection... */ 536229945Spjd if (proto_client(NULL, cfg->hc_controladdr, &controlconn) == -1) { 537204076Spjd pjdlog_exit(EX_OSERR, 538204076Spjd "Unable to setup control connection to %s", 539204076Spjd cfg->hc_controladdr); 540204076Spjd } 541204076Spjd /* ...and connect to hastd. */ 542229945Spjd if (proto_connect(controlconn, HAST_TIMEOUT) == -1) { 543204076Spjd pjdlog_exit(EX_OSERR, "Unable to connect to hastd via %s", 544204076Spjd cfg->hc_controladdr); 545204076Spjd } 546218215Spjd 547221899Spjd if (drop_privs(NULL) != 0) 548218215Spjd exit(EX_CONFIG); 549218215Spjd 550204076Spjd /* Send the command to the server... */ 551229945Spjd if (hast_proto_send(NULL, controlconn, nv, NULL, 0) == -1) { 552204076Spjd pjdlog_exit(EX_UNAVAILABLE, 553204076Spjd "Unable to send command to hastd via %s", 554204076Spjd cfg->hc_controladdr); 555204076Spjd } 556204076Spjd nv_free(nv); 557204076Spjd /* ...and receive reply. */ 558229945Spjd if (hast_proto_recv_hdr(controlconn, &nv) == -1) { 559204076Spjd pjdlog_exit(EX_UNAVAILABLE, 560204076Spjd "cannot receive reply from hastd via %s", 561204076Spjd cfg->hc_controladdr); 562204076Spjd } 563204076Spjd 564204076Spjd error = nv_get_int16(nv, "error"); 565204076Spjd if (error != 0) { 566204076Spjd pjdlog_exitx(EX_SOFTWARE, "Error %d received from hastd.", 567204076Spjd error); 568204076Spjd } 569204076Spjd nv_set_error(nv, 0); 570204076Spjd 571204076Spjd switch (cmd) { 572204076Spjd case CMD_ROLE: 573204076Spjd error = control_set_role(nv, argv[0]); 574204076Spjd break; 575248291Smarck case CMD_LIST: 576248291Smarck error = control_list(nv); 577248291Smarck break; 578204076Spjd case CMD_STATUS: 579204076Spjd error = control_status(nv); 580204076Spjd break; 581204076Spjd default: 582225785Spjd PJDLOG_ABORT("Impossible command!"); 583204076Spjd } 584204076Spjd 585204076Spjd exit(error); 586204076Spjd} 587