Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.ovf_unittest.py @ 415feb2e

History | View | Annotate | Download (29.9 kB)

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()