2
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3
# Use is subject to license terms.
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21
import virtconv.formats as formats
22
import virtconv.vmcfg as vmcfg
23
import virtconv.diskcfg as diskcfg
24
import virtconv.netdevcfg as netdevcfg
29
def parse_netdev_entry(vm, fullkey, value):
31
Parse a particular key/value for a network. Throws ValueError.
34
ignore, ignore, inst, key = re.split("^(ethernet)([0-9]+).", fullkey)
36
lvalue = value.lower()
38
if key == "present" and lvalue == "false":
41
if not vm.netdevs.get(inst):
42
vm.netdevs[inst] = netdevcfg.netdev(type = netdevcfg.NETDEV_TYPE_UNKNOWN)
44
# "vlance", "vmxnet", "e1000"
45
if key == "virtualDev":
46
vm.netdevs[inst].driver = lvalue
47
if key == "addressType" and lvalue == "generated":
48
vm.netdevs[inst].mac = "auto"
49
# we ignore .generatedAddress for auto mode
51
vm.netdevs[inst].mac = lvalue
53
def parse_disk_entry(vm, fullkey, value):
55
Parse a particular key/value for a disk. FIXME: this should be a
59
# skip bus values, e.g. 'scsi0.present = "TRUE"'
60
if re.match(r"^(scsi|ide)[0-9]+[^:]", fullkey):
63
ignore, bus, bus_nr, inst, key = re.split(r"^(scsi|ide)([0-9]+):([0-9]+)\.",
66
lvalue = value.lower()
68
if key == "present" and lvalue == "false":
71
# Does anyone else think it's scary that we're still doing things
74
inst = int(inst) + int(bus_nr) * 2
77
if not vm.disks.get(devid):
78
vm.disks[devid] = diskcfg.disk(bus = bus,
79
type = diskcfg.DISK_TYPE_DISK)
81
if key == "deviceType":
82
if lvalue == "atapi-cdrom" or lvalue == "cdrom-raw":
83
vm.disks[devid].type = diskcfg.DISK_TYPE_CDROM
84
elif lvalue == "cdrom-image":
85
vm.disks[devid].type = diskcfg.DISK_TYPE_ISO
88
vm.disks[devid].path = value
89
vm.disks[devid].format = diskcfg.DISK_FORMAT_RAW
90
if lvalue.endswith(".vmdk"):
91
vm.disks[devid].format = diskcfg.DISK_FORMAT_VMDK
95
class vmx_parser(formats.parser):
97
Support for VMWare .vmx files. Note that documentation is
98
particularly sparse on this format, with pretty much the best
99
resource being http://sanbarrow.com/vmx.html
109
def identify_file(input_file):
111
Return True if the given file is of this format.
113
infile = open(input_file, "r")
114
line = infile.readline()
117
# some .vmx files don't bother with the header
118
if re.match(r'^config.version\s+=', line):
120
return re.match(r'^#!\s*/usr/bin/vm(ware|player)', line) is not None
123
def import_file(input_file):
125
Import a configuration file. Raises if the file couldn't be
126
opened, or parsing otherwise failed.
131
infile = open(input_file, "r")
132
contents = infile.readlines()
137
# strip out comment and blank lines for easy splitting of values
138
for line in contents:
139
if not line.strip() or line.startswith("#"):
146
# split out all remaining entries of key = value form
147
for (line_nr, line) in enumerate(lines):
149
before_eq, after_eq = line.split("=", 1)
150
key = before_eq.strip()
151
value = after_eq.strip().strip('"')
154
if key.startswith("scsi") or key.startswith("ide"):
155
parse_disk_entry(vm, key, value)
156
if key.startswith("ethernet"):
157
parse_netdev_entry(vm, key, value)
159
raise Exception("Syntax error at line %d: %s" %
160
(line_nr + 1, line.strip()))
162
for devid, disk in vm.disks.iteritems():
163
if disk.type == diskcfg.DISK_TYPE_DISK:
166
# vmx files often have dross left in path for CD entries
167
if (disk.path == "auto detect" or
168
not os.path.exists(disk.path)):
169
vm.disks[devid].path = None
171
if not config.get("displayName"):
172
raise ValueError("No displayName defined in \"%s\"" % input_file)
173
vm.name = config.get("displayName")
175
vm.memory = config.get("memsize")
176
vm.description = config.get("annotation")
177
vm.nr_vcpus = config.get("numvcpus")
183
def export_file(vm, output_file):
185
Export a configuration file.
186
@vm vm configuration instance
189
Raises ValueError if configuration is not suitable, or another
190
exception on failure to write the output file.
193
raise NotImplementedError
195
formats.register_parser(vmx_parser)