1 // stapvirt - systemtap libvirt helper
2 // Copyright (C) 2013 Red Hat Inc.
4 // This file is part of systemtap, and is free software. You can
5 // redistribute it and/or modify it under the terms of the GNU General
6 // Public License (GPL); either version 2, or (at your option) any
21 #include <libvirt/libvirt.h>
22 #include <libvirt/virterror.h>
24 #include <libxml/parser.h>
25 #include <libxml/xpath.h>
26 #include <libxml/xpathInternals.h>
30 #define eprintf(format, args...) do { \
31 fprintf (stderr, format, ## args); } while (0)
33 #define dbug(verb, format, args...) do { \
34 if (verb > verbose) break; \
35 eprintf("stapvirt:%s:%d " format, \
36 __FUNCTION__, __LINE__, ## args); } while (0)
38 #define err(format, args...) do { \
39 dbug(2, "ERROR: " format, ## args); \
40 eprintf("stapvirt: ERROR: " format, ## args); } while (0)
42 /* Converts a virDomainState into a human-friendly string */
44 domainStateStr(virDomainState state
)
47 case VIR_DOMAIN_NOSTATE
:
49 case VIR_DOMAIN_RUNNING
:
51 case VIR_DOMAIN_BLOCKED
:
53 case VIR_DOMAIN_PAUSED
:
55 case VIR_DOMAIN_SHUTDOWN
:
56 return "shutting down";
57 case VIR_DOMAIN_SHUTOFF
:
59 case VIR_DOMAIN_CRASHED
:
61 case VIR_DOMAIN_PMSUSPENDED
:
67 return "unknown state";
70 /* Used to silence libvirt error messages when necessary */
72 silentErr(void __attribute__((__unused__
)) *userdata
, virErrorPtr err
)
74 dbug(2, "libvirt: code %d: domain %d: %s\n", err
->code
, err
->domain
,
80 /* Tries to find a domain by name, ID, or UUID on the given node */
82 findDomain(virConnectPtr conn
, const char *domStr
)
84 virDomainPtr dom
= NULL
;
86 // Override the default libvirt error handler so we silently fail lookups
87 virSetErrorFunc(NULL
, silentErr
);
90 const char *end
= domStr
+ strlen(domStr
);
91 char *stopchar
= NULL
;
93 int id
= strtoul(domStr
, &stopchar
, 0);
94 if (errno
== 0 && stopchar
== end
)
95 dom
= virDomainLookupByID(conn
, id
);
99 dom
= virDomainLookupByName(conn
, domStr
);
103 dom
= virDomainLookupByUUIDString(conn
, domStr
);
105 virSetErrorFunc(NULL
, NULL
);
109 /* Retrieves the list of active domains using the old API. Returns the number
110 * of domains collected in the ids array, or -1 on error. The array must be
111 * freed if any domains are found. */
113 getActiveDomains(virConnectPtr conn
, int **ids
)
118 idsn
= virConnectNumOfDomains(conn
);
122 *ids
= (int*) calloc(sizeof(int), idsn
);
126 idsn
= virConnectListDomains(conn
, *ids
, idsn
);
135 /* Retrieves the list of inactive domains using the old API. Returns the number
136 * of domains collected in the names array, or -1 on error. The array must be
137 * freed if any domains are found. */
139 getInactiveDomains(virConnectPtr conn
, char ***names
)
144 namesn
= virConnectNumOfDefinedDomains(conn
);
148 *names
= (char**) calloc(sizeof(char*), namesn
);
152 namesn
= virConnectListDefinedDomains(conn
, *names
, namesn
);
161 /* Retrieves the list of all domains using the old API. Returns the number of
162 * domains collected in the domains array, or -1 on error. The array must be
163 * freed if any domains are found. */
165 getAllDomains(virConnectPtr conn
, virDomainPtr
**domains
)
169 int idsn
, namesn
, domainsn
;
170 idsn
= namesn
= domainsn
= 0;
173 // We need to use the older functions
174 idsn
= getActiveDomains(conn
, &ids
);
176 err("Couldn't retrieve list of active domains\n");
179 namesn
= getInactiveDomains(conn
, &names
);
181 err("Couldn't retrieve list of inactive domains\n");
186 // Make sure we got something to print
187 if (idsn
+ namesn
== 0)
190 // Time to prepare virDomainPtr array
191 *domains
= (virDomainPtr
*) calloc(sizeof(virDomainPtr
), idsn
+namesn
);
192 if (*domains
== NULL
) {
193 err("Can't allocate domains array\n");
198 for (i
= 0; i
< idsn
; i
++) {
199 virDomainPtr dom
= virDomainLookupByID(conn
, ids
[i
]);
202 (*domains
)[domainsn
++] = dom
;
204 for (i
= 0; i
< namesn
; i
++) {
205 virDomainPtr dom
= virDomainLookupByName(conn
, names
[i
]);
208 (*domains
)[domainsn
++] = dom
;
218 /* Returns nonzero if the libvirtd version is greater than target. Be careful
219 * when using this function due to the double meaning of 0. */
221 libvirtdCheckVers(virConnectPtr conn
, unsigned long targetVer
)
223 unsigned long version
;
224 if (virConnectGetLibVersion(conn
, &version
) != 0) {
225 err("Couldn't retrieve libvirtd version\n");
228 return (version
>= targetVer
);
231 /* Returns nonzero if libvirtd supports virDomainOpenChannel(). Be careful when
232 * using this function due to the double meaning of 0. */
234 libvirtdCanOpenChannel(virConnectPtr conn
)
236 // version = major * 1000000 + minor * 1000 + release
238 return libvirtdCheckVers(conn
, 1*1000000+0*1000+2);
241 /* Returns nonzero if libvirtd supports virConnectListAllDomains(). Be careful
242 * when using this function due to the double meaning of 0. */
244 libvirtdCanListAll(virConnectPtr conn
)
246 // version = major * 1000000 + minor * 1000 + release
248 return libvirtdCheckVers(conn
, 0*1000000+9*1000+13);
251 /* Returns nonzero if libvirtd supports hotplugging. Be careful when using this
252 * function due to the double meaning of 0. */
254 libvirtdCanHotplug(virConnectPtr conn
)
256 // version = major * 1000000 + minor * 1000 + release
258 return libvirtdCheckVers(conn
, 1*1000000+1*1000+1);
261 /* Returns nonzero if libvirt supports hotplugging. Be careful when using this
262 * function due to the double meaning of 0. */
264 libvirtCanHotplug(void)
266 unsigned long version
;
267 if (virGetVersion(&version
, NULL
, NULL
) != 0) {
268 err("Couldn't retrieve libvirt version\n");
272 // version = major * 1000000 + minor * 1000 + release
274 return (version
>= (1*1000000+1*1000+1));
277 /* Returns nonzero if qemu supports hotplugging. Be careful when using this
278 * function due to the double meaning of 0. */
280 qemuCanHotplug(virConnectPtr conn
)
282 const char *hv
= virConnectGetType(conn
);
284 err("Couldn't retrieve hypervisor type\n");
288 if (strcmp(hv
, "QEMU") != 0)
291 unsigned long version
;
292 if (virConnectGetVersion(conn
, &version
) != 0) {
293 err("Couldn't retrieve hypervisor version\n");
297 // version = major * 1000000 + minor * 1000 + release
299 return (version
>= (10*1000));
302 /* Returns nonzero if hotplugging is supported. Be careful when using this
303 * function due to the double meaning of 0. */
305 canHotplug(virConnectPtr conn
)
307 // We need to check if both the local library as well as the remote daemon
308 // supports the holplugging API for virtio-serial
309 return libvirtCanHotplug()
310 && libvirtdCanHotplug(conn
)
311 && qemuCanHotplug(conn
);
314 /* Retrieves and parses the domain's XML. Returns NULL on error or an xmlDocPtr
315 * of the domain on success. Note that the xmlDocPtr returned must be freed by
318 getDomainXML(virDomainPtr dom
, int liveConfig
)
320 virDomainXMLFlags flags
= 0;
322 flags
|= VIR_DOMAIN_XML_INACTIVE
;
324 char *domXML
= virDomainGetXMLDesc(dom
, flags
);
325 if (domXML
== NULL
) {
326 err("Couldn't retrieve the domain's XML\n");
330 xmlDocPtr domXMLDoc
= xmlParseDoc(BAD_CAST domXML
);
331 if (domXMLDoc
== NULL
)
332 err("Couldn't parse the domain's XML\n");
338 /* Retrieves info from the port node. Used to retrieve either the path
339 * attribute or the name attribute by getXmlPortPath() and getXmlPortName().
340 * The advantage of this method over xmlGetProp() is that we don't have to
341 * worry about de-allocating memory after. */
342 static const xmlChar
*
343 getXmlPortInfo(xmlNodePtr port
, const xmlChar
* type
, const xmlChar
* attr
)
346 xmlNodePtr child
= port
->children
;
347 while (child
!= NULL
&& !xmlStrEqual(child
->name
, type
))
351 err("Couldn't find target type\n");
356 xmlAttrPtr prop
= child
->properties
;
357 while (prop
!= NULL
&& !xmlStrEqual(prop
->name
, attr
))
360 if (prop
== NULL
|| prop
->children
== NULL
) {
361 err("Couldn't find target attr\n");
365 return prop
->children
->content
;
369 getXmlPortPath(xmlNodePtr port
)
371 return (const char *)
372 getXmlPortInfo(port
, BAD_CAST
"source", BAD_CAST
"path");
376 getXmlPortName(xmlNodePtr port
)
378 return (const char *)
379 getXmlPortInfo(port
, BAD_CAST
"target", BAD_CAST
"name");
382 /* Returns nonzero if port is a valid SystemTap port */
384 isValidPort(xmlNodePtr port
, const char *basename
)
386 const char *name
= getXmlPortName(port
);
390 // Check if it starts with basename
391 if (strstr(name
, basename
) != name
)
394 // Check that the dot after basename is the last dot
395 const char *lastdot
= strrchr(name
, '.');
396 if (lastdot
== NULL
|| (size_t)(lastdot
-name
) != strlen(basename
))
399 // Check that there is something between the dot and the end
400 const char *end
= name
+ strlen(name
);
401 if (lastdot
>= end
-1)
404 // Check that the stuff between dot and end is a valid positive number
406 char *stopchar
= NULL
;
407 long num
= strtol(lastdot
+1, &stopchar
, 10);
408 if (errno
|| stopchar
!= end
|| num
< 0)
414 /* Retrieves the list of SystemTap ports from a domain's XML doc. Note that the
415 * xmlNodeSetPtr must be freed with xmlXPathFreeNodeSet() */
417 getXmlPorts(xmlDocPtr domXMLDoc
, const char *basename
)
419 xmlXPathContextPtr ctxt
= xmlXPathNewContext(domXMLDoc
);
420 xmlXPathObjectPtr res
= NULL
;
421 xmlNodeSetPtr ports
= NULL
;
423 /* xpath expression is based on libguestfs code in src/libvirt-domain.c */
425 // Unfortunately, the XPath of libxml2 does not support the matches()
426 // function, which would allow us to use a regex to match the port name
427 // precisely. Instead as a first approximation, we only require that the
428 // port start with the basename. We then use isValidPort() to check for the
431 int rc
= asprintf(&xpath
, "//devices/channel[@type=\"unix\" and "
432 "./source/@mode=\"bind\" and "
433 "./source/@path and "
434 "./target/@type=\"virtio\" and "
435 "./target/@name[starts-with(.,\"%s\")]]", basename
);
437 err("Couldn't call asprintf for xpath\n");
441 res
= xmlXPathEvalExpression(BAD_CAST xpath
, ctxt
);
445 err("Couldn't parse SystemTap ports\n");
449 // We wait until now to initialize the return NodeSet since we know now that
450 // the XPath eval went well
451 ports
= xmlXPathNodeSetCreate(NULL
);
453 // Go through each port and add only the valid ones to the NodeSet
455 for (i
= 0; i
< res
->nodesetval
->nodeNr
; i
++) {
456 xmlNodePtr port
= res
->nodesetval
->nodeTab
[i
];
457 if (isValidPort(port
, basename
))
458 xmlXPathNodeSetAdd(ports
, port
);
461 xmlXPathFreeObject(res
);
463 xmlXPathFreeContext(ctxt
);
467 /* Retrieves the number of the port node. No error-checking is done since these
468 * ports are assumed to have gone through isValidPort() */
470 getXmlPortNumber(xmlNodePtr port
)
472 const char *name
= getXmlPortName(port
);
473 char *lastdot
= strrchr(name
, '.');
474 return strtol(lastdot
+1, NULL
, 10);
477 /* Shortcut to call getDomainXML and then getXmlPorts. Sets domXMLdoc and ports.
478 * Returns zero on success and nonzero on error (in which case, no de-allocation
479 * needs to be done by the caller). */
481 getDomainPorts(virDomainPtr dom
, int liveConfig
, const char *basename
,
482 xmlDocPtr
*domXMLdoc
, xmlNodeSetPtr
*ports
)
484 // We explicitly set domXMLdoc and ports to NULL in case of error so that
485 // callers don't try to free them even if we failed
487 *domXMLdoc
= getDomainXML(dom
, liveConfig
);
488 if (*domXMLdoc
== NULL
) {
489 err("Couldn't get domain's XML\n");
494 *ports
= getXmlPorts(*domXMLdoc
, basename
);
495 if (*ports
== NULL
) {
496 err("Couldn't search for SystemTap ports\n");
497 xmlFreeDoc(*domXMLdoc
);
505 /* Sets maxPort to the port in the NodeSet with the highest port number. Returns
506 * zero on success, nonzero on error. */
508 findPortWithMaxNum(xmlNodeSetPtr ports
, xmlNodePtr
*maxPort
)
510 // Go through each port and remember the highest port number
511 // (libxml guarantees no particular order)
514 for (i
= 0; i
< ports
->nodeNr
; i
++) {
515 xmlNodePtr port
= ports
->nodeTab
[i
];
516 int num
= getXmlPortNumber(port
);
518 return -1; // proper error msg already emitted
525 // maxPort is either NULL (no ports in NodeSet) or has the port with max num
529 /* Creates an XML node for a SystemTap port with the given UNIX socket path and
532 createXmlPort(const char* path
, const char* name
)
534 // No need for error-checking here, these functions cannot fail
535 xmlNodePtr channel
, node
;
537 channel
= xmlNewNode(NULL
, BAD_CAST
"channel");
538 xmlNewProp(channel
, BAD_CAST
"type", BAD_CAST
"unix");
539 node
= xmlNewChild(channel
, NULL
, BAD_CAST
"source", NULL
);
540 xmlNewProp(node
, BAD_CAST
"mode", BAD_CAST
"bind");
541 xmlNewProp(node
, BAD_CAST
"path", BAD_CAST path
);
542 node
= xmlNewChild(channel
, NULL
, BAD_CAST
"target", NULL
);
543 xmlNewProp(node
, BAD_CAST
"type", BAD_CAST
"virtio");
544 xmlNewProp(node
, BAD_CAST
"name", BAD_CAST name
);
549 /* Looks at the list of ports and creates a new port with port number one higher
550 * than the maximum of the existing port numbers. Returns zero on success,
551 * nonzero on failure. */
553 generateNextPort(xmlNodeSetPtr ports
, virDomainPtr dom
, const char *sockDir
,
554 const char *basename
, xmlNodePtr
*newPort
)
558 if (findPortWithMaxNum(ports
, &maxPort
) != 0)
559 return -1; // proper error msg already emitted
561 // maxPort == NULL means this will be the first port
562 int next
= (maxPort
== NULL
) ? 0 : (getXmlPortNumber(maxPort
)+1);
564 const char *domName
= virDomainGetName(dom
);
565 if (domName
== NULL
) {
566 err("Couldn't retrieve domain name\n");
571 if (asprintf(&path
, "%s/%s.%s.%d.sock",
572 sockDir
, domName
, basename
, next
) == -1) {
573 err("Couldn't call asprintf for path\n");
578 if (asprintf(&name
, "%s.%d", basename
, next
) == -1) {
579 err("Couldn't call asprintf for name\n");
584 *newPort
= createXmlPort(path
, name
);
592 /* Adds an XML node representing a SystemTap port to the <devices> list. Returns
593 * zero on success, nonzero on failure. */
595 addXmlPort(xmlDocPtr domXMLDoc
, xmlNodePtr port
)
600 xmlXPathContextPtr ctxt
= xmlXPathNewContext(domXMLDoc
);
601 xmlXPathObjectPtr devres
=
602 xmlXPathEvalExpression(BAD_CAST
"//devices", ctxt
);
603 if (devres
== NULL
) {
604 err("Couldn't search for <devices> node\n");
609 if (xmlXPathNodeSetIsEmpty(devres
->nodesetval
)) {
610 err("No <devices> node found in domain XML\n");
615 xmlNodePtr devices
= devres
->nodesetval
->nodeTab
[0];
616 if (xmlAddChild(devices
, port
) == NULL
) {
617 err("Could not add port in XML\n");
623 xmlXPathFreeObject(devres
);
625 xmlXPathFreeContext(ctxt
);
629 /* Redefines the domain defined by domXMLdoc at the hypervisor connected to
630 * conn. Returns zero on success and nonzero on failure. */
632 redefineDomain(virConnectPtr conn
, xmlDocPtr domXMLdoc
)
635 xmlDocDumpMemoryEnc(domXMLdoc
, &buf
, NULL
, "UTF-8");
637 virDomainPtr rcDom
= virDomainDefineXML(conn
, (const char*) buf
);
641 err("Couldn't redefine the domain\n");
644 virDomainFree(rcDom
);
649 /* Attaches or detaches a port to a live domain. Returns zero on success and
650 * nonzero on failure. */
652 hotplugPort(int attach
, virDomainPtr dom
,
653 xmlDocPtr domXMLdoc
, xmlNodePtr port
)
656 xmlBufferPtr buf
= xmlBufferCreate();
658 if (xmlNodeDump(buf
, domXMLdoc
, port
, 0, 0) == -1) {
659 err("Couldn't dump new port XML\n");
664 int rc
= attach
? virDomainAttachDevice(dom
, (const char *) buf
->content
)
665 : virDomainDetachDevice(dom
, (const char *) buf
->content
);
667 err("Couldn't %s the device\n", attach
? "attach" : "detach");
677 /* Tries to open one of the ports in the set on the target domain. Returns NULL
678 * if an error occurred. Note that the virStreamPtr object must be freed with
679 * virStreamFree(). */
681 domainOpenChannel(virConnectPtr conn
, virDomainPtr dom
, xmlNodeSetPtr ports
)
683 virStreamPtr stream
= virStreamNew(conn
, VIR_STREAM_NONBLOCK
);
684 if (stream
== NULL
) {
685 err("Couldn't create a new stream object\n");
689 // Override libvirt default err handler so that we suppress error msgs when
690 // we try to connect to busy channels
691 virSetErrorFunc(NULL
, silentErr
);
694 for (i
= 0; i
< ports
->nodeNr
; i
++) {
695 xmlNodePtr port
= ports
->nodeTab
[i
];
696 const char *name
= getXmlPortName(port
);
699 if (virDomainOpenChannel(dom
, name
, stream
, 0) == 0)
701 dbug(1, "channel %s is already in use\n", name
);
704 // Restore error handler to the default
705 virSetErrorFunc(NULL
, NULL
);
707 if (i
== ports
->nodeNr
) {
708 virStreamFree(stream
);
716 printName(virDomainPtr dom
)
718 const char *name
= virDomainGetName(dom
);
719 printf("%s", name
!= NULL
? name
: "<undefined>");
723 printUUID(virDomainPtr dom
)
725 char uuid
[VIR_UUID_STRING_BUFLEN
];
726 if (virDomainGetUUIDString(dom
, (char *) &uuid
) != 0)
727 strncpy(uuid
, "INVALID_UUID", VIR_UUID_STRING_BUFLEN
);
732 printState(virDomainPtr dom
)
735 if (virDomainGetState(dom
, &state
, NULL
, 0) != 0)
736 state
= VIR_DOMAIN_NOSTATE
;
737 printf("%s", domainStateStr(state
));
741 printID(virDomainPtr dom
)
743 if (virDomainIsActive(dom
) == 1)
744 printf("%u", virDomainGetID(dom
));
750 printType(virDomainPtr dom
)
752 int pers
= virDomainIsPersistent(dom
);
754 printf("<undefined>");
756 printf(pers
? "persistent" : "transient");
760 printHotplug(virConnectPtr conn
)
762 if (!canHotplug(conn
))
768 printPortNum(virDomainPtr dom
, const char *basename
)
770 xmlDocPtr domXMLdoc
= NULL
;
771 xmlNodeSetPtr ports
= NULL
;
773 if (getDomainPorts(dom
, 0, basename
, &domXMLdoc
, &ports
) != 0)
774 return; // proper error msg already emitted
776 printf("%u", (unsigned)ports
->nodeNr
);
777 xmlXPathFreeNodeSet(ports
);
778 xmlFreeDoc(domXMLdoc
);
781 /**************************************
782 *********** USER COMMANDS ************
783 **************************************
786 #define PORT_BASENAME "org.systemtap.stapsh"
788 static int cmd_list (void);
789 static int cmd_port_add (void);
790 static int cmd_port_remove (void);
791 static int cmd_query (void);
792 static int cmd_port_list (void);
793 static int cmd_connect (void);
802 const command commands
[] = {
803 { "list", 0, 1, cmd_list
},
804 { "port-add", 1, 0, cmd_port_add
},
805 { "port-remove", 1, 0, cmd_port_remove
},
806 { "query", 1, 1, cmd_query
},
807 { "port-list", 1, 1, cmd_port_list
},
808 { "connect", 1, 0, cmd_connect
},
810 const unsigned ncommands
= sizeof(commands
) / sizeof(*commands
);
812 char *sockDir
= "/var/lib/libvirt/qemu";
814 virConnectPtr conn
= NULL
;
816 char *targetDomStr
= NULL
;
817 virDomainPtr targetDom
= NULL
;
823 virDomainPtr
*domains
= NULL
;
825 printf("Available domains on URI '%s':\n", virConnectGetURI(conn
));
826 printf("ID\tState\tType\tName\n");
828 // virConnectListAllDomains is more safe, but was introduced in 0.9.13
829 domainsn
= libvirtdCanListAll(conn
)
830 ? virConnectListAllDomains(conn
, &domains
, 0)
831 : getAllDomains(conn
, &domains
);
833 err("Couldn't retrieve list of domains\n");
838 for (i
= 0; i
< domainsn
; i
++) {
839 printID(domains
[i
]); printf("\t");
840 printState(domains
[i
]); printf("\t");
841 printType(domains
[i
]); printf("\t");
842 printName(domains
[i
]); printf("\n");
843 virDomainFree(domains
[i
]);
853 // start with newlines because the virPrint* funcs don't put them
854 printf("\n Name: "); printName(targetDom
);
855 printf("\n UUID: "); printUUID(targetDom
);
856 printf("\n State: "); printState(targetDom
);
857 printf("\n ID: "); printID(targetDom
);
858 printf("\n Type: "); printType(targetDom
);
859 printf("\n Permanent Ports: "); printPortNum(targetDom
,PORT_BASENAME
);
860 printf("\n Hotplugging: "); printHotplug(conn
);
870 xmlDocPtr domXMLdoc
= NULL
;
871 xmlNodeSetPtr ports
= NULL
;
872 xmlNodePtr newPort
= NULL
;
874 if (getDomainPorts(targetDom
, 0, PORT_BASENAME
, &domXMLdoc
, &ports
) != 0)
875 return -1; // proper error msg already emitted
876 if (generateNextPort(ports
, targetDom
, sockDir
,
877 PORT_BASENAME
, &newPort
) != 0)
878 goto error
; // proper error msg already emitted
879 if (addXmlPort(domXMLdoc
, newPort
) != 0)
880 goto error
; // proper error msg already emitted
881 if (redefineDomain(conn
, domXMLdoc
) != 0)
882 goto error
; // proper error msg already emitted
884 printf("Added new port %s\n", getXmlPortName(newPort
));
885 if (virDomainIsActive(targetDom
) == 1) // helpful hint for user
886 printf("The domain must be powered off before changes take effect.\n");
892 xmlXPathFreeNodeSet(ports
);
893 xmlFreeDoc(domXMLdoc
);
901 xmlDocPtr domXMLdoc
= NULL
;
902 xmlNodeSetPtr ports
= NULL
;
903 xmlNodePtr maxPort
= NULL
;
905 if (getDomainPorts(targetDom
, 0, PORT_BASENAME
, &domXMLdoc
, &ports
) != 0)
906 return -1; // proper error msg already emitted
907 if (findPortWithMaxNum(ports
, &maxPort
) != 0)
908 goto error
; // proper error msg already emitted
910 if (maxPort
== NULL
) {
911 err("No SystemTap port to remove\n");
915 xmlUnlinkNode(maxPort
);
916 if (redefineDomain(conn
, domXMLdoc
) != 0)
917 goto error
; // proper error msg already emitted
919 printf("Removed port %s\n", getXmlPortName(maxPort
));
920 if (virDomainIsActive(targetDom
) == 1) // helpful hint for user
921 printf("The domain must be powered off before changes take effect.\n");
927 xmlXPathFreeNodeSet(ports
);
928 xmlFreeDoc(domXMLdoc
);
935 xmlDocPtr domXMLdoc
= NULL
;
936 xmlNodeSetPtr ports
= NULL
;
938 if (getDomainPorts(targetDom
, 0, PORT_BASENAME
, &domXMLdoc
, &ports
) != 0)
939 return -1; // proper error msg already emitted
942 for (i
= 0; i
< ports
->nodeNr
; i
++) {
943 xmlNodePtr port
= ports
->nodeTab
[i
];
944 printf("%s\n", getXmlPortPath(port
));
947 xmlXPathFreeNodeSet(ports
);
948 xmlFreeDoc(domXMLdoc
);
952 // The structure of the code for cmd_connect and the event callbacks is largely
953 // based on the "virsh console" command
961 char termbuf
[1024]; /* term to st */
963 char stbuf
[1024]; /* st to term */
968 stdin_event(__attribute__((unused
)) int watch
, int fd
,
969 int events
, void *opaque
)
971 event_context
*ctxt
= opaque
;
973 if ((events
& VIR_EVENT_HANDLE_READABLE
)
974 && (ctxt
->termbuf_off
< sizeof(ctxt
->termbuf
))) {
975 // if there's no space in the buffer, we need to wait until more has
976 // been written to the stream
978 int bytes_read
= read(fd
, ctxt
->termbuf
+ ctxt
->termbuf_off
,
979 sizeof(ctxt
->termbuf
) - ctxt
->termbuf_off
);
980 if (bytes_read
< 0) {
985 if (bytes_read
== 0) {
987 virStreamFinish(ctxt
->st
);
991 ctxt
->termbuf_off
+= bytes_read
;
994 if (ctxt
->termbuf_off
) { // we have stuff to write to the stream
995 virStreamEventUpdateCallback(ctxt
->st
, VIR_STREAM_EVENT_READABLE
996 | VIR_STREAM_EVENT_WRITABLE
);
999 if (events
& (VIR_EVENT_HANDLE_ERROR
|VIR_EVENT_HANDLE_HANGUP
))
1004 stdout_event(__attribute__((unused
)) int watch
, int fd
,
1005 int events
, void *opaque
)
1007 event_context
*ctxt
= opaque
;
1009 if (events
& VIR_EVENT_HANDLE_WRITABLE
&& ctxt
->stbuf_off
) {
1010 ssize_t bytes_written
= write(fd
, ctxt
->stbuf
, ctxt
->stbuf_off
);
1011 if (bytes_written
< 0) {
1012 if (errno
!= EAGAIN
)
1017 memmove(ctxt
->stbuf
, ctxt
->stbuf
+ bytes_written
,
1018 ctxt
->stbuf_off
- bytes_written
);
1019 ctxt
->stbuf_off
-= bytes_written
;
1022 if (ctxt
->stbuf_off
== 0) // there's nothing else to write to stdout
1023 virEventUpdateHandle(ctxt
->stdout_w
, 0);
1025 if (events
& (VIR_EVENT_HANDLE_ERROR
|VIR_EVENT_HANDLE_HANGUP
))
1030 stream_event(virStreamPtr st
, int events
, void *opaque
)
1032 event_context
*ctxt
= opaque
;
1034 if ((events
& VIR_STREAM_EVENT_READABLE
)
1035 && (ctxt
->stbuf_off
< sizeof(ctxt
->stbuf
))) {
1036 // if there's no space in the buffer, we need to wait until more has
1037 // been written to stdout
1039 int bytes_recv
= virStreamRecv(st
, ctxt
->stbuf
+ ctxt
->stbuf_off
,
1040 sizeof(ctxt
->stbuf
) - ctxt
->stbuf_off
);
1041 if (bytes_recv
== -2)
1043 if (bytes_recv
<= 0) {
1044 if (bytes_recv
== 0)
1045 virStreamFinish(st
);
1049 ctxt
->stbuf_off
+= bytes_recv
;
1052 if (ctxt
->stbuf_off
) // we have stuff to write to stdout
1053 virEventUpdateHandle(ctxt
->stdout_w
, VIR_EVENT_HANDLE_WRITABLE
);
1055 if (events
& VIR_STREAM_EVENT_WRITABLE
&& ctxt
->termbuf_off
) {
1056 ssize_t bytes_sent
= virStreamSend(st
, ctxt
->termbuf
,
1058 if (bytes_sent
== -2)
1060 if (bytes_sent
< 0) {
1065 memmove(ctxt
->termbuf
, ctxt
->termbuf
+ bytes_sent
,
1066 ctxt
->termbuf_off
- bytes_sent
);
1067 ctxt
->termbuf_off
-= bytes_sent
;
1070 if (!ctxt
->termbuf_off
) // there's nothing else to write to the stream
1071 virStreamEventUpdateCallback(st
, VIR_STREAM_EVENT_READABLE
);
1073 if (events
& (VIR_STREAM_EVENT_ERROR
|VIR_STREAM_EVENT_HANGUP
))
1078 on_child_exit(int sig
)
1080 if (sig
== SIGCHLD
) // sanity check
1088 xmlDocPtr domXMLdoc
= NULL
;
1089 xmlNodeSetPtr ports
= NULL
;
1090 xmlNodePtr newPort
= NULL
;
1094 memset(&ctxt
, 0, sizeof(ctxt
));
1096 // check that libvirtd supports channels
1097 if (!libvirtdCanOpenChannel(conn
)) {
1098 err("Channel support requires libvirtd v1.0.2+\n");
1102 if (virDomainIsActive(targetDom
) != 1) {
1103 err("The domain is not running\n");
1107 // NB: setting liveConfig to 1
1108 if (getDomainPorts(targetDom
, 1, PORT_BASENAME
, &domXMLdoc
, &ports
) != 0)
1109 return -1; // proper error msg already emitted
1111 // give a nice hint to the user
1112 if (ports
->nodeNr
== 0 && !canHotplug(conn
)) {
1113 err("No SystemTap ports detected and hotplugging not available. Try "
1114 "using the command \'stapvirt port-add %s\' to add a port.\n",
1115 virDomainGetName(targetDom
));
1119 // print an error if no channel found and we can't hotplug
1120 dbug(2, "trying to open a permanent port\n");
1121 ctxt
.st
= domainOpenChannel(conn
, targetDom
, ports
);
1122 if (ctxt
.st
== NULL
&& !canHotplug(conn
)) {
1123 err("Couldn't connect to any SystemTap port. Try using the command "
1124 "\'stapvirt port-add %s\' if more SystemTap ports are required.\n",
1125 virDomainGetName(targetDom
));
1129 // let's try hotplugging!
1130 if (ctxt
.st
== NULL
) {
1131 dbug(2, "trying to hotplug a port\n");
1132 if (generateNextPort(ports
, targetDom
, sockDir
,
1133 PORT_BASENAME
, &newPort
) != 0)
1134 goto error
; // proper error msg already emitted
1135 if (hotplugPort(1, targetDom
, domXMLdoc
, newPort
) != 0)
1136 goto error
; // proper error msg already emitted
1139 ctxt
.st
= virStreamNew(conn
, VIR_STREAM_NONBLOCK
);
1140 if (ctxt
.st
== NULL
) {
1141 err("Couldn't create a new stream object\n");
1145 const char *name
= getXmlPortName(newPort
);
1146 if (virDomainOpenChannel(targetDom
, name
, ctxt
.st
, 0) != 0) {
1147 err("Couldn't open channel on hotplugged port\n");
1150 dbug(2, "successfully hotplugged a port\n");
1152 dbug(2, "successfully opened permanent port\n");
1155 // change stdin and stdout to O_NONBLOCK: even if libvirt uses poll(), it
1156 // can happen for read/write to block even though we got POLLIN/POLLOUT
1157 // (see the BUGS section of select(2))
1158 int flags
= fcntl(STDIN_FILENO
, F_GETFL
);
1159 if (flags
== -1 || fcntl(STDIN_FILENO
, F_SETFL
, flags
|O_NONBLOCK
) == -1) {
1160 err("Couldn't change stdin to non-blocking mode\n");
1163 flags
= fcntl(STDOUT_FILENO
, F_GETFL
);
1164 if (flags
== -1 || fcntl(STDOUT_FILENO
, F_SETFL
, flags
|O_NONBLOCK
) == -1) {
1165 err("Couldn't change stdout to non-blocking mode\n");
1169 // install callbacks
1170 ctxt
.stdin_w
= virEventAddHandle(STDIN_FILENO
, VIR_EVENT_HANDLE_READABLE
,
1171 stdin_event
, &ctxt
, NULL
);
1172 if (ctxt
.stdin_w
< 0) {
1173 err("Couldn't add handle for stdin\n");
1176 ctxt
.stdout_w
= virEventAddHandle(STDOUT_FILENO
, 0,
1177 stdout_event
, &ctxt
, NULL
);
1178 if (ctxt
.stdout_w
< 0) {
1179 err("Couldn't add handle for stdout\n");
1182 if (virStreamEventAddCallback(ctxt
.st
, VIR_STREAM_EVENT_READABLE
,
1183 stream_event
, &ctxt
, NULL
) < 0) {
1184 err("Couldn't add handle for stream\n");
1188 // install signal handler for SIGCHLD so that we stop the connection in case
1189 // the underlying transport app (e.g. ssh) exits (see also related note in
1190 // the libvirt_stapsh class in remote.cxx)
1191 struct sigaction sa
;
1192 memset(&sa
, 0, sizeof(sa
));
1193 sa
.sa_handler
= on_child_exit
;
1194 if (sigaction(SIGCHLD
, &sa
, NULL
) != 0) {
1195 err("Couldn't add signal handler for SIGCHLD\n");
1199 // silence libvirt as some error messages might occur when child processes
1200 // such as ssh receive SIGINT
1201 virSetErrorFunc(NULL
, silentErr
);
1203 dbug(2, "entering event loop\n");
1204 while (!disconnect
) {
1205 if (virEventRunDefaultImpl() != 0)
1209 virStreamAbort(ctxt
.st
);
1210 virStreamFree(ctxt
.st
);
1212 // restore error printing
1213 virSetErrorFunc(NULL
, NULL
);
1218 virStreamFree(ctxt
.st
);
1222 if (hotplugged
&& hotplugPort(0, targetDom
, domXMLdoc
, newPort
) != 0)
1223 dbug(2, "could not unplug port\n");
1224 xmlXPathFreeNodeSet(ports
);
1225 xmlFreeDoc(domXMLdoc
);
1232 // 80 screen width = 94 here --> put last printed char in col 93 at the V after this... V
1233 // The port-add command purposely does not also hotplug the port, even if
1235 // - It would make it harder to figure out the final state
1236 // - If hotplugging is supported, users would not need to do port-add in
1237 // the first place, since they would let stap do the hotplugging
1238 eprintf("stapvirt v%s\n", VERSION
);
1239 eprintf("Usage: stapvirt [-c URI] [-d PATH] [-v] COMMAND ARGUMENTS\n\n");
1240 eprintf(" -c Specify the libvirt driver URI to which to connect [default: NULL]\n");
1241 eprintf(" -d Specify the directory in which sockets should be placed [default:\n");
1242 eprintf(" /var/lib/libvirt/qemu]\n");
1243 eprintf(" -v Increase verbosity\n");
1247 eprintf("Try the 'help' command for more information.\n");
1251 eprintf("Available commands are:\n");
1254 eprintf(" Display this message.\n");
1256 eprintf(" List available domains.\n");
1257 eprintf(" port-add <domain>\n");
1258 eprintf(" Add a permanent SystemTap port to the domain's definition. If the\n");
1259 eprintf(" domain is currently running, it must be powered off before changes\n");
1260 eprintf(" take effect.\n");
1261 eprintf(" port-list <domain>\n");
1262 eprintf(" List the UNIX socket paths of the permanent SystemTap ports in the\n");
1263 eprintf(" domain's definition.\n");
1264 eprintf(" port-remove <domain>\n");
1265 eprintf(" Remove a permanent SystemTap port from the domain's definition. If\n");
1266 eprintf(" the domain is currently running, it must be powered off before\n");
1267 eprintf(" changes take effect.\n");
1268 eprintf(" query <domain>\n");
1269 eprintf(" Display the following information about the domain: its name, its\n");
1270 eprintf(" UUID, its state, the number of permanent SystemTap ports installed,\n");
1271 eprintf(" and whether hotplugging is supported.\n");
1272 /* UNDOCUMENTED COMMAND (for stap only)
1273 eprintf(" connect <domain>\n");
1274 eprintf(" Open up a connection to the domain. If successful, stapvirt becomes a\n");
1275 eprintf(" pass-through for stapsh. If no port found and hotplugging is\n");
1276 eprintf(" supported, then a new port is hotplugged for the duration of the\n");
1277 eprintf(" connection.\n");
1280 eprintf("Domains can be specified using their name, UUID, or ID.\n");
1286 parse_args(int argc
, char* const argv
[])
1289 while ((c
= getopt(argc
, argv
, "c:d:hv")) != -1) {
1290 dbug(2, "received opt %c\n", c
);
1299 usage(0); // no return
1304 usage(1); // no return
1309 static const command
*
1310 lookupCommand(const char *cmd
)
1313 for (i
= 0; i
< ncommands
; ++i
) {
1314 if (strcmp(cmd
, commands
[i
].name
) == 0)
1315 return &commands
[i
];
1321 preCommand(const command
*cmd
)
1323 // virConnect() may not be our first call, so let's explicitly initialize it
1325 if (virInitialize() != 0) {
1326 err("Couldn't initialize libvirt library\n");
1330 // For connect to work, we need to call virEventRegisterDefaultImpl()
1331 // before even connecting. This requirement may be because we don't
1333 if (strcmp(cmd
->name
, "connect") == 0) {
1334 if (virEventRegisterDefaultImpl() != 0) {
1335 err("Couldn't register the default event implementation\n");
1340 dbug(1, "opening%s connection on URI '%s'\n",
1341 cmd
->read_only
? " read-only" : "", virURI
);
1343 conn
= virConnectOpenAuth(virURI
, virConnectAuthPtrDefault
,
1344 cmd
->read_only
? VIR_CONNECT_RO
: 0);
1346 err("Couldn't connect to %s\n", virURI
);
1350 // if the command needs it, retrieve the domain
1351 if (cmd
->need_domain
&& targetDomStr
!= NULL
) {
1352 dbug(2, "searching for domain '%s'\n", targetDomStr
);
1353 targetDom
= findDomain(conn
, targetDomStr
);
1354 if (targetDom
== NULL
) {
1355 err("Couldn't find domain '%s' on URI '%s'\n",
1356 targetDomStr
, virConnectGetURI(conn
));
1357 virConnectClose(conn
);
1368 if (targetDom
!= NULL
)
1369 virDomainFree(targetDom
);
1370 virConnectClose(conn
);
1374 main(int argc
, char* const argv
[])
1376 // initialize lib and make sure there's no version mismatch
1379 parse_args(argc
, argv
);
1381 // move to first non-option argument
1382 // getopt() puts them all at the end for us
1388 // check that we have at least a command
1390 usage(1); // no return
1391 else if (strcmp(argv
[0], "help") == 0)
1392 usage(0); // no return
1394 dbug(2, "looking up command '%s'\n", argv
[0]);
1395 const command
*cmd
= lookupCommand(argv
[0]);
1397 err("Invalid command '%s'\n", argv
[0]);
1398 usage(1); // no return
1401 if (cmd
->need_domain
) {
1403 err("Command %s requires a <domain> argument\n", cmd
->name
);
1404 usage(1); // no return
1406 targetDomStr
= argv
[1];
1410 if (preCommand(cmd
) == -1)
1411 return EXIT_FAILURE
; // preCommand printed an error already
1413 dbug(2, "calling command %s\n", cmd
->name
);
1420 /* vim: set sw=4 : */