Package VMBuilder :: Package plugins :: Package ubuntu :: Module distro
[frames] | no frames]

Source Code for Module VMBuilder.plugins.ubuntu.distro

  1  # 
  2  #    Uncomplicated VM Builder 
  3  #    Copyright (C) 2007-2010 Canonical Ltd. 
  4  # 
  5  #    See AUTHORS for list of contributors 
  6  # 
  7  #    This program is free software: you can redistribute it and/or modify 
  8  #    it under the terms of the GNU General Public License version 3, as 
  9  #    published by the Free Software Foundation. 
 10  # 
 11  #    This program is distributed in the hope that it will be useful, 
 12  #    but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 14  #    GNU 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, see <http://www.gnu.org/licenses/>. 
 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   
28 -class Ubuntu(Distro):
29 name = 'Ubuntu' 30 arg = 'ubuntu' 31 suites = ['dapper', 'gutsy', 'hardy', 'intrepid', 'jaunty', 32 'karmic', 'lucid', 'maverick', 'natty', 'oneiric', 33 'precise' ] 34 35 # Maps host arch to valid guest archs 36 valid_archs = { 'amd64' : ['amd64', 'i386', 'lpia' ], 37 'i386' : [ 'i386', 'lpia' ], 38 'lpia' : [ 'i386', 'lpia' ] } 39 40 xen_kernel = '' 41
42 - def register_options(self):
43 group = self.setting_group('Package options') 44 group.add_setting('addpkg', type='list', metavar='PKG', help='Install PKG into the guest (can be specified multiple times).') 45 group.add_setting('removepkg', type='list', metavar='PKG', help='Remove PKG from the guest (can be specified multiple times)') 46 group.add_setting('seedfile', metavar="SEEDFILE", help='Seed the debconf database with the contents of this seed file before installing packages') 47 48 group = self.setting_group('General OS options') 49 self.host_arch = run_cmd('dpkg', '--print-architecture').rstrip() 50 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)') 51 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.') 52 53 group = self.setting_group('Installation options') 54 group.add_setting('suite', default='lucid', help='Suite to install. Valid options: %s [default: %%default]' % ' '.join(self.suites)) 55 group.add_setting('flavour', extra_args=['--kernel-flavour'], help='Kernel flavour to use. Default and valid options depend on architecture and suite') 56 group.add_setting('variant', metavar='VARIANT', help='Passed to debootstrap --variant flag; use minbase, buildd, or fakechroot.') 57 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.') 58 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') 59 group.add_setting('proxy', metavar='URL', help='Use proxy at URL for cached packages') 60 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') 61 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.') 62 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') 63 group.add_setting('components', type='list', metavar='COMPS', help='A comma seperated list of distro components to include (e.g. main,universe).') 64 group.add_setting('ppa', metavar='PPA', type='list', help='Add ppa belonging to PPA to the vm\'s sources.list.') 65 group.add_setting('lang', metavar='LANG', default=get_locale(), help='Set the locale to LANG [default: %default]') 66 group.add_setting('timezone', metavar='TZ', default='UTC', help='Set the timezone to TZ in the vm. [default: %default]') 67 68 group = self.setting_group('Settings for the initial user') 69 group.add_setting('user', default='ubuntu', help='Username of initial user [default: %default]') 70 group.add_setting('name', default='Ubuntu', help='Full name of initial user [default: %default]') 71 group.add_setting('pass', default='ubuntu', help='Password of initial user [default: %default]') 72 group.add_setting('rootpass', help='Initial root password (WARNING: this has strong security implications).') 73 group.add_setting('uid', type='int', help='Initial UID value.') 74 group.add_setting('gid', help='Initial GID value.') 75 group.add_setting('lock-user', type='bool', default=False, help='Lock the initial user [default: %default]') 76 77 group = self.setting_group('Other options') 78 group.add_setting('ssh-key', metavar='PATH', help='Add PATH to root\'s ~/.ssh/authorized_keys (WARNING: this has strong security implications).') 79 group.add_setting('ssh-user-key', help='Add PATH to the user\'s ~/.ssh/authorized_keys.') 80 group.add_setting('manifest', metavar='PATH', help='If passed, a manifest will be written to PATH')
81
82 - def set_defaults(self):
83 arch = self.get_setting('arch') 84 85 if arch == 'lpia': 86 self.set_setting_default('mirror', 'http://ports.ubuntu.com/ubuntu-ports') 87 self.set_setting_default('security-mirror', 'http://ports.ubuntu.com/ubuntu-ports') 88 else: 89 self.set_setting_default('mirror', 'http://archive.ubuntu.com/ubuntu') 90 self.set_setting_default('security-mirror', 'http://security.ubuntu.com/ubuntu') 91 92 self.set_setting_default('components', ['main', 'restricted', 'universe'])
93
94 - def preflight_check(self):
95 """While not all of these are strictly checks, their failure would inevitably 96 lead to failure, and since we can check them before we start setting up disk 97 and whatnot, we might as well go ahead an do this now.""" 98 99 suite = self.get_setting('suite') 100 if not suite in self.suites: 101 raise VMBuilderUserError('Invalid suite: "%s". Valid suites are: %s' % (suite, ' '.join(self.suites))) 102 103 modname = 'VMBuilder.plugins.ubuntu.%s' % (suite, ) 104 mod = __import__(modname, fromlist=[suite]) 105 self.suite = getattr(mod, suite.capitalize())(self) 106 107 arch = self.get_setting('arch') 108 if arch not in self.valid_archs[self.host_arch] or \ 109 not self.suite.check_arch_validity(arch): 110 raise VMBuilderUserError('%s is not a valid architecture. Valid architectures are: %s' % (arch, 111 ' '.join(self.valid_archs[self.host_arch]))) 112 113 components = self.get_setting('components') 114 if not components: 115 self.set_config_value_list = ['main', 'restricted', 'universe'] 116 else: 117 if type(components) is str: 118 self.vm.components = self.vm.components.split(',') 119 120 self.context.virtio_net = self.use_virtio_net() 121 122 # check if the seedfile exists if one is to be used 123 seedfile = self.context.get_setting('seedfile') 124 if seedfile and not os.path.exists(seedfile): 125 raise VMBuilderUserError("Seedfile '%s' does not exist" % seedfile) 126 127 lang = self.get_setting('lang')
128 129 # FIXME 130 # if getattr(self.vm, 'ec2', False): 131 # self.get_ec2_kernel() 132 # self.get_ec2_ramdisk() 133 # self.apply_ec2_settings() 134
135 - def bootstrap(self):
136 self.suite.debootstrap() 137 self.suite.pre_install()
138
139 - def configure_os(self):
140 self.suite.install_sources_list() 141 self.suite.install_apt_proxy() 142 self.suite.create_devices() 143 self.suite.prevent_daemons_starting() 144 self.suite.mount_dev_proc() 145 self.suite.install_extras() 146 self.suite.create_initial_user() 147 self.suite.install_authorized_keys() 148 self.suite.set_timezone() 149 self.suite.set_locale() 150 self.suite.update() 151 self.suite.install_sources_list(final=True) 152 self.suite.run_in_target('apt-get', 'clean'); 153 self.suite.unmount_volatile() 154 self.suite.unmount_proc() 155 self.suite.unmount_dev_pts() 156 self.suite.unmount_dev() 157 self.suite.unprevent_daemons_starting() 158 self.suite.create_manifest()
159
160 - def configure_networking(self, nics):
163
164 - def configure_mounting(self, disks, filesystems):
165 self.suite.install_fstab(disks, filesystems)
166
167 - def install(self, destdir):
168 self.destdir = destdir 169 self.suite.install(destdir)
170
171 - def install_vmbuilder_log(self, logfile, rootdir):
172 self.suite.install_vmbuilder_log(logfile, rootdir)
173
174 - def post_mount(self, fs):
175 self.suite.post_mount(fs)
176
177 - def use_virtio_net(self):
178 return self.suite.virtio_net
179
180 - def install_bootloader_cleanup(self, chroot_dir):
181 self.context.cancel_cleanup(self.install_bootloader_cleanup) 182 tmpdir = '%s/tmp/vmbuilder-grub' % chroot_dir 183 for disk in os.listdir(tmpdir): 184 if disk != 'device.map': 185 run_cmd('umount', os.path.join(tmpdir, disk)) 186 shutil.rmtree(tmpdir)
187
188 - def install_kernel(self, destdir):
189 self.suite.install_kernel(destdir)
190
191 - def install_bootloader(self, chroot_dir, disks):
192 root_dev = VMBuilder.disk.bootpart(disks).get_grub_id() 193 194 tmpdir = '/tmp/vmbuilder-grub' 195 os.makedirs('%s%s' % (chroot_dir, tmpdir)) 196 self.context.add_clean_cb(self.install_bootloader_cleanup) 197 devmapfile = os.path.join(tmpdir, 'device.map') 198 devmap = open('%s%s' % (chroot_dir, devmapfile), 'w') 199 for (disk, id) in zip(disks, range(len(disks))): 200 new_filename = os.path.join(tmpdir, os.path.basename(disk.filename)) 201 open('%s%s' % (chroot_dir, new_filename), 'w').close() 202 run_cmd('mount', '--bind', disk.filename, '%s%s' % (chroot_dir, new_filename)) 203 st = os.stat(disk.filename) 204 if stat.S_ISBLK(st.st_mode): 205 for (part, part_id) in zip(disk.partitions, range(len(disk.partitions))): 206 part_mountpnt = '%s%s%d' % (chroot_dir, new_filename, part_id+1) 207 open(part_mountpnt, 'w').close() 208 run_cmd('mount', '--bind', part.filename, part_mountpnt) 209 devmap.write("(hd%d) %s\n" % (id, new_filename)) 210 devmap.close() 211 run_cmd('cat', '%s%s' % (chroot_dir, devmapfile)) 212 self.suite.install_grub(chroot_dir) 213 self.run_in_target('grub', '--device-map=%s' % devmapfile, '--batch', stdin='''root %s 214 setup (hd0) 215 EOT''' % root_dev) 216 self.suite.install_menu_lst(disks) 217 self.install_bootloader_cleanup(chroot_dir)
218
219 - def xen_kernel_version(self):
220 if self.suite.xen_kernel_flavour: 221 # if this is ec2, do not call rmadison. 222 # this could be replaced with a method to get most recent 223 # stable kernel, but really, this is not used at all for ec2 224 if hasattr(self.context, 'ec2') and self.context.ec2: 225 logging.debug("selecting ec2 kernel") 226 self.xen_kernel = "2.6.ec2-kernel" 227 return self.xen_kernel 228 if not self.xen_kernel: 229 rmad = run_cmd('rmadison', 'linux-image-%s' % self.suite.xen_kernel_flavour) 230 version = ['0', '0','0', '0'] 231 232 for line in rmad.splitlines(): 233 sline = line.split('|') 234 235 if sline[2].strip().startswith(self.context.get_setting('suite')): 236 vt = sline[1].strip().split('.') 237 for i in range(4): 238 if int(vt[i]) > int(version[i]): 239 version = vt 240 break 241 242 if version[0] == '0': 243 raise VMBuilderException('Something is wrong, no valid xen kernel for the suite %s found by rmadison' % self.context.suite) 244 245 self.xen_kernel = '%s.%s.%s-%s' % (version[0],version[1],version[2],version[3]) 246 return self.xen_kernel 247 else: 248 raise VMBuilderUserError('There is no valid xen kernel for the suite selected.')
249
250 - def xen_kernel_initrd_path(self, which):
251 path = '/boot/%s-%s-%s' % (which, self.xen_kernel_version(), self.suite.xen_kernel_flavour) 252 return path
253
254 - def xen_kernel_path(self):
255 return self.xen_kernel_initrd_path('kernel')
256
257 - def xen_ramdisk_path(self):
258 return self.xen_kernel_initrd_path('ramdisk')
259
260 - def get_ec2_kernel(self):
261 if self.suite.ec2_kernel_info: 262 return self.suite.ec2_kernel_info[self.context.arch] 263 else: 264 raise VMBuilderUserError('EC2 is not supported for the suite selected')
265
266 - def get_ec2_ramdisk(self):
267 if self.suite.ec2_ramdisk_info: 268 return self.suite.ec2_ramdisk_info[self.context.arch] 269 else: 270 raise VMBuilderUserError('EC2 is not supported for the suite selected')
271
272 - def disable_hwclock_access(self):
273 return self.suite.disable_hwclock_access()
274
275 - def apply_ec2_settings(self):
276 return self.suite.apply_ec2_settings()
277 280
281 - def preferred_filesystem(self):
282 return self.suite.preferred_filesystem
283
284 -def get_locale():
285 lang = os.getenv('LANG') 286 if lang is None: 287 return 'C' 288 # People's $LANG looks different since lucid, but locale-gen still 289 # wants the old format. 290 if lang.endswith('utf8'): 291 return lang[:-4] + 'UTF-8' 292 return lang
293 294 register_distro(Ubuntu) 295