bash_completion: Enable extglob while parsing file
[ganeti-local] / test / ganeti.ovf_unittest.py
1 #!/usr/bin/python
2 #
3
4 # Copyright (C) 2011 Google Inc.
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 # 02110-1301, USA.
20
21
22 """Script for testing ganeti.ovf.
23
24 """
25
26 import optparse
27 import os
28 import os.path
29 import re
30 import shutil
31 import sys
32 import tempfile
33 import unittest
34
35 try:
36   import xml.etree.ElementTree as ET
37 except ImportError:
38   import elementtree.ElementTree as ET
39
40 from ganeti import constants
41 from ganeti import errors
42 from ganeti import ovf
43 from ganeti import utils
44
45 import testutils
46
47 OUTPUT_DIR = "newdir"
48
49 GANETI_DISKS = {
50   "disk_count": "1",
51   "disk0_dump": "new_disk.raw",
52   "disk0_size": "0",
53   "disk0_ivname": "disk/0",
54 }
55 GANETI_NETWORKS = {
56   "nic_count": "1",
57   "nic0_mode": "bridged",
58   "nic0_ip": "none",
59   "nic0_mac": "aa:00:00:d8:2c:1e",
60   "nic0_link": "xen-br0",
61 }
62 GANETI_HYPERVISOR = {
63   "hypervisor_name": "xen-pvm",
64   "root-path": "/dev/sda",
65   "kernel_args": "ro",
66 }
67 GANETI_OS = {"os_name": "lenny-image"}
68 GANETI_BACKEND = {
69   "vcpus": "1",
70   "memory" : "2048",
71   "auto_balance": "False",
72 }
73 GANETI_NAME = "ganeti-test-xen"
74 GANETI_TEMPLATE = "plain"
75 GANETI_TAGS = None
76 GANETI_VERSION = "0"
77
78 VIRTUALBOX_DISKS = {
79   "disk_count": "2",
80   "disk0_ivname": "disk/0",
81   "disk0_dump": "new_disk.raw",
82   "disk0_size": "0",
83   "disk1_ivname": "disk/1",
84   "disk1_dump": "second_disk.raw",
85   "disk1_size": "0",
86 }
87 VIRTUALBOX_NETWORKS = {
88   "nic_count": "1",
89   "nic0_mode": "bridged",
90   "nic0_ip": "none",
91   "nic0_link": "auto",
92   "nic0_mac": "auto",
93 }
94 VIRTUALBOX_HYPERVISOR = {"hypervisor_name": "auto"}
95 VIRTUALBOX_OS = {"os_name": None}
96 VIRTUALBOX_BACKEND = {
97  "vcpus": "1",
98   "memory" : "2048",
99   "auto_balance": "auto",
100 }
101 VIRTUALBOX_NAME = None
102 VIRTUALBOX_TEMPLATE = None
103 VIRTUALBOX_TAGS = None
104 VIRTUALBOX_VERSION = None
105
106 EMPTY_DISKS = {}
107 EMPTY_NETWORKS = {}
108 EMPTY_HYPERVISOR = {"hypervisor_name": "auto"}
109 EMPTY_OS = {}
110 EMPTY_BACKEND = {
111   "vcpus": "auto",
112   "memory" : "auto",
113   "auto_balance": "auto",
114 }
115 EMPTY_NAME = None
116 EMPTY_TEMPLATE = None
117 EMPTY_TAGS = None
118 EMPTY_VERSION = None
119
120 CMDARGS_DISKS = {
121   "disk_count": "1",
122   "disk0_ivname": "disk/0",
123   "disk0_dump": "disk0.raw",
124   "disk0_size": "8",
125 }
126 CMDARGS_NETWORKS = {
127   "nic0_link": "auto",
128   "nic0_mode": "bridged",
129   "nic0_ip": "none",
130   "nic0_mac": "auto",
131   "nic_count": "1",
132 }
133 CMDARGS_HYPERVISOR = {
134   "hypervisor_name": "xen-pvm"
135 }
136 CMDARGS_OS = {"os_name": "lenny-image"}
137 CMDARGS_BACKEND = {
138   "auto_balance": False,
139   "vcpus": "1",
140   "memory": "256",
141 }
142 CMDARGS_NAME = "test-instance"
143 CMDARGS_TEMPLATE = "plain"
144 CMDARGS_TAGS = "test-tag-1,test-tag-2"
145
146 ARGS_EMPTY = {
147   "output_dir": None,
148   "nics": [],
149   "disks": [],
150   "name": "test-instance",
151   "ova_package": False,
152   "ext_usage": False,
153   "disk_format": "cow",
154   "compression": False,
155 }
156 ARGS_EXPORT_DIR = dict(ARGS_EMPTY, **{
157   "output_dir": OUTPUT_DIR,
158   "name": None,
159   "hypervisor": None,
160   "os": None,
161   "beparams": {},
162   "no_nics": False,
163   "disk_template": None,
164   "tags": None,
165 })
166 ARGS_VBOX = dict(ARGS_EXPORT_DIR, **{
167   "output_dir": OUTPUT_DIR,
168   "name": "test-instance",
169   "os": "lenny-image",
170   "hypervisor": ("xen-pvm", {}),
171   "osparams":{},
172   "disks": [],
173 })
174 ARGS_COMPLETE = dict(ARGS_VBOX, **{
175   "beparams": {"vcpus":"1", "memory":"256", "auto_balance": False},
176   "disks": [(0,{"size":"5mb"})],
177   "nics": [("0",{"mode":"bridged"})],
178   "disk_template": "plain",
179   "tags": "test-tag-1,test-tag-2",
180 })
181 ARGS_BROKEN = dict(ARGS_EXPORT_DIR , **{
182   "no_nics": True,
183   "disk_template": "diskless",
184   "name": "test-instance",
185   "os": "lenny-image",
186   "osparams": {},
187 })
188
189 EXP_ARGS_COMPRESSED = dict(ARGS_EXPORT_DIR, **{
190   "compression": True,
191 })
192
193 EXP_DISKS_LIST = [
194   {
195     "format": "vmdk",
196     "compression": "gzip",
197     "virt-size": 90000,
198     "real-size": 203,
199     "path": "new_disk.cow.gz",
200   },
201   {
202     "format": "cow",
203     "virt-size": 15,
204     "real-size": 15,
205     "path": "new_disk.cow",
206   },
207 ]
208 EXP_NETWORKS_LIST = [
209   {"mac": "aa:00:00:d8:2c:1e", "ip":"None", "link":"br0","mode":"routed"},
210 ]
211 EXP_PARTIAL_GANETI_DICT = {
212   "hypervisor": {"name": "xen-kvm"},
213   "os": {"name": "lenny-image"},
214   "auto_balance": "True",
215   "version": "0",
216 }
217 EXP_GANETI_DICT = {
218   'tags': None,
219   'auto_balance': 'False',
220   'hypervisor': {
221      'root-path': '/dev/sda',
222      'name': 'xen-pvm',
223      'kernel_args': 'ro'
224    },
225   'version': '0',
226   'disk_template': None,
227   'os': {'name': 'lenny-image'}
228 }
229 EXP_NAME ="xen-dev-i1"
230 EXP_VCPUS = 1
231 EXP_MEMORY = 512
232
233 EXPORT_EMPTY = ("<Envelope xml:lang=\"en-US\" xmlns=\"http://schemas.dmtf.org/"
234                 "ovf/envelope/1\" xmlns:gnt=\"http://ganeti\" xmlns:ovf=\""
235                 "http://schemas.dmtf.org/ovf/envelope/1\" xmlns:rasd=\""
236                 "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_Resource"
237                 "AllocationSettingData\" xmlns:vssd=\"http://schemas.dmtf.org"
238                 "/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData\""
239                 " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" />")
240 EXPORT_DISKS_EMPTY = ("<References /><DiskSection><Info>Virtual disk"
241                       " information</Info></DiskSection>")
242 EXPORT_DISKS = ("<References><File ovf:compression=\"gzip\" ovf:href=\"new_disk"
243                 ".cow.gz\" ovf:id=\"file0\" ovf:size=\"203\" /><File ovf:href="
244                 "\"new_disk.cow\" ovf:id=\"file1\" ovf:size=\"15\" />"
245                 "</References><DiskSection><Info>Virtual disk information"
246                 "</Info><Disk ovf:capacity=\"90000\" ovf:diskId=\"disk0\" ovf"
247                 ":fileRef=\"file0\" ovf:format=\"http://www.vmware.com/"
248                 "interfaces/specifications/vmdk.html#monolithicSparse\" /><Disk"
249                 " ovf:capacity=\"15\" ovf:diskId=\"disk1\" ovf:fileRef"
250                 "=\"file1\" ovf:format=\"http://www.gnome.org/~markmc/qcow"
251                 "-image-format.html\" /></DiskSection>")
252 EXPORT_NETWORKS_EMPTY = ("<NetworkSection><Info>List of logical networks</Info>"
253                          "</NetworkSection>")
254 EXPORT_NETWORKS = ("<NetworkSection><Info>List of logical networks</Info>"
255                    "<Network ovf:name=\"routed0\" /></NetworkSection>")
256 EXPORT_GANETI_INCOMPLETE = ("<gnt:GanetiSection><gnt:Version>0</gnt:Version>"
257                             "<gnt:AutoBalance>True</gnt:AutoBalance><gnt:"
258                             "OperatingSystem><gnt:Name>lenny-image</gnt:Name>"
259                             "<gnt:Parameters /></gnt:OperatingSystem><gnt:"
260                             "Hypervisor><gnt:Name>xen-kvm</gnt:Name><gnt:"
261                             "Parameters /></gnt:Hypervisor><gnt:Network><gnt:"
262                             "Nic ovf:name=\"routed0\"><gnt:Mode>routed</gnt:"
263                             "Mode><gnt:MACAddress>aa:00:00:d8:2c:1e</gnt:"
264                             "MACAddress><gnt:IPAddress>None</gnt:IPAddress>"
265                             "<gnt:Link>br0</gnt:Link></gnt:Nic></gnt:Network>"
266                             "</gnt:GanetiSection>")
267 EXPORT_GANETI = ("<gnt:GanetiSection><gnt:Version>0</gnt:Version><gnt:"
268                  "AutoBalance>False</gnt:AutoBalance><gnt:OperatingSystem>"
269                  "<gnt:Name>lenny-image</gnt:Name><gnt:Parameters /></gnt:"
270                  "OperatingSystem><gnt:Hypervisor><gnt:Name>xen-pvm</gnt:Name>"
271                  "<gnt:Parameters><gnt:root-path>/dev/sda</gnt:root-path><gnt:"
272                  "kernel_args>ro</gnt:kernel_args></gnt:Parameters></gnt:"
273                  "Hypervisor><gnt:Network><gnt:Nic ovf:name=\"routed0\"><gnt:"
274                  "Mode>routed</gnt:Mode><gnt:MACAddress>aa:00:00:d8:2c:1e</gnt:"
275                  "MACAddress><gnt:IPAddress>None</gnt:IPAddress><gnt:Link>br0"
276                  "</gnt:Link></gnt:Nic></gnt:Network></gnt:GanetiSection>")
277 EXPORT_SYSTEM = ("<References><File ovf:compression=\"gzip\" ovf:href=\"new_"
278                  "disk.cow.gz\" ovf:id=\"file0\" ovf:size=\"203\" /><File ovf:"
279                  "href=\"new_disk.cow\" ovf:id=\"file1\" ovf:size=\"15\" />"
280                  "</References><DiskSection><Info>Virtual disk information"
281                  "</Info><Disk ovf:capacity=\"90000\" ovf:diskId=\"disk0\""
282                  " ovf:fileRef=\"file0\" ovf:format=\"http://www.vmware.com"
283                  "/interfaces/specifications/vmdk.html#monolithicSparse\" />"
284                  "<Disk ovf:capacity=\"15\" ovf:diskId=\"disk1\" ovf:fileRef"
285                  "=\"file1\" ovf:format=\"http://www.gnome.org/~markmc/qcow"
286                  "-image-format.html\" /></DiskSection><NetworkSection><Info>"
287                  "List of logical networks</Info><Network ovf:name=\"routed0\""
288                  " /></NetworkSection><VirtualSystem ovf:id=\"xen-dev-i1\">"
289                  "<Info>A virtual machine</Info><Name>xen-dev-i1</Name>"
290                  "<OperatingSystemSection ovf:id=\"0\"><Info>Installed guest"
291                  " operating system</Info></OperatingSystemSection><Virtual"
292                  "HardwareSection><Info>Virtual hardware requirements</Info>"
293                  "<System><vssd:ElementName>Virtual Hardware Family"
294                  "</vssd:ElementName><vssd:InstanceID>0</vssd:InstanceID><vssd:"
295                  "VirtualSystemIdentifier>xen-dev-i1</vssd:VirtualSystem"
296                  "Identifier><vssd:VirtualSystemType>ganeti-ovf</vssd:Virtual"
297                  "SystemType></System><Item><rasd:ElementName>1 virtual CPU(s)"
298                  "</rasd:ElementName><rasd:InstanceID>1</rasd:InstanceID><rasd:"
299                  "ResourceType>3</rasd:ResourceType><rasd:VirtualQuantity>1"
300                  "</rasd:VirtualQuantity></Item><Item><rasd:AllocationUnits>"
301                  "byte * 2^20</rasd:AllocationUnits><rasd:ElementName>512MB of"
302                  " memory</rasd:ElementName><rasd:InstanceID>2</rasd:"
303                  "InstanceID><rasd:ResourceType>4</rasd:ResourceType><rasd:"
304                  "VirtualQuantity>512</rasd:VirtualQuantity></Item><Item>"
305                  "<rasd:Address>0</rasd:Address><rasd:ElementName>scsi"
306                  "_controller0</rasd:ElementName><rasd:InstanceID>3"
307                  "</rasd:InstanceID><rasd:ResourceSubType>lsilogic</rasd"
308                  ":ResourceSubType><rasd:ResourceType>6</rasd:ResourceType>"
309                  "</Item><Item><rasd:ElementName>disk0</rasd:ElementName><rasd"
310                  ":HostResource>ovf:/disk/disk0</rasd:HostResource><rasd"
311                  ":InstanceID>4</rasd:InstanceID><rasd:Parent>3</rasd:Parent>"
312                  "<rasd:ResourceType>17</rasd:ResourceType></Item><Item><rasd:"
313                  "ElementName>disk1</rasd:ElementName><rasd:HostResource>ovf:/"
314                  "disk/disk1</rasd:HostResource><rasd:InstanceID>5</rasd"
315                  ":InstanceID><rasd:Parent>3</rasd:Parent><rasd:ResourceType>17"
316                  "</rasd:ResourceType></Item><Item><rasd:Address>aa:00"
317                  ":00:d8:2c:1e</rasd:Address><rasd:Connection>routed0</rasd"
318                  ":Connection><rasd:ElementName>routed0</rasd:ElementName><rasd"
319                  ":InstanceID>6</rasd:InstanceID><rasd:ResourceType>10</rasd"
320                  ":ResourceType></Item></VirtualHardwareSection>"
321                  "</VirtualSystem>")
322
323
324 def _GetArgs(args, with_name=False):
325   options = optparse.Values()
326   needed = args
327   if with_name:
328     needed["name"] = "test-instance"
329   options._update_loose(needed)
330   return options
331
332
333 OPTS_EMPTY = _GetArgs(ARGS_EMPTY)
334 OPTS_EXPORT_NO_NAME = _GetArgs(ARGS_EXPORT_DIR)
335 OPTS_EXPORT = _GetArgs(ARGS_EXPORT_DIR, with_name=True)
336
337 EXP_OPTS = OPTS_EXPORT_NO_NAME
338 EXP_OPTS_COMPRESSED = _GetArgs(EXP_ARGS_COMPRESSED)
339
340 OPTS_VBOX = _GetArgs(ARGS_VBOX)
341 OPTS_COMPLETE = _GetArgs(ARGS_COMPLETE)
342 OPTS_NONIC_NODISK = _GetArgs(ARGS_BROKEN)
343
344
345 def _GetFullFilename(file_name):
346   file_path = "%s/test/data/ovfdata/%s" % (testutils.GetSourceDir(),
347     file_name)
348   file_path = os.path.abspath(file_path)
349   return file_path
350
351
352 class BetterUnitTest(unittest.TestCase):
353   def assertRaisesRegexp(self, exception, regexp_val, function, *args):
354     try:
355       function(*args)
356       self.fail("Expected raising %s" % exception)
357     except exception, err:
358       regexp = re.compile(regexp_val)
359       if re.search(regexp, str(err)) == None:
360         self.fail("Expected matching '%s', got '%s'" %
361           (regexp_val, str(err)))
362
363
364 class TestOVFImporter(BetterUnitTest):
365   def setUp(self):
366     self.non_existing_file = _GetFullFilename("not_the_file.ovf")
367     self.ganeti_ovf = _GetFullFilename("ganeti.ovf")
368     self.virtualbox_ovf = _GetFullFilename("virtualbox.ovf")
369     self.ova_package = _GetFullFilename("ova.ova")
370     self.empty_ovf = _GetFullFilename("empty.ovf")
371     self.wrong_extension = _GetFullFilename("wrong_extension.ovd")
372     self.wrong_ova_archive = _GetFullFilename("wrong_ova.ova")
373     self.no_ovf_in_ova = _GetFullFilename("no_ovf.ova")
374     self.importer = None
375
376   def tearDown(self):
377     if self.importer:
378       self.importer.Cleanup()
379     del_dir = os.path.abspath(OUTPUT_DIR)
380     try:
381       shutil.rmtree(del_dir)
382     except OSError:
383       pass
384
385   def testFileDoesNotExistError(self):
386     self.assertRaisesRegexp(errors.OpPrereqError, "does not exist",
387       ovf.OVFImporter, self.non_existing_file, None)
388
389   def testWrongInputFileExtensionError(self):
390     self.assertRaisesRegexp(errors.OpPrereqError,
391       "Unknown file extension", ovf.OVFImporter,
392       self.wrong_extension, None)
393
394   def testOVAUnpackingDirectories(self):
395     self.importer = ovf.OVFImporter(self.ova_package, OPTS_EMPTY)
396     self.assertTrue(self.importer.input_dir != None)
397     self.assertEquals(self.importer.output_dir , constants.EXPORT_DIR)
398     self.assertTrue(self.importer.temp_dir != None)
399
400   def testOVFUnpackingDirectories(self):
401     self.importer = ovf.OVFImporter(self.virtualbox_ovf,
402       OPTS_EMPTY)
403     self.assertEquals(self.importer.input_dir , _GetFullFilename(""))
404     self.assertEquals(self.importer.output_dir , constants.EXPORT_DIR)
405     self.assertEquals(self.importer.temp_dir , None)
406
407   def testOVFSetOutputDirDirectories(self):
408     self.importer = ovf.OVFImporter(self.ganeti_ovf, OPTS_EXPORT)
409     self.assertEquals(self.importer.input_dir , _GetFullFilename(""))
410     self.assertTrue(OUTPUT_DIR in self.importer.output_dir)
411     self.assertEquals(self.importer.temp_dir , None)
412
413   def testWrongOVAArchiveError(self):
414     self.assertRaisesRegexp(errors.OpPrereqError, "not a proper tar",
415       ovf.OVFImporter, self.wrong_ova_archive, None)
416
417   def testNoOVFFileInOVAPackageError(self):
418     self.assertRaisesRegexp(errors.OpPrereqError, "No .ovf file",
419       ovf.OVFImporter, self.no_ovf_in_ova, None)
420
421   def testParseGanetiOvf(self):
422     self.importer = ovf.OVFImporter(self.ganeti_ovf, OPTS_EXPORT_NO_NAME)
423     self.importer.Parse()
424     self.assertTrue("%s/ganeti-test-xen" % OUTPUT_DIR in
425       self.importer.output_dir)
426     self.assertEqual(self.importer.results_disk, GANETI_DISKS)
427     self.assertEqual(self.importer.results_network, GANETI_NETWORKS)
428     self.assertEqual(self.importer.results_hypervisor, GANETI_HYPERVISOR)
429     self.assertEqual(self.importer.results_os, GANETI_OS)
430     self.assertEqual(self.importer.results_backend, GANETI_BACKEND)
431     self.assertEqual(self.importer.results_name, GANETI_NAME)
432     self.assertEqual(self.importer.results_template, GANETI_TEMPLATE)
433     self.assertEqual(self.importer.results_tags, GANETI_TAGS)
434     self.assertEqual(self.importer.results_version, GANETI_VERSION)
435
436   def testParseVirtualboxOvf(self):
437     self.importer = ovf.OVFImporter(self.virtualbox_ovf, OPTS_VBOX)
438     self.importer.Parse()
439     self.assertTrue("%s/test-instance" % OUTPUT_DIR in self.importer.output_dir)
440     self.assertEquals(self.importer.results_disk, VIRTUALBOX_DISKS)
441     self.assertEquals(self.importer.results_network, VIRTUALBOX_NETWORKS)
442     self.assertEquals(self.importer.results_hypervisor, CMDARGS_HYPERVISOR)
443     self.assertEquals(self.importer.results_os, CMDARGS_OS)
444     self.assertEquals(self.importer.results_backend, VIRTUALBOX_BACKEND)
445     self.assertEquals(self.importer.results_name, CMDARGS_NAME)
446     self.assertEquals(self.importer.results_template, VIRTUALBOX_TEMPLATE)
447     self.assertEqual(self.importer.results_tags, VIRTUALBOX_TAGS)
448     self.assertEqual(self.importer.results_version, constants.EXPORT_VERSION)
449
450   def testParseEmptyOvf(self):
451     self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_COMPLETE)
452     self.importer.Parse()
453     self.assertTrue("%s/test-instance" % OUTPUT_DIR in self.importer.output_dir)
454     self.assertEquals(self.importer.results_disk, CMDARGS_DISKS)
455     self.assertEquals(self.importer.results_network, CMDARGS_NETWORKS)
456     self.assertEquals(self.importer.results_hypervisor, CMDARGS_HYPERVISOR)
457     self.assertEquals(self.importer.results_os, CMDARGS_OS)
458     self.assertEquals(self.importer.results_backend, CMDARGS_BACKEND)
459     self.assertEquals(self.importer.results_name, CMDARGS_NAME)
460     self.assertEquals(self.importer.results_template, CMDARGS_TEMPLATE)
461     self.assertEqual(self.importer.results_tags, CMDARGS_TAGS)
462     self.assertEqual(self.importer.results_version, constants.EXPORT_VERSION)
463
464   def testParseNameOptions(self):
465     self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_COMPLETE)
466     results = self.importer._ParseNameOptions()
467     self.assertEquals(results, CMDARGS_NAME)
468
469   def testParseHypervisorOptions(self):
470     self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_COMPLETE)
471     results = self.importer._ParseHypervisorOptions()
472     self.assertEquals(results, CMDARGS_HYPERVISOR)
473
474   def testParseOSOptions(self):
475     self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_COMPLETE)
476     results = self.importer._ParseOSOptions()
477     self.assertEquals(results, CMDARGS_OS)
478
479   def testParseBackendOptions(self):
480     self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_COMPLETE)
481     results = self.importer._ParseBackendOptions()
482     self.assertEquals(results, CMDARGS_BACKEND)
483
484   def testParseTags(self):
485     self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_COMPLETE)
486     results = self.importer._ParseTags()
487     self.assertEquals(results, CMDARGS_TAGS)
488
489   def testParseNicOptions(self):
490     self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_COMPLETE)
491     results = self.importer._ParseNicOptions()
492     self.assertEquals(results, CMDARGS_NETWORKS)
493
494   def testParseDiskOptionsFromGanetiOVF(self):
495     self.importer = ovf.OVFImporter(self.ganeti_ovf, OPTS_EXPORT)
496     os.mkdir(OUTPUT_DIR)
497     results = self.importer._GetDiskInfo()
498     self.assertEquals(results, GANETI_DISKS)
499
500   def testParseTemplateOptions(self):
501     self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_COMPLETE)
502     results = self.importer._ParseTemplateOptions()
503     self.assertEquals(results, GANETI_TEMPLATE)
504
505   def testParseDiskOptionsFromCmdLine(self):
506     self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_COMPLETE)
507     os.mkdir(OUTPUT_DIR)
508     results = self.importer._ParseDiskOptions()
509     self.assertEquals(results, CMDARGS_DISKS)
510
511   def testGetDiskFormat(self):
512     self.importer = ovf.OVFImporter(self.ganeti_ovf, OPTS_EXPORT)
513     disks_list = self.importer.ovf_reader.GetDisksNames()
514     results = [self.importer._GetDiskQemuInfo("%s/%s" %
515       (self.importer.input_dir, path), "file format: (\S+)")
516       for (path, _) in disks_list]
517     self.assertEqual(results, ["vmdk"])
518
519   def testNoInstanceNameOVF(self):
520     self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_EXPORT_NO_NAME)
521     self.assertRaisesRegexp(errors.OpPrereqError, "Name of instance",
522       self.importer.Parse)
523
524   def testErrorNoOSNameOVF(self):
525     self.importer = ovf.OVFImporter(self.virtualbox_ovf, OPTS_EXPORT)
526     self.assertRaisesRegexp(errors.OpPrereqError, "OS name",
527       self.importer.Parse)
528
529   def testErrorNoDiskAndNoNetwork(self):
530     self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_NONIC_NODISK)
531     self.assertRaisesRegexp(errors.OpPrereqError,
532       "Either disk specification or network"
533       " description", self.importer.Parse)
534
535
536 class TestOVFExporter(BetterUnitTest):
537   def setUp(self):
538     self.exporter = None
539     self.wrong_config_file = _GetFullFilename("wrong_config.ini")
540     self.unsafe_path_to_disk = _GetFullFilename("unsafe_path.ini")
541     self.disk_image_not_exist = _GetFullFilename("no_disk.ini")
542     self.empty_config = _GetFullFilename("empty.ini")
543     self.standard_export = _GetFullFilename("config.ini")
544     self.wrong_network_mode = self.disk_image_not_exist
545     self.no_memory = self.disk_image_not_exist
546     self.no_vcpus = self.disk_image_not_exist
547     self.no_os = _GetFullFilename("no_os.ini")
548     self.no_hypervisor = self.disk_image_not_exist
549
550   def tearDown(self):
551     if self.exporter:
552       self.exporter.Cleanup()
553     del_dir = os.path.abspath(OUTPUT_DIR)
554     try:
555       shutil.rmtree(del_dir)
556     except OSError:
557       pass
558
559   def testErrorWrongConfigFile(self):
560     self.assertRaisesRegexp(errors.OpPrereqError,
561       "Error when trying to read", ovf.OVFExporter,
562       self.wrong_config_file, EXP_OPTS)
563
564   def testErrorPathToTheDiskIncorrect(self):
565     self.exporter = ovf.OVFExporter(self.unsafe_path_to_disk, EXP_OPTS)
566     self.assertRaisesRegexp(errors.OpPrereqError, "contains a directory name",
567       self.exporter._ParseDisks)
568
569   def testErrorDiskImageNotExist(self):
570     self.exporter = ovf.OVFExporter(self.disk_image_not_exist, EXP_OPTS)
571     self.assertRaisesRegexp(errors.OpPrereqError, "Disk image does not exist",
572       self.exporter._ParseDisks)
573
574   def testParseNetworks(self):
575     self.exporter = ovf.OVFExporter(self.standard_export, EXP_OPTS)
576     results = self.exporter._ParseNetworks()
577     self.assertEqual(results, EXP_NETWORKS_LIST)
578
579   def testErrorWrongNetworkMode(self):
580     self.exporter = ovf.OVFExporter(self.wrong_network_mode, EXP_OPTS)
581     self.assertRaisesRegexp(errors.OpPrereqError,
582       "Network mode nic not recognized", self.exporter._ParseNetworks)
583
584   def testParseVCPusMem(self):
585     self.exporter = ovf.OVFExporter(self.standard_export, EXP_OPTS)
586     vcpus = self.exporter._ParseVCPUs()
587     memory = self.exporter._ParseMemory()
588     self.assertEqual(vcpus, EXP_VCPUS)
589     self.assertEqual(memory, EXP_MEMORY)
590
591   def testErrorNoVCPUs(self):
592     self.exporter = ovf.OVFExporter(self.no_vcpus, EXP_OPTS)
593     self.assertRaisesRegexp(errors.OpPrereqError, "No CPU information found",
594       self.exporter._ParseVCPUs)
595
596   def testErrorNoMemory(self):
597     self.exporter = ovf.OVFExporter(self.no_memory, EXP_OPTS)
598     self.assertRaisesRegexp(errors.OpPrereqError, "No memory information found",
599       self.exporter._ParseMemory)
600
601   def testParseGaneti(self):
602     self.exporter = ovf.OVFExporter(self.standard_export, EXP_OPTS)
603     results = self.exporter._ParseGaneti()
604     self.assertEqual(results, EXP_GANETI_DICT)
605
606   def testErrorNoHypervisor(self):
607     self.exporter = ovf.OVFExporter(self.no_hypervisor, EXP_OPTS)
608     self.assertRaisesRegexp(errors.OpPrereqError,
609       "No hypervisor information found", self.exporter._ParseGaneti)
610
611   def testErrorNoOS(self):
612     self.exporter = ovf.OVFExporter(self.no_os, EXP_OPTS)
613     self.assertRaisesRegexp(errors.OpPrereqError,
614       "No operating system information found", self.exporter._ParseGaneti)
615
616   def testErrorParseNoInstanceName(self):
617     self.exporter = ovf.OVFExporter(self.empty_config, EXP_OPTS)
618     self.assertRaisesRegexp(errors.OpPrereqError, "No instance name found",
619       self.exporter.Parse)
620
621
622 class TestOVFReader(BetterUnitTest):
623   def setUp(self):
624     self.wrong_xml_file = _GetFullFilename("wrong_xml.ovf")
625     self.ganeti_ovf = _GetFullFilename("ganeti.ovf")
626     self.virtualbox_ovf = _GetFullFilename("virtualbox.ovf")
627     self.corrupted_ovf = _GetFullFilename("corrupted_resources.ovf")
628     self.wrong_manifest_ovf = _GetFullFilename("wrong_manifest.ovf")
629     self.no_disk_in_ref_ovf = _GetFullFilename("no_disk_in_ref.ovf")
630     self.empty_ovf = _GetFullFilename("empty.ovf")
631     self.compressed_disk = _GetFullFilename("gzip_disk.ovf")
632
633   def tearDown(self):
634     pass
635
636   def testXMLParsingError(self):
637     self.assertRaisesRegexp(errors.OpPrereqError,
638       "Error while reading .ovf", ovf.OVFReader, self.wrong_xml_file)
639
640   def testFileInResourcesDoesNotExistError(self):
641     self.assertRaisesRegexp(errors.OpPrereqError, "does not exist",
642       ovf.OVFReader, self.corrupted_ovf)
643
644   def testWrongManifestChecksumError(self):
645     reader = ovf.OVFReader(self.wrong_manifest_ovf)
646     self.assertRaisesRegexp(errors.OpPrereqError,
647       "does not match the value in manifest file", reader.VerifyManifest)
648
649   def testGoodManifestChecksum(self):
650     reader = ovf.OVFReader(self.ganeti_ovf)
651     self.assertEqual(reader.VerifyManifest(), None)
652
653   def testGetDisksNamesOVFCorruptedError(self):
654     reader = ovf.OVFReader(self.no_disk_in_ref_ovf)
655     self.assertRaisesRegexp(errors.OpPrereqError,
656       "not found in references", reader.GetDisksNames)
657
658   def testGetDisksNamesVirtualbox(self):
659     reader = ovf.OVFReader(self.virtualbox_ovf)
660     disk_names = reader.GetDisksNames()
661     expected_names = [
662       ("new_disk.vmdk", None) ,
663       ("second_disk.vmdk", None),
664     ]
665     self.assertEqual(sorted(disk_names), sorted(expected_names))
666
667   def testGetDisksNamesEmpty(self):
668     reader = ovf.OVFReader(self.empty_ovf)
669     disk_names = reader.GetDisksNames()
670     self.assertEqual(disk_names, [])
671
672   def testGetDisksNamesCompressed(self):
673     reader = ovf.OVFReader(self.compressed_disk)
674     disk_names = reader.GetDisksNames()
675     self.assertEqual(disk_names, [("compr_disk.vmdk.gz", "gzip")])
676
677   def testGetNetworkDataGaneti(self):
678     reader = ovf.OVFReader(self.ganeti_ovf)
679     networks = reader.GetNetworkData()
680     self.assertEqual(networks, GANETI_NETWORKS)
681
682   def testGetNetworkDataVirtualbox(self):
683     reader = ovf.OVFReader(self.virtualbox_ovf)
684     networks = reader.GetNetworkData()
685     self.assertEqual(networks, VIRTUALBOX_NETWORKS)
686
687   def testGetNetworkDataEmpty(self):
688     reader = ovf.OVFReader(self.empty_ovf)
689     networks = reader.GetNetworkData()
690     self.assertEqual(networks, EMPTY_NETWORKS)
691
692   def testGetHypervisorDataGaneti(self):
693     reader = ovf.OVFReader(self.ganeti_ovf)
694     hypervisor = reader.GetHypervisorData()
695     self.assertEqual(hypervisor, GANETI_HYPERVISOR)
696
697   def testGetHypervisorDataEmptyOvf(self):
698     reader = ovf.OVFReader(self.empty_ovf)
699     hypervisor = reader.GetHypervisorData()
700     self.assertEqual(hypervisor, EMPTY_HYPERVISOR)
701
702   def testGetOSDataGaneti(self):
703     reader = ovf.OVFReader(self.ganeti_ovf)
704     osys = reader.GetOSData()
705     self.assertEqual(osys, GANETI_OS)
706
707   def testGetOSDataEmptyOvf(self):
708     reader = ovf.OVFReader(self.empty_ovf)
709     osys = reader.GetOSData()
710     self.assertEqual(osys, EMPTY_OS)
711
712   def testGetBackendDataGaneti(self):
713     reader = ovf.OVFReader(self.ganeti_ovf)
714     backend = reader.GetBackendData()
715     self.assertEqual(backend, GANETI_BACKEND)
716
717   def testGetBackendDataVirtualbox(self):
718     reader = ovf.OVFReader(self.virtualbox_ovf)
719     backend = reader.GetBackendData()
720     self.assertEqual(backend, VIRTUALBOX_BACKEND)
721
722   def testGetBackendDataEmptyOvf(self):
723     reader = ovf.OVFReader(self.empty_ovf)
724     backend = reader.GetBackendData()
725     self.assertEqual(backend, EMPTY_BACKEND)
726
727   def testGetInstanceNameGaneti(self):
728     reader = ovf.OVFReader(self.ganeti_ovf)
729     name = reader.GetInstanceName()
730     self.assertEqual(name, GANETI_NAME)
731
732   def testGetInstanceNameDataEmptyOvf(self):
733     reader = ovf.OVFReader(self.empty_ovf)
734     name = reader.GetInstanceName()
735     self.assertEqual(name, EMPTY_NAME)
736
737   def testGetDiskTemplateGaneti(self):
738     reader = ovf.OVFReader(self.ganeti_ovf)
739     name = reader.GetDiskTemplate()
740     self.assertEqual(name, GANETI_TEMPLATE)
741
742   def testGetDiskTemplateEmpty(self):
743     reader = ovf.OVFReader(self.empty_ovf)
744     name = reader.GetDiskTemplate()
745     self.assertEqual(name, EMPTY_TEMPLATE)
746
747   def testGetTagsGaneti(self):
748     reader = ovf.OVFReader(self.ganeti_ovf)
749     tags = reader.GetTagsData()
750     self.assertEqual(tags, GANETI_TAGS)
751
752   def testGetTagsEmpty(self):
753     reader = ovf.OVFReader(self.empty_ovf)
754     tags = reader.GetTagsData()
755     self.assertEqual(tags, EMPTY_TAGS)
756
757   def testGetVersionGaneti(self):
758     reader = ovf.OVFReader(self.ganeti_ovf)
759     version = reader.GetVersionData()
760     self.assertEqual(version, GANETI_VERSION)
761
762   def testGetVersionEmpty(self):
763     reader = ovf.OVFReader(self.empty_ovf)
764     version = reader.GetVersionData()
765     self.assertEqual(version, EMPTY_VERSION)
766
767
768 class TestOVFWriter(BetterUnitTest):
769   def setUp(self):
770     self.writer = ovf.OVFWriter(True)
771
772   def tearDown(self):
773     pass
774
775   def testOVFWriterInit(self):
776     result = ET.tostring(self.writer.tree)
777     self.assertTrue(EXPORT_EMPTY in result)
778
779   def testSaveDisksDataEmpty(self):
780     self.writer.SaveDisksData([])
781     result = ET.tostring(self.writer.tree)
782     self.assertTrue(EXPORT_DISKS_EMPTY in result)
783
784   def testSaveDisksData(self):
785     self.writer.SaveDisksData(EXP_DISKS_LIST)
786     result = ET.tostring(self.writer.tree)
787     self.assertTrue(EXPORT_DISKS in result)
788
789   def testSaveNetworkDataEmpty(self):
790     self.writer.SaveNetworksData([])
791     result = ET.tostring(self.writer.tree)
792     self.assertTrue(EXPORT_NETWORKS_EMPTY in result)
793
794   def testSaveNetworksData(self):
795     self.writer.SaveNetworksData(EXP_NETWORKS_LIST)
796     result = ET.tostring(self.writer.tree)
797     self.assertTrue(EXPORT_NETWORKS in result)
798
799   def testSaveGanetiDataIncomplete(self):
800     self.writer.SaveGanetiData(EXP_PARTIAL_GANETI_DICT, EXP_NETWORKS_LIST)
801     result = ET.tostring(self.writer.tree)
802     self.assertTrue(EXPORT_GANETI_INCOMPLETE in result)
803
804   def testSaveGanetiDataComplete(self):
805     self.writer.SaveGanetiData(EXP_GANETI_DICT, EXP_NETWORKS_LIST)
806     result = ET.tostring(self.writer.tree)
807     self.assertTrue(EXPORT_GANETI in result)
808
809   def testSaveVirtualSystem(self):
810     self.writer.SaveDisksData(EXP_DISKS_LIST)
811     self.writer.SaveNetworksData(EXP_NETWORKS_LIST)
812     self.writer.SaveVirtualSystemData(EXP_NAME, EXP_VCPUS, EXP_MEMORY)
813     result = ET.tostring(self.writer.tree)
814     self.assertTrue(EXPORT_SYSTEM in result)
815
816
817 if __name__ == "__main__":
818   testutils.GanetiTestProgram()