You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

941 lines
26 KiB

  1. /*
  2. * virsh.c: a shell to exercise the libvirt API
  3. *
  4. * Copyright (C) 2005, 2007-2015 Red Hat, Inc.
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library. If not, see
  18. * <http://www.gnu.org/licenses/>.
  19. */
  20. #include <config.h>
  21. #include "virsh.h"
  22. #include <stdarg.h>
  23. #include <unistd.h>
  24. #include <getopt.h>
  25. #include <sys/time.h>
  26. #include <fcntl.h>
  27. #include <time.h>
  28. #include <sys/stat.h>
  29. #include <inttypes.h>
  30. #if WITH_READLINE
  31. # include <readline/readline.h>
  32. # include <readline/history.h>
  33. #endif
  34. #include "internal.h"
  35. #include "virerror.h"
  36. #include "virbuffer.h"
  37. #include "viralloc.h"
  38. #include "virfile.h"
  39. #include "virthread.h"
  40. #include "vircommand.h"
  41. #include "virtypedparam.h"
  42. #include "virstring.h"
  43. #include "virgettext.h"
  44. #include "virsh-backup.h"
  45. #include "virsh-checkpoint.h"
  46. #include "virsh-console.h"
  47. #include "virsh-domain.h"
  48. #include "virsh-domain-monitor.h"
  49. #include "virsh-host.h"
  50. #include "virsh-interface.h"
  51. #include "virsh-network.h"
  52. #include "virsh-nodedev.h"
  53. #include "virsh-nwfilter.h"
  54. #include "virsh-pool.h"
  55. #include "virsh-secret.h"
  56. #include "virsh-snapshot.h"
  57. #include "virsh-volume.h"
  58. static char *progname;
  59. static const vshCmdGrp cmdGroups[];
  60. static const vshClientHooks hooks;
  61. /*
  62. * Detection of disconnections and automatic reconnection support
  63. */
  64. static int disconnected; /* we may have been disconnected */
  65. /*
  66. * virshCatchDisconnect:
  67. *
  68. * We get here when the connection was closed. We can't do much in the
  69. * handler, just save the fact it was raised.
  70. */
  71. static void
  72. virshCatchDisconnect(virConnectPtr conn,
  73. int reason,
  74. void *opaque)
  75. {
  76. if (reason != VIR_CONNECT_CLOSE_REASON_CLIENT) {
  77. vshControl *ctl = opaque;
  78. const char *str = "unknown reason";
  79. virErrorPtr error;
  80. char *uri;
  81. virErrorPreserveLast(&error);
  82. uri = virConnectGetURI(conn);
  83. switch ((virConnectCloseReason) reason) {
  84. case VIR_CONNECT_CLOSE_REASON_ERROR:
  85. str = N_("Disconnected from %s due to I/O error");
  86. break;
  87. case VIR_CONNECT_CLOSE_REASON_EOF:
  88. str = N_("Disconnected from %s due to end of file");
  89. break;
  90. case VIR_CONNECT_CLOSE_REASON_KEEPALIVE:
  91. str = N_("Disconnected from %s due to keepalive timeout");
  92. break;
  93. /* coverity[dead_error_condition] */
  94. case VIR_CONNECT_CLOSE_REASON_CLIENT:
  95. case VIR_CONNECT_CLOSE_REASON_LAST:
  96. break;
  97. }
  98. vshError(ctl, _(str), NULLSTR(uri));
  99. VIR_FREE(uri);
  100. virErrorRestore(&error);
  101. disconnected++;
  102. vshEventDone(ctl);
  103. }
  104. }
  105. /* Main Function which should be used for connecting.
  106. * This function properly handles keepalive settings. */
  107. virConnectPtr
  108. virshConnect(vshControl *ctl, const char *uri, bool readonly)
  109. {
  110. virConnectPtr c = NULL;
  111. int interval = 5; /* Default */
  112. int count = 6; /* Default */
  113. bool keepalive_forced = false;
  114. virPolkitAgentPtr pkagent = NULL;
  115. int authfail = 0;
  116. bool agentCreated = false;
  117. if (ctl->keepalive_interval >= 0) {
  118. interval = ctl->keepalive_interval;
  119. keepalive_forced = true;
  120. }
  121. if (ctl->keepalive_count >= 0) {
  122. count = ctl->keepalive_count;
  123. keepalive_forced = true;
  124. }
  125. do {
  126. virErrorPtr err;
  127. if ((c = virConnectOpenAuth(uri, virConnectAuthPtrDefault,
  128. readonly ? VIR_CONNECT_RO : 0)))
  129. break;
  130. if (readonly)
  131. goto cleanup;
  132. err = virGetLastError();
  133. if (!agentCreated &&
  134. err && err->domain == VIR_FROM_POLKIT &&
  135. err->code == VIR_ERR_AUTH_UNAVAILABLE) {
  136. if (!pkagent && !(pkagent = virPolkitAgentCreate()))
  137. goto cleanup;
  138. agentCreated = true;
  139. } else if (err && err->domain == VIR_FROM_POLKIT &&
  140. err->code == VIR_ERR_AUTH_FAILED) {
  141. authfail++;
  142. } else {
  143. goto cleanup;
  144. }
  145. virResetLastError();
  146. /* Failure to authenticate 5 times should be enough.
  147. * No sense prolonging the agony.
  148. */
  149. } while (authfail < 5);
  150. if (!c)
  151. goto cleanup;
  152. if (interval > 0 &&
  153. virConnectSetKeepAlive(c, interval, count) != 0) {
  154. if (keepalive_forced) {
  155. vshError(ctl, "%s",
  156. _("Cannot setup keepalive on connection "
  157. "as requested, disconnecting"));
  158. virConnectClose(c);
  159. c = NULL;
  160. goto cleanup;
  161. }
  162. vshDebug(ctl, VSH_ERR_INFO, "%s",
  163. _("Failed to setup keepalive on connection\n"));
  164. }
  165. cleanup:
  166. virPolkitAgentDestroy(pkagent);
  167. return c;
  168. }
  169. /*
  170. * virshReconnect:
  171. *
  172. * Reconnect after a disconnect from libvirtd
  173. *
  174. */
  175. static int
  176. virshReconnect(vshControl *ctl, const char *name, bool readonly, bool force)
  177. {
  178. bool connected = false;
  179. virshControlPtr priv = ctl->privData;
  180. /* If the flag was not specified, then it depends on whether we are
  181. * reconnecting to the current URI (in which case we want to keep the
  182. * readonly flag as it was) or to a specified URI in which case it
  183. * should stay false */
  184. if (!readonly && !name)
  185. readonly = priv->readonly;
  186. if (priv->conn) {
  187. int ret;
  188. connected = true;
  189. virConnectUnregisterCloseCallback(priv->conn, virshCatchDisconnect);
  190. ret = virConnectClose(priv->conn);
  191. if (ret < 0)
  192. vshError(ctl, "%s", _("Failed to disconnect from the hypervisor"));
  193. else if (ret > 0)
  194. vshError(ctl, "%s", _("One or more references were leaked after "
  195. "disconnect from the hypervisor"));
  196. }
  197. priv->conn = virshConnect(ctl, name ? name : ctl->connname, readonly);
  198. if (!priv->conn) {
  199. if (disconnected)
  200. vshError(ctl, "%s", _("Failed to reconnect to the hypervisor"));
  201. else
  202. vshError(ctl, "%s", _("failed to connect to the hypervisor"));
  203. return -1;
  204. } else {
  205. if (name) {
  206. VIR_FREE(ctl->connname);
  207. ctl->connname = g_strdup(name);
  208. }
  209. priv->readonly = readonly;
  210. if (virConnectRegisterCloseCallback(priv->conn, virshCatchDisconnect,
  211. ctl, NULL) < 0)
  212. vshError(ctl, "%s", _("Unable to register disconnect callback"));
  213. if (connected && !force)
  214. vshError(ctl, "%s", _("Reconnected to the hypervisor"));
  215. }
  216. disconnected = 0;
  217. priv->useGetInfo = false;
  218. priv->useSnapshotOld = false;
  219. priv->blockJobNoBytes = false;
  220. return 0;
  221. }
  222. /* ---------------
  223. * Command Connect
  224. * ---------------
  225. */
  226. static const vshCmdOptDef opts_connect[] = {
  227. {.name = "name",
  228. .type = VSH_OT_STRING,
  229. .flags = VSH_OFLAG_EMPTY_OK,
  230. .help = N_("hypervisor connection URI")
  231. },
  232. {.name = "readonly",
  233. .type = VSH_OT_BOOL,
  234. .help = N_("read-only connection")
  235. },
  236. {.name = NULL}
  237. };
  238. static const vshCmdInfo info_connect[] = {
  239. {.name = "help",
  240. .data = N_("(re)connect to hypervisor")
  241. },
  242. {.name = "desc",
  243. .data = N_("Connect to local hypervisor. This is built-in "
  244. "command after shell start up.")
  245. },
  246. {.name = NULL}
  247. };
  248. static bool
  249. cmdConnect(vshControl *ctl, const vshCmd *cmd)
  250. {
  251. bool ro = vshCommandOptBool(cmd, "readonly");
  252. const char *name = NULL;
  253. if (vshCommandOptStringReq(ctl, cmd, "name", &name) < 0)
  254. return false;
  255. if (virshReconnect(ctl, name, ro, true) < 0)
  256. return false;
  257. return true;
  258. }
  259. /* ---------------
  260. * Utils for work with runtime commands data
  261. * ---------------
  262. */
  263. static bool
  264. virshConnectionUsability(vshControl *ctl, virConnectPtr conn)
  265. {
  266. if (!conn ||
  267. virConnectIsAlive(conn) == 0) {
  268. vshError(ctl, "%s", _("no valid connection"));
  269. return false;
  270. }
  271. /* The connection is considered dead only if
  272. * virConnectIsAlive() successfully says so.
  273. */
  274. vshResetLibvirtError();
  275. return true;
  276. }
  277. static void *
  278. virshConnectionHandler(vshControl *ctl)
  279. {
  280. virshControlPtr priv = ctl->privData;
  281. if ((!priv->conn || disconnected) &&
  282. virshReconnect(ctl, NULL, false, false) < 0)
  283. return NULL;
  284. if (virshConnectionUsability(ctl, priv->conn))
  285. return priv->conn;
  286. return NULL;
  287. }
  288. /*
  289. * Initialize connection.
  290. */
  291. static bool
  292. virshInit(vshControl *ctl)
  293. {
  294. virshControlPtr priv = ctl->privData;
  295. /* Since we have the commandline arguments parsed, we need to
  296. * reload our initial settings to make debugging and readline
  297. * work properly */
  298. vshInitReload(ctl);
  299. if (priv->conn)
  300. return false;
  301. /* set up the library error handler */
  302. virSetErrorFunc(NULL, vshErrorHandler);
  303. if (virEventRegisterDefaultImpl() < 0) {
  304. vshReportError(ctl);
  305. return false;
  306. }
  307. if (virThreadCreate(&ctl->eventLoop, true, vshEventLoop, ctl) < 0) {
  308. vshReportError(ctl);
  309. return false;
  310. }
  311. ctl->eventLoopStarted = true;
  312. if ((ctl->eventTimerId = virEventAddTimeout(-1, vshEventTimeout, ctl,
  313. NULL)) < 0) {
  314. vshReportError(ctl);
  315. return false;
  316. }
  317. if (ctl->connname) {
  318. /* Connecting to a named connection must succeed, but we delay
  319. * connecting to the default connection until we need it
  320. * (since the first command might be 'connect' which allows a
  321. * non-default connection, or might be 'help' which needs no
  322. * connection).
  323. */
  324. if (virshReconnect(ctl, NULL, false, false) < 0) {
  325. vshReportError(ctl);
  326. return false;
  327. }
  328. }
  329. return true;
  330. }
  331. static void
  332. virshDeinitTimer(int timer G_GNUC_UNUSED, void *opaque G_GNUC_UNUSED)
  333. {
  334. /* nothing to be done here */
  335. }
  336. /*
  337. * Deinitialize virsh
  338. */
  339. static bool
  340. virshDeinit(vshControl *ctl)
  341. {
  342. virshControlPtr priv = ctl->privData;
  343. vshDeinit(ctl);
  344. VIR_FREE(ctl->connname);
  345. if (priv->conn) {
  346. int ret;
  347. virConnectUnregisterCloseCallback(priv->conn, virshCatchDisconnect);
  348. ret = virConnectClose(priv->conn);
  349. if (ret < 0)
  350. vshError(ctl, "%s", _("Failed to disconnect from the hypervisor"));
  351. else if (ret > 0)
  352. vshError(ctl, "%s", _("One or more references were leaked after "
  353. "disconnect from the hypervisor"));
  354. }
  355. virResetLastError();
  356. if (ctl->eventLoopStarted) {
  357. int timer;
  358. virMutexLock(&ctl->lock);
  359. ctl->quit = true;
  360. /* HACK: Add a dummy timeout to break event loop */
  361. timer = virEventAddTimeout(0, virshDeinitTimer, NULL, NULL);
  362. virMutexUnlock(&ctl->lock);
  363. virThreadJoin(&ctl->eventLoop);
  364. if (timer != -1)
  365. virEventRemoveTimeout(timer);
  366. if (ctl->eventTimerId != -1)
  367. virEventRemoveTimeout(ctl->eventTimerId);
  368. ctl->eventLoopStarted = false;
  369. }
  370. virMutexDestroy(&ctl->lock);
  371. return true;
  372. }
  373. /*
  374. * Print usage
  375. */
  376. static void
  377. virshUsage(void)
  378. {
  379. const vshCmdGrp *grp;
  380. const vshCmdDef *cmd;
  381. fprintf(stdout, _("\n%s [options]... [<command_string>]"
  382. "\n%s [options]... <command> [args...]\n\n"
  383. " options:\n"
  384. " -c | --connect=URI hypervisor connection URI\n"
  385. " -d | --debug=NUM debug level [0-4]\n"
  386. " -e | --escape <char> set escape sequence for console\n"
  387. " -h | --help this help\n"
  388. " -k | --keepalive-interval=NUM\n"
  389. " keepalive interval in seconds, 0 for disable\n"
  390. " -K | --keepalive-count=NUM\n"
  391. " number of possible missed keepalive messages\n"
  392. " -l | --log=FILE output logging to file\n"
  393. " -q | --quiet quiet mode\n"
  394. " -r | --readonly connect readonly\n"
  395. " -t | --timing print timing information\n"
  396. " -v short version\n"
  397. " -V long version\n"
  398. " --version[=TYPE] version, TYPE is short or long (default short)\n"
  399. " commands (non interactive mode):\n\n"), progname,
  400. progname);
  401. for (grp = cmdGroups; grp->name; grp++) {
  402. fprintf(stdout, _(" %s (help keyword '%s')\n"),
  403. grp->name, grp->keyword);
  404. for (cmd = grp->commands; cmd->name; cmd++) {
  405. if (cmd->flags & VSH_CMD_FLAG_ALIAS)
  406. continue;
  407. fprintf(stdout,
  408. " %-30s %s\n", cmd->name,
  409. _(vshCmddefGetInfo(cmd, "help")));
  410. }
  411. fprintf(stdout, "\n");
  412. }
  413. fprintf(stdout, "%s",
  414. _("\n (specify help <group> for details about the commands in the group)\n"));
  415. fprintf(stdout, "%s",
  416. _("\n (specify help <command> for details about the command)\n\n"));
  417. return;
  418. }
  419. /*
  420. * Show version and options compiled in
  421. */
  422. static void
  423. virshShowVersion(vshControl *ctl G_GNUC_UNUSED)
  424. {
  425. /* FIXME - list a copyright blurb, as in GNU programs? */
  426. vshPrint(ctl, _("Virsh command line tool of libvirt %s\n"), VERSION);
  427. vshPrint(ctl, _("See web site at %s\n\n"), "https://libvirt.org/");
  428. vshPrint(ctl, "%s", _("Compiled with support for:\n"));
  429. vshPrint(ctl, "%s", _(" Hypervisors:"));
  430. #ifdef WITH_QEMU
  431. vshPrint(ctl, " QEMU/KVM");
  432. #endif
  433. #ifdef WITH_LXC
  434. vshPrint(ctl, " LXC");
  435. #endif
  436. #ifdef WITH_LIBXL
  437. vshPrint(ctl, " LibXL");
  438. #endif
  439. #ifdef WITH_OPENVZ
  440. vshPrint(ctl, " OpenVZ");
  441. #endif
  442. #ifdef WITH_VZ
  443. vshPrint(ctl, " Virtuozzo");
  444. #endif
  445. #ifdef WITH_VMWARE
  446. vshPrint(ctl, " VMware");
  447. #endif
  448. #ifdef WITH_VBOX
  449. vshPrint(ctl, " VirtualBox");
  450. #endif
  451. #ifdef WITH_ESX
  452. vshPrint(ctl, " ESX");
  453. #endif
  454. #ifdef WITH_HYPERV
  455. vshPrint(ctl, " Hyper-V");
  456. #endif
  457. #ifdef WITH_BHYVE
  458. vshPrint(ctl, " Bhyve");
  459. #endif
  460. #ifdef WITH_TEST
  461. vshPrint(ctl, " Test");
  462. #endif
  463. vshPrint(ctl, "\n");
  464. vshPrint(ctl, "%s", _(" Networking:"));
  465. #ifdef WITH_REMOTE
  466. vshPrint(ctl, " Remote");
  467. #endif
  468. #ifdef WITH_NETWORK
  469. vshPrint(ctl, " Network");
  470. #endif
  471. #ifdef WITH_BRIDGE
  472. vshPrint(ctl, " Bridging");
  473. #endif
  474. #if defined(WITH_INTERFACE)
  475. vshPrint(ctl, " Interface");
  476. # if defined(WITH_NETCF)
  477. vshPrint(ctl, " netcf");
  478. # elif defined(WITH_UDEV)
  479. vshPrint(ctl, " udev");
  480. # endif
  481. #endif
  482. #ifdef WITH_NWFILTER
  483. vshPrint(ctl, " Nwfilter");
  484. #endif
  485. #ifdef WITH_VIRTUALPORT
  486. vshPrint(ctl, " VirtualPort");
  487. #endif
  488. vshPrint(ctl, "\n");
  489. vshPrint(ctl, "%s", _(" Storage:"));
  490. #ifdef WITH_STORAGE_DIR
  491. vshPrint(ctl, " Dir");
  492. #endif
  493. #ifdef WITH_STORAGE_DISK
  494. vshPrint(ctl, " Disk");
  495. #endif
  496. #ifdef WITH_STORAGE_FS
  497. vshPrint(ctl, " Filesystem");
  498. #endif
  499. #ifdef WITH_STORAGE_SCSI
  500. vshPrint(ctl, " SCSI");
  501. #endif
  502. #ifdef WITH_STORAGE_MPATH
  503. vshPrint(ctl, " Multipath");
  504. #endif
  505. #ifdef WITH_STORAGE_ISCSI
  506. vshPrint(ctl, " iSCSI");
  507. #endif
  508. #ifdef WITH_STORAGE_LVM
  509. vshPrint(ctl, " LVM");
  510. #endif
  511. #ifdef WITH_STORAGE_RBD
  512. vshPrint(ctl, " RBD");
  513. #endif
  514. #ifdef WITH_STORAGE_SHEEPDOG
  515. vshPrint(ctl, " Sheepdog");
  516. #endif
  517. #ifdef WITH_STORAGE_GLUSTER
  518. vshPrint(ctl, " Gluster");
  519. #endif
  520. #ifdef WITH_STORAGE_ZFS
  521. vshPrint(ctl, " ZFS");
  522. #endif
  523. #ifdef WITH_STORAGE_VSTORAGE
  524. vshPrint(ctl, "Virtuozzo Storage");
  525. #endif
  526. vshPrint(ctl, "\n");
  527. vshPrint(ctl, "%s", _(" Miscellaneous:"));
  528. #ifdef WITH_LIBVIRTD
  529. vshPrint(ctl, " Daemon");
  530. #endif
  531. #ifdef WITH_NODE_DEVICES
  532. vshPrint(ctl, " Nodedev");
  533. #endif
  534. #ifdef WITH_SECDRIVER_APPARMOR
  535. vshPrint(ctl, " AppArmor");
  536. #endif
  537. #ifdef WITH_SECDRIVER_SELINUX
  538. vshPrint(ctl, " SELinux");
  539. #endif
  540. #ifdef WITH_SECRETS
  541. vshPrint(ctl, " Secrets");
  542. #endif
  543. #ifdef ENABLE_DEBUG
  544. vshPrint(ctl, " Debug");
  545. #endif
  546. #ifdef WITH_DTRACE_PROBES
  547. vshPrint(ctl, " DTrace");
  548. #endif
  549. #if WITH_READLINE
  550. vshPrint(ctl, " Readline");
  551. #endif
  552. vshPrint(ctl, "\n");
  553. }
  554. static bool
  555. virshAllowedEscapeChar(char c)
  556. {
  557. /* Allowed escape characters:
  558. * a-z A-Z @ [ \ ] ^ _
  559. */
  560. return ('a' <= c && c <= 'z') ||
  561. ('@' <= c && c <= '_');
  562. }
  563. /*
  564. * argv[]: virsh [options] [command]
  565. *
  566. */
  567. static bool
  568. virshParseArgv(vshControl *ctl, int argc, char **argv)
  569. {
  570. int arg, len, debug, keepalive;
  571. size_t i;
  572. int longindex = -1;
  573. virshControlPtr priv = ctl->privData;
  574. struct option opt[] = {
  575. {"connect", required_argument, NULL, 'c'},
  576. {"debug", required_argument, NULL, 'd'},
  577. {"escape", required_argument, NULL, 'e'},
  578. {"help", no_argument, NULL, 'h'},
  579. {"keepalive-interval", required_argument, NULL, 'k'},
  580. {"keepalive-count", required_argument, NULL, 'K'},
  581. {"log", required_argument, NULL, 'l'},
  582. {"quiet", no_argument, NULL, 'q'},
  583. {"readonly", no_argument, NULL, 'r'},
  584. {"timing", no_argument, NULL, 't'},
  585. {"version", optional_argument, NULL, 'v'},
  586. {NULL, 0, NULL, 0}
  587. };
  588. /* Standard (non-command) options. The leading + ensures that no
  589. * argument reordering takes place, so that command options are
  590. * not confused with top-level virsh options. */
  591. while ((arg = getopt_long(argc, argv, "+:c:d:e:hk:K:l:qrtvV", opt, &longindex)) != -1) {
  592. switch (arg) {
  593. case 'c':
  594. VIR_FREE(ctl->connname);
  595. ctl->connname = g_strdup(optarg);
  596. break;
  597. case 'd':
  598. if (virStrToLong_i(optarg, NULL, 10, &debug) < 0) {
  599. vshError(ctl, _("option %s takes a numeric argument"),
  600. longindex == -1 ? "-d" : "--debug");
  601. exit(EXIT_FAILURE);
  602. }
  603. if (debug < VSH_ERR_DEBUG || debug > VSH_ERR_ERROR)
  604. vshError(ctl, _("ignoring debug level %d out of range [%d-%d]"),
  605. debug, VSH_ERR_DEBUG, VSH_ERR_ERROR);
  606. else
  607. ctl->debug = debug;
  608. break;
  609. case 'e':
  610. len = strlen(optarg);
  611. if ((len == 2 && *optarg == '^' &&
  612. virshAllowedEscapeChar(optarg[1])) ||
  613. (len == 1 && *optarg != '^')) {
  614. priv->escapeChar = optarg;
  615. } else {
  616. vshError(ctl, _("Invalid string '%s' for escape sequence"),
  617. optarg);
  618. exit(EXIT_FAILURE);
  619. }
  620. break;
  621. case 'h':
  622. virshUsage();
  623. exit(EXIT_SUCCESS);
  624. break;
  625. case 'k':
  626. if (virStrToLong_i(optarg, NULL, 0, &keepalive) < 0) {
  627. vshError(ctl,
  628. _("Invalid value for option %s"),
  629. longindex == -1 ? "-k" : "--keepalive-interval");
  630. exit(EXIT_FAILURE);
  631. }
  632. if (keepalive < 0) {
  633. vshError(ctl,
  634. _("option %s requires a positive integer argument"),
  635. longindex == -1 ? "-k" : "--keepalive-interval");
  636. exit(EXIT_FAILURE);
  637. }
  638. ctl->keepalive_interval = keepalive;
  639. break;
  640. case 'K':
  641. if (virStrToLong_i(optarg, NULL, 0, &keepalive) < 0) {
  642. vshError(ctl,
  643. _("Invalid value for option %s"),
  644. longindex == -1 ? "-K" : "--keepalive-count");
  645. exit(EXIT_FAILURE);
  646. }
  647. if (keepalive < 0) {
  648. vshError(ctl,
  649. _("option %s requires a positive integer argument"),
  650. longindex == -1 ? "-K" : "--keepalive-count");
  651. exit(EXIT_FAILURE);
  652. }
  653. ctl->keepalive_count = keepalive;
  654. break;
  655. case 'l':
  656. vshCloseLogFile(ctl);
  657. ctl->logfile = g_strdup(optarg);
  658. vshOpenLogFile(ctl);
  659. break;
  660. case 'q':
  661. ctl->quiet = true;
  662. break;
  663. case 't':
  664. ctl->timing = true;
  665. break;
  666. case 'r':
  667. priv->readonly = true;
  668. break;
  669. case 'v':
  670. if (STRNEQ_NULLABLE(optarg, "long")) {
  671. puts(VERSION);
  672. exit(EXIT_SUCCESS);
  673. }
  674. G_GNUC_FALLTHROUGH;
  675. case 'V':
  676. virshShowVersion(ctl);
  677. exit(EXIT_SUCCESS);
  678. case ':':
  679. for (i = 0; opt[i].name != NULL; i++) {
  680. if (opt[i].val == optopt)
  681. break;
  682. }
  683. if (opt[i].name)
  684. vshError(ctl, _("option '-%c'/'--%s' requires an argument"),
  685. optopt, opt[i].name);
  686. else
  687. vshError(ctl, _("option '-%c' requires an argument"), optopt);
  688. exit(EXIT_FAILURE);
  689. case '?':
  690. if (optopt)
  691. vshError(ctl, _("unsupported option '-%c'. See --help."), optopt);
  692. else
  693. vshError(ctl, _("unsupported option '%s'. See --help."), argv[optind - 1]);
  694. exit(EXIT_FAILURE);
  695. default:
  696. vshError(ctl, _("unknown option"));
  697. exit(EXIT_FAILURE);
  698. }
  699. longindex = -1;
  700. }
  701. if (argc == optind) {
  702. ctl->imode = true;
  703. } else {
  704. /* parse command */
  705. ctl->imode = false;
  706. if (argc - optind == 1) {
  707. vshDebug(ctl, VSH_ERR_INFO, "commands: \"%s\"\n", argv[optind]);
  708. return vshCommandStringParse(ctl, argv[optind], NULL);
  709. } else {
  710. return vshCommandArgvParse(ctl, argc - optind, argv + optind);
  711. }
  712. }
  713. return true;
  714. }
  715. static const vshCmdDef virshCmds[] = {
  716. VSH_CMD_CD,
  717. VSH_CMD_ECHO,
  718. VSH_CMD_EXIT,
  719. VSH_CMD_HELP,
  720. VSH_CMD_PWD,
  721. VSH_CMD_QUIT,
  722. VSH_CMD_SELF_TEST,
  723. VSH_CMD_COMPLETE,
  724. {.name = "connect",
  725. .handler = cmdConnect,
  726. .opts = opts_connect,
  727. .info = info_connect,
  728. .flags = VSH_CMD_FLAG_NOCONNECT
  729. },
  730. {.name = NULL}
  731. };
  732. static const vshCmdGrp cmdGroups[] = {
  733. {VIRSH_CMD_GRP_DOM_MANAGEMENT, "domain", domManagementCmds},
  734. {VIRSH_CMD_GRP_DOM_MONITORING, "monitor", domMonitoringCmds},
  735. {VIRSH_CMD_GRP_HOST_AND_HV, "host", hostAndHypervisorCmds},
  736. {VIRSH_CMD_GRP_CHECKPOINT, "checkpoint", checkpointCmds},
  737. {VIRSH_CMD_GRP_IFACE, "interface", ifaceCmds},
  738. {VIRSH_CMD_GRP_NWFILTER, "filter", nwfilterCmds},
  739. {VIRSH_CMD_GRP_NETWORK, "network", networkCmds},
  740. {VIRSH_CMD_GRP_NODEDEV, "nodedev", nodedevCmds},
  741. {VIRSH_CMD_GRP_SECRET, "secret", secretCmds},
  742. {VIRSH_CMD_GRP_SNAPSHOT, "snapshot", snapshotCmds},
  743. {VIRSH_CMD_GRP_BACKUP, "backup", backupCmds},
  744. {VIRSH_CMD_GRP_STORAGE_POOL, "pool", storagePoolCmds},
  745. {VIRSH_CMD_GRP_STORAGE_VOL, "volume", storageVolCmds},
  746. {VIRSH_CMD_GRP_VIRSH, "virsh", virshCmds},
  747. {NULL, NULL, NULL}
  748. };
  749. static const vshClientHooks hooks = {
  750. .connHandler = virshConnectionHandler
  751. };
  752. int
  753. main(int argc, char **argv)
  754. {
  755. vshControl _ctl, *ctl = &_ctl;
  756. virshControl virshCtl;
  757. bool ret = true;
  758. memset(ctl, 0, sizeof(vshControl));
  759. memset(&virshCtl, 0, sizeof(virshControl));
  760. ctl->name = "virsh"; /* hardcoded name of the binary */
  761. ctl->env_prefix = "VIRSH";
  762. ctl->log_fd = -1; /* Initialize log file descriptor */
  763. ctl->debug = VSH_DEBUG_DEFAULT;
  764. ctl->hooks = &hooks;
  765. /* In order to distinguish default from setting to 0 */
  766. ctl->keepalive_interval = -1;
  767. ctl->keepalive_count = -1;
  768. ctl->eventPipe[0] = -1;
  769. ctl->eventPipe[1] = -1;
  770. ctl->eventTimerId = -1;
  771. virshCtl.escapeChar = "^]"; /* Same default as telnet */
  772. ctl->privData = &virshCtl;
  773. if (!(progname = strrchr(argv[0], '/')))
  774. progname = argv[0];
  775. else
  776. progname++;
  777. ctl->progname = progname;
  778. if (virGettextInitialize() < 0)
  779. return EXIT_FAILURE;
  780. if (isatty(STDIN_FILENO)) {
  781. ctl->istty = true;
  782. #ifndef WIN32
  783. if (tcgetattr(STDIN_FILENO, &ctl->termattr) < 0)
  784. ctl->istty = false;
  785. #endif
  786. }
  787. if (virMutexInit(&ctl->lock) < 0) {
  788. vshError(ctl, "%s", _("Failed to initialize mutex"));
  789. return EXIT_FAILURE;
  790. }
  791. if (virInitialize() < 0) {
  792. vshError(ctl, "%s", _("Failed to initialize libvirt"));
  793. return EXIT_FAILURE;
  794. }
  795. virFileActivateDirOverrideForProg(argv[0]);
  796. if (!vshInit(ctl, cmdGroups, NULL))
  797. exit(EXIT_FAILURE);
  798. if (!virshParseArgv(ctl, argc, argv) ||
  799. !virshInit(ctl)) {
  800. virshDeinit(ctl);
  801. exit(EXIT_FAILURE);
  802. }
  803. if (!ctl->connname)
  804. ctl->connname = g_strdup(getenv("VIRSH_DEFAULT_CONNECT_URI"));
  805. if (!ctl->imode) {
  806. ret = vshCommandRun(ctl, ctl->cmd);
  807. } else {
  808. /* interactive mode */
  809. if (!ctl->quiet) {
  810. vshPrint(ctl,
  811. _("Welcome to %s, the virtualization interactive terminal.\n\n"),
  812. progname);
  813. vshPrint(ctl, "%s",
  814. _("Type: 'help' for help with commands\n"
  815. " 'quit' to quit\n\n"));
  816. }
  817. do {
  818. const char *prompt = virshCtl.readonly ? VIRSH_PROMPT_RO
  819. : VIRSH_PROMPT_RW;
  820. ctl->cmdstr =
  821. vshReadline(ctl, prompt);
  822. if (ctl->cmdstr == NULL)
  823. break; /* EOF */
  824. if (*ctl->cmdstr) {
  825. #if WITH_READLINE
  826. add_history(ctl->cmdstr);
  827. #endif
  828. if (vshCommandStringParse(ctl, ctl->cmdstr, NULL))
  829. vshCommandRun(ctl, ctl->cmd);
  830. }
  831. VIR_FREE(ctl->cmdstr);
  832. } while (ctl->imode);
  833. if (ctl->cmdstr == NULL)
  834. fputc('\n', stdout); /* line break after alone prompt */
  835. }
  836. virshDeinit(ctl);
  837. exit(ret ? EXIT_SUCCESS : EXIT_FAILURE);
  838. }