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', 'karmic', 'lucid', 'maverick']
32
33
34 valid_archs = { 'amd64' : ['amd64', 'i386', 'lpia' ],
35 'i386' : [ 'i386', 'lpia' ],
36 'lpia' : [ 'i386', 'lpia' ] }
37
38 xen_kernel = ''
39
41 group = self.setting_group('Package options')
42 group.add_setting('addpkg', type='list', metavar='PKG', help='Install PKG into the guest (can be specfied multiple times).')
43 group.add_setting('removepkg', type='list', metavar='PKG', help='Remove PKG from the guest (can be specfied multiple times)')
44 group.add_setting('seedfile', metavar="SEEDFILE", help='Seed the debconf database with the contents of this seed file before installing packages')
45
46 group = self.setting_group('General OS options')
47 self.host_arch = run_cmd('dpkg', '--print-architecture').rstrip()
48 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)')
49 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.')
50
51 group = self.setting_group('Installation options')
52 group.add_setting('suite', default='lucid', help='Suite to install. Valid options: %s [default: %%default]' % ' '.join(self.suites))
53 group.add_setting('flavour', extra_args=['--kernel-flavour'], help='Kernel flavour to use. Default and valid options depend on architecture and suite')
54 group.add_setting('variant', metavar='VARIANT', help='Passed to debootstrap --variant flag; use minbase, buildd, or fakechroot.')
55 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.')
56 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')
57 group.add_setting('proxy', metavar='URL', help='Use proxy at URL for cached packages')
58 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')
59 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.')
60 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')
61 group.add_setting('components', type='list', metavar='COMPS', help='A comma seperated list of distro components to include (e.g. main,universe).')
62 group.add_setting('ppa', metavar='PPA', type='list', help='Add ppa belonging to PPA to the vm\'s sources.list.')
63 group.add_setting('lang', metavar='LANG', default=self.get_locale(), help='Set the locale to LANG [default: %default]')
64 group.add_setting('timezone', metavar='TZ', default='UTC', help='Set the timezone to TZ in the vm. [default: %default]')
65
66 group = self.setting_group('Settings for the initial user')
67 group.add_setting('user', default='ubuntu', help='Username of initial user [default: %default]')
68 group.add_setting('name', default='Ubuntu', help='Full name of initial user [default: %default]')
69 group.add_setting('pass', default='ubuntu', help='Password of initial user [default: %default]')
70 group.add_setting('rootpass', help='Initial root password (WARNING: this has strong security implications).')
71 group.add_setting('uid', type='int', help='Initial UID value.')
72 group.add_setting('gid', help='Initial GID value.')
73 group.add_setting('lock-user', type='bool', default=False, help='Lock the initial user [default: %default]')
74
75 group = self.setting_group('Other options')
76 group.add_setting('ssh-key', metavar='PATH', help='Add PATH to root\'s ~/.ssh/authorized_keys (WARNING: this has strong security implications).')
77 group.add_setting('ssh-user-key', help='Add PATH to the user\'s ~/.ssh/authorized_keys.')
78 group.add_setting('manifest', metavar='PATH', help='If passed, a manifest will be written to PATH')
79
91
93 lang = os.getenv('LANG')
94
95
96 if lang.endswith('utf8'):
97 return lang[:-4] + 'UTF-8'
98 return os.getenv('LANG')
99
101 """While not all of these are strictly checks, their failure would inevitably
102 lead to failure, and since we can check them before we start setting up disk
103 and whatnot, we might as well go ahead an do this now."""
104
105 suite = self.get_setting('suite')
106 if not suite in self.suites:
107 raise VMBuilderUserError('Invalid suite: "%s". Valid suites are: %s' % (suite, ' '.join(self.suites)))
108
109 modname = 'VMBuilder.plugins.ubuntu.%s' % (suite, )
110 mod = __import__(modname, fromlist=[suite])
111 self.suite = getattr(mod, suite.capitalize())(self)
112
113 arch = self.get_setting('arch')
114 if arch not in self.valid_archs[self.host_arch] or \
115 not self.suite.check_arch_validity(arch):
116 raise VMBuilderUserError('%s is not a valid architecture. Valid architectures are: %s' % (arch,
117 ' '.join(self.valid_archs[self.host_arch])))
118
119 components = self.get_setting('components')
120 if not components:
121 self.set_config_value_list = ['main', 'restricted', 'universe']
122 else:
123 if type(components) is str:
124 self.vm.components = self.vm.components.split(',')
125
126 self.context.virtio_net = self.use_virtio_net()
127
128
129 seedfile = self.context.get_setting('seedfile')
130 if seedfile and not os.path.exists(seedfile):
131 raise VMBuilderUserError("Seedfile '%s' does not exist" % seedfile)
132
133 lang = self.get_setting('lang')
134
135
136
137
138
139
140
144
166
169
172
176
179
180 - def post_mount(self, fs):
182
185
193
196
198 root_dev = VMBuilder.disk.bootpart(disks).get_grub_id()
199
200 tmpdir = '/tmp/vmbuilder-grub'
201 os.makedirs('%s%s' % (chroot_dir, tmpdir))
202 self.context.add_clean_cb(self.install_bootloader_cleanup)
203 devmapfile = os.path.join(tmpdir, 'device.map')
204 devmap = open('%s%s' % (chroot_dir, devmapfile), 'w')
205 for (disk, id) in zip(disks, range(len(disks))):
206 new_filename = os.path.join(tmpdir, os.path.basename(disk.filename))
207 open('%s%s' % (chroot_dir, new_filename), 'w').close()
208 run_cmd('mount', '--bind', disk.filename, '%s%s' % (chroot_dir, new_filename))
209 st = os.stat(disk.filename)
210 if stat.S_ISBLK(st.st_mode):
211 for (part, part_id) in zip(disk.partitions, range(len(disk.partitions))):
212 part_mountpnt = '%s%s%d' % (chroot_dir, new_filename, part_id+1)
213 open(part_mountpnt, 'w').close()
214 run_cmd('mount', '--bind', part.filename, part_mountpnt)
215 devmap.write("(hd%d) %s\n" % (id, new_filename))
216 devmap.close()
217 run_cmd('cat', '%s%s' % (chroot_dir, devmapfile))
218 self.suite.install_grub(chroot_dir)
219 self.run_in_target('grub', '--device-map=%s' % devmapfile, '--batch', stdin='''root %s
220 setup (hd0)
221 EOT''' % root_dev)
222 self.suite.install_menu_lst(disks)
223 self.install_bootloader_cleanup(chroot_dir)
224
226 if self.suite.xen_kernel_flavour:
227
228
229
230 if hasattr(self.context, 'ec2') and self.context.ec2:
231 logging.debug("selecting ec2 kernel")
232 self.xen_kernel = "2.6.ec2-kernel"
233 return self.xen_kernel
234 if not self.xen_kernel:
235 rmad = run_cmd('rmadison', 'linux-image-%s' % self.suite.xen_kernel_flavour)
236 version = ['0', '0','0', '0']
237
238 for line in rmad.splitlines():
239 sline = line.split('|')
240
241 if sline[2].strip().startswith(self.context.get_setting('suite')):
242 vt = sline[1].strip().split('.')
243 for i in range(4):
244 if int(vt[i]) > int(version[i]):
245 version = vt
246 break
247
248 if version[0] == '0':
249 raise VMBuilderException('Something is wrong, no valid xen kernel for the suite %s found by rmadison' % self.context.suite)
250
251 self.xen_kernel = '%s.%s.%s-%s' % (version[0],version[1],version[2],version[3])
252 return self.xen_kernel
253 else:
254 raise VMBuilderUserError('There is no valid xen kernel for the suite selected.')
255
259
262
265
271
277
280
283
286
289
290 register_distro(Ubuntu)
291