2 * virsh-util.c: helpers for virsh
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.
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.
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/>.
21 #include "virsh-util.h"
24 #include "virstring.h"
28 virshLookupDomainInternal(vshControl
*ctl
,
33 virDomainPtr dom
= NULL
;
35 virshControl
*priv
= ctl
->privData
;
37 virCheckFlags(VIRSH_BYID
| VIRSH_BYUUID
| VIRSH_BYNAME
, NULL
);
40 if (flags
& VIRSH_BYID
) {
41 if (virStrToLong_i(name
, NULL
, 10, &id
) == 0 && id
>= 0) {
42 vshDebug(ctl
, VSH_ERR_DEBUG
, "%s: <domain> looks like ID\n",
44 dom
= virDomainLookupByID(priv
->conn
, id
);
49 if (!dom
&& (flags
& VIRSH_BYUUID
) &&
50 strlen(name
) == VIR_UUID_STRING_BUFLEN
-1) {
51 vshDebug(ctl
, VSH_ERR_DEBUG
, "%s: <domain> trying as domain UUID\n",
53 dom
= virDomainLookupByUUIDString(priv
->conn
, name
);
57 if (!dom
&& (flags
& VIRSH_BYNAME
)) {
58 vshDebug(ctl
, VSH_ERR_DEBUG
, "%s: <domain> trying as domain NAME\n",
60 dom
= virDomainLookupByName(priv
->conn
, name
);
63 vshResetLibvirtError();
66 vshError(ctl
, _("failed to get domain '%1$s'"), name
);
73 virshLookupDomainBy(vshControl
*ctl
,
77 return virshLookupDomainInternal(ctl
, "unknown", name
, flags
);
82 virshCommandOptDomainBy(vshControl
*ctl
,
88 const char *optname
= "domain";
90 if (vshCommandOptString(ctl
, cmd
, optname
, &n
) < 0)
93 vshDebug(ctl
, VSH_ERR_INFO
, "%s: found option <%s>: %s\n",
94 cmd
->def
->name
, optname
, n
);
99 return virshLookupDomainInternal(ctl
, cmd
->def
->name
, n
, flags
);
104 virshCommandOptDomain(vshControl
*ctl
,
108 return virshCommandOptDomainBy(ctl
, cmd
, name
,
109 VIRSH_BYID
| VIRSH_BYUUID
| VIRSH_BYNAME
);
114 virshDomainState(vshControl
*ctl
,
119 virshControl
*priv
= ctl
->privData
;
124 if (!priv
->useGetInfo
) {
126 if (virDomainGetState(dom
, &state
, reason
, 0) < 0) {
127 if (virGetLastErrorCode() == VIR_ERR_NO_SUPPORT
)
128 priv
->useGetInfo
= true;
136 /* fall back to virDomainGetInfo if virDomainGetState is not supported */
137 if (virDomainGetInfo(dom
, &info
) < 0)
144 virshStreamSink(virStreamPtr st G_GNUC_UNUSED
,
149 virshStreamCallbackData
*cbData
= opaque
;
151 return safewrite(cbData
->fd
, bytes
, nbytes
);
156 virshStreamSource(virStreamPtr st G_GNUC_UNUSED
,
161 virshStreamCallbackData
*cbData
= opaque
;
164 return saferead(fd
, bytes
, nbytes
);
169 virshStreamSourceSkip(virStreamPtr st G_GNUC_UNUSED
,
173 virshStreamCallbackData
*cbData
= opaque
;
176 if (lseek(fd
, offset
, SEEK_CUR
) == (off_t
) -1)
184 virshStreamSkip(virStreamPtr st G_GNUC_UNUSED
,
188 virshStreamCallbackData
*cbData
= opaque
;
191 if (cbData
->isBlock
) {
192 g_autofree
char * buf
= NULL
;
193 const size_t buflen
= 1 * 1024 * 1024; /* 1MiB */
195 /* While for files it's enough to lseek() and ftruncate() to create
196 * a hole which would emulate zeroes on read(), for block devices
197 * we have to write zeroes to read() zeroes. And we have to write
198 * @got bytes of zeroes. Do that in smaller chunks though.*/
200 buf
= g_new0(char, buflen
);
203 size_t count
= MIN(offset
, buflen
);
206 if ((r
= safewrite(cbData
->fd
, buf
, count
)) < 0)
212 if ((cur
= lseek(cbData
->fd
, offset
, SEEK_CUR
)) == (off_t
) -1)
215 if (ftruncate(cbData
->fd
, cur
) < 0)
224 virshStreamInData(virStreamPtr st G_GNUC_UNUSED
,
229 virshStreamCallbackData
*cbData
= opaque
;
230 vshControl
*ctl
= cbData
->ctl
;
233 if (cbData
->isBlock
) {
234 /* Block devices are always in data section by definition. The
235 * @sectionLen is slightly more tricky. While we could try and get
236 * how much bytes is there left until EOF, we can pretend there is
237 * always X bytes left and let the saferead() below hit EOF (which
238 * is then handled gracefully anyway). Worst case scenario, this
239 * branch is called more than once.
240 * X was chosen to be 1MiB but it has ho special meaning. */
242 *offset
= 1 * 1024 * 1024;
244 if (virFileInData(fd
, inData
, offset
) < 0) {
245 vshError(ctl
, "%s", _("Unable to get current position in stream"));
255 virshDomainFree(virDomainPtr dom
)
260 vshSaveLibvirtHelperError();
261 virDomainFree(dom
); /* sc_prohibit_obj_free_apis_in_virsh */
266 virshDomainCheckpointFree(virDomainCheckpointPtr chk
)
271 vshSaveLibvirtHelperError();
272 virDomainCheckpointFree(chk
); /* sc_prohibit_obj_free_apis_in_virsh */
277 virshDomainSnapshotFree(virDomainSnapshotPtr snap
)
282 vshSaveLibvirtHelperError();
283 virDomainSnapshotFree(snap
); /* sc_prohibit_obj_free_apis_in_virsh */
288 virshInterfaceFree(virInterfacePtr iface
)
293 vshSaveLibvirtHelperError();
294 virInterfaceFree(iface
); /* sc_prohibit_obj_free_apis_in_virsh */
299 virshNetworkFree(virNetworkPtr network
)
304 vshSaveLibvirtHelperError();
305 virNetworkFree(network
); /* sc_prohibit_obj_free_apis_in_virsh */
310 virshNodeDeviceFree(virNodeDevicePtr device
)
315 vshSaveLibvirtHelperError();
316 virNodeDeviceFree(device
); /* sc_prohibit_obj_free_apis_in_virsh */
321 virshNWFilterFree(virNWFilterPtr nwfilter
)
326 vshSaveLibvirtHelperError();
327 virNWFilterFree(nwfilter
); /* sc_prohibit_obj_free_apis_in_virsh */
332 virshSecretFree(virSecretPtr secret
)
337 vshSaveLibvirtHelperError();
338 virSecretFree(secret
); /* sc_prohibit_obj_free_apis_in_virsh */
343 virshStoragePoolFree(virStoragePoolPtr pool
)
348 vshSaveLibvirtHelperError();
349 virStoragePoolFree(pool
); /* sc_prohibit_obj_free_apis_in_virsh */
354 virshStorageVolFree(virStorageVolPtr vol
)
359 vshSaveLibvirtHelperError();
360 virStorageVolFree(vol
); /* sc_prohibit_obj_free_apis_in_virsh */
366 virshStreamFree(virStreamPtr stream
)
371 vshSaveLibvirtHelperError();
372 virStreamFree(stream
); /* sc_prohibit_obj_free_apis_in_virsh */
377 virshDomainGetXMLFromDom(vshControl
*ctl
,
381 xmlXPathContextPtr
*ctxt
)
383 g_autofree
char *desc
= NULL
;
385 if (!(desc
= virDomainGetXMLDesc(dom
, flags
))) {
386 vshError(ctl
, _("Failed to get domain description xml"));
390 *xml
= virXMLParseStringCtxt(desc
, _("(domain_definition)"), ctxt
);
393 vshError(ctl
, _("Failed to parse domain description xml"));
402 virshNetworkGetXMLFromNet(vshControl
*ctl
,
406 xmlXPathContextPtr
*ctxt
)
408 g_autofree
char *desc
= NULL
;
410 if (!(desc
= virNetworkGetXMLDesc(net
, flags
))) {
411 vshError(ctl
, _("Failed to get network description xml"));
415 *xml
= virXMLParseStringCtxt(desc
, _("(network_definition)"), ctxt
);
418 vshError(ctl
, _("Failed to parse network description xml"));
427 virshDomainGetXML(vshControl
*ctl
,
431 xmlXPathContextPtr
*ctxt
)
436 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
439 ret
= virshDomainGetXMLFromDom(ctl
, dom
, flags
, xml
, ctxt
);
441 virshDomainFree(dom
);
447 VIR_ENUM_IMPL(virshDomainBlockJob
,
448 VIR_DOMAIN_BLOCK_JOB_TYPE_LAST
,
453 N_("Active Block Commit"),
459 virshDomainBlockJobToString(int type
)
461 const char *str
= virshDomainBlockJobTypeToString(type
);
462 return str
? _(str
) : _("Unknown job");
466 virshDumpXML(vshControl
*ctl
,
472 g_autoptr(xmlDoc
) doc
= NULL
;
473 g_autoptr(xmlXPathContext
) ctxt
= NULL
;
474 g_autofree xmlNodePtr
*nodes
= NULL
;
479 vshPrint(ctl
, "%s", xml
);
483 doc
= virXMLParseStringCtxtWithIndent(xml
, url
, &ctxt
);
487 if ((nnodes
= virXPathNodeSet(xpath
, ctxt
, &nodes
)) < 0) {
492 g_autoptr(xmlDoc
) newdoc
= xmlNewDoc((xmlChar
*)"1.0");
493 xmlNodePtr newroot
= xmlNewNode(NULL
, (xmlChar
*)"nodes");
494 g_autofree
char *xmlbit
= NULL
;
496 xmlDocSetRootElement(newdoc
, newroot
);
498 for (i
= 0; i
< nnodes
; i
++) {
499 g_autoptr(xmlNode
) copy
= xmlDocCopyNode(nodes
[i
], newdoc
, 1);
500 if (!xmlAddChild(newroot
, copy
))
506 xmlbit
= virXMLNodeToString(doc
, newroot
);
507 vshPrint(ctl
, "%s\n", xmlbit
);
509 for (i
= 0; i
< nnodes
; i
++) {
510 g_autofree
char *xmlbit
= virXMLNodeToString(doc
, nodes
[i
]);
511 vshPrint(ctl
, "%s\n", xmlbit
);