Merge lp:~bigkevmcd/landscape-client/vm-info-in-registration into lp:~landscape/landscape-client/trunk

Proposed by Kevin McDermott
Status: Merged
Approved by: Thomas Herve
Approved revision: 337
Merged at revision: 331
Proposed branch: lp:~bigkevmcd/landscape-client/vm-info-in-registration
Merge into: lp:~landscape/landscape-client/trunk
Diff against target: 577 lines (+208/-214)
7 files modified
landscape/broker/registration.py (+3/-1)
landscape/broker/tests/test_registration.py (+39/-5)
landscape/lib/tests/test_vm_info.py (+121/-0)
landscape/lib/vm_info.py (+39/-0)
landscape/message_schemas.py (+5/-5)
landscape/monitor/computerinfo.py (+0/-37)
landscape/monitor/tests/test_computerinfo.py (+1/-166)
To merge this branch: bzr merge lp:~bigkevmcd/landscape-client/vm-info-in-registration
Reviewer Review Type Date Requested Status
Thomas Herve (community) Approve
Free Ekanayaka (community) Approve
Review via email: mp+64272@code.launchpad.net

Description of the change

Register with vm-info so that we add the computer to the correct licence if possible...

To post a comment you must log in.
Revision history for this message
Free Ekanayaka (free.ekanayaka) wrote :

Looks good! +1

[1]

Maybe instead of mocking get_vm_info we could add:

class Registration(object):

    root_path = "/"

and override it in the tests.

review: Approve
Revision history for this message
Thomas Herve (therve) wrote :

+1!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'landscape/broker/registration.py'
2--- landscape/broker/registration.py 2011-01-12 16:30:14 +0000
3+++ landscape/broker/registration.py 2011-06-11 00:36:37 +0000
4@@ -9,6 +9,7 @@
5 from landscape.lib.fetch import fetch, FetchError
6 from landscape.lib.tag import is_valid_tag_list
7 from landscape.lib.network import get_fqdn
8+from landscape.lib.vm_info import get_vm_info
9
10
11 EC2_HOST = "169.254.169.254"
12@@ -279,7 +280,8 @@
13 "account_name": id.account_name,
14 "registration_password": id.registration_password,
15 "hostname": get_fqdn(),
16- "tags": tags}
17+ "tags": tags,
18+ "vm-info": get_vm_info()}
19 self._exchange.send(message)
20 else:
21 self._reactor.fire("registration-failed")
22
23=== modified file 'landscape/broker/tests/test_registration.py'
24--- landscape/broker/tests/test_registration.py 2011-01-12 16:30:14 +0000
25+++ landscape/broker/tests/test_registration.py 2011-06-11 00:36:37 +0000
26@@ -16,6 +16,7 @@
27 from landscape.lib.bpickle import dumps
28 from landscape.lib.fetch import HTTPCodeError, FetchError
29 from landscape.lib.persist import Persist
30+from landscape.lib.vm_info import get_vm_info
31 from landscape.configuration import print_text
32
33
34@@ -154,7 +155,34 @@
35 "account_name": "account_name",
36 "registration_password": None,
37 "hostname": "ooga.local",
38- "tags": None}])
39+ "tags": None,
40+ "vm-info": get_vm_info()}])
41+ self.assertEqual(self.logfile.getvalue().strip(),
42+ "INFO: Queueing message to register with account "
43+ "'account_name' without a password.")
44+
45+ def test_queue_message_on_exchange_with_vm_info(self):
46+ """
47+ When a computer_title and account_name are available, no
48+ secure_id is set, and an exchange is about to happen,
49+ queue a registration message.
50+ """
51+ get_vm_info_mock = self.mocker.replace(get_vm_info)
52+ get_vm_info_mock()
53+ self.mocker.result("vmware")
54+ self.mocker.replay()
55+ self.mstore.set_accepted_types(["register"])
56+ self.config.computer_title = "Computer Title"
57+ self.config.account_name = "account_name"
58+ self.reactor.fire("pre-exchange")
59+ self.assertMessages(self.mstore.get_pending_messages(),
60+ [{"type": "register",
61+ "computer_title": "Computer Title",
62+ "account_name": "account_name",
63+ "registration_password": None,
64+ "hostname": "ooga.local",
65+ "tags": None,
66+ "vm-info": u"vmware"}])
67 self.assertEqual(self.logfile.getvalue().strip(),
68 "INFO: Queueing message to register with account "
69 "'account_name' without a password.")
70@@ -172,7 +200,8 @@
71 "account_name": "account_name",
72 "registration_password": "SEKRET",
73 "hostname": "ooga.local",
74- "tags": None}])
75+ "tags": None,
76+ "vm-info": get_vm_info()}])
77 self.assertEqual(self.logfile.getvalue().strip(),
78 "INFO: Queueing message to register with account "
79 "'account_name' with a password.")
80@@ -194,7 +223,8 @@
81 "account_name": "account_name",
82 "registration_password": "SEKRET",
83 "hostname": "ooga.local",
84- "tags": u"computer,tag"}])
85+ "tags": u"computer,tag",
86+ "vm-info": get_vm_info()}])
87 self.assertEqual(self.logfile.getvalue().strip(),
88 "INFO: Queueing message to register with account "
89 "'account_name' and tags computer,tag "
90@@ -219,7 +249,8 @@
91 "account_name": "account_name",
92 "registration_password": "SEKRET",
93 "hostname": "ooga.local",
94- "tags": None}])
95+ "tags": None,
96+ "vm-info": get_vm_info()}])
97 self.assertEqual(self.logfile.getvalue().strip(),
98 "ERROR: Invalid tags provided for cloud "
99 "registration.\n "
100@@ -244,7 +275,8 @@
101 "account_name": "account_name",
102 "registration_password": "SEKRET",
103 "hostname": "ooga.local",
104- "tags": u"prova\N{LATIN SMALL LETTER J WITH CIRCUMFLEX}o"}])
105+ "tags": u"prova\N{LATIN SMALL LETTER J WITH CIRCUMFLEX}o",
106+ "vm-info": get_vm_info()}])
107 self.assertEqual(self.logfile.getvalue().strip(),
108 "INFO: Queueing message to register with account "
109 "'account_name' and tags prova\xc4\xb5o "
110@@ -433,6 +465,7 @@
111 "account_name": "account_name",
112 "registration_password": "SEKRET",
113 "hostname": socket.getfqdn(),
114+ "vm-info": get_vm_info(),
115 "tags": None}])
116
117
118@@ -828,6 +861,7 @@
119 "account_name": u"onward",
120 "registration_password": u"password",
121 "hostname": socket.getfqdn(),
122+ "vm-info": get_vm_info(),
123 "tags": None}])
124
125 def test_should_register_in_cloud(self):
126
127=== added file 'landscape/lib/tests/test_vm_info.py'
128--- landscape/lib/tests/test_vm_info.py 1970-01-01 00:00:00 +0000
129+++ landscape/lib/tests/test_vm_info.py 2011-06-11 00:36:37 +0000
130@@ -0,0 +1,121 @@
131+import os
132+
133+from landscape.tests.helpers import LandscapeTest
134+
135+from landscape.lib.vm_info import get_vm_info
136+
137+
138+class VMInfoTest(LandscapeTest):
139+
140+ sample_kvm_cpuinfo = """
141+processor : 0
142+vendor_id : GenuineIntel
143+cpu family : 6
144+model : 2
145+model name : QEMU Virtual CPU version 0.14.0
146+stepping : 3
147+cpu MHz : 2653.112
148+cache size : 4096 KB
149+fpu : yes
150+fpu_exception : yes
151+cpuid level : 4
152+wp : yes
153+flags : fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca
154+bogomips : 5306.22
155+clflush size : 64
156+cache_alignment : 64
157+address sizes : 40 bits physical, 48 bits virtual
158+power management:
159+"""
160+
161+ def test_get_vm_info_empty_when_no_virtualization_is_found(self):
162+ """
163+ L{get_vm_info} should be empty when there's no virtualisation.
164+ """
165+ root_path = self.makeDir()
166+ self.assertEqual(u"", get_vm_info(root_path=root_path))
167+
168+ def test_get_vm_info_is_openvz_when_proc_vz_exists(self):
169+ """
170+ L{get_vm_info} should return 'openvz' when /proc/vz exists.
171+ """
172+ root_path = self.makeDir()
173+ proc_path = os.path.join(root_path, "proc")
174+ self.makeDir(path=proc_path)
175+
176+ proc_vz_path = os.path.join(proc_path, "vz")
177+ self.makeFile(path=proc_vz_path, content="foo")
178+
179+ self.assertEqual("openvz", get_vm_info(root_path=root_path))
180+
181+ def test_get_vm_info_is_xen_when_proc_sys_xen_exists(self):
182+ """
183+ L{get_vm_info} should return 'xen' when /proc/sys/xen exists.
184+ """
185+ root_path = self.makeDir()
186+ proc_path = os.path.join(root_path, "proc")
187+ self.makeDir(path=proc_path)
188+
189+ proc_sys_path = os.path.join(proc_path, "sys")
190+ self.makeDir(path=proc_sys_path)
191+
192+ proc_sys_xen_path = os.path.join(proc_sys_path, "xen")
193+ self.makeFile(path=proc_sys_xen_path, content="foo")
194+
195+ self.assertEqual("xen", get_vm_info(root_path=root_path))
196+
197+ def test_get_vm_info_is_xen_when_sys_bus_xen_exists(self):
198+ """
199+ L{get_vm_info} should return 'xen' when /sys/bus/xen exists.
200+ """
201+ root_path = self.makeDir()
202+ sys_path = os.path.join(root_path, "sys")
203+ self.makeDir(path=sys_path)
204+
205+ sys_bus_path = os.path.join(sys_path, "bus")
206+ self.makeDir(path=sys_bus_path)
207+
208+ sys_bus_xen_path = os.path.join(sys_bus_path, "xen")
209+ self.makeFile(path=sys_bus_xen_path, content="foo")
210+
211+ self.assertEqual("xen", get_vm_info(root_path=root_path))
212+
213+ def test_get_vm_info_is_xen_when_proc_xen_exists(self):
214+ """
215+ L{get_vm_info} should return 'xen' when /proc/xen exists.
216+ """
217+ root_path = self.makeDir()
218+ proc_path = os.path.join(root_path, "proc")
219+ self.makeDir(path=proc_path)
220+
221+ proc_xen_path = os.path.join(proc_path, "xen")
222+ self.makeFile(path=proc_xen_path, content="foo")
223+
224+ self.assertEqual("xen", get_vm_info(root_path=root_path))
225+
226+ def test_get_vminfo_is_kvm_when_qemu_is_found_in_proc_cpuinfo(self):
227+ """
228+ L{get_vm_info} should return 'kvm' when QEMU Virtual CPU is found in
229+ /proc/cpuinfo.
230+ """
231+ root_path = self.makeDir()
232+ proc_path = os.path.join(root_path, "proc")
233+ self.makeDir(path=proc_path)
234+
235+ cpuinfo_path = os.path.join(proc_path, "cpuinfo")
236+ self.makeFile(path=cpuinfo_path, content=self.sample_kvm_cpuinfo)
237+
238+ self.assertEqual("kvm", get_vm_info(root_path=root_path))
239+
240+ def test_get_vm_info_is_empty_when_qemu_is_not_found_in_proc_cpuinfo(self):
241+ """
242+ L{get_vm_info} should have an empty string when QEMU Virtual CPU is not
243+ found in /proc/cpuinfo.
244+ """
245+ root_path = self.makeDir()
246+ proc_path = os.path.join(root_path, "proc")
247+ self.makeDir(path=proc_path)
248+
249+ cpuinfo_path = os.path.join(proc_path, "cpuinfo")
250+ self.makeFile(path=cpuinfo_path, content="foo")
251+ self.assertEqual(u"", get_vm_info(root_path=root_path))
252
253=== added file 'landscape/lib/vm_info.py'
254--- landscape/lib/vm_info.py 1970-01-01 00:00:00 +0000
255+++ landscape/lib/vm_info.py 2011-06-11 00:36:37 +0000
256@@ -0,0 +1,39 @@
257+"""
258+Network introspection utilities using ioctl and the /proc filesystem.
259+"""
260+import os
261+
262+
263+def get_vm_info(root_path="/"):
264+ """
265+ This is a utility that returns the virtualization type
266+
267+ It loops through some possible configurations and return a string with
268+ the name of the technology being used or None if there's no match
269+ """
270+ virt_info = ""
271+
272+ def join_root_path(path):
273+ return os.path.join(root_path, path)
274+
275+ xen_paths = ["proc/sys/xen", "sys/bus/xen", "proc/xen"]
276+ xen_paths = map(join_root_path, xen_paths)
277+
278+ vz_path = os.path.join(root_path, "proc/vz")
279+ if os.path.exists(vz_path):
280+ virt_info = "openvz"
281+
282+ elif filter(os.path.exists, xen_paths):
283+ virt_info = "xen"
284+
285+ cpu_info_path = os.path.join(root_path, "proc/cpuinfo")
286+ if os.path.exists(cpu_info_path):
287+ try:
288+ fd = open(cpu_info_path)
289+ cpuinfo = fd.read()
290+ if "QEMU Virtual CPU" in cpuinfo:
291+ virt_info = "kvm"
292+ finally:
293+ fd.close()
294+
295+ return virt_info
296
297=== modified file 'landscape/message_schemas.py'
298--- landscape/message_schemas.py 2011-05-12 10:21:22 +0000
299+++ landscape/message_schemas.py 2011-06-11 00:36:37 +0000
300@@ -68,11 +68,10 @@
301 "computer-info",
302 {"hostname": utf8,
303 "total-memory": Int(),
304- "total-swap": Int(),
305- "vm-info": String()},
306+ "total-swap": Int()},
307 # Not sure why these are all optional, but it's explicitly tested
308 # in the server
309- optional=["hostname", "total-memory", "total-swap", "vm-info"])
310+ optional=["hostname", "total-memory", "total-swap"])
311
312 DISTRIBUTION_INFO = Message(
313 "distribution-info",
314@@ -139,9 +138,10 @@
315 "computer_title": utf8,
316 "hostname": utf8,
317 "account_name": utf8,
318- "tags": Any(utf8, Constant(None))},
319+ "tags": Any(utf8, Constant(None)),
320+ "vm-info": String()},
321 # hostname wasn't around in old versions
322- optional=["registration_password", "hostname", "tags"])
323+ optional=["registration_password", "hostname", "tags", "vm-info"])
324
325 REGISTER_CLOUD_VM = Message(
326 "register-cloud-vm",
327
328=== modified file 'landscape/monitor/computerinfo.py'
329--- landscape/monitor/computerinfo.py 2011-04-25 17:56:33 +0000
330+++ landscape/monitor/computerinfo.py 2011-06-11 00:36:37 +0000
331@@ -1,5 +1,4 @@
332 import logging
333-import os
334
335 from landscape.lib.lsb_release import LSB_RELEASE_FILENAME, parse_lsb_release
336 from landscape.lib.network import get_fqdn
337@@ -60,8 +59,6 @@
338 self._add_if_new(message, "total-memory",
339 total_memory)
340 self._add_if_new(message, "total-swap", total_swap)
341- vm_info = self._get_vm_info()
342- self._add_if_new(message, "vm-info", vm_info)
343 return message
344
345 def _add_if_new(self, message, key, value):
346@@ -95,37 +92,3 @@
347 message = {}
348 message.update(parse_lsb_release(self._lsb_release_filename))
349 return message
350-
351- def _get_vm_info(self):
352- """
353- This is a utility that returns the virtualization type
354-
355- It loops through some possible configurations and return a string with
356- the name of the technology being used or None if there's no match
357- """
358- virt_info = ""
359-
360- def join_root_path(path):
361- return os.path.join(self._root_path, path)
362-
363- xen_paths = ["proc/sys/xen", "sys/bus/xen", "proc/xen"]
364- xen_paths = map(join_root_path, xen_paths)
365-
366- vz_path = os.path.join(self._root_path, "proc/vz")
367- if os.path.exists(vz_path):
368- virt_info = "openvz"
369-
370- elif filter(os.path.exists, xen_paths):
371- virt_info = "xen"
372-
373- cpu_info_path = os.path.join(self._root_path, "proc/cpuinfo")
374- if os.path.exists(cpu_info_path):
375- try:
376- fd = open(cpu_info_path)
377- cpuinfo = fd.read()
378- if "QEMU Virtual CPU" in cpuinfo:
379- virt_info = "kvm"
380- finally:
381- fd.close()
382-
383- return virt_info
384
385=== modified file 'landscape/monitor/tests/test_computerinfo.py'
386--- landscape/monitor/tests/test_computerinfo.py 2011-04-25 17:56:33 +0000
387+++ landscape/monitor/tests/test_computerinfo.py 2011-06-11 00:36:37 +0000
388@@ -1,5 +1,4 @@
389 import re
390-import os
391
392 from landscape.monitor.computerinfo import ComputerInfo
393 from landscape.tests.helpers import LandscapeTest, MonitorHelper
394@@ -45,27 +44,6 @@
395 VmallocChunk: 107432 kB
396 """
397
398- sample_kvm_cpuinfo = """
399-processor : 0
400-vendor_id : GenuineIntel
401-cpu family : 6
402-model : 2
403-model name : QEMU Virtual CPU version 0.14.0
404-stepping : 3
405-cpu MHz : 2653.112
406-cache size : 4096 KB
407-fpu : yes
408-fpu_exception : yes
409-cpuid level : 4
410-wp : yes
411-flags : fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca
412-bogomips : 5306.22
413-clflush size : 64
414-cache_alignment : 64
415-address sizes : 40 bits physical, 48 bits virtual
416-power management:
417-"""
418-
419 def setUp(self):
420 LandscapeTest.setUp(self)
421 self.lsb_release_filename = self.makeFile(SAMPLE_LSB_RELEASE)
422@@ -302,7 +280,7 @@
423 plugin.exchange()
424 computer_info = {"type": "computer-info", "hostname": "ooga.local",
425 "timestamp": 0, "total-memory": 1510,
426- "total-swap": 1584, "vm-info": ""}
427+ "total-swap": 1584}
428 dist_info = {"type": "distribution-info",
429 "code-name": "dapper", "description": "Ubuntu 6.06.1 LTS",
430 "distributor-id": "Ubuntu", "release": "6.06"}
431@@ -347,146 +325,3 @@
432
433 self.mstore.set_accepted_types(["distribution-info", "computer-info"])
434 self.assertMessages(list(self.mstore.get_pending_messages()), [])
435-
436- def test_vminfo_empty_when_no_virtualization_is_found(self):
437- """
438- L{ComputerInfo} should always have the vm-info key even when no
439- virtualization is used.
440-
441- And it should be an empty string.
442- """
443- self.mstore.set_accepted_types(["computer-info"])
444- root_path = self.makeDir()
445- plugin = ComputerInfo(root_path=root_path)
446- self.monitor.add(plugin)
447-
448- plugin.exchange()
449- message = self.mstore.get_pending_messages()[0]
450- self.assertTrue("vm-info" in message)
451- self.assertEqual("", message["vm-info"])
452-
453- def test_vminfo_is_openvz_when_proc_vz_exists(self):
454- """
455- L{ComputerInfo} should have 'openvz' as the value of vm-info when
456- /proc/vz exists.
457- """
458- root_path = self.makeDir()
459- proc_path = os.path.join(root_path, "proc")
460- self.makeDir(path=proc_path)
461-
462- proc_vz_path = os.path.join(proc_path, "vz")
463- self.makeFile(path=proc_vz_path, content="foo")
464-
465- self.mstore.set_accepted_types(["computer-info"])
466- plugin = ComputerInfo(root_path=root_path)
467- self.monitor.add(plugin)
468-
469- plugin.exchange()
470- message = self.mstore.get_pending_messages()[0]
471- self.assertEquals('openvz', message["vm-info"])
472-
473- def test_vminfo_is_xen_when_proc_sys_xen_exists(self):
474- """
475- L{ComputerInfo} should have 'xen' as the value of vm-info when
476- /proc/sys/xen exists.
477- """
478- root_path = self.makeDir()
479- proc_path = os.path.join(root_path, "proc")
480- self.makeDir(path=proc_path)
481-
482- proc_sys_path = os.path.join(proc_path, "sys")
483- self.makeDir(path=proc_sys_path)
484-
485- proc_sys_xen_path = os.path.join(proc_sys_path, "xen")
486- self.makeFile(path=proc_sys_xen_path, content="foo")
487-
488- self.mstore.set_accepted_types(["computer-info"])
489- plugin = ComputerInfo(root_path=root_path)
490- self.monitor.add(plugin)
491-
492- plugin.exchange()
493- message = self.mstore.get_pending_messages()[0]
494- self.assertEquals('xen', message["vm-info"])
495-
496- def test_vminfo_is_xen_when_sys_bus_xen_exists(self):
497- """
498- L{ComputerInfo} should have 'xen' as value of vm-info when
499- /sys/bus/xen exists
500- """
501- root_path = self.makeDir()
502- sys_path = os.path.join(root_path, "sys")
503- self.makeDir(path=sys_path)
504-
505- sys_bus_path = os.path.join(sys_path, "bus")
506- self.makeDir(path=sys_bus_path)
507-
508- sys_bus_xen_path = os.path.join(sys_bus_path, "xen")
509- self.makeFile(path=sys_bus_xen_path, content="foo")
510-
511- self.mstore.set_accepted_types(["computer-info"])
512- plugin = ComputerInfo(root_path=root_path)
513- self.monitor.add(plugin)
514-
515- plugin.exchange()
516- message = self.mstore.get_pending_messages()[0]
517- self.assertEquals('xen', message["vm-info"])
518-
519- def test_vminfo_is_xen_when_proc_xen_exists(self):
520- """
521- L{ComputerInfo} should have 'xen' as value of vm-info when
522- /proc/xen exists.
523- """
524- root_path = self.makeDir()
525- proc_path = os.path.join(root_path, "proc")
526- self.makeDir(path=proc_path)
527-
528- proc_xen_path = os.path.join(proc_path, "xen")
529- self.makeFile(path=proc_xen_path, content="foo")
530-
531- self.mstore.set_accepted_types(["computer-info"])
532- plugin = ComputerInfo(root_path=root_path)
533- self.monitor.add(plugin)
534-
535- plugin.exchange()
536- message = self.mstore.get_pending_messages()[0]
537- self.assertEquals('xen', message["vm-info"])
538-
539- def test_vminfo_is_kvm_when_qemu_is_found_in_proc_cpuinfo(self):
540- """
541- L{ComputerInfo} should have 'kvm' as value of vm-info when
542- QEMU Virtual CPU is found in /proc/cpuinfo.
543- """
544- root_path = self.makeDir()
545- proc_path = os.path.join(root_path, "proc")
546- self.makeDir(path=proc_path)
547-
548- cpuinfo_path = os.path.join(proc_path, "cpuinfo")
549- self.makeFile(path=cpuinfo_path, content=self.sample_kvm_cpuinfo)
550-
551- self.mstore.set_accepted_types(["computer-info"])
552- plugin = ComputerInfo(root_path=root_path)
553- self.monitor.add(plugin)
554-
555- plugin.exchange()
556- message = self.mstore.get_pending_messages()[0]
557- self.assertEqual("kvm", message["vm-info"])
558-
559- def test_vminfo_is_empty_when_qemu_is_not_found_in_proc_cpuinfo(self):
560- """
561- L{ComputerInfo} should have an empty string as value of vm-info when
562- QEMU Virtual CPU is not found in /proc/cpuinfo.
563- """
564- root_path = self.makeDir()
565- proc_path = os.path.join(root_path, "proc")
566- self.makeDir(path=proc_path)
567-
568- cpuinfo_path = os.path.join(proc_path, "cpuinfo")
569- self.makeFile(path=cpuinfo_path, content="foo")
570-
571- self.mstore.set_accepted_types(["computer-info"])
572- plugin = ComputerInfo(root_path=root_path)
573- self.monitor.add(plugin)
574-
575- plugin.exchange()
576- message = self.mstore.get_pending_messages()[0]
577- self.assertEqual("", message["vm-info"])

Subscribers

People subscribed via source and target branches

to all changes: