[PATCH 0 of 2] #2 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: -Removed 2 patches of unecessary junk.

# HG changeset patch # User kaitlin@elm3b43.beaverton.ibm.com # Date 1224552270 25200 # Node ID 22262aa6c752e15e6c9fa462cd3bb84b7ff49fd2 # Parent e043f46f299ec3dd3d1e48e51e57437fa90db136 #2 Add get_vnc_sessions() to determine all of the VNC ports available or in use. 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 e043f46f299e -r 22262aa6c752 src/Virt_KVMRedirectionSAP.c --- a/src/Virt_KVMRedirectionSAP.c Wed Oct 22 08:28:37 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,58 @@ } else if (count == 0) goto out; + port_list.list = malloc(count * sizeof(struct vnc_port *)); + if (!port_list.list) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Unable to allocate guest port list"); + goto out; + + } + + for (i = 0; i < count; i++) + port_list.list[i] = NULL; + for (i = 0; i < count; i++) { - CMPIInstance *inst = NULL; - 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] = malloc(sizeof(struct vnc_port)); + if (!port_list.list[port_list.cur]) { + cu_statusf(_BROKER, &s, + CMPI_RC_ERR_FAILED, + "Unable to allocate guest port list"); + goto out; + } + + port_list.list[port_list.cur]->name = strdup(dominfo->name); + 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 +331,13 @@ out: free(domain_list); inst_list_free(&list); + + for (i = 0; i < port_list.max; 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 e043f46f299e -r 22262aa6c752 src/svpc_types.h --- a/src/svpc_types.h Wed Oct 22 08:28:37 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>

KR> + tcp_info = fopen(path, "r"); KR> + if (tcp_info== NULL) { Whitespace before the == ... KR> + port_list.list = malloc(count * sizeof(struct vnc_port *)); Why not allocate the space for the structs too? KR> + port_list.list[port_list.cur] = malloc(sizeof(struct vnc_port)); If you do the above, then you won't have to allocate here. Otherwise I think it looks fine. -- Dan Smith IBM Linux Technology Center Open Hypervisor Team email: danms@us.ibm.com

# HG changeset patch # User kaitlin@elm3b43.beaverton.ibm.com # Date 1224552270 25200 # Node ID c4e40b8d7aa0ad1135e9ea4273e3becff2fd3cbb # Parent 22262aa6c752e15e6c9fa462cd3bb84b7ff49fd2 #2 Have get_console_sap_by_name() use Name attribute to determine session status Updates: -Removed function that parses the Name attribute Signed-off-by: Kaitlin Rupert <karupert@us.ibm.com> diff -r 22262aa6c752 -r c4e40b8d7aa0 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 @@ -344,7 +344,7 @@ CMPIStatus get_console_sap_by_name(const CMPIBroker *broker, const CMPIObjectPath *ref, - const char *name, + const char *sys, CMPIInstance **_inst) { virConnectPtr conn; @@ -352,6 +352,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) { @@ -361,12 +365,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; } @@ -374,9 +378,29 @@ 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)); + port->name = strdup(dominfo->name); + port->port = lport; + port->remote_port = rport; + + inst = get_console_sap(_BROKER, ref, conn, port, &s); virDomainFree(dom); @@ -387,6 +411,9 @@ out: virConnectClose(conn); + free(port->name); + free(port); + port = NULL; return s; } @@ -399,10 +426,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; }

KR> + port = malloc(sizeof(struct vnc_port)); Check your malloc() result. KR> + port->name = strdup(dominfo->name); Check your strdup() result. KR> out: KR> virConnectClose(conn); KR> + free(port->name); KR> + free(port); KR> + port = NULL; This "port = NULL" doesn't do anything, does it? -- Dan Smith IBM Linux Technology Center Open Hypervisor Team email: danms@us.ibm.com
participants (2)
-
Dan Smith
-
Kaitlin Rupert