[Ovirt-devel] [PATCH] ovirt-identify-node now submits all extended CPU details.
Darryl L. Pierce
dpierce at redhat.com
Tue Jul 8 14:06:03 UTC 2008
From: Darryl Pierce <dpierce at redhat.com>
Signed-off-by: Darryl L. Pierce <dpierce at redhat.com>
---
ovirt-managed-node/src/ovirt-identify-node.c | 420 +++++++++++++++-----
ovirt-managed-node/src/ovirt-identify-node.h | 56 +++
wui/src/app/models/cpu.rb | 24 ++
wui/src/app/models/host.rb | 23 +-
wui/src/db/migrate/010_create_cpus.rb | 32 ++
wui/src/dutils/active_record_env.rb | 5 +-
wui/src/host-browser/host-browser.rb | 103 +++++-
wui/src/host-browser/test-host-browser-awake.rb | 94 +++++
wui/src/host-browser/test-host-browser-awaken.rb | 94 -----
wui/src/host-browser/test-host-browser-identify.rb | 345 ++++++++++------
wui/src/test/fixtures/cpus.yml | 21 +
wui/src/test/fixtures/hosts.yml | 24 +-
wui/src/test/unit/cpu_test.rb | 8 +
13 files changed, 881 insertions(+), 368 deletions(-)
create mode 100644 ovirt-managed-node/src/ovirt-identify-node.h
create mode 100644 wui/src/app/models/cpu.rb
create mode 100644 wui/src/db/migrate/010_create_cpus.rb
create mode 100755 wui/src/host-browser/test-host-browser-awake.rb
delete mode 100755 wui/src/host-browser/test-host-browser-awaken.rb
create mode 100644 wui/src/test/fixtures/cpus.yml
create mode 100644 wui/src/test/unit/cpu_test.rb
diff --git a/ovirt-managed-node/src/ovirt-identify-node.c b/ovirt-managed-node/src/ovirt-identify-node.c
index 819f700..f114d81 100644
--- a/ovirt-managed-node/src/ovirt-identify-node.c
+++ b/ovirt-managed-node/src/ovirt-identify-node.c
@@ -31,31 +31,7 @@
#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(const char *const expected);
-int create_connection(void);
-
-int debug = 1;
-int verbose = 1;
-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;
-int hostport = -1;
-int socketfd;
+#include "ovirt-identify-node.h"
int main(int argc,char** argv)
{
@@ -63,9 +39,11 @@ int main(int argc,char** argv)
virConnectPtr connection;
virNodeInfo info;
+ fprintf(stdout,"Sending managed node details to server.\n");
+
if(!config(argc,argv))
{
- fprintf(stdout,"Connecting to libvirt.\n");
+ if(verbose) fprintf(stdout,"Connecting to libvirt.\n");
connection = virConnectOpenReadOnly(testing ? "test:///default" : NULL);
@@ -73,42 +51,68 @@ int main(int argc,char** argv)
if(connection)
{
- if(debug) fprintf(stdout,"Getting hostname: %s\n", uuid);
+ if(verbose) fprintf(stdout,"Getting hostname: %s\n", uuid);
if(!strlen(uuid)) gethostname(uuid,sizeof uuid);
- if(debug) fprintf(stdout,"Retrieving node information.\n");
+ if(verbose) fprintf(stdout,"Retrieving node information.\n");
if(!virNodeGetInfo(connection,&info))
{
snprintf(arch, BUFFER_LENGTH, "%s", info.model);
snprintf(memsize, BUFFER_LENGTH, "%ld", info.memory);
- snprintf(numcpus, BUFFER_LENGTH, "%d", info.cpus);
- snprintf(cpuspeed, BUFFER_LENGTH, "%d", info.mhz);
- if(debug)
+ cpu_info = NULL;
+
+ if(!get_cpu_info())
{
- 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(verbose) fprintf(stdout, "Getting CPU info.\n");
+
+ 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);
+
+ t_cpu_info* current = cpu_info;
+ while(current != NULL)
+ {
+ fprintf(stdout,"\n");
+ fprintf(stdout," CPU Number: %s\n", current->cpu_num);
+ fprintf(stdout," Core Number: %s\n", current->core_num);
+ fprintf(stdout,"Number of Cores: %s\n", current->number_of_cores);
+ fprintf(stdout," Vendor: %s\n", current->vendor);
+ fprintf(stdout," Model: %s\n", current->model);
+ fprintf(stdout," Family: %s\n", current->family);
+ fprintf(stdout," CPUID Level: %s\n", current->cpuid_level);
+ fprintf(stdout," CPU Speed: %s\n", current->speed);
+ fprintf(stdout," Cache Size: %s\n", current->cache);
+ fprintf(stdout," CPU Flags: %s\n", current->flags);
+
+ current = current->next;
+ }
+ }
+
+ if(verbose) fprintf(stdout, "Retrieved node information.\n");
+
+ if(!start_conversation() && !send_details() && !end_conversation())
+ {
+ fprintf(stdout,"Finished!\n");
+ result = 0;
+ }
}
-
- if(debug) fprintf(stdout, "Retrieved node information.\n");
-
- if(!start_conversation() && !send_details() && !end_conversation())
+ else
{
- result = 0;
+ if(verbose) fprintf(stderr,"Failed to get CPU info.\n");
}
}
else
{
- if(debug) fprintf(stderr,"Failed to get node info.\n");
+ if(verbose) fprintf(stderr,"Failed to get node info.\n");
}
}
else
{
- if(debug) fprintf(stderr,"Could not connect to libvirt.\n");
+ if(verbose) fprintf(stderr,"Could not connect to libvirt.\n");
}
}
else
@@ -181,35 +185,35 @@ int start_conversation(void)
{
if(debug || verbose) fprintf(stdout,"Connected.\n");
- if (!get_text("HELLO?\n"))
+ if (!get_text("HELLO?"))
{
- if(debug) fprintf(stdout,"Checking for handshake.\n");
+ if(verbose) fprintf(stdout,"Checking for handshake.\n");
- if(!send_text("HELLO!\n"))
+ if(!send_text("HELLO!"))
{
- if(debug) fprintf(stdout,"Handshake received. Starting conversation.\n");
+ if(verbose) fprintf(stdout,"Handshake received. Starting conversation.\n");
- if(!get_text("MODE?\n"))
+ if(!get_text("MODE?"))
{
- if(debug) fprintf(stdout,"Shifting to IDENTIFY mode.\n");
+ if(verbose) fprintf(stdout,"Shifting to IDENTIFY mode.\n");
- if(!send_text("IDENTIFY\n")) result = 0;
+ if(!send_text("IDENTIFY")) result = 0;
}
else
{
- if(debug) fprintf(stderr,"Was not asked for a mode.\n");
+ if(verbose) fprintf(stderr,"Was not asked for a mode.\n");
}
}
}
else
{
- if(debug) fprintf(stderr,"Did not receive a proper handshake.\n");
+ if(verbose) fprintf(stderr,"Did not receive a proper handshake.\n");
}
}
else
{
- if(debug) fprintf(stderr,"Did not get a connection.\n");
+ if(verbose) fprintf(stderr,"Did not get a connection.\n");
}
if(debug) fprintf(stdout,"start_conversation: result=%d\n", result);
@@ -223,19 +227,15 @@ int send_value(char* label,char* value)
int result = 1;
char expected[BUFFER_LENGTH];
- snprintf(buffer,BUFFER_LENGTH,"%s=%s\n", label, value);
+ snprintf(buffer,BUFFER_LENGTH,"%s=%s", label, value);
if(!send_text(buffer))
{
- snprintf(expected, BUFFER_LENGTH, "ACK %s\n", label);
+ snprintf(expected, BUFFER_LENGTH, "ACK %s", label);
- if(debug) fprintf(stdout,"Expecting \"%s\"\n", expected);
-
- if (!get_text(expected))
- {
- result = 0;
- }
+ if(verbose) fprintf(stdout,"Expecting \"%s\"\n", expected);
+ result = get_text(expected);
}
return result;
@@ -245,40 +245,238 @@ int send_details(void)
{
int result = 1;
- fprintf(stdout,"Sending node details.\n");
+ if(verbose) fprintf(stdout,"Sending node details.\n");
- if (!get_text("INFO?\n"))
+ if (!get_text("INFO?"))
{
if((!send_value("ARCH", arch)) &&
(!send_value("UUID", uuid)) &&
- (!send_value("NUMCPUS", numcpus)) &&
- (!send_value("CPUSPEED", cpuspeed)) &&
- (!send_value("MEMSIZE", memsize)))
+ (!send_value("MEMSIZE", memsize)) &&
+ (!send_cpu_details()))
{
- if(!send_text("ENDINFO\n")) result = 0;
+ if(!send_text("ENDINFO")) result = 0;
}
}
else
{
- if(debug) fprintf(stdout,"Was not interrogated for hardware info.\n");
+ if(verbose) fprintf(stdout,"Was not interrogated for hardware info.\n");
}
return result;
}
+int send_cpu_details(void)
+{
+ int result = 1;
+ t_cpu_info* current = cpu_info;
+
+ while(current != NULL)
+ {
+ send_text("CPU");
+
+ if(!(get_text("CPUINFO?")) &&
+ (!send_value("CPUNUM",current->cpu_num)) &&
+ (!send_value("CORENUM",current->core_num)) &&
+ (!send_value("NUMCORES",current->number_of_cores)) &&
+ (!send_value("VENDOR",current->vendor)) &&
+ (!send_value("MODEL",current->model)) &&
+ (!send_value("FAMILY",current->family)) &&
+ (!send_value("CPUIDLVL",current->cpuid_level)) &&
+ (!send_value("SPEED",current->speed)) &&
+ (!send_value("CACHE", current->cache)) &&
+ (!send_value("FLAGS", current->flags)))
+ {
+ send_text("ENDCPU");
+ result = get_text("ACK CPU");
+ }
+
+ current = current->next;
+ }
+
+
+ return result;
+}
+
int end_conversation(void)
{
int result = 0;
- fprintf(stdout,"Ending conversation.\n");
+ if(debug || verbose) fprintf(stdout,"Ending conversation.\n");
- send_text("ENDINFO\n");
+ send_text("ENDINFO");
close(socketfd);
return result;
}
+void get_label_and_value(char* text,
+ char* label, size_t label_length,
+ char* value, size_t value_length)
+{
+ int offset = 0;
+ int which = 0; /* 0 = label, 1 = value */
+ char* current = text;
+
+ /* iterate through the text supplied and find where the
+ * label ends with a colon, then copy that into the supplied
+ * label buffer and trim any trailing spaces
+ */
+
+ while(current != NULL && *current != '\0')
+ {
+ /* if we're on the separator, then switch modes and reset
+ * the offset indicator, otherwise just process the character
+ */
+ if(which == 0 && *current == ':')
+ {
+ which = 1;
+ offset = 0;
+ }
+ else
+ {
+ char* buffer = (which == 0 ? label : value);
+ int length = (which == 0 ? label_length : value_length);
+
+ /* only copy if we're past the first character and it's not
+ * a space
+ */
+ if((offset > 0 || (*current != 9 && *current != ' ')) && offset < (length - 1))
+ {
+ buffer[offset++] = *current;
+ buffer[offset] = 0;
+ }
+ }
+
+ current++;
+ }
+
+ /* now trim all trailing spaces from the values */
+ while(label[strlen(label) - 1 ] == 9)
+ label[strlen(label) - 1] = 0;
+ while(value[strlen(value) - 1] == 9)
+ value[strlen(value) - 1] = 0;
+}
+
+int get_cpu_info(void)
+{
+ int result = 1;
+ FILE* inputfd;
+ t_cpu_info* current = NULL;
+
+ if(( inputfd = fopen("/proc/cpuinfo","rb")) != NULL)
+ {
+ if(verbose) fprintf(stdout,"Parsing CPU information\n");
+ do
+ {
+ char buffer[255];
+ char label[BUFFER_LENGTH];
+ char value[BUFFER_LENGTH];
+
+ fgets(buffer, 255, inputfd);
+ if(strlen(buffer) > 0) buffer[strlen(buffer) - 1] = '\0';
+
+ get_label_and_value(buffer,
+ label,BUFFER_LENGTH,
+ value,BUFFER_LENGTH);
+
+ if(debug)
+ fprintf(stdout,"label=\"%s\", value=\"%s\"\n", label, value);
+
+ if(strlen(label))
+ {
+ if(!strcmp(label,"processor"))
+ {
+ if(debug || verbose)
+ fprintf(stdout,"Starting new CPU\n");
+
+ t_cpu_info* last = current;
+
+ current = create_cpu_info();
+ if(last != NULL)
+ {
+ last->next = current;
+ }
+ else
+ {
+ cpu_info = current;
+ }
+
+ COPY_VALUE_TO_BUFFER(value,current->cpu_num,BUFFER_LENGTH);
+ }
+ else
+ if(!strcmp(label,"core id"))
+ {
+ COPY_VALUE_TO_BUFFER(value,current->core_num,BUFFER_LENGTH);
+ }
+ else
+ if(!strcmp(label,"cpu cores"))
+ {
+ COPY_VALUE_TO_BUFFER(value,current->number_of_cores,BUFFER_LENGTH);
+ }
+ else
+ if(!strcmp(label,"vendor_id"))
+ {
+ COPY_VALUE_TO_BUFFER(value,current->vendor,BUFFER_LENGTH);
+ }
+ else
+ if(!strcmp(label,"model"))
+ {
+ COPY_VALUE_TO_BUFFER(value,current->model,BUFFER_LENGTH);
+ }
+ else
+ if(!strcmp(label,"cpu family"))
+ {
+ COPY_VALUE_TO_BUFFER(value,current->family,BUFFER_LENGTH);
+ }
+ else
+ if(!strcmp(label,"cpuid level"))
+ {
+ COPY_VALUE_TO_BUFFER(value,current->cpuid_level,BUFFER_LENGTH);
+ }
+ else
+ if(!strcmp(label,"cpu MHz"))
+ {
+ COPY_VALUE_TO_BUFFER(value,current->speed,BUFFER_LENGTH);
+ }
+ else
+ if(!strcmp(label,"cache size"))
+ {
+ COPY_VALUE_TO_BUFFER(value,current->cache,BUFFER_LENGTH);
+ }
+ else
+ if(!strcmp(label,"flags"))
+ {
+ COPY_VALUE_TO_BUFFER(value,current->flags,BUFFER_LENGTH);
+ }
+ }
+
+ } while(!feof(inputfd));
+
+ fclose(inputfd);
+
+ result = 0;
+ }
+ else
+ {
+ if(verbose) fprintf(stderr,"Unable to open /proc/cpuinfo\n");
+ }
+
+ return result;
+}
+
+t_cpu_info* create_cpu_info(void)
+{
+ t_cpu_info* result = calloc(1,sizeof(t_cpu_info));
+ bzero(result,sizeof(t_cpu_info));
+
+ strcpy(result->core_num,"0");
+ strcpy(result->number_of_cores,"1");
+
+
+ return result;
+}
+
ssize_t safewrite(int fd, const void *buf, size_t count)
{
size_t nwritten = 0;
@@ -303,9 +501,10 @@ int send_text(char* text)
int result = 1;
int sent;
- if(debug || verbose) fprintf(stdout,"\"%s\" -> %s:%d\n", text, hostname, hostport);
+ if(verbose) fprintf(stdout,"Sending: \"%s\"\n", text);
sent = safewrite(socketfd, text, strlen(text));
+ sent += safewrite(socketfd, "\n", 1);
if(sent >= 0)
{
@@ -317,35 +516,46 @@ int send_text(char* text)
return result;
}
-int saferead(int fd, void *buf, size_t count)
+int saferead(int fd, char *buf, size_t count)
{
ssize_t bytes,offset;
int len_left;
+ int done = 0;
if(debug) fprintf(stdout,"Begin saferead(%d, %p, %ld)\n", fd, buf, count);
offset = 0;
len_left = count;
- while(len_left > 0) {
- bytes = read(fd, buf+offset, len_left);
- fprintf(stderr,"After read, bytes is %ld\n",bytes);
- if (bytes < 0) {
- if (errno == EINTR) {
- continue;
- }
- else {
- offset = -1;
- break;
- }
- }
- else if (bytes == 0) {
- // reached EOF; break out of here
- break;
- }
-
- offset += bytes;
- len_left -= bytes;
+
+ while(!done)
+ {
+ if(debug) fprintf(stdout,"Before read(%ld,%p,%ld)\n",fd,buf+offset,len_left);
+
+ bytes = read(fd, buf+offset, len_left);
+
+ if(debug) fprintf(stdout,"After read: bytes=%ld\n", bytes);
+
+ if(bytes == 0)
+ {
+ done = 1;
+ }
+ else if(bytes > 0)
+ {
+ offset += bytes;
+ len_left -= bytes;
+ done = 1;
+ }
+ else if(errno == EINTR)
+ {
+ continue;
+ }
+ else
+ {
+ done = 1;
+ }
+
+ if(debug) fprintf(stdout,"End of decision loop: offset=%ld, len_left=%dl, done=%d\n",offset, len_left, done);
}
return offset;
@@ -353,22 +563,22 @@ int saferead(int fd, void *buf, size_t count)
int get_text(const char *const expected)
{
+ int result = 1;
int received;
char buffer[BUFFER_LENGTH];
+ bzero(buffer,BUFFER_LENGTH);
- if(debug) fprintf(stdout, "Looking to receive %s\n", expected);
+ if(verbose) fprintf(stdout, "Looking to receive %s\n", expected);
- received = saferead(socketfd, buffer, strlen(expected));
+ received = saferead(socketfd, buffer, BUFFER_LENGTH);
buffer[received - 1] = 0;
- if(debug) fprintf(stdout,"Received \"%s\": size=%d (trimmed ending carriage return)\n", buffer, received);
+ if(verbose) fprintf(stdout,"Received \"%s\": size=%d (trimmed ending carriage return)\n", buffer, received);
- if (strncmp(expected, buffer, strlen(expected)) != 0) {
- return 0;
- }
+ result = strcmp(expected,buffer);
- return 1;
+ return result;
}
int create_connection(void)
@@ -379,7 +589,7 @@ int create_connection(void)
char port[6];
struct addrinfo* rptr;
- if(debug) fprintf(stdout,"Creating the socket connection.\n");
+ if(verbose) fprintf(stdout,"Creating the socket connection.\n");
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
@@ -387,13 +597,13 @@ int create_connection(void)
hints.ai_flags = 0;
hints.ai_protocol = 0;
- if(debug) fprintf(stdout,"Searching for host candidates.\n");
+ if(verbose) fprintf(stdout,"Searching for host candidates.\n");
snprintf(port, 6, "%d", hostport);
if(!getaddrinfo(hostname, port, &hints, &results))
{
- if(debug) fprintf(stdout,"Got address information. Searching for a proper entry.\n");
+ if(verbose) fprintf(stdout,"Got address information. Searching for a proper entry.\n");
for(rptr = results; rptr != NULL; rptr = rptr->ai_next)
{
@@ -416,13 +626,13 @@ int create_connection(void)
}
// invalid connection, so close it
- if(debug) fprintf(stdout, "Invalid connection.\n");
+ if(verbose) fprintf(stdout, "Invalid connection.\n");
close(socketfd);
}
if(rptr == NULL)
{
- if(debug) fprintf(stdout,"Unable to connect to server %s:%d\n", hostname, hostport);
+ if(verbose) fprintf(stdout,"Unable to connect to server %s:%d\n", hostname, hostport);
}
else
{
@@ -434,7 +644,7 @@ int create_connection(void)
}
else
{
- if(debug) fprintf(stderr,"No hosts found. Exiting...\n");
+ if(verbose) fprintf(stderr,"No hosts found. Exiting...\n");
}
if(debug) fprintf(stdout, "create_connection: result=%d\n", result);
diff --git a/ovirt-managed-node/src/ovirt-identify-node.h b/ovirt-managed-node/src/ovirt-identify-node.h
new file mode 100644
index 0000000..1cb1526
--- /dev/null
+++ b/ovirt-managed-node/src/ovirt-identify-node.h
@@ -0,0 +1,56 @@
+#ifndef __OVIRT_IDENTIFY_NODE_H
+#define __OVIRT_IDENTIFY_NODE_H
+
+#define BUFFER_LENGTH 128
+#define CPU_FLAGS_BUFFER_LENGTH 256
+
+typedef struct _cpu_info {
+ char cpu_num[BUFFER_LENGTH];
+ char core_num[BUFFER_LENGTH];
+ char number_of_cores[BUFFER_LENGTH];
+ char vendor[BUFFER_LENGTH];
+ char model[BUFFER_LENGTH];
+ char family[BUFFER_LENGTH];
+ char cpuid_level[BUFFER_LENGTH];
+ char speed[BUFFER_LENGTH];
+ char cache[BUFFER_LENGTH];
+ char flags[CPU_FLAGS_BUFFER_LENGTH];
+ struct _cpu_info* next;
+} t_cpu_info;
+
+#define COPY_VALUE_TO_BUFFER(value,buffer,length) \
+ snprintf(buffer,length,"%s",value)
+
+int config(int argc,char** argv);
+void usage(void);
+
+int start_conversation(void);
+int send_details(void);
+int send_cpu_details(void);
+int end_conversation(void);
+
+void get_label_and_value(char* text,
+ char* label,size_t label_length,
+ char* value,size_t value_length);
+t_cpu_info* create_cpu_info(void);
+int get_cpu_info(void);
+
+int send_text(char* text);
+int get_text(const char *const expected);
+int create_connection(void);
+
+int debug = 0;
+int verbose = 0;
+int testing = 0;
+
+char arch[BUFFER_LENGTH];
+char uuid[VIR_UUID_BUFLEN];
+char memsize[BUFFER_LENGTH];
+char numcpus[BUFFER_LENGTH];
+char cpuspeed[BUFFER_LENGTH];
+char *hostname;
+int hostport = -1;
+int socketfd;
+t_cpu_info* cpu_info;
+
+#endif
diff --git a/wui/src/app/models/cpu.rb b/wui/src/app/models/cpu.rb
new file mode 100644
index 0000000..1a7d3cf
--- /dev/null
+++ b/wui/src/app/models/cpu.rb
@@ -0,0 +1,24 @@
+#
+# 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.
+
+# +Cpu+ represents the details for a single CPU on a managed node.
+#
+class Cpu < ActiveRecord::Base
+ belongs_to :host
+end
diff --git a/wui/src/app/models/host.rb b/wui/src/app/models/host.rb
index 6917226..90e18d5 100644
--- a/wui/src/app/models/host.rb
+++ b/wui/src/app/models/host.rb
@@ -1,4 +1,4 @@
-#
+#
# Copyright (C) 2008 Red Hat, Inc.
# Written by Scott Seago <sseago at redhat.com>
#
@@ -21,8 +21,11 @@ require 'util/ovirt'
class Host < ActiveRecord::Base
belongs_to :hardware_pool
+
+ has_many :cpus, :dependent => :destroy
has_many :nics, :dependent => :destroy
- has_many :vms, :dependent => :nullify do
+ has_many :vms, :dependent => :nullify do
+
def consuming_resources
find(:all, :conditions=>{:state=>Vm::RUNNING_STATES})
end
@@ -32,7 +35,7 @@ class Host < ActiveRecord::Base
find(:all, :conditions=>{:state=>Task::STATE_QUEUED})
end
def pending_clear_tasks
- find(:all, :conditions=>{:state=>Task::WORKING_STATES,
+ find(:all, :conditions=>{:state=>Task::WORKING_STATES,
:action=>HostTask::ACTION_CLEAR_VMS})
end
end
@@ -42,12 +45,18 @@ class Host < ActiveRecord::Base
STATE_UNAVAILABLE = "unavailable"
STATE_AVAILABLE = "available"
STATES = [STATE_UNAVAILABLE, STATE_AVAILABLE]
+
+ KVM_HYPERVISOR_TYPE = "KVM"
+ HYPERVISOR_TYPES = [KVM_HYPERVISOR_TYPE]
+
def memory_in_mb
kb_to_mb(memory)
end
+
def memory_in_mb=(mem)
self[:memory]=(mb_to_kb(mem))
end
+
def status_str
"#{state} (#{disabled? ? 'disabled':'enabled'})"
end
@@ -61,4 +70,12 @@ class Host < ActiveRecord::Base
not(disabled? and vms.consuming_resources.empty?) and
tasks.pending_clear_tasks.empty?
end
+
+ def num_cpus
+ return cpu_details.size
+ end
+
+ def cpu_speed
+ "FIX ME!"
+ end
end
diff --git a/wui/src/db/migrate/010_create_cpus.rb b/wui/src/db/migrate/010_create_cpus.rb
new file mode 100644
index 0000000..bd17274
--- /dev/null
+++ b/wui/src/db/migrate/010_create_cpus.rb
@@ -0,0 +1,32 @@
+class CreateCpus < ActiveRecord::Migration
+ def self.up
+ create_table :cpus do |t|
+ t.integer :host_id
+ t.integer :cpu_number
+ t.integer :core_number
+ t.integer :number_of_cores
+ t.string :vendor, :limit => 128
+ t.integer :model
+ t.integer :family
+ t.integer :cpuid_level
+ t.float :speed
+ t.string :cache
+ t.string :flags
+
+ t.timestamps
+ end
+
+ execute "alter table cpus add constraint fk_host_cpus
+ foreign key (host_id) references hosts(id)"
+
+ remove_column :hosts, :cpu_speed
+ remove_column :hosts, :num_cpus
+ end
+
+ def self.down
+ drop_table :cpus
+
+ add_column :hosts, :cpu_speed, :integer
+ add_column :hosts, :num_cpus, :integer
+ end
+end
diff --git a/wui/src/dutils/active_record_env.rb b/wui/src/dutils/active_record_env.rb
index b0aef04..72feb89 100644
--- a/wui/src/dutils/active_record_env.rb
+++ b/wui/src/dutils/active_record_env.rb
@@ -1,5 +1,5 @@
#!/usr/bin/ruby
-#
+#
# Copyright (C) 2008 Red Hat, Inc.
# Written by Scott Seago <sseago at redhat.com>
#
@@ -23,7 +23,7 @@ $: << File.join(File.dirname(__FILE__), "../vendor/plugins/betternestedset/lib")
require 'rubygems'
-gem 'activeldap'
+gem 'activeldap'
require 'active_ldap'
require 'active_support'
@@ -58,6 +58,7 @@ require 'models/quota.rb'
require 'models/hardware_pool.rb'
require 'models/host.rb'
+require 'models/cpu.rb'
require 'models/nic.rb'
require 'models/vm_resource_pool.rb'
diff --git a/wui/src/host-browser/host-browser.rb b/wui/src/host-browser/host-browser.rb
index 691e4ed..e66493d 100755
--- a/wui/src/host-browser/host-browser.rb
+++ b/wui/src/host-browser/host-browser.rb
@@ -19,6 +19,7 @@
# also available at http://www.gnu.org/copyleft/gpl.html.
$: << File.join(File.dirname(__FILE__), "../dutils")
+$: << File.join(File.dirname(__FILE__), "../")
require 'rubygems'
require 'libvirt'
@@ -73,16 +74,61 @@ class HostBrowser
#
def get_remote_info
puts "#{@log_prefix} Begin remote info collection" unless defined?(TESTING)
- result = {}
+ result = Hash.new
result['HOSTNAME'] = @session.peeraddr[2]
result['IPADDR'] = @session.peeraddr[3]
+
@session.write("INFO?\n")
loop do
info = @session.readline.chomp
+ puts "Received info='#{info}'"
+
break if info == "ENDINFO"
+ # if we got the start of a CPU details marker, then process it
+ if info == "CPU"
+ cpu = get_cpu_info
+ cpu_info = result['CPUINFO']
+
+ if(cpu_info == nil)
+ cpu_info = Array.new
+ result['CPUINFO'] = cpu_info
+ end
+
+ cpu_info << cpu
+
+ else
+
+ raise Exception.new("ERRINFO! Excepted key=value : #{info}\n") unless info =~ /[\w]+[\s]*=[\w]/
+
+ key, value = info.split("=")
+
+ puts "#{@log_prefix} ::Received - #{key}:#{value}" unless defined?(TESTING)
+ result[key] = value
+
+ @session.write("ACK #{key}\n")
+ end
+ end
+
+ return result
+ end
+
+ # Extracts CPU details from the managed node.
+ #
+ def get_cpu_info
+ puts "Begin receiving CPU details"
+
+ result = Hash.new
+
+ @session.write("CPUINFO?\n")
+
+ loop do
+ info = @session.readline.chomp
+
+ break if info == "ENDCPU"
+
raise Exception.new("ERRINFO! Excepted key=value : #{info}\n") unless info =~ /[\w]+[\s]*=[\w]/
key, value = info.split("=")
@@ -93,6 +139,8 @@ class HostBrowser
@session.write("ACK #{key}\n")
end
+ @session.write("ACK CPU\n");
+
return result
end
@@ -100,10 +148,24 @@ class HostBrowser
#
def write_host_info(host_info)
ensure_present(host_info,'HOSTNAME')
- ensure_present(host_info,'NUMCPUS')
- ensure_present(host_info,'CPUSPEED')
ensure_present(host_info,'ARCH')
ensure_present(host_info,'MEMSIZE')
+ ensure_present(host_info,'CPUINFO')
+
+ cpu_info = host_info['CPUINFO']
+
+ cpu_info.each do |cpu|
+ ensure_present(cpu,'CPUNUM')
+ ensure_present(cpu,'CORENUM')
+ ensure_present(cpu,'NUMCORES')
+ ensure_present(cpu,'VENDOR')
+ ensure_present(cpu,'MODEL')
+ ensure_present(cpu,'FAMILY')
+ ensure_present(cpu,'CPUIDLVL')
+ ensure_present(cpu,'SPEED')
+ ensure_present(cpu,'CACHE')
+ ensure_present(cpu,'FLAGS')
+ end
puts "Searching for existing host record..." unless defined?(TESTING)
host = Host.find(:first, :conditions => ["hostname = ?", host_info['HOSTNAME']])
@@ -112,31 +174,49 @@ class HostBrowser
begin
puts "Creating a new record for #{host_info['HOSTNAME']}..." unless defined?(TESTING)
- Host.new(
+ host = Host.create(
"uuid" => host_info['UUID'],
"hostname" => host_info['HOSTNAME'],
"hypervisor_type" => host_info['HYPERVISOR_TYPE'],
- "num_cpus" => host_info['NUMCPUS'],
- "cpu_speed" => host_info['CPUSPEED'],
"arch" => host_info['ARCH'],
"memory_in_mb" => host_info['MEMSIZE'],
"is_disabled" => 0,
"hardware_pool" => HardwarePool.get_default_pool,
# Let host-status mark it available when it
# successfully connects to it via libvirt.
- "state" => Host::STATE_UNAVAILABLE).save
+ "state" => Host::STATE_UNAVAILABLE)
+ host.save!
rescue Exception => error
puts "Error while creating record: #{error.message}" unless defined?(TESTING)
end
else
host.uuid = host_info['UUID']
host.hostname = host_info['HOSTNAME']
- host.num_cpus = host_info['NUMCPUS']
- host.cpu_speed = host_info['CPUSPEED']
host.arch = host_info['ARCH']
host.memory_in_mb = host_info['MEMSIZE']
end
+ # delete an existing CPUs and create new ones based on the data
+ puts "Deleting any existing CPUs"
+ Cpu.delete_all(['host_id = ?', host.id])
+
+ puts "Saving new CPU records"
+ cpu_info.collect do |cpu|
+ detail = Cpu.new(
+ "cpu_number" => cpu['CPUNUM'],
+ "core_number" => cpu['CORENUM]'],
+ "number_of_cores" => cpu['NUMCORES'],
+ "vendor" => cpu['VENDOR'],
+ "model" => cpu['MODEL'],
+ "family" => cpu['FAMILY'],
+ "cpuid_level" => cpu['CPUIDLVL'],
+ "speed" => cpu['SPEED'],
+ "cache" => cpu['CACHE'],
+ "flags" => cpu['FLAGS'])
+
+ host.cpus << detail
+ end
+
return host
end
@@ -181,8 +261,8 @@ class HostBrowser
# Private method to ensure that a required field is present.
#
- def ensure_present(host_info,key)
- raise Exception.new("ERROR! Missing '#{key}'...") if host_info[key] == nil
+ def ensure_present(info,key)
+ raise Exception.new("ERROR! Missing '#{key}'...") if info[key] == nil
end
# Executes an external program to support the keytab function.
@@ -226,7 +306,6 @@ def entry_point(server)
end
unless defined?(TESTING)
-
# The main entry point.
#
unless ARGV[0] == "-n"
diff --git a/wui/src/host-browser/test-host-browser-awake.rb b/wui/src/host-browser/test-host-browser-awake.rb
new file mode 100755
index 0000000..02e9146
--- /dev/null
+++ b/wui/src/host-browser/test-host-browser-awake.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}/ipa/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-awaken.rb b/wui/src/host-browser/test-host-browser-awaken.rb
deleted file mode 100755
index a5ca2e7..0000000
--- a/wui/src/host-browser/test-host-browser-awaken.rb
+++ /dev/null
@@ -1,94 +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'
-
-# +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
index 8f215e9..4197e19 100755
--- a/wui/src/host-browser/test-host-browser-identify.rb
+++ b/wui/src/host-browser/test-host-browser-identify.rb
@@ -27,136 +27,219 @@ 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 the server is fine when no UUID is present.
- #
- def test_write_host_info_with_missing_uuid
- @host_info['UUID'] = nil
-
- assert_nothing_raised { @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
+ 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['ARCH'] = 'x86_64'
+ @host_info['MEMSIZE'] = '16384'
+ @host_info['DISABLED'] = '0'
+
+ @host_info['NUMCPUS'] = '2'
+
+ @host_info['CPUINFO'] = Array.new
+ @host_info['CPUINFO'][0] = {}
+ @host_info['CPUINFO'][0]['CPUNUM'] = '0'
+ @host_info['CPUINFO'][0]['CORENUM'] = '0'
+ @host_info['CPUINFO'][0]['NUMCORES'] = '2'
+ @host_info['CPUINFO'][0]['VENDOR'] = 'GenuineIntel'
+ @host_info['CPUINFO'][0]['MODEL'] = '15'
+ @host_info['CPUINFO'][0]['FAMILY'] = '6'
+ @host_info['CPUINFO'][0]['CPUIDLVL'] = '10'
+ @host_info['CPUINFO'][0]['SPEED'] = '3'
+ @host_info['CPUINFO'][0]['CACHE'] = '4096 kb'
+ @host_info['CPUINFO'][0]['FLAGS'] = 'fpu vme de pse tsc msr pae \
+ mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx \
+ fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs \
+ bts pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr lahf_lm'
+
+ @host_info['CPUINFO'][1] = {}
+ @host_info['CPUINFO'][1]['CPUNUM'] = '1'
+ @host_info['CPUINFO'][1]['CORENUM'] = '1'
+ @host_info['CPUINFO'][1]['NUMCORES'] = '2'
+ @host_info['CPUINFO'][1]['VENDOR'] = 'GenuineIntel'
+ @host_info['CPUINFO'][1]['MODEL'] = '15'
+ @host_info['CPUINFO'][1]['FAMILY'] = '6'
+ @host_info['CPUINFO'][1]['CPUIDLVL'] = '10'
+ @host_info['CPUINFO'][1]['SPEED'] = '3'
+ @host_info['CPUINFO'][1]['CACHE'] = '4096 kb'
+ @host_info['CPUINFO'][1]['FLAGS'] = 'fpu vme de pse tsc msr pae \
+ mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx \
+ fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs \
+ bts pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr lahf_lm'
+ 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 four keys"
+ assert info.include?("IPADDR")
+ assert info.include?("HOSTNAME")
+ assert info.include?("key1")
+ assert info.include?("key2")
+ end
+
+ # Ensures that the server is fine when no UUID is present.
+ #
+ def test_write_host_info_with_missing_uuid
+ @host_info['UUID'] = nil
+
+ assert_nothing_raised { @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 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 no cpu info was available, the server raises an
+ # exception.
+ #
+ def test_write_host_info_with_missing_cpuinfo
+ @host_info['CPUINFO'] = nil
+
+ assert_raise(Exception) { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures the browser can properly parse the CPU details.
+ #
+ def test_parse_cpu_info
+ @session.should_receive(:write).with("INFO?\n").once().returns { |request| request.length }
+ @session.should_receive(:readline).once().returns { "CPU\n" }
+ @session.should_receive(:write).with("CPUINFO?\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 { "ENDCPU\n" }
+ @session.should_receive(:write).with("ACK CPU\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 four keys"
+ assert info.include?("CPUINFO")
+ end
+
+ # Ensures the browser can properly parse the CPU details of two CPUs.
+ #
+ def test_parse_cpu_info
+ @session.should_receive(:write).with("INFO?\n").once().returns { |request| request.length }
+
+ # CPU 0
+ @session.should_receive(:readline).once().returns { "CPU\n" }
+ @session.should_receive(:write).with("CPUINFO?\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 { "ENDCPU\n" }
+ @session.should_receive(:write).with("ACK CPU\n").once().returns { |request| request.length }
+
+ # CPU 1
+ @session.should_receive(:readline).once().returns { "CPU\n" }
+ @session.should_receive(:write).with("CPUINFO?\n").once().returns { |request| request.length }
+ @session.should_receive(:readline).once().returns { "key3=value3\n" }
+ @session.should_receive(:write).with("ACK key3\n").once().returns { |request| request.length }
+ @session.should_receive(:readline).once().returns { "key4=value4\n" }
+ @session.should_receive(:write).with("ACK key4\n").once().returns { |request| request.length }
+ @session.should_receive(:readline).once().returns { "ENDCPU\n" }
+ @session.should_receive(:write).with("ACK CPU\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 four keys"
+ assert info.include?('CPUINFO')
+ assert_equal 2, info['CPUINFO'].size, "Should contain details for two CPUs"
+ assert_not_nil info['CPUINFO'][0]['key1']
+ assert_not_nil info['CPUINFO'][0]['key2']
+ assert_not_nil info['CPUINFO'][1]['key3']
+ assert_not_nil info['CPUINFO'][1]['key4']
+ end
end
diff --git a/wui/src/test/fixtures/cpus.yml b/wui/src/test/fixtures/cpus.yml
new file mode 100644
index 0000000..5586303
--- /dev/null
+++ b/wui/src/test/fixtures/cpus.yml
@@ -0,0 +1,21 @@
+# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
+
+one:
+ cpu_number: 1
+ core_number: 1
+ cpu_id_level: 1
+ vendor: 1
+ family: 1
+ model: 1
+ family: MyString
+ flags: MyString
+
+two:
+ cpu_number: 1
+ core_number: 1
+ cpu_id_level: 1
+ vendor: 1
+ family: 1
+ model: 1
+ family: MyString
+ flags: MyString
diff --git a/wui/src/test/fixtures/hosts.yml b/wui/src/test/fixtures/hosts.yml
index 3b93aea..f10a756 100644
--- a/wui/src/test/fixtures/hosts.yml
+++ b/wui/src/test/fixtures/hosts.yml
@@ -2,8 +2,6 @@ one:
id: 1
uuid: '1148fdf8-961d-11dc-9387-001558c41534'
hostname: 'prod.corp.com'
- num_cpus: 8
- cpu_speed: 4096
arch: 'i686'
memory: 18384
is_disabled: 0
@@ -13,8 +11,6 @@ two:
id: 2
uuid: '1f2a8694-961d-11dc-9387-001558c41534'
hostname: 'myworkstation.dev.corp.com'
- num_cpus: 4
- cpu_speed: 2048
arch: 'i386'
memory: 2048
is_disabled: 0
@@ -24,30 +20,24 @@ three:
id: 3
uuid: '58a85f44-75fd-4934-805f-88e45b40d4b4'
hostname: 'macworkstation.foobar.com'
- num_cpus: 8
- cpu_speed: 1024
arch: 'mips'
memory: 2048
- is_disabled: 0
+ is_disabled: 0
hypervisor_type: 'kvm'
hardware_pool_id: 3
four:
id: 4
uuid: '520bbb34-6515-490e-9d07-0c8b14f76805'
hostname: 'fedoraworkstation.foobar.com'
- num_cpus: 8
- cpu_speed: 3072
arch: 'i386'
memory: 2048
- is_disabled: 1
+ is_disabled: 1
hypervisor_type: 'kvm'
hardware_pool_id: 3
five:
id: 5
uuid: '2e422f66-324e-48d4-973f-0b91b33070f9'
hostname: 'pipeline.foobar.com'
- num_cpus: 32
- cpu_speed: 4096
arch: 'xeon'
memory: 1048576
is_disabled: 0
@@ -57,19 +47,15 @@ six:
id: 6
uuid: 'bb0ce7c7-f234-49ae-84b5-6f4fd8bddcaa'
hostname: 'prod.foobar.com'
- num_cpus: 32
- cpu_speed: 4096
arch: 'xeon'
memory: 16384
- is_disabled: 0
+ is_disabled: 0
hypervisor_type: 'kvm'
hardware_pool_id: 3
seven:
id: 7
uuid: '6ae3d22e-97e0-4d86-9712-5395b20a0f45'
hostname: 'mystation.dev.corp.com'
- num_cpus: 4
- cpu_speed: 3072
arch: 'i686'
memory: 2048
is_disabled: 0
@@ -79,8 +65,6 @@ eight:
id: 8
uuid: 'ec0d86de-657b-48f6-b7cc-e733a3f9a834'
hostname: 'issue.qa.corp.com'
- num_cpus: 8
- cpu_speed: 4096
arch: 'x86'
memory: 4096
is_disabled: 0
@@ -90,8 +74,6 @@ nine:
id: 9
uuid: '81c15560-dbf4-45f5-9b75-106cdbd63aeb'
hostname: 'somehost'
- num_cpus: 4
- cpu_speed: 4096
arch: 'x86'
memory: 4096
is_disabled: 0
diff --git a/wui/src/test/unit/cpu_test.rb b/wui/src/test/unit/cpu_test.rb
new file mode 100644
index 0000000..5b64ca7
--- /dev/null
+++ b/wui/src/test/unit/cpu_test.rb
@@ -0,0 +1,8 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+class CpuTest < ActiveSupport::TestCase
+ # Replace this with your real tests.
+ def test_truth
+ assert true
+ end
+end
--
1.5.5.1
More information about the ovirt-devel
mailing list