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.
 
 
 
 
 
 

309 lines
7.0 KiB

  1. /*
  2. * virsh-util.c: helpers for virsh
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library. If not, see
  16. * <http://www.gnu.org/licenses/>.
  17. */
  18. #include <config.h>
  19. #include "virsh-util.h"
  20. #include "virfile.h"
  21. #include "virstring.h"
  22. #include "viralloc.h"
  23. static virDomainPtr
  24. virshLookupDomainInternal(vshControl *ctl,
  25. const char *cmdname,
  26. const char *name,
  27. unsigned int flags)
  28. {
  29. virDomainPtr dom = NULL;
  30. int id;
  31. virCheckFlags(VIRSH_BYID | VIRSH_BYUUID | VIRSH_BYNAME, NULL);
  32. virshControlPtr priv = ctl->privData;
  33. /* try it by ID */
  34. if (flags & VIRSH_BYID) {
  35. if (virStrToLong_i(name, NULL, 10, &id) == 0 && id >= 0) {
  36. vshDebug(ctl, VSH_ERR_DEBUG, "%s: <domain> looks like ID\n",
  37. cmdname);
  38. dom = virDomainLookupByID(priv->conn, id);
  39. }
  40. }
  41. /* try it by UUID */
  42. if (!dom && (flags & VIRSH_BYUUID) &&
  43. strlen(name) == VIR_UUID_STRING_BUFLEN-1) {
  44. vshDebug(ctl, VSH_ERR_DEBUG, "%s: <domain> trying as domain UUID\n",
  45. cmdname);
  46. dom = virDomainLookupByUUIDString(priv->conn, name);
  47. }
  48. /* try it by NAME */
  49. if (!dom && (flags & VIRSH_BYNAME)) {
  50. vshDebug(ctl, VSH_ERR_DEBUG, "%s: <domain> trying as domain NAME\n",
  51. cmdname);
  52. dom = virDomainLookupByName(priv->conn, name);
  53. }
  54. vshResetLibvirtError();
  55. if (!dom)
  56. vshError(ctl, _("failed to get domain '%s'"), name);
  57. return dom;
  58. }
  59. virDomainPtr
  60. virshLookupDomainBy(vshControl *ctl,
  61. const char *name,
  62. unsigned int flags)
  63. {
  64. return virshLookupDomainInternal(ctl, "unknown", name, flags);
  65. }
  66. virDomainPtr
  67. virshCommandOptDomainBy(vshControl *ctl,
  68. const vshCmd *cmd,
  69. const char **name,
  70. unsigned int flags)
  71. {
  72. const char *n = NULL;
  73. const char *optname = "domain";
  74. if (vshCommandOptStringReq(ctl, cmd, optname, &n) < 0)
  75. return NULL;
  76. vshDebug(ctl, VSH_ERR_INFO, "%s: found option <%s>: %s\n",
  77. cmd->def->name, optname, n);
  78. if (name)
  79. *name = n;
  80. return virshLookupDomainInternal(ctl, cmd->def->name, n, flags);
  81. }
  82. virDomainPtr
  83. virshCommandOptDomain(vshControl *ctl,
  84. const vshCmd *cmd,
  85. const char **name)
  86. {
  87. return virshCommandOptDomainBy(ctl, cmd, name,
  88. VIRSH_BYID | VIRSH_BYUUID | VIRSH_BYNAME);
  89. }
  90. int
  91. virshDomainState(vshControl *ctl,
  92. virDomainPtr dom,
  93. int *reason)
  94. {
  95. virDomainInfo info;
  96. virshControlPtr priv = ctl->privData;
  97. if (reason)
  98. *reason = -1;
  99. if (!priv->useGetInfo) {
  100. int state;
  101. if (virDomainGetState(dom, &state, reason, 0) < 0) {
  102. if (virGetLastErrorCode() == VIR_ERR_NO_SUPPORT)
  103. priv->useGetInfo = true;
  104. else
  105. return -1;
  106. } else {
  107. return state;
  108. }
  109. }
  110. /* fall back to virDomainGetInfo if virDomainGetState is not supported */
  111. if (virDomainGetInfo(dom, &info) < 0)
  112. return -1;
  113. else
  114. return info.state;
  115. }
  116. int
  117. virshStreamSink(virStreamPtr st G_GNUC_UNUSED,
  118. const char *bytes,
  119. size_t nbytes,
  120. void *opaque)
  121. {
  122. int *fd = opaque;
  123. return safewrite(*fd, bytes, nbytes);
  124. }
  125. int
  126. virshStreamSource(virStreamPtr st G_GNUC_UNUSED,
  127. char *bytes,
  128. size_t nbytes,
  129. void *opaque)
  130. {
  131. virshStreamCallbackDataPtr cbData = opaque;
  132. int fd = cbData->fd;
  133. return saferead(fd, bytes, nbytes);
  134. }
  135. int
  136. virshStreamSourceSkip(virStreamPtr st G_GNUC_UNUSED,
  137. long long offset,
  138. void *opaque)
  139. {
  140. virshStreamCallbackDataPtr cbData = opaque;
  141. int fd = cbData->fd;
  142. off_t cur;
  143. if ((cur = lseek(fd, offset, SEEK_CUR)) == (off_t) -1)
  144. return -1;
  145. return 0;
  146. }
  147. int
  148. virshStreamSkip(virStreamPtr st G_GNUC_UNUSED,
  149. long long offset,
  150. void *opaque)
  151. {
  152. int *fd = opaque;
  153. off_t cur;
  154. if ((cur = lseek(*fd, offset, SEEK_CUR)) == (off_t) -1)
  155. return -1;
  156. if (ftruncate(*fd, cur) < 0)
  157. return -1;
  158. return 0;
  159. }
  160. int
  161. virshStreamInData(virStreamPtr st G_GNUC_UNUSED,
  162. int *inData,
  163. long long *offset,
  164. void *opaque)
  165. {
  166. virshStreamCallbackDataPtr cbData = opaque;
  167. vshControl *ctl = cbData->ctl;
  168. int fd = cbData->fd;
  169. int ret;
  170. if ((ret = virFileInData(fd, inData, offset)) < 0)
  171. vshError(ctl, "%s", _("Unable to get current position in stream"));
  172. return ret;
  173. }
  174. void
  175. virshDomainFree(virDomainPtr dom)
  176. {
  177. if (!dom)
  178. return;
  179. vshSaveLibvirtHelperError();
  180. virDomainFree(dom); /* sc_prohibit_obj_free_apis_in_virsh */
  181. }
  182. void
  183. virshDomainCheckpointFree(virDomainCheckpointPtr chk)
  184. {
  185. if (!chk)
  186. return;
  187. vshSaveLibvirtHelperError();
  188. virDomainCheckpointFree(chk); /* sc_prohibit_obj_free_apis_in_virsh */
  189. }
  190. void
  191. virshDomainSnapshotFree(virDomainSnapshotPtr snap)
  192. {
  193. if (!snap)
  194. return;
  195. vshSaveLibvirtHelperError();
  196. virDomainSnapshotFree(snap); /* sc_prohibit_obj_free_apis_in_virsh */
  197. }
  198. void
  199. virshSecretFree(virSecretPtr secret)
  200. {
  201. if (!secret)
  202. return;
  203. vshSaveLibvirtHelperError();
  204. virSecretFree(secret); /* sc_prohibit_obj_free_apis_in_virsh */
  205. }
  206. int
  207. virshDomainGetXMLFromDom(vshControl *ctl,
  208. virDomainPtr dom,
  209. unsigned int flags,
  210. xmlDocPtr *xml,
  211. xmlXPathContextPtr *ctxt)
  212. {
  213. char *desc = NULL;
  214. if (!(desc = virDomainGetXMLDesc(dom, flags))) {
  215. vshError(ctl, _("Failed to get domain description xml"));
  216. return -1;
  217. }
  218. *xml = virXMLParseStringCtxt(desc, _("(domain_definition)"), ctxt);
  219. VIR_FREE(desc);
  220. if (!(*xml)) {
  221. vshError(ctl, _("Failed to parse domain description xml"));
  222. return -1;
  223. }
  224. return 0;
  225. }
  226. int
  227. virshDomainGetXML(vshControl *ctl,
  228. const vshCmd *cmd,
  229. unsigned int flags,
  230. xmlDocPtr *xml,
  231. xmlXPathContextPtr *ctxt)
  232. {
  233. virDomainPtr dom;
  234. int ret;
  235. if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
  236. return -1;
  237. ret = virshDomainGetXMLFromDom(ctl, dom, flags, xml, ctxt);
  238. virshDomainFree(dom);
  239. return ret;
  240. }