Add a proper machine table rather than just using the hostname
Should have done this in the first place ;-(

Added a new machine class to frontend, etc as well.

THIS WILL NECESSITATE REBUILDING THE DATABASE

Signed-off-by: Martin J. Bligh <mbligh@google.com>



git-svn-id: http://test.kernel.org/svn/autotest/trunk@730 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/tko/create_db b/tko/create_db
index 30c05ea..310a3be 100644
--- a/tko/create_db
+++ b/tko/create_db
@@ -1,4 +1,3 @@
-
 -- kernel versions
 DROP TABLE IF EXISTS kernels;
 CREATE TABLE kernels (
@@ -9,11 +8,20 @@
 );
 
 -- main jobs table
+DROP TABLE IF EXISTS machines;
+CREATE TABLE machines (
+machine_idx int(10) unsigned NOT NULL auto_increment PRIMARY KEY,
+hostname VARCHAR(100),			-- hostname
+machine_group VARCHAR(80),		-- group name
+owner VARCHAR(80)			-- owner name
+);
+
+-- main jobs table
 DROP TABLE IF EXISTS jobs;
 CREATE TABLE jobs (
 job_idx int(10) unsigned NOT NULL auto_increment PRIMARY KEY,		-- index number
 tag VARCHAR(100),			-- job key
-machine VARCHAR(80)			-- machine name
+machine_idx int(10)			-- reference to machine table
 );
 
 -- One entry per patch used, anywhere
@@ -35,7 +43,7 @@
 kernel_idx INTEGER,			-- kernel test was AGAINST
 status INTEGER,				-- test status
 reason VARCHAR(100),			-- reason for test status
-machine VARCHAR(80)			-- machine name
+machine_idx int(10)			-- reference to machine table
 );
 
 -- test functional results
diff --git a/tko/db.py b/tko/db.py
index 151d4d4..1bb0afa 100644
--- a/tko/db.py
+++ b/tko/db.py
@@ -94,7 +94,10 @@
 
 
 	def insert_job(self, tag, job):
-		self.insert('jobs', {'tag':tag, 'machine':job.machine})
+		job.machine_idx = self.lookup_machine(job.machine)
+		if not job.machine_idx:
+			job.machine_idx = self.insert_machine(job.machine)
+		self.insert('jobs', {'tag':tag, 'machine_idx':job.machine_idx})
 		job.index = self.find_job(tag)
 		for test in job.tests:
 			self.insert_test(job, test)
@@ -105,7 +108,7 @@
 		data = {'job_idx':job.index, 'test':test.testname,
 			'subdir':test.subdir, 'kernel_idx':kver,
 			'status':self.status_idx[test.status],
-			'reason':test.reason, 'machine':test.machine }
+			'reason':test.reason, 'machine_idx':job.machine_idx }
 		self.insert('tests', data)
 		test_idx = self.find_test(job.index, test.subdir)
 		data = { 'test_idx':test_idx }
@@ -118,6 +121,20 @@
 				self.insert('iteration_result', data)
 
 
+	def insert_machine(self, hostname):
+		self.insert('machines', { 'hostname' : hostname })
+		return self.lookup_machine(hostname)
+
+
+	def lookup_machine(self, hostname):
+		where = { 'hostname' : hostname }
+		rows = self.select('machine_idx', 'machines', where)
+		if rows:
+			return rows[0][0]
+		else:
+			return None
+
+
 	def lookup_kernel(self, kernel):
 		rows = self.select('kernel_idx', 'kernels', 
 				{'kernel_hash':kernel.kernel_hash})
diff --git a/tko/frontend.py b/tko/frontend.py
index 26991b0..c48c5a1 100755
--- a/tko/frontend.py
+++ b/tko/frontend.py
@@ -1,5 +1,5 @@
 #!/usr/bin/python
-import os, re, db
+import os, re, db, sys
 
 # Pulling hierarchy:
 #
@@ -8,7 +8,31 @@
 #
 # Note that job does put pull test - test is the primary object.
 
-html_root = 'http://test.kernel.org/google/'
+tko = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0])))
+root_url_file = os.path.join(tko, '.root_url')
+if os.path.exists(root_url_file):
+        html_root = open(root_url_file, 'r').readline().rstrip()
+else:
+        html_root = 'http://test.kernel.org/google/'
+
+
+class machine:
+	@classmethod
+	def select(klass, db, where = {}):
+		fields = ['machine_idx', 'hostname', 'machine_group', 'owner']
+		machines = []
+		for row in db.select(','.join(fields), 'machines', where):
+			machines.append(klass(db, *row))
+		return machines
+
+
+	def __init__(self, db, idx, hostname, group, owner):
+		self.db = db
+		self.idx = idx
+		self.hostname = hostname
+		self.group = group
+		self.owner = owner
+		
 
 class kernel:
 	@classmethod
@@ -33,22 +57,23 @@
 	@classmethod
 	def select(klass, db, where = {}, distinct = False):
 		fields = ['test_idx', 'job_idx', 'test', 'subdir', 
-			  'kernel_idx', 'status', 'reason', 'machine']
+			  'kernel_idx', 'status', 'reason', 'machine_idx']
 		tests = []
 		for row in db.select(','.join(fields), 'tests', where, distinct):
 			tests.append(klass(db, *row))
 		return tests
 
 
-	def __init__(self, db, test_idx, job_idx, testname, subdir, kernel_idx, status_num, reason, machine):
+	def __init__(self, db, test_idx, job_idx, testname, subdir, kernel_idx, status_num, reason, machine_idx):
 		self.idx = test_idx
 		self.job = job(db, job_idx)
-		# self.machine = self.job.machine
 		self.testname = testname
 		self.subdir = subdir
 		self.kernel_idx = kernel_idx
 		self.__kernel = None
 		self.__iterations = None
+		self.machine_idx = machine_idx
+		self.__machine = None
 		self.status_num = status_num
 		self.status_word = db.status_word[status_num]
 		self.reason = reason
@@ -86,13 +111,23 @@
 		return self.__kernel
 
 
+	def machine(self):
+		"""
+		Caching function for kernels
+		"""
+		if not self.__machine:
+			where = {'machine_idx' : self.machine_idx}
+			self.__machine = machine.select(self.db, where)[0]
+		return self.__machine
+
+
 class job:
 	def __init__(self, db, job_idx):
 		where = {'job_idx' : job_idx}
-		rows = db.select('tag, machine', 'jobs', where)
+		rows = db.select('tag, machine_idx', 'jobs', where)
 		if not rows:
 			return None
-		(self.tag, self.machine) = rows[0]
+		(self.tag, self.machine_idx) = rows[0]
 
  
 class iteration:
diff --git a/tko/machine_benchmark.cgi b/tko/machine_benchmark.cgi
index beb7762..1bdfbb9 100755
--- a/tko/machine_benchmark.cgi
+++ b/tko/machine_benchmark.cgi
@@ -30,8 +30,7 @@
 		benchmarks.append(benchmark)
 	benchmarks = display.sort_tests(benchmarks)
 
-	rows = db.select('machine', 'jobs', {}, distinct = True)
-	machines = [row[0] for row in rows]
+	machines = frontend.machine.select(db)
 
 	print '<h1>Performance</h1>'
 
@@ -40,9 +39,10 @@
 	
 	matrix = [header_row]
 	for machine in machines:
-		row = [display.box(machine)]
+		row = [display.box(machine.hostname)]
 		for benchmark in benchmarks:
-			where = { 'machine' : machine, 'subdir' : benchmark }
+			where = { 'machine_idx' : machine.idx,
+				  'subdir' : benchmark }
 			rows = db.select('count(test_idx)', 'tests', where)
 			count = rows[0][0]
 			if not count:
@@ -51,7 +51,7 @@
 			testname = re.sub(r'\..*', '', benchmark)
 			url = 'machine_test_attribute_graph.cgi'
 			url += '?machine=%s&benchmark=%s&key=%s' % \
-				(machine, benchmark, benchmark_key[testname])
+				(machine.idx, benchmark, benchmark_key[testname])
 			html = '<a href="%s">%d</a>' % (url, count)
 			row.append(display.box(html))
 		matrix.append(row)
diff --git a/tko/machine_kernel.cgi b/tko/machine_kernel.cgi
index 8d83250..436c0b4 100755
--- a/tko/machine_kernel.cgi
+++ b/tko/machine_kernel.cgi
@@ -1,5 +1,4 @@
 #!/usr/bin/python
-
 import cgi, cgitb, os, sys
 cgitb.enable()
 
@@ -15,8 +14,7 @@
 
 def main():
 	print "Content-type: text/html\n"
-	rows = db.select('distinct machine', 'jobs', {})
-	machines = [row[0] for row in rows]
+	machines = frontend.machine.select(db)
 	print_machines_vs_all_kernels(machines)
 
 
@@ -39,7 +37,7 @@
 	status = None
 	status_word = ''
 	tests = frontend.test.select(db, { 'kernel_idx' : kernel.idx ,
-					   'machine' : machine })
+					   'machine_idx' : machine.idx })
 
 	status_count = {}
 	for t in tests:
@@ -53,7 +51,7 @@
 			status_word = db.status_word[status]
 
 	link = 'machine_kernel_test.cgi?machine=%s&kernel=%s' % \
-					(machine, kernel.idx)
+					(machine.idx, kernel.idx)
 	if status_word:
 		html = '<a href="%s">%s</a>' % (link, status_html(status_count))
 	else:
@@ -66,7 +64,7 @@
 
 
 def print_machines_vs_all_kernels(machines):
-	headers = ['Version'] + machines
+	headers = ['Version'] + [machine.hostname for machine in machines]
 	header_row = [ display.box(x, header=True) for x in headers ] 
 
 	kernels = frontend.kernel.select(db)
diff --git a/tko/machine_kernel_test.cgi b/tko/machine_kernel_test.cgi
index 9e4a238..c11bc71 100755
--- a/tko/machine_kernel_test.cgi
+++ b/tko/machine_kernel_test.cgi
@@ -7,7 +7,6 @@
 sys.path.insert(0, tko)
 import db, display, frontend
 
-html_root = 'http://test.kernel.org/google/'
 db = db.db()
 
 def main():
@@ -15,21 +14,23 @@
 	sys.stdout.flush()
 
 	form = cgi.FieldStorage()
-	if not form.has_key("machine") and form.has_key("kernel"):
-		raise
+	machine_idxs = form["machine"].value
+	kernel_idx = form["kernel"].value
 
-	machine = form["machine"].value
-	kernel_version = form["kernel"].value
-
-	print_kernel_machines_vs_test([machine], kernel_version, html_root)
+	kernel = frontend.kernel.select(db, {'kernel_idx' : kernel_idx })[0]
+	machines = []
+	for idx in machine_idxs.split(','):
+		machine = frontend.machine.select(db, {'machine_idx' : idx})[0]
+		machines.append(machine)
+	print_kernel_machines_vs_test(machines, kernel)
 
 
-def print_kernel_machines_vs_test(machines, kernel_idx, html_root):
+def print_kernel_machines_vs_test(machines, kernel):
 	# first we have to get a list of all run tests across all machines
 	all_tests = []
 	results = {}         # will be a 2d hash [machine][testname]
 	for machine in machines:
-		where = { 'kernel_idx' : kernel_idx , 'machine' : machine }
+		where = { 'kernel_idx':kernel.idx , 'machine_idx':machine.idx }
 		tests = frontend.test.select(db, where)
 		test_dict = {}
 		for test in tests:
@@ -37,10 +38,9 @@
 			test_dict[test.testname] = test
 		# FIXME. What happens on multiple counts of the same test?
 		# ie. we run two identical jobs on the same machine ...
-		results[machine] = test_dict
+		results[machine.idx] = test_dict
 	test_list = display.sort_tests(list(set(all_tests)))
 
-	kernel = frontend.kernel.select(db, {'kernel_idx' : kernel_idx })[0]
 	print '<h1>%s</h1>' % kernel.printable
 
 	header_row = [ display.box('Version', header=True) ]
@@ -49,13 +49,13 @@
 
 	matrix = [header_row]
 	for machine in machines:
-		row = [display.box(machine)]
+		row = [display.box(machine.hostname)]
 		for testname in test_list:
-			if not results.has_key(machine):
+			if not results.has_key(machine.idx):
 				continue
-			if not results[machine].has_key(testname):
+			if not results[machine.idx].has_key(testname):
 				continue
-			test = results[machine][testname]
+			test = results[machine.idx][testname]
 			if test.url:
 				html = '<a href="%s">%s</a>' % \
 						(test.url, test.status_word)
diff --git a/tko/machine_test_attribute_graph.cgi b/tko/machine_test_attribute_graph.cgi
index 8bff1d5..8a16a6b 100755
--- a/tko/machine_test_attribute_graph.cgi
+++ b/tko/machine_test_attribute_graph.cgi
@@ -17,12 +17,14 @@
 
 def main():
 	form = cgi.FieldStorage()
-	machine = form["machine"].value
+	machine_idx = form["machine"].value
 	benchmark = form["benchmark"].value
 	key = form["key"].value
 
+	machine = frontend.machine.select(db, {'machine_idx' : machine_idx})[0]
+
 	data = {}
-	where = { 'subdir' : benchmark, 'machine' : machine }
+	where = { 'subdir' : benchmark, 'machine_idx' : machine.idx }
 	for test in frontend.test.select(db, where):
 		iterations = test.iterations()
 		if iterations.has_key(key):
@@ -30,7 +32,7 @@
 
 	# for kernel in sort_kernels(data.keys()):
 	#	print "%s %s" % (kernel, str(data[kernel]))
-	title = "%s on %s" % (benchmark, machine)
+	title = "%s on %s" % (benchmark, machine.hostname)
 	graph = plotgraph.gnuplot(title, 'Kernel', key, xsort = sort_kernels)
 	graph.add_dataset('all kernels', data)
 	graph.plot(cgi_header = True)
diff --git a/tko/parse b/tko/parse
index 6942865..50c5927 100755
--- a/tko/parse
+++ b/tko/parse
@@ -25,7 +25,7 @@
 		print "\t%s %s %s" % (test.subdir, test.status, test.reason)
 	db.insert_job(j, job)
 
-rows = db.select('distinct machine', 'jobs', {})
+rows = db.select('distinct hostname', 'machines', {})
 machines = [row[0] for row in rows]
 
 for machine in machines: