[Ovirt-devel] [PATCH] Rewriting the identify-node piece into two managed node units to submit a wake-up request and an identify request. The bulk of the ovirt-identify work is done via a C application.

Darryl L. Pierce dpierce at redhat.com
Tue Jun 24 02:17:29 UTC 2008


I'm having a trouble with getting the ovirt-managed-node RPM into the LiveCD image. If someone could take a few minutes, I'd appreciate some feedback on how to fix build-all.sh. Thanks.


Signed-off-by: Darryl L. Pierce <dpierce at redhat.com>
---
 build-all.sh                                       |    8 +
 ovirt-host-creator/common-pkgs.ks                  |    1 +
 ovirt-host-creator/version                         |    2 +-
 ovirt-managed-node/AUTHOR                          |    1 +
 ovirt-managed-node/ChangeLog                       |    2 +
 ovirt-managed-node/Makefile                        |   76 ++++
 ovirt-managed-node/NEWS                            |    2 +
 ovirt-managed-node/README                          |    2 +
 ovirt-managed-node/ovirt-awake                     |   82 ++++
 ovirt-managed-node/ovirt-identify                  |   46 ++
 ovirt-managed-node/ovirt-identify-node.c           |  438 ++++++++++++++++++++
 ovirt-managed-node/ovirt-managed-node.spec         |   45 ++
 wui/src/host-browser/host-browser.rb               |  106 +++--
 wui/src/host-browser/test-host-browser-awaken.rb   |   94 +++++
 wui/src/host-browser/test-host-browser-identify.rb |  162 ++++++++
 wui/src/host-browser/test-host-browser.rb          |  204 ---------
 wui/version                                        |    2 +-
 17 files changed, 1021 insertions(+), 252 deletions(-)
 create mode 100644 ovirt-managed-node/AUTHOR
 create mode 100644 ovirt-managed-node/ChangeLog
 create mode 100644 ovirt-managed-node/Makefile
 create mode 100644 ovirt-managed-node/NEWS
 create mode 100644 ovirt-managed-node/README
 create mode 100644 ovirt-managed-node/ovirt-awake
 create mode 100644 ovirt-managed-node/ovirt-identify
 create mode 100644 ovirt-managed-node/ovirt-identify-node.c
 create mode 100644 ovirt-managed-node/ovirt-managed-node.spec
 create mode 100755 wui/src/host-browser/test-host-browser-awaken.rb
 create mode 100755 wui/src/host-browser/test-host-browser-identify.rb
 delete mode 100755 wui/src/host-browser/test-host-browser.rb

diff --git a/build-all.sh b/build-all.sh
index 8c3a7e9..3d2666c 100755
--- a/build-all.sh
+++ b/build-all.sh
@@ -126,13 +126,21 @@ fi
 set -e
 
 # build ovirt-wui RPM
+# also build the ovirt-managed-node RPM
 if [ $update_wui = 1 ]; then
+    cd $BASE/ovirt-managed-node
+    rm -rf rpm-build
+    make rpms
+    rm -f $OVIRT/ovirt-managed-node*rpm
+    cp rpm-build/ovirt-managed-node*rpm
+
     cd $BASE/wui
     rm -rf rpm-build
     bumpver
     make rpms
     rm -f $OVIRT/ovirt-wui*rpm
     cp rpm-build/ovirt-wui*rpm $OVIRT
+
     cd $OVIRT
     createrepo .
 fi
diff --git a/ovirt-host-creator/common-pkgs.ks b/ovirt-host-creator/common-pkgs.ks
index 814f6a9..6fe4f26 100644
--- a/ovirt-host-creator/common-pkgs.ks
+++ b/ovirt-host-creator/common-pkgs.ks
@@ -26,6 +26,7 @@ augeas
 nc
 bind-utils
 syslinux
+ovirt-managed-node
 -policycoreutils
 -audit-libs-python
 -hdparm
diff --git a/ovirt-host-creator/version b/ovirt-host-creator/version
index f644984..c5b5338 100644
--- a/ovirt-host-creator/version
+++ b/ovirt-host-creator/version
@@ -1 +1 @@
-0.91 1
+0.92 0.1.200806240052git63f6a5a
diff --git a/ovirt-managed-node/AUTHOR b/ovirt-managed-node/AUTHOR
new file mode 100644
index 0000000..d37a107
--- /dev/null
+++ b/ovirt-managed-node/AUTHOR
@@ -0,0 +1 @@
+Darryl L. Pierce <dpierce at redhat.com>
diff --git a/ovirt-managed-node/ChangeLog b/ovirt-managed-node/ChangeLog
new file mode 100644
index 0000000..61dc8cc
--- /dev/null
+++ b/ovirt-managed-node/ChangeLog
@@ -0,0 +1,2 @@
+* Tue 17 Jun 2008 Darryl L. Pierce <dpierce at redhat.com> - 0.0.1-1
+- Created the initial RPM structure.
diff --git a/ovirt-managed-node/Makefile b/ovirt-managed-node/Makefile
new file mode 100644
index 0000000..564be1d
--- /dev/null
+++ b/ovirt-managed-node/Makefile
@@ -0,0 +1,76 @@
+# Copyright (C) 2008 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA  02110-1301, USA.  A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+CC=gcc
+CFLAGS=-Wall -c -g
+LFLAGS=-lvirt
+OBJECTS=ovirt-identify-node.o
+TARGET=ovirt-identify-node
+SPECFILE=ovirt-managed-node.spec
+NAME=ovirt-managed-node
+VERSION=0.1
+NV=$(NAME)-$(VERSION)
+RPM_FLAGS=\
+	--define "_topdir	%(pwd)/rpm-build" \
+	--define "_builddir	%{_topdir}" \
+	--define "_rpmdir	%{_topdir}" \
+	--define "_srcrpmdir	%{_topdir}" \
+	--define '_rpmfilename %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm' \
+	--define "_specdir	%{_topdir}" \
+	--define "_sourcedir	%{_topdir}"
+SOURCES=\
+	AUTHOR \
+	ChangeLog \
+	Makefile \
+	NEWS \
+	ovirt-awake \
+	ovirt-identify \
+	ovirt-identify-node.c \
+	ovirt-managed-node.spec \
+	README	
+
+
+ALL: $(TARGET)
+
+.c.o:
+	$(CC) $(CFLAGS) $< -o $@
+
+clean:
+	rm -rf $(OBJECTS) $(TARGET) $(NV) rpm-build
+
+bumpgit:
+	-echo "$(VERSION) $(GITRELEASE)" > version
+
+bumprelease:
+	-echo "$(VERSION) $(NEWRELEASE)" > version
+
+setversion:
+	-echo "$(VERSION) 0" > version
+
+$(TARGET): $(OBJECTS)
+	$(CC) -o $@ $(OBJECTS) $(LFLAGS)
+
+tar: clean $(TARGET)
+	mkdir -p $(NV)
+	cp -a $(SOURCES) $(NV)
+	mkdir -p rpm-build
+	tar zcvf rpm-build/$(NV).tar $(NV)
+	rm -rf $(NV)
+
+rpms: tar
+	rpmbuild $(RPM_FLAGS) -ba $(SPECFILE)
diff --git a/ovirt-managed-node/NEWS b/ovirt-managed-node/NEWS
new file mode 100644
index 0000000..139597f
--- /dev/null
+++ b/ovirt-managed-node/NEWS
@@ -0,0 +1,2 @@
+
+
diff --git a/ovirt-managed-node/README b/ovirt-managed-node/README
new file mode 100644
index 0000000..139597f
--- /dev/null
+++ b/ovirt-managed-node/README
@@ -0,0 +1,2 @@
+
+
diff --git a/ovirt-managed-node/ovirt-awake b/ovirt-managed-node/ovirt-awake
new file mode 100644
index 0000000..f7f643b
--- /dev/null
+++ b/ovirt-managed-node/ovirt-awake
@@ -0,0 +1,82 @@
+#!/bin/bash
+#
+# ovirt-awake   Notifies the oVirt server that a managed node is
+#               starting up.
+#
+# Copyright (C) 2008 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA  02110-1301, USA.  A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+# Source function library
+. /etc/init.d/ovirt-functions
+
+start () {
+    find-server identify tcp
+
+    connect-to-server
+
+    receive-text
+
+    if [ $REPLY == "HELLO?" ]; then
+        echo "Starting wakeup conversation."
+
+        send-text "HELLO!"
+
+        read 0<&3
+
+        if [ $REPLY == "MODE?" ]; then
+            send-text "AWAKEN"
+
+            receive-text
+
+            KEYTAB=`echo $REPLY | awk '{ print $2 }'`
+
+            if [ -n $KEYTAB ]; then
+                echo "Retrieving keytab: '$KEYTAB'"
+
+                wget $KEYTAB --output-document=$KEYTAB_FILE
+            else
+                echo "No keytab to retrieve"
+            fi
+        else
+            echo "Did not get a mode request."
+        fi
+    else
+        echo "Did not get a proper startup marker."
+    fi
+
+    echo "Disconnecting."
+
+    disconnect-from-server
+}
+
+case "$1" in
+    start)
+        KEYTAB_FILE=$2
+        SRV_HOST=$3
+        SRV_PORT=$4
+        start
+        RETVAL=$?
+    ;;
+
+    *)
+        echo "Usage: $0 start"
+        RETVAL=2
+    ;;
+esac
+
+exit $RETVAL
diff --git a/ovirt-managed-node/ovirt-identify b/ovirt-managed-node/ovirt-identify
new file mode 100644
index 0000000..53f21b0
--- /dev/null
+++ b/ovirt-managed-node/ovirt-identify
@@ -0,0 +1,46 @@
+#!/bin/bash
+#
+# ovirt-identify  Submits managed node details to the central server.
+#
+# Copyright (C) 2008 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA  02110-1301, USA.  A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+# Source function library
+. /etc/init.d/ovirt-functions
+
+start () {
+    find-server identify tcp
+
+    /sbin/ovirt-identify-node -s $SRV_HOST -p $SRV_PORT
+}
+
+case "$1" in
+    start)
+        SRV_HOST=$2
+        SRV_PORT=$3
+        start
+        RETVAL=$?
+    ;;
+
+    *)
+        echo "Usage: $0 start"
+        RETVAL=2
+    ;;
+esac
+
+exit $RETVAL
diff --git a/ovirt-managed-node/ovirt-identify-node.c b/ovirt-managed-node/ovirt-identify-node.c
new file mode 100644
index 0000000..5a5d3c3
--- /dev/null
+++ b/ovirt-managed-node/ovirt-identify-node.c
@@ -0,0 +1,438 @@
+/* identify-node -- Main entry point for the identify-node utility.
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ * Written by Darryl L. Pierce <dpierce at redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.  A copy of the GNU General Public License is
+ * also available at http://www.gnu.org/copyleft/gpl.html.
+ */
+
+#include <errno.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <libvirt/libvirt.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+int  config(int argc,char** argv);
+void usage(void);
+
+int start_conversation(void);
+int send_details(void);
+int end_conversation(void);
+
+int send_text(char* text);
+int get_text(char* response,int maxlength);
+int create_connection(void);
+
+int debug   = 0;
+int verbose = 0;
+int testing = 0;
+
+#define BUFFER_LENGTH 128
+
+char arch[BUFFER_LENGTH];
+char uuid[VIR_UUID_BUFLEN];
+char memsize[BUFFER_LENGTH];
+char numcpus[BUFFER_LENGTH];
+char cpuspeed[BUFFER_LENGTH];
+char hostname[256];
+int  hostport = -1;
+int  socketfd;
+
+int main(int argc,char** argv)
+{
+    int result = 1;
+
+    if(!config(argc,argv))
+    {
+        fprintf(stdout,"Connecting to libvirt.\n");
+
+        virConnectPtr connection = virConnectOpenReadOnly(testing ? "test:///default" : NULL);
+
+        if(debug) fprintf(stderr,"connection=%x\n",(unsigned int )connection);
+
+        if(connection)
+        {
+            if(debug) fprintf(stdout,"Getting hostname: %s\n", uuid);
+            if(!strlen(uuid)) gethostname(uuid,sizeof uuid);
+
+            virNodeInfo info;
+
+            if(debug) fprintf(stdout,"Retrieving node information.\n");
+            if(!virNodeGetInfo(connection,&info))
+            {
+                sprintf(arch,    "%s",  info.model);
+                sprintf(memsize, "%ld", info.memory);
+                sprintf(numcpus, "%d",  info.cpus);
+                sprintf(cpuspeed,"%d",  info.mhz);
+
+                if(debug)
+                {
+                    fprintf(stdout,"Node Info:\n");
+                    fprintf(stdout,"     UUID: %s\n", uuid);
+                    fprintf(stdout,"     Arch: %s\n", arch);
+                    fprintf(stdout,"   Memory: %s\n", memsize);
+                    fprintf(stdout,"   # CPUs: %s\n", numcpus);
+                    fprintf(stdout,"CPU Speed: %s\n", cpuspeed);
+                }
+
+                if(debug) fprintf(stdout, "Retrieved node information.\n");
+
+                if(!start_conversation() && !send_details() && !end_conversation())
+                {
+                    result = 0;
+                }
+            }
+            else
+            {
+                if(debug) fprintf(stderr,"Failed to get node info.\n");
+            }
+        }
+        else
+        {
+            if(debug) fprintf(stderr,"Could not connect to libvirt.\n");
+        }
+    }
+    else
+    {
+        usage();
+    }
+
+    return result;
+}
+
+int config(int argc,char** argv)
+{
+    int result = 0;
+    int option;
+
+    while((option = getopt(argc,argv,"s:p:dvth")) != -1)
+    {
+        if(debug) fprintf(stdout,"Processing argument: %c (optarg:%s)\n",option,optarg);
+
+        switch(option)
+        {
+            case 's': strcpy(hostname,optarg); break;
+            case 'p': hostport = atoi(optarg); break;
+            case 't': testing  = 1; break;
+            case 'd': debug    = 1; break;
+            case 'v': verbose  = 1; break;
+            case 'h':
+            // fall thru
+            default : result   = 1; break;
+        }
+    }
+
+    // verify that required options are provided
+    if(hostname == NULL || strlen(hostname) == 0)
+    {
+        fprintf(stderr,"ERROR: The server name is required. (-s [hostname])\n");
+        result = 1;
+    }
+
+    if(hostport <= 0)
+    {
+        fprintf(stderr,"ERROR: The server port is required. (-p [port])\n");
+        result = 1;
+    }
+
+    return result;
+}
+
+void usage()
+{
+    fprintf(stdout,"\n");
+    fprintf(stdout,"Usage: ovirt-identify [OPTION]\n");
+    fprintf(stdout,"\n");
+    fprintf(stdout,"\t-s [server]\t\tThe remote server's hostname.\n");
+    fprintf(stdout,"\t-p [port]\t\tThe remote server's port.\n");
+    fprintf(stdout,"\t-d\t\tDisplays debug information during execution.\n");
+    fprintf(stdout,"\t-v\t\tDisplays verbose information during execution.\n");
+    fprintf(stdout,"\t-h\t\tDisplays this help information and then exits.\n");
+    fprintf(stdout,"\n");
+}
+
+int start_conversation(void)
+{
+    int result = 1;
+
+    if(verbose || debug) fprintf(stdout,"Starting conversation with %s:%d.\n",hostname,hostport);
+
+    if(!create_connection())
+    {
+        if(debug || verbose) fprintf(stdout,"Connected.\n");
+
+        char buffer[BUFFER_LENGTH];
+
+        get_text(buffer,sizeof buffer);
+
+        if(!strcmp(buffer,"HELLO?"))
+        {
+            if(debug) fprintf(stdout,"Checking for handshake.\n");
+
+            if(!send_text("HELLO!"))
+            {
+                if(debug) fprintf(stdout,"Handshake received. Starting conversation.\n");
+
+                get_text(buffer,sizeof buffer);
+
+                if(!strcmp(buffer,"MODE?"))
+                {
+                    if(debug) fprintf(stdout,"Shifting to IDENTIFY mode.\n");
+
+                    if(!send_text("IDENTIFY")) result = 0;
+                }
+                else
+                {
+                    if(debug) fprintf(stderr,"Was not asked for a mode.\n");
+                }
+            }
+        }
+        else
+        {
+            if(debug) fprintf(stderr,"Did not receive a proper handshake.\n");
+        }
+    }
+
+    else
+    {
+        if(debug) fprintf(stderr,"Did not get a connection.\n");
+    }
+
+    if(debug) fprintf(stdout,"start_conversation: result=%d\n", result);
+
+    return result;
+}
+
+int send_value(char* label,char* value)
+{
+    char buffer[BUFFER_LENGTH];
+
+    bzero(buffer,sizeof buffer);
+
+    sprintf(buffer,"%s=%s", label, value);
+
+    int result = 1;
+
+    if(!send_text(buffer))
+    {
+        char expected[BUFFER_LENGTH];
+
+        bzero(expected,sizeof buffer);
+        bzero(buffer,sizeof buffer);
+
+        get_text(buffer,sizeof buffer);
+
+        sprintf(expected, "ACK %s", label);
+
+        if(debug) fprintf(stdout,"Expecting \"%s\" : Received \"%s\"\n", expected, buffer);
+
+        if(!strcmp(expected,buffer))
+        {
+            result = 0;
+        }
+    }
+
+    return result;
+}
+
+int send_details(void)
+{
+    int result = 1;
+
+    fprintf(stdout,"Sending node details.\n");
+
+    char buffer[BUFFER_LENGTH];
+
+    get_text(buffer,sizeof buffer);
+
+    if(!strcmp(buffer,"INFO?"))
+    {
+        if((!send_value("ARCH",     arch))     &&
+           (!send_value("UUID",     uuid))     &&
+           (!send_value("NUMCPUS",  numcpus))  &&
+           (!send_value("CPUSPEED", cpuspeed)) &&
+           (!send_value("MEMSIZE",  memsize)))
+        {
+            if(!send_text("ENDINFO")) result = 0;
+        }
+    }
+    else
+    {
+        if(debug) fprintf(stdout,"Was not interrogated for hardware info.\n");
+    }
+
+    return result;
+}
+
+int end_conversation(void)
+{
+    int result = 0;
+
+    fprintf(stdout,"Ending conversation.\n");
+
+    send_text("ENDINFO");
+
+    close(socketfd);
+
+    return result;
+}
+
+ssize_t safewrite(int fd, const void *buf, size_t count)
+{
+        size_t nwritten = 0;
+        while (count > 0) {
+                ssize_t r = write(fd, buf, count);
+
+                if (r < 0 && errno == EINTR)
+                        continue;
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return nwritten;
+                buf = (const char *)buf + r;
+                count -= r;
+                nwritten += r;
+        }
+        return nwritten;
+}
+
+int send_text(char* text)
+{
+    int result = 1;
+
+    if(debug || verbose) fprintf(stdout,"\"%s\" -> %s:%d\n", text, hostname, hostport);
+
+    char buffer[strlen(text) + 2];
+
+    sprintf(buffer,"%s\n",text);
+
+    // int sent = write(socketfd,buffer,strlen(buffer));
+
+    int sent = safewrite(socketfd, buffer, strlen(buffer));
+
+    if(sent >= 0)
+    {
+        if(debug) fprintf(stdout,"Sent %d bytes total.\n", sent);
+
+        result = 0;
+    }
+
+    return result;
+}
+
+int saferead(int fd, void *buf, size_t count)
+{
+    if(debug) fprintf(stdout,"Begin saferead(%d, %x, %d)\n", fd, (unsigned int)buf, count);
+
+    while (1)
+    {
+        ssize_t r = read (fd, buf, count);
+        if (r < 0 && errno == EINTR) continue;
+        return r;
+    }
+}
+
+int get_text(char* response,int maxlength)
+{
+    if(debug) fprintf(stdout,"Reading up to %d bytes from socket.\n", maxlength);
+    // int received = read(socketfd,response,maxlength);
+    int received = saferead(socketfd,response,maxlength);
+
+    response[received - 1] = 0;
+
+    if(debug) fprintf(stdout,"Received \"%s\": size=%d (trimmed ending carriage return)\n", response, received);
+
+    return received;
+}
+
+int create_connection(void)
+{
+    int result = 1;
+
+    if(debug) fprintf(stdout,"Creating the socket connection.\n");
+
+    struct addrinfo hints;
+    struct addrinfo* results;
+
+    memset(&hints, 0, sizeof(struct addrinfo));
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_flags = 0;
+    hints.ai_protocol = 0;
+
+    if(debug) fprintf(stdout,"Searching for host candidates.\n");
+
+    char port[6];
+
+    sprintf(port,"%d", hostport);
+
+    if(!getaddrinfo(hostname, port, &hints, &results))
+    {
+        if(debug) fprintf(stdout,"Got address information. Searching for a proper entry.\n");
+        struct addrinfo* rptr;
+
+        for(rptr = results; rptr != NULL; rptr = rptr->ai_next)
+        {
+            if(debug)
+            {
+                fprintf(stdout,"Attempting connection: family=%d, socket type=%d, protocol=%d\n",
+                rptr->ai_family, rptr->ai_socktype, rptr->ai_protocol);
+            }
+
+            socketfd = socket(rptr->ai_family, rptr->ai_socktype, rptr->ai_protocol);
+
+            if(socketfd == -1)
+            {
+                continue;
+            }
+
+            if(connect(socketfd, rptr->ai_addr, rptr->ai_addrlen) != -1)
+            {
+                break;
+            }
+
+            //  invalid connection, so close it
+            if(debug) fprintf(stdout, "Invalid connection.\n");
+            close(socketfd);
+        }
+
+        if(rptr == NULL)
+        {
+            if(debug) fprintf(stdout,"Unable to connect to server %s:%d\n", hostname, hostport);
+        }
+        else
+        {
+            // success
+            result = 0;
+        }
+
+        freeaddrinfo(results);
+    }
+    else
+    {
+        if(debug) fprintf(stderr,"No hosts found. Exiting...\n");
+    }
+
+    if(debug) fprintf(stdout, "create_connection: result=%d\n", result);
+
+    return result;
+}
diff --git a/ovirt-managed-node/ovirt-managed-node.spec b/ovirt-managed-node/ovirt-managed-node.spec
new file mode 100644
index 0000000..7f33344
--- /dev/null
+++ b/ovirt-managed-node/ovirt-managed-node.spec
@@ -0,0 +1,45 @@
+Summary:        The managed node demons for oVirt.
+Name:           ovirt-managed-node
+Version:        0.1
+Release:        1%{?dist}
+License:        Fedora
+Group:          Applications/System
+Source0:        http://www.ovirt.org/sources/%{name}-%{version}.tar
+
+BuildRoot:      %{_tmppath}/%{name}-%{version}-root
+URL:            http://www.ovirt.org/
+BuildRequires:  libvirt-devel
+Requires:       libvirt
+ExclusiveArch:  %{ix86} x86_64 ia64
+
+
+%description
+Provides a series of daemons and support utilities to allow an
+oVirt managed node to interact with the oVirt server.
+
+
+%prep
+%setup
+
+rm -rf $RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT
+
+
+%build
+make
+
+mkdir -p $RPM_BUILD_ROOT/sbin
+cp ovirt-awake         $RPM_BUILD_ROOT/sbin
+cp ovirt-identify      $RPM_BUILD_ROOT/sbin
+cp ovirt-identify-node $RPM_BUILD_ROOT/sbin
+
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(755,root,root)
+%doc README NEWS AUTHOR ChangeLog
+/sbin/ovirt-awake
+/sbin/ovirt-identify
+/sbin/ovirt-identify-node
diff --git a/wui/src/host-browser/host-browser.rb b/wui/src/host-browser/host-browser.rb
index e127ddb..3e242cf 100755
--- a/wui/src/host-browser/host-browser.rb
+++ b/wui/src/host-browser/host-browser.rb
@@ -1,5 +1,5 @@
 #!/usr/bin/ruby -Wall
-# 
+#
 # Copyright (C) 2008 Red Hat, Inc.
 # Written by Darryl L. Pierce <dpierce at redhat.com>
 #
@@ -41,7 +41,7 @@ class HostBrowser
     attr_accessor :logfile
     attr_accessor :keytab_dir
     attr_accessor :keytab_filename
-  
+
     def initialize(session)
         @session = session
         @log_prefix = "[#{session.peeraddr[3]}] "
@@ -51,19 +51,31 @@ class HostBrowser
     # Ensures the conversation starts properly.
     #
     def begin_conversation
-        puts "#{@log_prefix} Begin conversation"
+        puts "#{@log_prefix} Begin conversation" unless defined?(TESTING)
         @session.write("HELLO?\n")
 
         response = @session.readline.chomp
         raise Exception.new("received #{response}, expected HELLO!") unless response == "HELLO!"
     end
 
+    # Retrieves the mode request from the remote system.
+    #
+    def get_mode
+        puts "#{@log_prefix} Determining the runtime mode." unless defined?(TESTING)
+        @session.write("MODE?\n")
+        response = @session.readline.chomp
+        puts "#{@log_prefix} MODE=#{response}" unless defined?(TESTING)
+
+        response
+    end
+
     # Requests node information from the remote system.
     #
     def get_remote_info
-        puts "#{@log_prefix} Begin remote info collection"
+        puts "#{@log_prefix} Begin remote info collection" unless defined?(TESTING)
         result = {}
-        result['IPADDR'] = @session.peeraddr[3]
+        result['HOSTNAME'] = @session.peeraddr[2]
+        result['IPADDR']   = @session.peeraddr[3]
         @session.write("INFO?\n")
 
         loop do
@@ -75,9 +87,9 @@ class HostBrowser
 
             key, value = info.split("=")
 
-            puts "#{@log_prefix} ::Received - #{key}:#{value}"
+            puts "#{@log_prefix} ::Received - #{key}:#{value}" unless defined?(TESTING)
             result[key] = value
-        
+
             @session.write("ACK #{key}\n")
         end
 
@@ -94,13 +106,13 @@ class HostBrowser
         ensure_present(host_info,'ARCH')
         ensure_present(host_info,'MEMSIZE')
 
-        puts "Searching for existing host record..."
+        puts "Searching for existing host record..." unless defined?(TESTING)
         host = Host.find(:first, :conditions => ["uuid = ?", host_info['UUID']])
 
         if host == nil
             begin
-                puts "Creating a new record for #{host_info['HOSTNAME']}..."
-            
+                puts "Creating a new record for #{host_info['HOSTNAME']}..." unless defined?(TESTING)
+
                 Host.new(
                     "uuid"            => host_info['UUID'],
                     "hostname"        => host_info['HOSTNAME'],
@@ -115,7 +127,7 @@ class HostBrowser
                     # successfully connects to it via libvirt.
                     "state"           => "unavailable").save
             rescue Exception => error
-                puts "Error while creating record: #{error.message}"
+                puts "Error while creating record: #{error.message}" unless defined?(TESTING)
             end
         else
             host.uuid         = host_info['UUID']
@@ -125,45 +137,45 @@ class HostBrowser
             host.arch         = host_info['ARCH']
             host.memory_in_mb = host_info['MEMSIZE']
         end
-    
+
         return host
     end
 
-    # Ends the conversation, notifying the user of the key version number.
-    #
-    def end_conversation(ktab)
-        puts "#{@log_prefix} Ending conversation"
-
-        @session.write("KTAB #{ktab}\n")
-
-        response = @session.readline.chomp
-
-        raise Exception.new("ERROR! Malformed response : expected ACK, got #{response}") unless response == "ACK"
-
-        @session.write("BYE\n");
-    end
-  
     # Creates a keytab if one is needed, returning the filename.
     #
-    def create_keytab(host_info, krb5_arg = nil)
+    def create_keytab(hostname, ipaddress, krb5_arg = nil)
         krb5 = krb5_arg || Krb5.new
-  
+
         default_realm = krb5.get_default_realm
-        libvirt_princ = 'libvirt/' + host_info['HOSTNAME'] + '@' + default_realm
-        outfile = host_info['IPADDR'] + '-libvirt.tab'
+        libvirt_princ = 'libvirt/' + hostname + '@' + default_realm
+        outfile = ipaddress + '-libvirt.tab'
         @keytab_filename = @keytab_dir + outfile
 
         # TODO need a way to test this portion
         unless defined? TESTING || File.exists?(@keytab_filename)
             # TODO replace with Kr5Auth when it supports admin actions
-            puts "Writing keytab file: #{@keytab_filename}"
+            puts "Writing keytab file: #{@keytab_filename}" unless defined?(TESTING)
             kadmin_local('addprinc -randkey ' + libvirt_princ)
             kadmin_local('ktadd -k ' + @keytab_filename + ' ' + libvirt_princ)
 
             File.chmod(0644, at keytab_filename)
         end
 
-        return outfile
+        hostname = `hostname -f`.chomp
+
+        @session.write("KTAB http://#{hostname}/config/#{outfile}\n")
+
+        response = @session.readline.chomp
+
+        raise Exception.new("ERRINFO! No keytab acknowledgement") unless response == "ACK"
+    end
+
+    # Ends the conversation, notifying the user of the key version number.
+    #
+    def end_conversation
+        puts "#{@log_prefix} Ending conversation" unless defined?(TESTING)
+
+        @session.write("BYE\n");
     end
 
     private
@@ -185,35 +197,37 @@ def entry_point(server)
     while(session = server.accept)
         child = fork do
             remote = session.peeraddr[3]
-            
-            puts "Connected to #{remote}"
+
+            puts "Connected to #{remote}" unless defined?(TESTING)
 
             # This is needed because we just forked a new process
             # which now needs its own connection to the database.
             database_connect
-      
+
             begin
                 browser = HostBrowser.new(session)
 
                 browser.begin_conversation
-                host_info = browser.get_remote_info
-                browser.write_host_info(host_info)
-                keytab = browser.create_keytab(host_info)
-                browser.end_conversation(keytab)
+                case browser.get_mode
+                    when "AWAKEN": browser.create_keytab(remote,session.peeraddr[3])
+                    when "IDENTIFY": browser.write_host_info(browser.get_remote_info)
+                end
+
+                browser.end_conversation
             rescue Exception => error
                 session.write("ERROR #{error.message}\n")
-                puts "ERROR #{error.message}"
+                puts "ERROR #{error.message}" unless defined?(TESTING)
             end
-      
-            puts "Disconnected from #{remote}"
+
+            puts "Disconnected from #{remote}" unless defined?(TESTING)
         end
-    
-        Process.detach(child)        
-    end      
+
+        Process.detach(child)
+    end
 end
 
 unless defined?(TESTING)
-  
+
     # The main entry point.
     #
     unless ARGV[0] == "-n"
diff --git a/wui/src/host-browser/test-host-browser-awaken.rb b/wui/src/host-browser/test-host-browser-awaken.rb
new file mode 100755
index 0000000..a5ca2e7
--- /dev/null
+++ b/wui/src/host-browser/test-host-browser-awaken.rb
@@ -0,0 +1,94 @@
+#!/usr/bin/ruby -Wall
+#
+# Copyright (C) 2008 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA  02110-1301, USA.  A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+require File.dirname(__FILE__) + '/../test/test_helper'
+require 'test/unit'
+require 'flexmock/test_unit'
+
+TESTING=true
+
+require 'host-browser'
+
+# +TestHostBrowserAwaken+
+class TestHostBrowserAwaken < Test::Unit::TestCase
+
+  def setup
+    @session = flexmock('session')
+    @session.should_receive(:peeraddr).at_least.once.returns { [nil,nil,nil,"192.168.2.255"] }
+
+    @krb5 = flexmock('krb5')
+
+    @browser = HostBrowser.new(@session)
+    @browser.logfile = './unit-test.log'
+    @browser.keytab_dir = '/var/temp/'
+  end
+
+  # Ensures that the server raises an exception when it receives an
+  # improper handshake response.
+  #
+  def test_begin_conversation_with_improper_response_to_greeting
+    @session.should_receive(:write).with("HELLO?\n").once().returns { |greeting| greeting.length }
+    @session.should_receive(:readline).once().returns { "SUP?" }
+
+    assert_raise(Exception) { @browser.begin_conversation }
+  end
+
+  # Ensures the server accepts a proper response from the remote system.
+  #
+  def test_begin_conversation
+    @session.should_receive(:write).with("HELLO?\n").once().returns { |greeting| greeting.length }
+    @session.should_receive(:readline).once().returns { "HELLO!\n" }
+
+    assert_nothing_raised(Exception) { @browser.begin_conversation }
+  end
+
+  # Ensures that the server is satisfied if the remote system is
+  # making a wakeup call.
+  #
+  def test_get_mode_with_awaken_request
+    @session.should_receive(:write).with("MODE?\n").once().returns { |request| request.length }
+    @session.should_receive(:readline).once().returns { "AWAKEN\n" }
+
+    result = @browser.get_mode()
+
+    assert_equal "AWAKEN", result, "method did not return the right value"
+  end
+
+  # Ensures the host browser generates a keytab as expected.
+  #
+  def test_create_keytab
+    @krb5.should_receive(:get_default_realm).once().returns { "ovirt-test-realm" }
+    servername = `hostname -f`.chomp
+    @session.should_receive(:write).with("KTAB http://#{servername}/config/127.0.0.1-libvirt.tab\n").once().returns { |request| request.length }
+    @session.should_receive(:readline).once().returns { "ACK\n" }
+
+    assert_nothing_raised(Exception) { @browser.create_keytab('localhost','127.0.0.1', at krb5) }
+  end
+
+  # Ensures that, if a keytab is present and a key version number available,
+  # the server ends the conversation by returning the key version number.
+  #
+  def test_end_conversation
+    @session.should_receive(:write).with("BYE\n").once().returns { |request| request.length }
+
+    assert_nothing_raised(Exception) { @browser.end_conversation }
+  end
+
+end
diff --git a/wui/src/host-browser/test-host-browser-identify.rb b/wui/src/host-browser/test-host-browser-identify.rb
new file mode 100755
index 0000000..a70884d
--- /dev/null
+++ b/wui/src/host-browser/test-host-browser-identify.rb
@@ -0,0 +1,162 @@
+#!/usr/bin/ruby -Wall
+#
+# Copyright (C) 2008 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA  02110-1301, USA.  A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+require File.dirname(__FILE__) + '/../test/test_helper'
+require 'test/unit'
+require 'flexmock/test_unit'
+
+TESTING=true
+
+require 'host-browser'
+
+class TestHostBrowser < Test::Unit::TestCase
+
+  def setup
+    @session = flexmock('session')
+    @session.should_receive(:peeraddr).at_least.once.returns { [nil,nil,nil,"192.168.2.255"] }
+
+    @browser = HostBrowser.new(@session)
+    @browser.logfile = './unit-test.log'
+
+    # default host info
+    @host_info = {}
+    @host_info['UUID']     = 'node1'
+    @host_info['IPADDR']   = '192.168.2.2'
+    @host_info['HOSTNAME'] = 'node1.ovirt.redhat.com'
+    @host_info['NUMCPUS']  = '3'
+    @host_info['CPUSPEED'] = '3'
+    @host_info['ARCH']     = 'x86_64'
+    @host_info['MEMSIZE']  = '16384'
+    @host_info['DISABLED'] = '0'
+  end
+
+  # Ensures that the server is satisfied if the remote system is
+  # making a wakeup call.
+  #
+  def test_get_mode_with_awaken_request
+    @session.should_receive(:write).with("MODE?\n").once().returns { |request| request.length }
+    @session.should_receive(:readline).once().returns { "IDENTIFY\n" }
+
+    result = @browser.get_mode()
+
+    assert_equal "IDENTIFY", result, "method did not return the right value"
+  end
+
+  # Ensures that, if an info field is missing a key, the server raises
+  # an exception.
+  #
+  def test_get_info_with_missing_key
+    @session.should_receive(:write).with("INFO?\n").once().returns { |request| request.length }
+    @session.should_receive(:readline).once().returns { "=value1\n" }
+
+    assert_raise(Exception) { @browser.get_remote_info }
+  end
+
+  # Ensures that, if an info field is missing a value, the server raises
+  # an exception.
+  #
+  def test_get_info_with_missing_value
+    @session.should_receive(:write).with("INFO?\n").once().returns { |request| request.length }
+    @session.should_receive(:readline).once().returns { "key1=\n" }
+
+    assert_raise(Exception) { @browser.get_remote_info }
+  end
+
+  # Ensures that, if the server gets a poorly formed ending statement, it
+  # raises an exception.
+  #
+  def test_get_info_with_invalid_end
+    @session.should_receive(:write).with("INFO?\n").once().returns { |request| request.length }
+    @session.should_receive(:readline).once().returns { "key1=value1\n" }
+    @session.should_receive(:write).with("ACK key1\n").once().returns { |request| request.length }
+    @session.should_receive(:readline).once().returns { "ENDIFNO\n" }
+
+    assert_raise(Exception) { @browser.get_remote_info }
+  end
+
+  # Ensures that a well-formed transaction works as expected.
+  #
+  def test_get_info
+    @session.should_receive(:write).with("INFO?\n").once().returns { |request| request.length }
+    @session.should_receive(:readline).once().returns { "key1=value1\n" }
+    @session.should_receive(:write).with("ACK key1\n").once().returns { |request| request.length }
+    @session.should_receive(:readline).once().returns { "key2=value2\n" }
+    @session.should_receive(:write).with("ACK key2\n").once().returns { |request| request.length }
+    @session.should_receive(:readline).once().returns { "ENDINFO\n" }
+
+    info = @browser.get_remote_info
+
+    assert_equal 4,info.keys.size, "Should contain two keys"
+    assert info.include?("IPADDR")
+    assert info.include?("HOSTNAME")
+    assert info.include?("key1")
+    assert info.include?("key2")
+  end
+
+  # Ensures that, if no UUID is present, the server raises an exception.
+  #
+  def test_write_host_info_with_missing_uuid
+    @host_info['UUID'] = nil
+
+    assert_raise(Exception) { @browser.write_host_info(@host_info) }
+  end
+
+  # Ensures that, if the hostname is missing, the server
+  # raises an exception.
+  #
+  def test_write_host_info_with_missing_hostname
+    @host_info['HOSTNAME'] = nil
+
+    assert_raise(Exception) { @browser.write_host_info(@host_info) }
+  end
+
+  # Ensures that, if the number of CPUs is missing, the server raises an exception.
+  #
+  def test_write_host_info_with_missing_numcpus
+    @host_info['NUMCPUS'] = nil
+
+    assert_raise(Exception) { @browser.write_host_info(@host_info) }
+  end
+
+  # Ensures that, if the CPU speed is missing, the server raises an exception.
+  #
+  def test_write_host_info_with_missing_cpuspeed
+    @host_info['CPUSPEED'] = nil
+
+    assert_raise(Exception) { @browser.write_host_info(@host_info) }
+  end
+
+  # Ensures that, if the architecture is missing, the server raises an exception.
+  #
+  def test_write_host_info_with_missing_arch
+    @host_info['ARCH'] = nil
+
+    assert_raise(Exception) { @browser.write_host_info(@host_info) }
+  end
+
+  # Ensures that, if the memory size is missing, the server raises an exception.
+  #
+  def test_write_host_info_info_with_missing_memsize
+    @host_info['MEMSIZE'] = nil
+
+    assert_raise(Exception) { @browser.write_host_info(@host_info) }
+  end
+
+end
diff --git a/wui/src/host-browser/test-host-browser.rb b/wui/src/host-browser/test-host-browser.rb
deleted file mode 100755
index 6f4c660..0000000
--- a/wui/src/host-browser/test-host-browser.rb
+++ /dev/null
@@ -1,204 +0,0 @@
-#!/usr/bin/ruby -Wall
-#
-# Copyright (C) 2008 Red Hat, Inc.
-# Written by Darryl L. Pierce <dpierce at redhat.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-# MA  02110-1301, USA.  A copy of the GNU General Public License is
-# also available at http://www.gnu.org/copyleft/gpl.html.
-
-require File.dirname(__FILE__) + '/../test/test_helper'
-require 'test/unit'
-require 'flexmock/test_unit'
-
-TESTING=true
-
-require 'host-browser'
-
-class TestHostBrowser < Test::Unit::TestCase
-
-  def setup
-    @session = flexmock('session')
-    @session.should_receive(:peeraddr).at_least.once.returns { [nil,nil,nil,"192.168.2.255"] }
-
-    @krb5 = flexmock('krb5')
-
-    @browser = HostBrowser.new(@session)
-    @browser.logfile = './unit-test.log'
-    @browser.keytab_dir = '/var/temp/'
-
-    # default host info
-    @host_info = {}
-    @host_info['UUID']     = 'node1'
-    @host_info['IPADDR']   = '192.168.2.2'
-    @host_info['HOSTNAME'] = 'node1.ovirt.redhat.com'
-    @host_info['NUMCPUS']  = '3'
-    @host_info['CPUSPEED'] = '3'
-    @host_info['ARCH']     = 'x86_64'
-    @host_info['MEMSIZE']  = '16384'
-    @host_info['DISABLED'] = '0'
-  end
-
-  # Ensures that the server raises an exception when it receives an
-  # improper handshake response.
-  #
-  def test_begin_conversation_with_improper_response_to_greeting
-    @session.should_receive(:write).with("HELLO?\n").once().returns { |greeting| greeting.length }
-    @session.should_receive(:readline).once().returns { "SUP?" }
-
-    assert_raise(Exception) { @browser.begin_conversation }
-  end
-
-  # Ensures the server accepts a proper response from the remote system.
-  #
-  def test_begin_conversation
-    @session.should_receive(:write).with("HELLO?\n").once().returns { |greeting| greeting.length }
-    @session.should_receive(:readline).once().returns { "HELLO!\n" }
-
-    assert_nothing_raised(Exception) { @browser.begin_conversation }
-  end
-
-  # Ensures that the server raises an exception when it receives
-  # poorly formed data while exchanging system information.
-  #
-  def test_get_info_with_bad_handshake
-    @session.should_receive(:write).with("INFO?\n").once().returns { |request| request.length }
-    @session.should_receive(:readline).once().returns { "key1=value1\n" }
-    @session.should_receive(:write).with("ACK key1\n").once().returns { |request| request.length }
-    @session.should_receive(:readline).once().returns { "farkledina\n" }
-
-    assert_raise(Exception) { @browser.get_remote_info }
-  end
-
-  # Ensures that, if an info field is missing a key, the server raises
-  # an exception.
-  #
-  def test_get_info_with_missing_key
-    @session.should_receive(:write).with("INFO?\n").once().returns { |request| request.length }
-    @session.should_receive(:readline).once().returns { "=value1\n" }
-
-    assert_raise(Exception) { @browser.get_remote_info }
-  end
-
-  # Ensures that, if an info field is missing a value, the server raises
-  # an exception.
-  #
-  def test_get_info_with_missing_value
-    @session.should_receive(:write).with("INFO?\n").once().returns { |request| request.length }
-    @session.should_receive(:readline).once().returns { "key1=\n" }
-
-    assert_raise(Exception) { @browser.get_remote_info }
-  end
-
-  # Ensures that, if the server gets a poorly formed ending statement, it
-  # raises an exception.
-  #
-  def test_get_info_with_invalid_end
-    @session.should_receive(:write).with("INFO?\n").once().returns { |request| request.length }
-    @session.should_receive(:readline).once().returns { "key1=value1\n" }
-    @session.should_receive(:write).with("ACK key1\n").once().returns { |request| request.length }
-    @session.should_receive(:readline).once().returns { "ENDIFNO\n" }
-
-    assert_raise(Exception) { @browser.get_remote_info }
-  end
-
-  # Ensures that a well-formed transaction works as expected.
-  #
-  def test_get_info
-    @session.should_receive(:write).with("INFO?\n").once().returns { |request| request.length }
-    @session.should_receive(:readline).once().returns { "key1=value1\n" }
-    @session.should_receive(:write).with("ACK key1\n").once().returns { |request| request.length }
-    @session.should_receive(:readline).once().returns { "key2=value2\n" }
-    @session.should_receive(:write).with("ACK key2\n").once().returns { |request| request.length }
-    @session.should_receive(:readline).once().returns { "ENDINFO\n" }
-
-    info = @browser.get_remote_info
-
-    assert_equal 3,info.keys.size, "Should contain two keys"
-    assert info.include?("IPADDR")
-    assert info.include?("key1")
-    assert info.include?("key2")
-  end
-
-  # Ensures the host browser generates a keytab as expected.
-  #
-  def test_create_keytab
-    @krb5.should_receive(:get_default_realm).once().returns { "ovirt-test-realm" }
-
-    result = @browser.create_keytab(@host_info, at krb5)
-
-    assert_equal @browser.keytab_filename, result, "Should have returned the keytab filename"
-  end
-
-  # Ensures that, if no UUID is present, the server raises an exception.
-  #
-  def test_write_host_info_with_missing_uuid
-    @host_info['UUID'] = nil
-
-    assert_raise(Exception) { @browser.write_host_info(@host_info) }
-  end
-
-  # Ensures that, if the hostname is missing, the server
-  # raises an exception.
-  #
-  def test_write_host_info_with_missing_hostname
-    @host_info['HOSTNAME'] = nil
-
-    assert_raise(Exception) { @browser.write_host_info(@host_info) }
-  end
-
-  # Ensures that, if the number of CPUs is missing, the server raises an exception.
-  #
-  def test_write_host_info_with_missing_numcpus
-    @host_info['NUMCPUS'] = nil
-
-    assert_raise(Exception) { @browser.write_host_info(@host_info) }
-  end
-
-  # Ensures that, if the CPU speed is missing, the server raises an exception.
-  #
-  def test_write_host_info_with_missing_cpuspeed
-    @host_info['CPUSPEED'] = nil
-
-    assert_raise(Exception) { @browser.write_host_info(@host_info) }
-  end
-
-  # Ensures that, if the architecture is missing, the server raises an exception.
-  #
-  def test_write_host_info_with_missing_arch
-    @host_info['ARCH'] = nil
-
-    assert_raise(Exception) { @browser.write_host_info(@host_info) }
-  end
-
-  # Ensures that, if the memory size is missing, the server raises an exception.
-  #
-  def test_write_host_info_info_with_missing_memsize
-    @host_info['MEMSIZE'] = nil
-
-    assert_raise(Exception) { @browser.write_host_info(@host_info) }
-  end
-
-  # Ensures that, if a keytab is present and a key version number available,
-  # the server ends the conversation by returning the key version number.
-  #
-  def test_end_conversation
-    @session.should_receive(:write).with("KTAB 12345\n").once().returns { |request| request.length }
-    @session.should_receive(:readline).once().returns { "ACK\n" }
-    @session.should_receive(:write).with("BYE\n").once().returns { |request| request.length }
-
-    assert_nothing_raised(Exception) { @browser.end_conversation(12345) }
-  end
-
-end
diff --git a/wui/version b/wui/version
index f644984..538368d 100644
--- a/wui/version
+++ b/wui/version
@@ -1 +1 @@
-0.91 1
+0.92 0.1.200806240034git63f6a5a
-- 
1.5.5.1




More information about the ovirt-devel mailing list