# HG changeset patch
# User kaitlin(a)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(a)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>