def spawn(self, instance): """Create VM instance""" vm = VMHelper.lookup(self._session, instance.name) if vm is not None: raise exception.Duplicate(_('Attempted to create' ' non-unique name %s') % instance.name) #ensure enough free memory is available if not VMHelper.ensure_free_mem(self._session, instance): name = instance['name'] LOG.exception(_('instance %(name)s: not enough free memory') % locals()) db.instance_set_state(context.get_admin_context(), instance['id'], power_state.SHUTDOWN) return user = AuthManager().get_user(instance.user_id) project = AuthManager().get_project(instance.project_id) #if kernel is not present we must download a raw disk if instance.kernel_id: disk_image_type = ImageType.DISK else: disk_image_type = ImageType.DISK_RAW vdi_uuid = VMHelper.fetch_image(self._session, instance.id, instance.image_id, user, project, disk_image_type) vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid) #Have a look at the VDI and see if it has a PV kernel pv_kernel = False if not instance.kernel_id: pv_kernel = VMHelper.lookup_image(self._session, instance.id, vdi_ref) kernel = None if instance.kernel_id: kernel = VMHelper.fetch_image(self._session, instance.id, instance.kernel_id, user, project, ImageType.KERNEL_RAMDISK) ramdisk = None if instance.ramdisk_id: ramdisk = VMHelper.fetch_image(self._session, instance.id, instance.ramdisk_id, user, project, ImageType.KERNEL_RAMDISK) vm_ref = VMHelper.create_vm(self._session, instance, kernel, ramdisk, pv_kernel) VMHelper.create_vbd(self._session, vm_ref, vdi_ref, 0, True) # write network info admin_context = context.get_admin_context() # TODO(tr3buchet) - remove comment in multi-nic # I've decided to go ahead and consider multiple IPs and networks # at this stage even though they aren't implemented because these will # be needed for multi-nic and there was no sense writing it for single # network/single IP and then having to turn around and re-write it IPs = db.fixed_ip_get_all_by_instance(admin_context, instance['id']) for network in db.network_get_all_by_instance(admin_context, instance['id']): network_IPs = [ip for ip in IPs if ip.network_id == network.id] def ip_dict(ip): return {'netmask': network['netmask'], 'enabled': '1', 'ip': ip.address} mac_id = instance.mac_address.replace(':', '') location = 'vm-data/networking/%s' % mac_id mapping = {'label': network['label'], 'gateway': network['gateway'], 'mac': instance.mac_address, 'dns': [network['dns']], 'ips': [ip_dict(ip) for ip in network_IPs]} self.write_to_param_xenstore(vm_ref, {location: mapping}) # TODO(tr3buchet) - remove comment in multi-nic # this bit here about creating the vifs will be updated # in multi-nic to handle multiple IPs on the same network # and multiple networks # for now it works as there is only one of each bridge = network['bridge'] network_ref = \ NetworkHelper.find_network_with_bridge(self._session, bridge) if network_ref: VMHelper.create_vif(self._session, vm_ref, network_ref, instance.mac_address) LOG.debug(_('Starting VM %s...'), vm_ref) self._session.call_xenapi('VM.start', vm_ref, False, False) instance_name = instance.name LOG.info(_('Spawning VM %(instance_name)s created %(vm_ref)s.') % locals()) def _inject_onset_files(): onset_files = instance.onset_files if onset_files: # Check if this is a JSON-encoded string and convert if needed. if isinstance(onset_files, basestring): try: onset_files = json.loads(onset_files) except ValueError: LOG.exception(_("Invalid value for onset_files: '%s'") % onset_files) onset_files = [] # Inject any files, if specified for path, contents in instance.onset_files: LOG.debug(_("Injecting file path: '%s'") % path) self.inject_file(instance, path, contents) # NOTE(armando): Do we really need to do this in virt? # NOTE(tr3buchet): not sure but wherever we do it, we need to call # reset_network afterwards timer = utils.LoopingCall(f=None) def _wait_for_boot(): try: state = self.get_info(instance['name'])['state'] db.instance_set_state(context.get_admin_context(), instance['id'], state) if state == power_state.RUNNING: LOG.debug(_('Instance %s: booted'), instance['name']) timer.stop() _inject_onset_files() return True except Exception, exc: LOG.warn(exc) LOG.exception(_('instance %s: failed to boot'), instance['name']) db.instance_set_state(context.get_admin_context(), instance['id'], power_state.SHUTDOWN) timer.stop() return False
def spawn(self, instance, disk): """Create VM instance""" instance_name = instance.name vm = VMHelper.lookup(self._session, instance_name) if vm is not None: raise exception.Duplicate(_('Attempted to create' ' non-unique name %s') % instance_name) #ensure enough free memory is available if not VMHelper.ensure_free_mem(self._session, instance): LOG.exception(_('instance %(instance_name)s: not enough free ' 'memory') % locals()) db.instance_set_state(context.get_admin_context(), instance['id'], power_state.SHUTDOWN) return user = AuthManager().get_user(instance.user_id) project = AuthManager().get_project(instance.project_id) vdi_ref = kernel = ramdisk = pv_kernel = None # Are we building from a pre-existing disk? if not disk: #if kernel is not present we must download a raw disk disk_image_type = VMHelper.determine_disk_image_type(instance) vdi_uuid = VMHelper.fetch_image(self._session, instance.id, instance.image_id, user, project, disk_image_type) vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid) else: vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', disk) if disk_image_type == ImageType.DISK_RAW: # Have a look at the VDI and see if it has a PV kernel pv_kernel = VMHelper.lookup_image(self._session, instance.id, vdi_ref) elif disk_image_type == ImageType.DISK_VHD: # TODO(sirp): Assuming PV for now; this will need to be # configurable as Windows will use HVM. pv_kernel = True if instance.kernel_id: kernel = VMHelper.fetch_image(self._session, instance.id, instance.kernel_id, user, project, ImageType.KERNEL_RAMDISK) if instance.ramdisk_id: ramdisk = VMHelper.fetch_image(self._session, instance.id, instance.ramdisk_id, user, project, ImageType.KERNEL_RAMDISK) vm_ref = VMHelper.create_vm(self._session, instance, kernel, ramdisk, pv_kernel) VMHelper.create_vbd(session=self._session, vm_ref=vm_ref, vdi_ref=vdi_ref, userdevice=0, bootable=True) # inject_network_info and create vifs networks = self.inject_network_info(instance) self.create_vifs(instance, networks) LOG.debug(_('Starting VM %s...'), vm_ref) self._start(instance, vm_ref) LOG.info(_('Spawning VM %(instance_name)s created %(vm_ref)s.') % locals()) def _inject_onset_files(): onset_files = instance.onset_files if onset_files: # Check if this is a JSON-encoded string and convert if needed. if isinstance(onset_files, basestring): try: onset_files = json.loads(onset_files) except ValueError: LOG.exception(_("Invalid value for onset_files: '%s'") % onset_files) onset_files = [] # Inject any files, if specified for path, contents in instance.onset_files: LOG.debug(_("Injecting file path: '%s'") % path) self.inject_file(instance, path, contents) # NOTE(armando): Do we really need to do this in virt? # NOTE(tr3buchet): not sure but wherever we do it, we need to call # reset_network afterwards timer = utils.LoopingCall(f=None) def _wait_for_boot(): try: state = self.get_info(instance_name)['state'] db.instance_set_state(context.get_admin_context(), instance['id'], state) if state == power_state.RUNNING: LOG.debug(_('Instance %s: booted'), instance_name) timer.stop() _inject_onset_files() return True except Exception, exc: LOG.warn(exc) LOG.exception(_('instance %s: failed to boot'), instance_name) db.instance_set_state(context.get_admin_context(), instance['id'], power_state.SHUTDOWN) timer.stop() return False