1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import logging
20 import os
21 import shutil
22 import stat
23 import VMBuilder
24 from VMBuilder import register_distro, Distro
25 from VMBuilder.util import run_cmd
26 from VMBuilder.exception import VMBuilderUserError, VMBuilderException
27
29 name = 'Ubuntu'
30 arg = 'ubuntu'
31 suites = ['dapper', 'gutsy', 'hardy', 'intrepid', 'jaunty',
32 'karmic', 'lucid', 'maverick', 'natty', 'oneiric',
33 'precise', 'quantal', 'raring', 'saucy', 'trusty',
34 'utopic', 'vivid', 'wily', 'xenial',
35 ]
36
37
38 valid_archs = { 'amd64' : ['amd64', 'i386', 'lpia' ],
39 'i386' : [ 'i386', 'lpia' ],
40 'lpia' : [ 'i386', 'lpia' ] }
41
42 xen_kernel = ''
43
45 group = self.setting_group('Package options')
46 group.add_setting('addpkg', type='list', metavar='PKG', help='Install PKG into the guest (can be specified multiple times).')
47 group.add_setting('removepkg', type='list', metavar='PKG', help='Remove PKG from the guest (can be specified multiple times)')
48 group.add_setting('seedfile', metavar="SEEDFILE", help='Seed the debconf database with the contents of this seed file before installing packages')
49
50 group = self.setting_group('General OS options')
51 self.host_arch = run_cmd('dpkg', '--print-architecture').rstrip()
52 group.add_setting('arch', extra_args=['-a'], default=self.host_arch, help='Specify the target architecture. Valid options: amd64 i386 lpia (defaults to host arch)')
53 group.add_setting('hostname', default='ubuntu', help='Set NAME as the hostname of the guest. Default: ubuntu. Also uses this name as the VM name.')
54
55 group = self.setting_group('Installation options')
56 group.add_setting('suite', default='lucid', help='Suite to install. Valid options: %s [default: %%default]' % ' '.join(self.suites))
57 group.add_setting('flavour', extra_args=['--kernel-flavour'], help='Kernel flavour to use. Default and valid options depend on architecture and suite')
58 group.add_setting('variant', metavar='VARIANT', help='Passed to debootstrap --variant flag; use minbase, buildd, or fakechroot.')
59 group.add_setting('debootstrap-tarball', metavar='FILE', help='Passed to debootstrap --unpack-tarball flag.')
60 group.add_setting('iso', metavar='PATH', help='Use an iso image as the source for installation of file. Full path to the iso must be provided. If --mirror is also provided, it will be used in the final sources.list of the vm. This requires suite and kernel parameter to match what is available on the iso, obviously.')
61 group.add_setting('mirror', metavar='URL', help='Use Ubuntu mirror at URL instead of the default, which is http://archive.ubuntu.com/ubuntu for official arches and http://ports.ubuntu.com/ubuntu-ports otherwise')
62 group.add_setting('proxy', metavar='URL', help='Use proxy at URL for cached packages')
63 group.add_setting('install-mirror', metavar='URL', help='Use Ubuntu mirror at URL for the installation only. Apt\'s sources.list will still use default or URL set by --mirror')
64 group.add_setting('security-mirror', metavar='URL', help='Use Ubuntu security mirror at URL instead of the default, which is http://security.ubuntu.com/ubuntu for official arches and http://ports.ubuntu.com/ubuntu-ports otherwise.')
65 group.add_setting('install-security-mirror', metavar='URL', help='Use the security mirror at URL for installation only. Apt\'s sources.list will still use default or URL set by --security-mirror')
66 group.add_setting('components', type='list', metavar='COMPS', help='A comma seperated list of distro components to include (e.g. main,universe).')
67 group.add_setting('ppa', metavar='PPA', type='list', help='Add ppa belonging to PPA to the vm\'s sources.list.')
68 group.add_setting('lang', metavar='LANG', default=get_locale(), help='Set the locale to LANG [default: %default]')
69 group.add_setting('timezone', metavar='TZ', default='UTC', help='Set the timezone to TZ in the vm. [default: %default]')
70
71 group = self.setting_group('Settings for the initial user')
72 group.add_setting('user', default='ubuntu', help='Username of initial user [default: %default]')
73 group.add_setting('name', default='Ubuntu', help='Full name of initial user [default: %default]')
74 group.add_setting('pass', default='ubuntu', help='Password of initial user [default: %default]')
75 group.add_setting('rootpass', help='Initial root password (WARNING: this has strong security implications).')
76 group.add_setting('uid', type='int', help='Initial UID value.')
77 group.add_setting('gid', help='Initial GID value.')
78 group.add_setting('lock-user', type='bool', default=False, help='Lock the initial user [default: %default]')
79
80 group = self.setting_group('Other options')
81 group.add_setting('ssh-key', metavar='PATH', help='Add PATH to root\'s ~/.ssh/authorized_keys (WARNING: this has strong security implications).')
82 group.add_setting('ssh-user-key', help='Add PATH to the user\'s ~/.ssh/authorized_keys.')
83 group.add_setting('manifest', metavar='PATH', help='If passed, a manifest will be written to PATH')
84
96
98 """While not all of these are strictly checks, their failure would inevitably
99 lead to failure, and since we can check them before we start setting up disk
100 and whatnot, we might as well go ahead an do this now."""
101
102 suite = self.get_setting('suite')
103 if not suite in self.suites:
104 raise VMBuilderUserError('Invalid suite: "%s". Valid suites are: %s' % (suite, ' '.join(self.suites)))
105
106 modname = 'VMBuilder.plugins.ubuntu.%s' % (suite, )
107 mod = __import__(modname, fromlist=[suite])
108 self.suite = getattr(mod, suite.capitalize())(self)
109
110 arch = self.get_setting('arch')
111 if arch not in self.valid_archs[self.host_arch] or \
112 not self.suite.check_arch_validity(arch):
113 raise VMBuilderUserError('%s is not a valid architecture. Valid architectures are: %s' % (arch,
114 ' '.join(self.valid_archs[self.host_arch])))
115
116 components = self.get_setting('components')
117 if not components:
118 self.set_config_value_list = ['main', 'restricted', 'universe']
119 else:
120 if type(components) is str:
121 self.vm.components = self.vm.components.split(',')
122
123 self.context.virtio_net = self.use_virtio_net()
124
125
126 seedfile = self.context.get_setting('seedfile')
127 if seedfile and not os.path.exists(seedfile):
128 raise VMBuilderUserError("Seedfile '%s' does not exist" % seedfile)
129
130 lang = self.get_setting('lang')
131
132
133
134
135
136
137
141
162
166
169
173
176
177 - def post_mount(self, fs):
179
182
190
193
195 root_dev = VMBuilder.disk.bootpart(disks).get_grub_id()
196
197 tmpdir = '/tmp/vmbuilder-grub'
198 os.makedirs('%s%s' % (chroot_dir, tmpdir))
199 self.context.add_clean_cb(self.install_bootloader_cleanup)
200 devmapfile = os.path.join(tmpdir, 'device.map')
201 devmap = open('%s%s' % (chroot_dir, devmapfile), 'w')
202 for (disk, id) in zip(disks, range(len(disks))):
203 new_filename = os.path.join(tmpdir, os.path.basename(disk.filename))
204 open('%s%s' % (chroot_dir, new_filename), 'w').close()
205 run_cmd('mount', '--bind', disk.filename, '%s%s' % (chroot_dir, new_filename))
206 st = os.stat(disk.filename)
207 if stat.S_ISBLK(st.st_mode):
208 for (part, part_id) in zip(disk.partitions, range(len(disk.partitions))):
209 part_mountpnt = '%s%s%d' % (chroot_dir, new_filename, part_id+1)
210 open(part_mountpnt, 'w').close()
211 run_cmd('mount', '--bind', part.filename, part_mountpnt)
212 devmap.write("(hd%d) %s\n" % (id, new_filename))
213 devmap.close()
214 run_cmd('cat', '%s%s' % (chroot_dir, devmapfile))
215 self.suite.install_grub(chroot_dir)
216 self.run_in_target('grub', '--device-map=%s' % devmapfile, '--batch', stdin='''root %s
217 setup (hd0)
218 EOT''' % root_dev)
219 self.suite.install_menu_lst(disks)
220 self.install_bootloader_cleanup(chroot_dir)
221
223 if self.suite.xen_kernel_flavour:
224
225
226
227 if hasattr(self.context, 'ec2') and self.context.ec2:
228 logging.debug("selecting ec2 kernel")
229 self.xen_kernel = "2.6.ec2-kernel"
230 return self.xen_kernel
231 if not self.xen_kernel:
232 rmad = run_cmd('rmadison', 'linux-image-%s' % self.suite.xen_kernel_flavour)
233 version = ['0', '0','0', '0']
234
235 for line in rmad.splitlines():
236 sline = line.split('|')
237
238 if sline[2].strip().startswith(self.context.get_setting('suite')):
239 vt = sline[1].strip().split('.')
240 for i in range(4):
241 if int(vt[i]) > int(version[i]):
242 version = vt
243 break
244
245 if version[0] == '0':
246 raise VMBuilderException('Something is wrong, no valid xen kernel for the suite %s found by rmadison' % self.context.suite)
247
248 self.xen_kernel = '%s.%s.%s-%s' % (version[0],version[1],version[2],version[3])
249 return self.xen_kernel
250 else:
251 raise VMBuilderUserError('There is no valid xen kernel for the suite selected.')
252
256
259
262
268
274
277
280
283
286
288 lang = os.getenv('LANG')
289 if lang is None:
290 return 'C'
291
292
293 if lang.endswith('utf8'):
294 return lang[:-4] + 'UTF-8'
295 return lang
296
297 register_distro(Ubuntu)
298