Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.ovf_unittest.py @ a5efec93

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
  "osparams_private":{},
177
  "disks": [],
178
})
179
ARGS_COMPLETE = dict(ARGS_VBOX, **{
180
  "beparams": {"vcpus":"1", "memory":"256", "auto_balance": False},
181
  "disks": [(0,{"size":"5mb"})],
182
  "nics": [("0",{"mode":"bridged"})],
183
  "disk_template": "plain",
184
  "tags": "test-tag-1,test-tag-2",
185
})
186
ARGS_BROKEN = dict(ARGS_EXPORT_DIR , **{
187
  "no_nics": True,
188
  "disk_template": "diskless",
189
  "name": "test-instance",
190
  "os": "lenny-image",
191
  "osparams": {},
192
  "osparams_private":{},
193
})
194

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

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

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

    
331

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

    
340

    
341
OPTS_EMPTY = _GetArgs(ARGS_EMPTY)
342
OPTS_EXPORT_NO_NAME = _GetArgs(ARGS_EXPORT_DIR)
343
OPTS_EXPORT = _GetArgs(ARGS_EXPORT_DIR, with_name=True)
344

    
345
EXP_OPTS = OPTS_EXPORT_NO_NAME
346
EXP_OPTS_COMPRESSED = _GetArgs(EXP_ARGS_COMPRESSED)
347

    
348
OPTS_VBOX = _GetArgs(ARGS_VBOX)
349
OPTS_COMPLETE = _GetArgs(ARGS_COMPLETE)
350
OPTS_NONIC_NODISK = _GetArgs(ARGS_BROKEN)
351

    
352

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

    
359

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

    
371

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
543

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
629

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

    
641
  def tearDown(self):
642
    pass
643

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
775

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

    
780
  def tearDown(self):
781
    pass
782

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

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

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

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

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

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

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

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

    
824

    
825
if __name__ == "__main__":
826
  testutils.GanetiTestProgram()