Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.ovf_unittest.py @ 14933c17

History | View | Annotate | Download (30.1 kB)

1
#!/usr/bin/python
2
#
3

    
4
# Copyright (C) 2011, 2012 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
  "nic0_network": "auto",
63
}
64
GANETI_HYPERVISOR = {
65
  "hypervisor_name": "xen-pvm",
66
  "root-path": "/dev/sda",
67
  "kernel_args": "ro",
68
}
69
GANETI_OS = {"os_name": "lenny-image"}
70
GANETI_BACKEND = {
71
  "vcpus": "1",
72
  "memory" : "2048",
73
  "auto_balance": "False",
74
}
75
GANETI_NAME = "ganeti-test-xen"
76
GANETI_TEMPLATE = "plain"
77
GANETI_TAGS = None
78
GANETI_VERSION = "0"
79

    
80
VIRTUALBOX_DISKS = {
81
  "disk_count": "2",
82
  "disk0_ivname": "disk/0",
83
  "disk0_dump": "new_disk.raw",
84
  "disk0_size": "0",
85
  "disk1_ivname": "disk/1",
86
  "disk1_dump": "second_disk.raw",
87
  "disk1_size": "0",
88
}
89
VIRTUALBOX_NETWORKS = {
90
  "nic_count": "1",
91
  "nic0_mode": "bridged",
92
  "nic0_ip": "none",
93
  "nic0_link": "auto",
94
  "nic0_mac": "auto",
95
  "nic0_network": "auto",
96
}
97
VIRTUALBOX_HYPERVISOR = {"hypervisor_name": "auto"}
98
VIRTUALBOX_OS = {"os_name": None}
99
VIRTUALBOX_BACKEND = {
100
 "vcpus": "1",
101
  "memory" : "2048",
102
  "auto_balance": "auto",
103
}
104
VIRTUALBOX_NAME = None
105
VIRTUALBOX_TEMPLATE = None
106
VIRTUALBOX_TAGS = None
107
VIRTUALBOX_VERSION = None
108

    
109
EMPTY_DISKS = {}
110
EMPTY_NETWORKS = {}
111
EMPTY_HYPERVISOR = {"hypervisor_name": "auto"}
112
EMPTY_OS = {}
113
EMPTY_BACKEND = {
114
  "vcpus": "auto",
115
  "memory" : "auto",
116
  "auto_balance": "auto",
117
}
118
EMPTY_NAME = None
119
EMPTY_TEMPLATE = None
120
EMPTY_TAGS = None
121
EMPTY_VERSION = None
122

    
123
CMDARGS_DISKS = {
124
  "disk_count": "1",
125
  "disk0_ivname": "disk/0",
126
  "disk0_dump": "disk0.raw",
127
  "disk0_size": "8",
128
}
129
CMDARGS_NETWORKS = {
130
  "nic0_link": "auto",
131
  "nic0_mode": "bridged",
132
  "nic0_ip": "none",
133
  "nic0_mac": "auto",
134
  "nic_count": "1",
135
  "nic0_network": "auto",
136
}
137
CMDARGS_HYPERVISOR = {
138
  "hypervisor_name": "xen-pvm"
139
}
140
CMDARGS_OS = {"os_name": "lenny-image"}
141
CMDARGS_BACKEND = {
142
  "auto_balance": False,
143
  "vcpus": "1",
144
  "memory": "256",
145
}
146
CMDARGS_NAME = "test-instance"
147
CMDARGS_TEMPLATE = "plain"
148
CMDARGS_TAGS = "test-tag-1,test-tag-2"
149

    
150
ARGS_EMPTY = {
151
  "output_dir": None,
152
  "nics": [],
153
  "disks": [],
154
  "name": "test-instance",
155
  "ova_package": False,
156
  "ext_usage": False,
157
  "disk_format": "cow",
158
  "compression": False,
159
}
160
ARGS_EXPORT_DIR = dict(ARGS_EMPTY, **{
161
  "output_dir": OUTPUT_DIR,
162
  "name": None,
163
  "hypervisor": None,
164
  "os": None,
165
  "beparams": {},
166
  "no_nics": False,
167
  "disk_template": None,
168
  "tags": None,
169
})
170
ARGS_VBOX = dict(ARGS_EXPORT_DIR, **{
171
  "output_dir": OUTPUT_DIR,
172
  "name": "test-instance",
173
  "os": "lenny-image",
174
  "hypervisor": ("xen-pvm", {}),
175
  "osparams":{},
176
  "disks": [],
177
})
178
ARGS_COMPLETE = dict(ARGS_VBOX, **{
179
  "beparams": {"vcpus":"1", "memory":"256", "auto_balance": False},
180
  "disks": [(0,{"size":"5mb"})],
181
  "nics": [("0",{"mode":"bridged"})],
182
  "disk_template": "plain",
183
  "tags": "test-tag-1,test-tag-2",
184
})
185
ARGS_BROKEN = dict(ARGS_EXPORT_DIR , **{
186
  "no_nics": True,
187
  "disk_template": "diskless",
188
  "name": "test-instance",
189
  "os": "lenny-image",
190
  "osparams": {},
191
})
192

    
193
EXP_ARGS_COMPRESSED = dict(ARGS_EXPORT_DIR, **{
194
  "compression": True,
195
})
196

    
197
EXP_DISKS_LIST = [
198
  {
199
    "format": "vmdk",
200
    "compression": "gzip",
201
    "virt-size": 90000,
202
    "real-size": 203,
203
    "path": "new_disk.cow.gz",
204
  },
205
  {
206
    "format": "cow",
207
    "virt-size": 15,
208
    "real-size": 15,
209
    "path": "new_disk.cow",
210
  },
211
]
212
EXP_NETWORKS_LIST = [
213
  {"mac": "aa:00:00:d8:2c:1e", "ip":"None", "link":"br0",
214
   "mode":"routed", "network": "test"},
215
]
216
EXP_PARTIAL_GANETI_DICT = {
217
  "hypervisor": {"name": "xen-kvm"},
218
  "os": {"name": "lenny-image"},
219
  "auto_balance": "True",
220
  "version": "0",
221
}
222
EXP_GANETI_DICT = {
223
  "tags": None,
224
  "auto_balance": "False",
225
  "hypervisor": {
226
     "root-path": "/dev/sda",
227
     "name": "xen-pvm",
228
     "kernel_args": "ro"
229
   },
230
  "version": "0",
231
  "disk_template": None,
232
  "os": {"name": "lenny-image"}
233
}
234
EXP_NAME ="xen-dev-i1"
235
EXP_VCPUS = 1
236
EXP_MEMORY = 512
237

    
238
EXPORT_EMPTY = ("<Envelope xml:lang=\"en-US\" xmlns=\"http://schemas.dmtf.org/"
239
                "ovf/envelope/1\" xmlns:gnt=\"http://ganeti\" xmlns:ovf=\""
240
                "http://schemas.dmtf.org/ovf/envelope/1\" xmlns:rasd=\""
241
                "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_Resource"
242
                "AllocationSettingData\" xmlns:vssd=\"http://schemas.dmtf.org"
243
                "/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData\""
244
                " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" />")
245
EXPORT_DISKS_EMPTY = ("<References /><DiskSection><Info>Virtual disk"
246
                      " information</Info></DiskSection>")
247
EXPORT_DISKS = ("<References><File ovf:compression=\"gzip\" ovf:href=\"new_disk"
248
                ".cow.gz\" ovf:id=\"file0\" ovf:size=\"203\" /><File ovf:href="
249
                "\"new_disk.cow\" ovf:id=\"file1\" ovf:size=\"15\" />"
250
                "</References><DiskSection><Info>Virtual disk information"
251
                "</Info><Disk ovf:capacity=\"90000\" ovf:diskId=\"disk0\" ovf"
252
                ":fileRef=\"file0\" ovf:format=\"http://www.vmware.com/"
253
                "interfaces/specifications/vmdk.html#monolithicSparse\" /><Disk"
254
                " ovf:capacity=\"15\" ovf:diskId=\"disk1\" ovf:fileRef"
255
                "=\"file1\" ovf:format=\"http://www.gnome.org/~markmc/qcow"
256
                "-image-format.html\" /></DiskSection>")
257
EXPORT_NETWORKS_EMPTY = ("<NetworkSection><Info>List of logical networks</Info>"
258
                         "</NetworkSection>")
259
EXPORT_NETWORKS = ("<NetworkSection><Info>List of logical networks</Info>"
260
                   "<Network ovf:name=\"routed0\" /></NetworkSection>")
261
EXPORT_GANETI_INCOMPLETE = ("<gnt:GanetiSection><gnt:Version>0</gnt:Version>"
262
                            "<gnt:AutoBalance>True</gnt:AutoBalance><gnt:"
263
                            "OperatingSystem><gnt:Name>lenny-image</gnt:Name>"
264
                            "<gnt:Parameters /></gnt:OperatingSystem><gnt:"
265
                            "Hypervisor><gnt:Name>xen-kvm</gnt:Name><gnt:"
266
                            "Parameters /></gnt:Hypervisor><gnt:Network><gnt:"
267
                            "Nic ovf:name=\"routed0\"><gnt:Mode>routed</gnt:"
268
                            "Mode><gnt:MACAddress>aa:00:00:d8:2c:1e</gnt:"
269
                            "MACAddress><gnt:IPAddress>None</gnt:IPAddress>"
270
                            "<gnt:Link>br0</gnt:Link><gnt:Net>test</gnt:Net>"
271
                            "</gnt:Nic></gnt:Network></gnt:GanetiSection>")
272
EXPORT_GANETI = ("<gnt:GanetiSection><gnt:Version>0</gnt:Version><gnt:"
273
                 "AutoBalance>False</gnt:AutoBalance><gnt:OperatingSystem>"
274
                 "<gnt:Name>lenny-image</gnt:Name><gnt:Parameters /></gnt:"
275
                 "OperatingSystem><gnt:Hypervisor><gnt:Name>xen-pvm</gnt:Name>"
276
                 "<gnt:Parameters><gnt:root-path>/dev/sda</gnt:root-path><gnt:"
277
                 "kernel_args>ro</gnt:kernel_args></gnt:Parameters></gnt:"
278
                 "Hypervisor><gnt:Network><gnt:Nic ovf:name=\"routed0\"><gnt:"
279
                 "Mode>routed</gnt:Mode><gnt:MACAddress>aa:00:00:d8:2c:1e</gnt:"
280
                 "MACAddress><gnt:IPAddress>None</gnt:IPAddress><gnt:Link>br0"
281
                 "</gnt:Link><gnt:Net>test</gnt:Net></gnt:Nic></gnt:Network>"
282
                 "</gnt:GanetiSection>")
283
EXPORT_SYSTEM = ("<References><File ovf:compression=\"gzip\" ovf:href=\"new_"
284
                 "disk.cow.gz\" ovf:id=\"file0\" ovf:size=\"203\" /><File ovf:"
285
                 "href=\"new_disk.cow\" ovf:id=\"file1\" ovf:size=\"15\" />"
286
                 "</References><DiskSection><Info>Virtual disk information"
287
                 "</Info><Disk ovf:capacity=\"90000\" ovf:diskId=\"disk0\""
288
                 " ovf:fileRef=\"file0\" ovf:format=\"http://www.vmware.com"
289
                 "/interfaces/specifications/vmdk.html#monolithicSparse\" />"
290
                 "<Disk ovf:capacity=\"15\" ovf:diskId=\"disk1\" ovf:fileRef"
291
                 "=\"file1\" ovf:format=\"http://www.gnome.org/~markmc/qcow"
292
                 "-image-format.html\" /></DiskSection><NetworkSection><Info>"
293
                 "List of logical networks</Info><Network ovf:name=\"routed0\""
294
                 " /></NetworkSection><VirtualSystem ovf:id=\"xen-dev-i1\">"
295
                 "<Info>A virtual machine</Info><Name>xen-dev-i1</Name>"
296
                 "<OperatingSystemSection ovf:id=\"0\"><Info>Installed guest"
297
                 " operating system</Info></OperatingSystemSection><Virtual"
298
                 "HardwareSection><Info>Virtual hardware requirements</Info>"
299
                 "<System><vssd:ElementName>Virtual Hardware Family"
300
                 "</vssd:ElementName><vssd:InstanceID>0</vssd:InstanceID><vssd:"
301
                 "VirtualSystemIdentifier>xen-dev-i1</vssd:VirtualSystem"
302
                 "Identifier><vssd:VirtualSystemType>ganeti-ovf</vssd:Virtual"
303
                 "SystemType></System><Item><rasd:ElementName>1 virtual CPU(s)"
304
                 "</rasd:ElementName><rasd:InstanceID>1</rasd:InstanceID><rasd:"
305
                 "ResourceType>3</rasd:ResourceType><rasd:VirtualQuantity>1"
306
                 "</rasd:VirtualQuantity></Item><Item><rasd:AllocationUnits>"
307
                 "byte * 2^20</rasd:AllocationUnits><rasd:ElementName>512MB of"
308
                 " memory</rasd:ElementName><rasd:InstanceID>2</rasd:"
309
                 "InstanceID><rasd:ResourceType>4</rasd:ResourceType><rasd:"
310
                 "VirtualQuantity>512</rasd:VirtualQuantity></Item><Item>"
311
                 "<rasd:Address>0</rasd:Address><rasd:ElementName>scsi"
312
                 "_controller0</rasd:ElementName><rasd:InstanceID>3"
313
                 "</rasd:InstanceID><rasd:ResourceSubType>lsilogic</rasd"
314
                 ":ResourceSubType><rasd:ResourceType>6</rasd:ResourceType>"
315
                 "</Item><Item><rasd:ElementName>disk0</rasd:ElementName><rasd"
316
                 ":HostResource>ovf:/disk/disk0</rasd:HostResource><rasd"
317
                 ":InstanceID>4</rasd:InstanceID><rasd:Parent>3</rasd:Parent>"
318
                 "<rasd:ResourceType>17</rasd:ResourceType></Item><Item><rasd:"
319
                 "ElementName>disk1</rasd:ElementName><rasd:HostResource>ovf:/"
320
                 "disk/disk1</rasd:HostResource><rasd:InstanceID>5</rasd"
321
                 ":InstanceID><rasd:Parent>3</rasd:Parent><rasd:ResourceType>17"
322
                 "</rasd:ResourceType></Item><Item><rasd:Address>aa:00"
323
                 ":00:d8:2c:1e</rasd:Address><rasd:Connection>routed0</rasd"
324
                 ":Connection><rasd:ElementName>routed0</rasd:ElementName><rasd"
325
                 ":InstanceID>6</rasd:InstanceID><rasd:ResourceType>10</rasd"
326
                 ":ResourceType></Item></VirtualHardwareSection>"
327
                 "</VirtualSystem>")
328

    
329

    
330
def _GetArgs(args, with_name=False):
331
  options = optparse.Values()
332
  needed = args
333
  if with_name:
334
    needed["name"] = "test-instance"
335
  options._update_loose(needed)
336
  return options
337

    
338

    
339
OPTS_EMPTY = _GetArgs(ARGS_EMPTY)
340
OPTS_EXPORT_NO_NAME = _GetArgs(ARGS_EXPORT_DIR)
341
OPTS_EXPORT = _GetArgs(ARGS_EXPORT_DIR, with_name=True)
342

    
343
EXP_OPTS = OPTS_EXPORT_NO_NAME
344
EXP_OPTS_COMPRESSED = _GetArgs(EXP_ARGS_COMPRESSED)
345

    
346
OPTS_VBOX = _GetArgs(ARGS_VBOX)
347
OPTS_COMPLETE = _GetArgs(ARGS_COMPLETE)
348
OPTS_NONIC_NODISK = _GetArgs(ARGS_BROKEN)
349

    
350

    
351
def _GetFullFilename(file_name):
352
  file_path = "%s/test/data/ovfdata/%s" % (testutils.GetSourceDir(),
353
    file_name)
354
  file_path = os.path.abspath(file_path)
355
  return file_path
356

    
357

    
358
class BetterUnitTest(unittest.TestCase):
359
  def assertRaisesRegexp(self, exception, regexp_val, function, *args):
360
    try:
361
      function(*args)
362
      self.fail("Expected raising %s" % exception)
363
    except exception, err:
364
      regexp = re.compile(regexp_val)
365
      if re.search(regexp, str(err)) == None:
366
        self.fail("Expected matching '%s', got '%s'" %
367
          (regexp_val, str(err)))
368

    
369

    
370
class TestOVFImporter(BetterUnitTest):
371
  def setUp(self):
372
    self.non_existing_file = _GetFullFilename("not_the_file.ovf")
373
    self.ganeti_ovf = _GetFullFilename("ganeti.ovf")
374
    self.virtualbox_ovf = _GetFullFilename("virtualbox.ovf")
375
    self.ova_package = _GetFullFilename("ova.ova")
376
    self.empty_ovf = _GetFullFilename("empty.ovf")
377
    self.wrong_extension = _GetFullFilename("wrong_extension.ovd")
378
    self.wrong_ova_archive = _GetFullFilename("wrong_ova.ova")
379
    self.no_ovf_in_ova = _GetFullFilename("no_ovf.ova")
380
    self.importer = None
381

    
382
  def tearDown(self):
383
    if self.importer:
384
      self.importer.Cleanup()
385
    del_dir = os.path.abspath(OUTPUT_DIR)
386
    try:
387
      shutil.rmtree(del_dir)
388
    except OSError:
389
      pass
390

    
391
  def testFileDoesNotExistError(self):
392
    self.assertRaisesRegexp(errors.OpPrereqError, "does not exist",
393
      ovf.OVFImporter, self.non_existing_file, None)
394

    
395
  def testWrongInputFileExtensionError(self):
396
    self.assertRaisesRegexp(errors.OpPrereqError,
397
      "Unknown file extension", ovf.OVFImporter,
398
      self.wrong_extension, None)
399

    
400
  def testOVAUnpackingDirectories(self):
401
    self.importer = ovf.OVFImporter(self.ova_package, OPTS_EMPTY)
402
    self.assertTrue(self.importer.input_dir != None)
403
    self.assertEquals(self.importer.output_dir , pathutils.EXPORT_DIR)
404
    self.assertTrue(self.importer.temp_dir != None)
405

    
406
  def testOVFUnpackingDirectories(self):
407
    self.importer = ovf.OVFImporter(self.virtualbox_ovf,
408
      OPTS_EMPTY)
409
    self.assertEquals(self.importer.input_dir , _GetFullFilename(""))
410
    self.assertEquals(self.importer.output_dir , pathutils.EXPORT_DIR)
411
    self.assertEquals(self.importer.temp_dir , None)
412

    
413
  def testOVFSetOutputDirDirectories(self):
414
    self.importer = ovf.OVFImporter(self.ganeti_ovf, OPTS_EXPORT)
415
    self.assertEquals(self.importer.input_dir , _GetFullFilename(""))
416
    self.assertTrue(OUTPUT_DIR in self.importer.output_dir)
417
    self.assertEquals(self.importer.temp_dir , None)
418

    
419
  def testWrongOVAArchiveError(self):
420
    self.assertRaisesRegexp(errors.OpPrereqError, "not a proper tar",
421
      ovf.OVFImporter, self.wrong_ova_archive, None)
422

    
423
  def testNoOVFFileInOVAPackageError(self):
424
    self.assertRaisesRegexp(errors.OpPrereqError, "No .ovf file",
425
      ovf.OVFImporter, self.no_ovf_in_ova, None)
426

    
427
  def testParseGanetiOvf(self):
428
    self.importer = ovf.OVFImporter(self.ganeti_ovf, OPTS_EXPORT_NO_NAME)
429
    self.importer.Parse()
430
    self.assertTrue("%s/ganeti-test-xen" % OUTPUT_DIR in
431
      self.importer.output_dir)
432
    self.assertEqual(self.importer.results_disk, GANETI_DISKS)
433
    self.assertEqual(self.importer.results_network, GANETI_NETWORKS)
434
    self.assertEqual(self.importer.results_hypervisor, GANETI_HYPERVISOR)
435
    self.assertEqual(self.importer.results_os, GANETI_OS)
436
    self.assertEqual(self.importer.results_backend, GANETI_BACKEND)
437
    self.assertEqual(self.importer.results_name, GANETI_NAME)
438
    self.assertEqual(self.importer.results_template, GANETI_TEMPLATE)
439
    self.assertEqual(self.importer.results_tags, GANETI_TAGS)
440
    self.assertEqual(self.importer.results_version, GANETI_VERSION)
441

    
442
  def testParseVirtualboxOvf(self):
443
    self.importer = ovf.OVFImporter(self.virtualbox_ovf, OPTS_VBOX)
444
    self.importer.Parse()
445
    self.assertTrue("%s/test-instance" % OUTPUT_DIR in self.importer.output_dir)
446
    self.assertEquals(self.importer.results_disk, VIRTUALBOX_DISKS)
447
    self.assertEquals(self.importer.results_network, VIRTUALBOX_NETWORKS)
448
    self.assertEquals(self.importer.results_hypervisor, CMDARGS_HYPERVISOR)
449
    self.assertEquals(self.importer.results_os, CMDARGS_OS)
450
    self.assertEquals(self.importer.results_backend, VIRTUALBOX_BACKEND)
451
    self.assertEquals(self.importer.results_name, CMDARGS_NAME)
452
    self.assertEquals(self.importer.results_template, VIRTUALBOX_TEMPLATE)
453
    self.assertEqual(self.importer.results_tags, VIRTUALBOX_TAGS)
454
    self.assertEqual(self.importer.results_version, constants.EXPORT_VERSION)
455

    
456
  def testParseEmptyOvf(self):
457
    self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_COMPLETE)
458
    self.importer.Parse()
459
    self.assertTrue("%s/test-instance" % OUTPUT_DIR in self.importer.output_dir)
460
    self.assertEquals(self.importer.results_disk, CMDARGS_DISKS)
461
    self.assertEquals(self.importer.results_network, CMDARGS_NETWORKS)
462
    self.assertEquals(self.importer.results_hypervisor, CMDARGS_HYPERVISOR)
463
    self.assertEquals(self.importer.results_os, CMDARGS_OS)
464
    self.assertEquals(self.importer.results_backend, CMDARGS_BACKEND)
465
    self.assertEquals(self.importer.results_name, CMDARGS_NAME)
466
    self.assertEquals(self.importer.results_template, CMDARGS_TEMPLATE)
467
    self.assertEqual(self.importer.results_tags, CMDARGS_TAGS)
468
    self.assertEqual(self.importer.results_version, constants.EXPORT_VERSION)
469

    
470
  def testParseNameOptions(self):
471
    self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_COMPLETE)
472
    results = self.importer._ParseNameOptions()
473
    self.assertEquals(results, CMDARGS_NAME)
474

    
475
  def testParseHypervisorOptions(self):
476
    self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_COMPLETE)
477
    results = self.importer._ParseHypervisorOptions()
478
    self.assertEquals(results, CMDARGS_HYPERVISOR)
479

    
480
  def testParseOSOptions(self):
481
    self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_COMPLETE)
482
    results = self.importer._ParseOSOptions()
483
    self.assertEquals(results, CMDARGS_OS)
484

    
485
  def testParseBackendOptions(self):
486
    self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_COMPLETE)
487
    results = self.importer._ParseBackendOptions()
488
    self.assertEquals(results, CMDARGS_BACKEND)
489

    
490
  def testParseTags(self):
491
    self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_COMPLETE)
492
    results = self.importer._ParseTags()
493
    self.assertEquals(results, CMDARGS_TAGS)
494

    
495
  def testParseNicOptions(self):
496
    self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_COMPLETE)
497
    results = self.importer._ParseNicOptions()
498
    self.assertEquals(results, CMDARGS_NETWORKS)
499

    
500
  def testParseDiskOptionsFromGanetiOVF(self):
501
    self.importer = ovf.OVFImporter(self.ganeti_ovf, OPTS_EXPORT)
502
    os.mkdir(OUTPUT_DIR)
503
    results = self.importer._GetDiskInfo()
504
    self.assertEquals(results, GANETI_DISKS)
505

    
506
  def testParseTemplateOptions(self):
507
    self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_COMPLETE)
508
    results = self.importer._ParseTemplateOptions()
509
    self.assertEquals(results, GANETI_TEMPLATE)
510

    
511
  def testParseDiskOptionsFromCmdLine(self):
512
    self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_COMPLETE)
513
    os.mkdir(OUTPUT_DIR)
514
    results = self.importer._ParseDiskOptions()
515
    self.assertEquals(results, CMDARGS_DISKS)
516

    
517
  def testGetDiskFormat(self):
518
    self.importer = ovf.OVFImporter(self.ganeti_ovf, OPTS_EXPORT)
519
    disks_list = self.importer.ovf_reader.GetDisksNames()
520
    results = [self.importer._GetDiskQemuInfo("%s/%s" %
521
      (self.importer.input_dir, path), "file format: (\S+)")
522
      for (path, _) in disks_list]
523
    self.assertEqual(results, ["vmdk"])
524

    
525
  def testNoInstanceNameOVF(self):
526
    self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_EXPORT_NO_NAME)
527
    self.assertRaisesRegexp(errors.OpPrereqError, "Name of instance",
528
      self.importer.Parse)
529

    
530
  def testErrorNoOSNameOVF(self):
531
    self.importer = ovf.OVFImporter(self.virtualbox_ovf, OPTS_EXPORT)
532
    self.assertRaisesRegexp(errors.OpPrereqError, "OS name",
533
      self.importer.Parse)
534

    
535
  def testErrorNoDiskAndNoNetwork(self):
536
    self.importer = ovf.OVFImporter(self.empty_ovf, OPTS_NONIC_NODISK)
537
    self.assertRaisesRegexp(errors.OpPrereqError,
538
      "Either disk specification or network"
539
      " description", self.importer.Parse)
540

    
541

    
542
class TestOVFExporter(BetterUnitTest):
543
  def setUp(self):
544
    self.exporter = None
545
    self.wrong_config_file = _GetFullFilename("wrong_config.ini")
546
    self.unsafe_path_to_disk = _GetFullFilename("unsafe_path.ini")
547
    self.disk_image_not_exist = _GetFullFilename("no_disk.ini")
548
    self.empty_config = _GetFullFilename("empty.ini")
549
    self.standard_export = _GetFullFilename("config.ini")
550
    self.wrong_network_mode = self.disk_image_not_exist
551
    self.no_memory = self.disk_image_not_exist
552
    self.no_vcpus = self.disk_image_not_exist
553
    self.no_os = _GetFullFilename("no_os.ini")
554
    self.no_hypervisor = self.disk_image_not_exist
555

    
556
  def tearDown(self):
557
    if self.exporter:
558
      self.exporter.Cleanup()
559
    del_dir = os.path.abspath(OUTPUT_DIR)
560
    try:
561
      shutil.rmtree(del_dir)
562
    except OSError:
563
      pass
564

    
565
  def testErrorWrongConfigFile(self):
566
    self.assertRaisesRegexp(errors.OpPrereqError,
567
      "Error when trying to read", ovf.OVFExporter,
568
      self.wrong_config_file, EXP_OPTS)
569

    
570
  def testErrorPathToTheDiskIncorrect(self):
571
    self.exporter = ovf.OVFExporter(self.unsafe_path_to_disk, EXP_OPTS)
572
    self.assertRaisesRegexp(errors.OpPrereqError, "contains a directory name",
573
      self.exporter._ParseDisks)
574

    
575
  def testErrorDiskImageNotExist(self):
576
    self.exporter = ovf.OVFExporter(self.disk_image_not_exist, EXP_OPTS)
577
    self.assertRaisesRegexp(errors.OpPrereqError, "Disk image does not exist",
578
      self.exporter._ParseDisks)
579

    
580
  def testParseNetworks(self):
581
    self.exporter = ovf.OVFExporter(self.standard_export, EXP_OPTS)
582
    results = self.exporter._ParseNetworks()
583
    self.assertEqual(results, EXP_NETWORKS_LIST)
584

    
585
  def testErrorWrongNetworkMode(self):
586
    self.exporter = ovf.OVFExporter(self.wrong_network_mode, EXP_OPTS)
587
    self.assertRaisesRegexp(errors.OpPrereqError,
588
      "Network mode nic not recognized", self.exporter._ParseNetworks)
589

    
590
  def testParseVCPusMem(self):
591
    self.exporter = ovf.OVFExporter(self.standard_export, EXP_OPTS)
592
    vcpus = self.exporter._ParseVCPUs()
593
    memory = self.exporter._ParseMemory()
594
    self.assertEqual(vcpus, EXP_VCPUS)
595
    self.assertEqual(memory, EXP_MEMORY)
596

    
597
  def testErrorNoVCPUs(self):
598
    self.exporter = ovf.OVFExporter(self.no_vcpus, EXP_OPTS)
599
    self.assertRaisesRegexp(errors.OpPrereqError, "No CPU information found",
600
      self.exporter._ParseVCPUs)
601

    
602
  def testErrorNoMemory(self):
603
    self.exporter = ovf.OVFExporter(self.no_memory, EXP_OPTS)
604
    self.assertRaisesRegexp(errors.OpPrereqError, "No memory information found",
605
      self.exporter._ParseMemory)
606

    
607
  def testParseGaneti(self):
608
    self.exporter = ovf.OVFExporter(self.standard_export, EXP_OPTS)
609
    results = self.exporter._ParseGaneti()
610
    self.assertEqual(results, EXP_GANETI_DICT)
611

    
612
  def testErrorNoHypervisor(self):
613
    self.exporter = ovf.OVFExporter(self.no_hypervisor, EXP_OPTS)
614
    self.assertRaisesRegexp(errors.OpPrereqError,
615
      "No hypervisor information found", self.exporter._ParseGaneti)
616

    
617
  def testErrorNoOS(self):
618
    self.exporter = ovf.OVFExporter(self.no_os, EXP_OPTS)
619
    self.assertRaisesRegexp(errors.OpPrereqError,
620
      "No operating system information found", self.exporter._ParseGaneti)
621

    
622
  def testErrorParseNoInstanceName(self):
623
    self.exporter = ovf.OVFExporter(self.empty_config, EXP_OPTS)
624
    self.assertRaisesRegexp(errors.OpPrereqError, "No instance name found",
625
      self.exporter.Parse)
626

    
627

    
628
class TestOVFReader(BetterUnitTest):
629
  def setUp(self):
630
    self.wrong_xml_file = _GetFullFilename("wrong_xml.ovf")
631
    self.ganeti_ovf = _GetFullFilename("ganeti.ovf")
632
    self.virtualbox_ovf = _GetFullFilename("virtualbox.ovf")
633
    self.corrupted_ovf = _GetFullFilename("corrupted_resources.ovf")
634
    self.wrong_manifest_ovf = _GetFullFilename("wrong_manifest.ovf")
635
    self.no_disk_in_ref_ovf = _GetFullFilename("no_disk_in_ref.ovf")
636
    self.empty_ovf = _GetFullFilename("empty.ovf")
637
    self.compressed_disk = _GetFullFilename("gzip_disk.ovf")
638

    
639
  def tearDown(self):
640
    pass
641

    
642
  def testXMLParsingError(self):
643
    self.assertRaisesRegexp(errors.OpPrereqError,
644
      "Error while reading .ovf", ovf.OVFReader, self.wrong_xml_file)
645

    
646
  def testFileInResourcesDoesNotExistError(self):
647
    self.assertRaisesRegexp(errors.OpPrereqError, "does not exist",
648
      ovf.OVFReader, self.corrupted_ovf)
649

    
650
  def testWrongManifestChecksumError(self):
651
    reader = ovf.OVFReader(self.wrong_manifest_ovf)
652
    self.assertRaisesRegexp(errors.OpPrereqError,
653
      "does not match the value in manifest file", reader.VerifyManifest)
654

    
655
  def testGoodManifestChecksum(self):
656
    reader = ovf.OVFReader(self.ganeti_ovf)
657
    self.assertEqual(reader.VerifyManifest(), None)
658

    
659
  def testGetDisksNamesOVFCorruptedError(self):
660
    reader = ovf.OVFReader(self.no_disk_in_ref_ovf)
661
    self.assertRaisesRegexp(errors.OpPrereqError,
662
      "not found in references", reader.GetDisksNames)
663

    
664
  def testGetDisksNamesVirtualbox(self):
665
    reader = ovf.OVFReader(self.virtualbox_ovf)
666
    disk_names = reader.GetDisksNames()
667
    expected_names = [
668
      ("new_disk.vmdk", None) ,
669
      ("second_disk.vmdk", None),
670
    ]
671
    self.assertEqual(sorted(disk_names), sorted(expected_names))
672

    
673
  def testGetDisksNamesEmpty(self):
674
    reader = ovf.OVFReader(self.empty_ovf)
675
    disk_names = reader.GetDisksNames()
676
    self.assertEqual(disk_names, [])
677

    
678
  def testGetDisksNamesCompressed(self):
679
    reader = ovf.OVFReader(self.compressed_disk)
680
    disk_names = reader.GetDisksNames()
681
    self.assertEqual(disk_names, [("compr_disk.vmdk.gz", "gzip")])
682

    
683
  def testGetNetworkDataGaneti(self):
684
    reader = ovf.OVFReader(self.ganeti_ovf)
685
    networks = reader.GetNetworkData()
686
    self.assertEqual(networks, GANETI_NETWORKS)
687

    
688
  def testGetNetworkDataVirtualbox(self):
689
    reader = ovf.OVFReader(self.virtualbox_ovf)
690
    networks = reader.GetNetworkData()
691
    self.assertEqual(networks, VIRTUALBOX_NETWORKS)
692

    
693
  def testGetNetworkDataEmpty(self):
694
    reader = ovf.OVFReader(self.empty_ovf)
695
    networks = reader.GetNetworkData()
696
    self.assertEqual(networks, EMPTY_NETWORKS)
697

    
698
  def testGetHypervisorDataGaneti(self):
699
    reader = ovf.OVFReader(self.ganeti_ovf)
700
    hypervisor = reader.GetHypervisorData()
701
    self.assertEqual(hypervisor, GANETI_HYPERVISOR)
702

    
703
  def testGetHypervisorDataEmptyOvf(self):
704
    reader = ovf.OVFReader(self.empty_ovf)
705
    hypervisor = reader.GetHypervisorData()
706
    self.assertEqual(hypervisor, EMPTY_HYPERVISOR)
707

    
708
  def testGetOSDataGaneti(self):
709
    reader = ovf.OVFReader(self.ganeti_ovf)
710
    osys = reader.GetOSData()
711
    self.assertEqual(osys, GANETI_OS)
712

    
713
  def testGetOSDataEmptyOvf(self):
714
    reader = ovf.OVFReader(self.empty_ovf)
715
    osys = reader.GetOSData()
716
    self.assertEqual(osys, EMPTY_OS)
717

    
718
  def testGetBackendDataGaneti(self):
719
    reader = ovf.OVFReader(self.ganeti_ovf)
720
    backend = reader.GetBackendData()
721
    self.assertEqual(backend, GANETI_BACKEND)
722

    
723
  def testGetBackendDataVirtualbox(self):
724
    reader = ovf.OVFReader(self.virtualbox_ovf)
725
    backend = reader.GetBackendData()
726
    self.assertEqual(backend, VIRTUALBOX_BACKEND)
727

    
728
  def testGetBackendDataEmptyOvf(self):
729
    reader = ovf.OVFReader(self.empty_ovf)
730
    backend = reader.GetBackendData()
731
    self.assertEqual(backend, EMPTY_BACKEND)
732

    
733
  def testGetInstanceNameGaneti(self):
734
    reader = ovf.OVFReader(self.ganeti_ovf)
735
    name = reader.GetInstanceName()
736
    self.assertEqual(name, GANETI_NAME)
737

    
738
  def testGetInstanceNameDataEmptyOvf(self):
739
    reader = ovf.OVFReader(self.empty_ovf)
740
    name = reader.GetInstanceName()
741
    self.assertEqual(name, EMPTY_NAME)
742

    
743
  def testGetDiskTemplateGaneti(self):
744
    reader = ovf.OVFReader(self.ganeti_ovf)
745
    name = reader.GetDiskTemplate()
746
    self.assertEqual(name, GANETI_TEMPLATE)
747

    
748
  def testGetDiskTemplateEmpty(self):
749
    reader = ovf.OVFReader(self.empty_ovf)
750
    name = reader.GetDiskTemplate()
751
    self.assertEqual(name, EMPTY_TEMPLATE)
752

    
753
  def testGetTagsGaneti(self):
754
    reader = ovf.OVFReader(self.ganeti_ovf)
755
    tags = reader.GetTagsData()
756
    self.assertEqual(tags, GANETI_TAGS)
757

    
758
  def testGetTagsEmpty(self):
759
    reader = ovf.OVFReader(self.empty_ovf)
760
    tags = reader.GetTagsData()
761
    self.assertEqual(tags, EMPTY_TAGS)
762

    
763
  def testGetVersionGaneti(self):
764
    reader = ovf.OVFReader(self.ganeti_ovf)
765
    version = reader.GetVersionData()
766
    self.assertEqual(version, GANETI_VERSION)
767

    
768
  def testGetVersionEmpty(self):
769
    reader = ovf.OVFReader(self.empty_ovf)
770
    version = reader.GetVersionData()
771
    self.assertEqual(version, EMPTY_VERSION)
772

    
773

    
774
class TestOVFWriter(BetterUnitTest):
775
  def setUp(self):
776
    self.writer = ovf.OVFWriter(True)
777

    
778
  def tearDown(self):
779
    pass
780

    
781
  def testOVFWriterInit(self):
782
    result = ET.tostring(self.writer.tree)
783
    self.assertTrue(EXPORT_EMPTY in result)
784

    
785
  def testSaveDisksDataEmpty(self):
786
    self.writer.SaveDisksData([])
787
    result = ET.tostring(self.writer.tree)
788
    self.assertTrue(EXPORT_DISKS_EMPTY in result)
789

    
790
  def testSaveDisksData(self):
791
    self.writer.SaveDisksData(EXP_DISKS_LIST)
792
    result = ET.tostring(self.writer.tree)
793
    self.assertTrue(EXPORT_DISKS in result)
794

    
795
  def testSaveNetworkDataEmpty(self):
796
    self.writer.SaveNetworksData([])
797
    result = ET.tostring(self.writer.tree)
798
    self.assertTrue(EXPORT_NETWORKS_EMPTY in result)
799

    
800
  def testSaveNetworksData(self):
801
    self.writer.SaveNetworksData(EXP_NETWORKS_LIST)
802
    result = ET.tostring(self.writer.tree)
803
    self.assertTrue(EXPORT_NETWORKS in result)
804

    
805
  def testSaveGanetiDataIncomplete(self):
806
    self.writer.SaveGanetiData(EXP_PARTIAL_GANETI_DICT, EXP_NETWORKS_LIST)
807
    result = ET.tostring(self.writer.tree)
808
    self.assertTrue(EXPORT_GANETI_INCOMPLETE in result)
809

    
810
  def testSaveGanetiDataComplete(self):
811
    self.writer.SaveGanetiData(EXP_GANETI_DICT, EXP_NETWORKS_LIST)
812
    result = ET.tostring(self.writer.tree)
813
    self.assertTrue(EXPORT_GANETI in result)
814

    
815
  def testSaveVirtualSystem(self):
816
    self.writer.SaveDisksData(EXP_DISKS_LIST)
817
    self.writer.SaveNetworksData(EXP_NETWORKS_LIST)
818
    self.writer.SaveVirtualSystemData(EXP_NAME, EXP_VCPUS, EXP_MEMORY)
819
    result = ET.tostring(self.writer.tree)
820
    self.assertTrue(EXPORT_SYSTEM in result)
821

    
822

    
823
if __name__ == "__main__":
824
  testutils.GanetiTestProgram()