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