[PATCH 0 of 2] #4 Update KVMRedirectionSAP to return avail sessions

This updated uses the listening / established port entries in /proc/net/tcp to determine whether a guest has any available / enabled VNC sessions. Updates from 1 to 2: -Removed 2 patches of unecessary junk.

# HG changeset patch # User kaitlin@elm3b43.beaverton.ibm.com # Date 1224552270 25200 # Node ID 5a55c724920bbe6c3df77c9465a150ac6423f946 # Parent 2df4433a10600aee5a8ed0aae0c1ded96a3e4d0f (#4) Add get_vnc_sessions() to determine all of VNC ports available or in use. Updated from 3 to 4: -Fix style issues -Add strdup allocation check Updates from 2 to 3: -Fix whitespace issues -Do entire vnc_port struct allocation at once Updates from 1 to 2: -Remove functions to convert port number to a string -Instead of using a hash table to hold the ports listed in /proc/net/tcp, use a list to hold the host/port values. Signed-off-by: Kaitlin Rupert <karupert@us.ibm.com> diff -r 2df4433a1060 -r 5a55c724920b src/Virt_KVMRedirectionSAP.c --- a/src/Virt_KVMRedirectionSAP.c Tue Oct 28 08:27:45 2008 -0700 +++ b/src/Virt_KVMRedirectionSAP.c Mon Oct 20 18:24:30 2008 -0700 @@ -39,11 +39,25 @@ #include "Virt_KVMRedirectionSAP.h" +#define PROC_TCP "/proc/net/tcp" + const static CMPIBroker *_BROKER; + +struct vnc_port { + char *name; + int port; + int remote_port; +}; + +struct vnc_ports { + struct vnc_port **list; + unsigned int max; + unsigned int cur; +}; static int inst_from_dom(const CMPIBroker *broker, const CMPIObjectPath *ref, - struct domain *dominfo, + struct vnc_port *port, CMPIInstance *inst) { char *sccn = NULL; @@ -52,8 +66,7 @@ uint16_t prop_val; int ret = 1; - if (asprintf(&id, "%s:%s", dominfo->name, - dominfo->dev_graphics->dev.graphics.type) == -1) { + if (asprintf(&id, "%d:%d", port->port, port->remote_port) == -1) { CU_DEBUG("Unable to format name"); ret = 0; goto out; @@ -66,7 +79,7 @@ (CMPIValue *)id, CMPI_chars); CMSetProperty(inst, "SystemName", - (CMPIValue *)dominfo->name, CMPI_chars); + (CMPIValue *)port->name, CMPI_chars); CMSetProperty(inst, "SystemCreationClassName", (CMPIValue *)sccn, CMPI_chars); @@ -74,19 +87,16 @@ CMSetProperty(inst, "ElementName", (CMPIValue *)id, CMPI_chars); - if (STREQ(dominfo->dev_graphics->dev.graphics.type, "vnc")) - prop_val = (uint16_t)CIM_CRS_VNC; - else - prop_val = (uint16_t)CIM_CRS_OTHER; - + prop_val = (uint16_t)CIM_CRS_VNC; CMSetProperty(inst, "KVMProtocol", (CMPIValue *)&prop_val, CMPI_uint16); - /* Need to replace this with a check that determines whether - the console session is enabled (in use) or available (not actively - in use). - */ - prop_val = (uint16_t)CIM_CRS_ENABLED_STATE; + if (port->remote_port < 0) + prop_val = (uint16_t)CIM_SAP_INACTIVE_STATE; + else if (port->remote_port == 0) + prop_val = (uint16_t)CIM_SAP_AVAILABLE_STATE; + else + prop_val = (uint16_t)CIM_SAP_ACTIVE_STATE; CMSetProperty(inst, "EnabledState", (CMPIValue *)&prop_val, CMPI_uint16); @@ -101,7 +111,7 @@ static CMPIInstance *get_console_sap(const CMPIBroker *broker, const CMPIObjectPath *reference, virConnectPtr conn, - struct domain *dominfo, + struct vnc_port *port, CMPIStatus *s) { @@ -119,7 +129,7 @@ goto out; } - if (inst_from_dom(broker, reference, dominfo, inst) != 1) { + if (inst_from_dom(broker, reference, port, inst) != 1) { cu_statusf(broker, s, CMPI_RC_ERR_FAILED, "Unable to get instance from domain"); @@ -127,6 +137,84 @@ out: return inst; +} + +static CMPIStatus get_vnc_sessions(const CMPIObjectPath *ref, + virConnectPtr conn, + struct vnc_ports ports, + struct inst_list *list) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst; + const char *path = PROC_TCP; + unsigned int lport = 0; + unsigned int rport = 0; + FILE *tcp_info; + char *line = NULL; + size_t len = 0; + int val; + int ret; + int i; + + tcp_info = fopen(path, "r"); + if (tcp_info == NULL) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Failed to open %s: %m", tcp_info); + goto out; + } + + if (getline(&line, &len, tcp_info) == -1) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Failed to read from %s", tcp_info); + goto out; + } + + while (getline(&line, &len, tcp_info) > 0) { + ret = sscanf(line, "%d: %*[^:]:%X %*[^:]:%X", &val, &lport, + &rport); + if (ret != 3) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Unable to determine active sessions"); + goto out; + } + + for (i = 0; i < ports.max; i++) { + if (lport != ports.list[i]->port) + continue; + + ports.list[i]->remote_port = rport; + inst = get_console_sap(_BROKER, + ref, + conn, + ports.list[i], + &s); + if ((s.rc != CMPI_RC_OK) || (inst == NULL)) + goto out; + + inst_list_add(list, inst); + } + } + + /* Handle any guests that were missed. These guest don't have active + or enabled sessions. */ + for (i = 0; i < ports.max; i++) { + if (ports.list[i]->remote_port != -1) + continue; + + inst = get_console_sap(_BROKER, ref, conn, ports.list[i], &s); + if ((s.rc != CMPI_RC_OK) || (inst == NULL)) + goto out; + + inst_list_add(list, inst); + } + + out: + tcp_info = fopen(path, "r"); + fclose(tcp_info); + return s; } static bool check_graphics(virDomainPtr dom, @@ -157,7 +245,10 @@ virDomainPtr *domain_list; struct domain *dominfo = NULL; struct inst_list list; + struct vnc_ports port_list; int count; + int lport; + int ret; int i; conn = connect_by_classname(_BROKER, CLASSNAME(ref), &s); @@ -165,6 +256,10 @@ return s; inst_list_init(&list); + + port_list.list = NULL; + port_list.max = 0; + port_list.cur = 0; count = get_domain_list(conn, &domain_list); if (count < 0) { @@ -175,23 +270,64 @@ } else if (count == 0) goto out; + port_list.list = malloc(count * sizeof(struct vnc_port *)); + if (port_list.list == NULL) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Unable to allocate guest port list"); + goto out; + + } + for (i = 0; i < count; i++) { - CMPIInstance *inst = NULL; + port_list.list[i] = malloc(sizeof(struct vnc_port)); + if (port_list.list[i] == NULL) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Unable to allocate guest port list"); + goto out; + } + } + for (i = 0; i < count; i++) { if (!check_graphics(domain_list[i], &dominfo)) { virDomainFree(domain_list[i]); cleanup_dominfo(&dominfo); continue; } - inst = get_console_sap(_BROKER, ref, conn, dominfo, &s); + ret = sscanf(dominfo->dev_graphics->dev.graphics.port, + "%d", + &lport); + if (ret != 1) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Unable to guest's console port"); + goto out; + } + + port_list.list[port_list.cur]->name = strdup(dominfo->name); + if (port_list.list[port_list.cur]->name == NULL) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Unable to allocate string"); + goto out; + } + + port_list.list[port_list.cur]->port = lport; + port_list.list[port_list.cur]->remote_port = -1; + port_list.cur++; virDomainFree(domain_list[i]); cleanup_dominfo(&dominfo); + } - if (inst != NULL) - inst_list_add(&list, inst); - } + port_list.max = port_list.cur; + port_list.cur = 0; + + s = get_vnc_sessions(ref, conn, port_list, &list); + if (s.rc != CMPI_RC_OK) + goto out; if (names_only) cu_return_instance_names(results, &list); @@ -201,6 +337,13 @@ out: free(domain_list); inst_list_free(&list); + + for (i = 0; i < count; i++) { + free(port_list.list[i]->name); + free(port_list.list[i]); + port_list.list[i] = NULL; + } + free(port_list.list); return s; } diff -r 2df4433a1060 -r 5a55c724920b src/svpc_types.h --- a/src/svpc_types.h Tue Oct 28 08:27:45 2008 -0700 +++ b/src/svpc_types.h Mon Oct 20 18:24:30 2008 -0700 @@ -60,6 +60,10 @@ #define CIM_CRS_OTHER 1 #define CIM_CRS_VNC 4 +#define CIM_SAP_ACTIVE_STATE 2 +#define CIM_SAP_INACTIVE_STATE 3 +#define CIM_SAP_AVAILABLE_STATE 6 + #include <libcmpiutil/libcmpiutil.h> #include <string.h>

# HG changeset patch # User kaitlin@elm3b43.beaverton.ibm.com # Date 1224552270 25200 # Node ID 739113a661c7a342e67bd7f19ce8c744e283bbff # Parent 5a55c724920bbe6c3df77c9465a150ac6423f946 (#3) Have get_console_sap_by_name() use Name attribute to determine session Updates from 2 to 3: -Check malloc() and strdup() returns -Remove unneeded NULL initialization Updates from 1 to 2: -Removed function that parses the Name attribute Signed-off-by: Kaitlin Rupert <karupert@us.ibm.com> diff -r 5a55c724920b -r 739113a661c7 src/Virt_KVMRedirectionSAP.c --- a/src/Virt_KVMRedirectionSAP.c Mon Oct 20 18:24:30 2008 -0700 +++ b/src/Virt_KVMRedirectionSAP.c Mon Oct 20 18:24:30 2008 -0700 @@ -350,7 +350,7 @@ CMPIStatus get_console_sap_by_name(const CMPIBroker *broker, const CMPIObjectPath *ref, - const char *name, + const char *sys, CMPIInstance **_inst) { virConnectPtr conn; @@ -358,6 +358,10 @@ CMPIStatus s = {CMPI_RC_OK, NULL}; CMPIInstance *inst = NULL; struct domain *dominfo = NULL; + struct vnc_port *port = NULL; + const char *name = NULL; + int lport; + int rport; conn = connect_by_classname(broker, CLASSNAME(ref), &s); if (conn == NULL) { @@ -367,12 +371,12 @@ goto out; } - dom = virDomainLookupByName(conn, name); + dom = virDomainLookupByName(conn, sys); if (dom == NULL) { cu_statusf(broker, &s, CMPI_RC_ERR_NOT_FOUND, "No such instance (%s)", - name); + sys); goto out; } @@ -380,9 +384,43 @@ cu_statusf(broker, &s, CMPI_RC_ERR_FAILED, "No console device for this guest"); + goto out; } - inst = get_console_sap(_BROKER, ref, conn, dominfo, &s); + if (cu_get_str_path(ref, "Name", &name) != CMPI_RC_OK) { + cu_statusf(broker, &s, + CMPI_RC_ERR_NOT_FOUND, + "No such instance (System)"); + goto out; + } + + if (sscanf(name, "%d:%d", &lport, &rport) != 2) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Unable to guest's console port"); + goto out; + } + + port = malloc(sizeof(struct vnc_port)); + if (port == NULL) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Unable to allocate guest port struct"); + goto out; + } + + port->name = strdup(dominfo->name); + if (port->name == NULL) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Unable to allocate string"); + goto out; + } + + port->port = lport; + port->remote_port = rport; + + inst = get_console_sap(_BROKER, ref, conn, port, &s); virDomainFree(dom); @@ -393,6 +431,8 @@ out: virConnectClose(conn); + free(port->name); + free(port); return s; } @@ -405,10 +445,10 @@ CMPIInstance *inst = NULL; const char *sys = NULL; - if (cu_get_str_path(reference, "System", &sys) != CMPI_RC_OK) { + if (cu_get_str_path(reference, "SystemName", &sys) != CMPI_RC_OK) { cu_statusf(broker, &s, CMPI_RC_ERR_NOT_FOUND, - "No such instance (System)"); + "No such instance (SystemName)"); goto out; }

Kaitlin Rupert wrote:
# HG changeset patch # User kaitlin@elm3b43.beaverton.ibm.com # Date 1224552270 25200 # Node ID 739113a661c7a342e67bd7f19ce8c744e283bbff # Parent 5a55c724920bbe6c3df77c9465a150ac6423f946 (#3) Have get_console_sap_by_name() use Name attribute to determine session
Updates from 2 to 3: -Check malloc() and strdup() returns -Remove unneeded NULL initialization
Updates from 1 to 2: -Removed function that parses the Name attribute
Signed-off-by: Kaitlin Rupert <karupert@us.ibm.com>
diff -r 5a55c724920b -r 739113a661c7 src/Virt_KVMRedirectionSAP.c --- a/src/Virt_KVMRedirectionSAP.c Mon Oct 20 18:24:30 2008 -0700 +++ b/src/Virt_KVMRedirectionSAP.c Mon Oct 20 18:24:30 2008 -0700 @@ -350,7 +350,7 @@
CMPIStatus get_console_sap_by_name(const CMPIBroker *broker, const CMPIObjectPath *ref, - const char *name, + const char *sys, CMPIInstance **_inst) { virConnectPtr conn; @@ -358,6 +358,10 @@ CMPIStatus s = {CMPI_RC_OK, NULL}; CMPIInstance *inst = NULL; struct domain *dominfo = NULL; + struct vnc_port *port = NULL; + const char *name = NULL; + int lport; + int rport;
conn = connect_by_classname(broker, CLASSNAME(ref), &s); if (conn == NULL) { @@ -367,12 +371,12 @@ goto out; }
- dom = virDomainLookupByName(conn, name); + dom = virDomainLookupByName(conn, sys); if (dom == NULL) { cu_statusf(broker, &s, CMPI_RC_ERR_NOT_FOUND, "No such instance (%s)", - name); + sys); goto out; }
@@ -380,9 +384,43 @@ cu_statusf(broker, &s, CMPI_RC_ERR_FAILED, "No console device for this guest"); + goto out; }
- inst = get_console_sap(_BROKER, ref, conn, dominfo, &s); + if (cu_get_str_path(ref, "Name", &name) != CMPI_RC_OK) { + cu_statusf(broker, &s, + CMPI_RC_ERR_NOT_FOUND, + "No such instance (System)");
Sorry for being late, just wondering if this error message has to be "No such instance (Name)" Thanks and Regards, Deepti.

- inst = get_console_sap(_BROKER, ref, conn, dominfo, &s); + if (cu_get_str_path(ref, "Name", &name) != CMPI_RC_OK) { + cu_statusf(broker, &s, + CMPI_RC_ERR_NOT_FOUND, + "No such instance (System)");
Sorry for being late, just wondering if this error message has to be
"No such instance (Name)"
Good catch! A patch is on the way for this. -- Kaitlin Rupert IBM Linux Technology Center kaitlin@linux.vnet.ibm.com
participants (2)
-
Deepti B Kalakeri
-
Kaitlin Rupert