def plug(self, instance, network, mapping, vm_ref=None, device=None): if not vm_ref: vm_ref = VMHelper.lookup(self._session, instance.name) if not device: device = 0 if mapping.get('should_create_vlan'): network_ref = self._ensure_vlan_bridge(network) else: network_ref = NetworkHelper.find_network_with_bridge( self._session, network['bridge']) vif_rec = {} vif_rec['device'] = str(device) vif_rec['network'] = network_ref vif_rec['VM'] = vm_ref vif_rec['MAC'] = mapping['mac'] vif_rec['MTU'] = '1500' vif_rec['other_config'] = {} if "rxtx_cap" in mapping: vif_rec['qos_algorithm_type'] = "ratelimit" vif_rec['qos_algorithm_params'] = \ {"kbps": str(mapping['rxtx_cap'] * 1024)} else: vif_rec['qos_algorithm_type'] = "" vif_rec['qos_algorithm_params'] = {} return vif_rec
def create_vifs(self, instance, networks=None): """ Creates vifs for an instance """ vm_opaque_ref = self._get_vm_opaque_ref(instance.id) logging.debug(_("creating vif(s) for vm: |%s|"), vm_opaque_ref) if networks is None: networks = db.network_get_all_by_instance(admin_context, instance['id']) # 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 for network in networks: bridge = network['bridge'] network_ref = \ NetworkHelper.find_network_with_bridge(self._session, bridge) if network_ref: try: device = "1" if instance._rescue else "0" except AttributeError: device = "0" VMHelper.create_vif( self._session, vm_opaque_ref, network_ref, instance.mac_address, device)
def ensure_vlan_bridge(self, xenapi_session, network): """Ensure that a VLAN bridge exists""" vlan_num = network['vlan'] bridge = network['bridge'] bridge_interface = network['bridge_interface'] # Check whether bridge already exists # Retrieve network whose name_label is "bridge" network_ref = NetworkHelper.find_network_with_name_label( xenapi_session, bridge) if network_ref is None: # If bridge does not exists # 1 - create network description = 'network for nova bridge %s' % bridge network_rec = {'name_label': bridge, 'name_description': description, 'other_config': {}} network_ref = xenapi_session.call_xenapi('network.create', network_rec) # 2 - find PIF for VLAN NOTE(salvatore-orlando): using double # quotes inside single quotes as xapi filter only support # tokens in double quotes expr = 'field "device" = "%s" and \ field "VLAN" = "-1"' % bridge_interface pifs = xenapi_session.call_xenapi('PIF.get_all_records_where', expr) pif_ref = None # Multiple PIF are ok: we are dealing with a pool if len(pifs) == 0: raise Exception(_('Found no PIF for device %s') % \ bridge_interface) for pif_ref in pifs.keys(): xenapi_session.call_xenapi('VLAN.create', pif_ref, str(vlan_num), network_ref) else: # Check VLAN tag is appropriate network_rec = xenapi_session.call_xenapi('network.get_record', network_ref) # Retrieve PIFs from network for pif_ref in network_rec['PIFs']: # Retrieve VLAN from PIF pif_rec = xenapi_session.call_xenapi('PIF.get_record', pif_ref) pif_vlan = int(pif_rec['VLAN']) # Raise an exception if VLAN != vlan_num if pif_vlan != vlan_num: raise Exception(_( "PIF %(pif_rec['uuid'])s for network " "%(bridge)s has VLAN id %(pif_vlan)d. " "Expected %(vlan_num)d") % locals()) return network_ref
def _ensure_vlan_bridge(self, network): """Ensure that a VLAN bridge exists""" vlan_num = network['vlan'] bridge = network['bridge'] bridge_interface = FLAGS.vlan_interface or network['bridge_interface'] # Check whether bridge already exists # Retrieve network whose name_label is "bridge" network_ref = NetworkHelper.find_network_with_name_label( self._session, bridge) if network_ref is None: # If bridge does not exists # 1 - create network description = 'network for nova bridge %s' % bridge network_rec = {'name_label': bridge, 'name_description': description, 'other_config': {}} network_ref = self._session.call_xenapi('network.create', network_rec) # 2 - find PIF for VLAN NOTE(salvatore-orlando): using double # quotes inside single quotes as xapi filter only support # tokens in double quotes expr = ('field "device" = "%s" and field "VLAN" = "-1"' % bridge_interface) pifs = self._session.call_xenapi('PIF.get_all_records_where', expr) pif_ref = None # Multiple PIF are ok: we are dealing with a pool if len(pifs) == 0: raise Exception(_('Found no PIF for device %s') % bridge_interface) for pif_ref in pifs.keys(): self._session.call_xenapi('VLAN.create', pif_ref, str(vlan_num), network_ref) else: # Check VLAN tag is appropriate network_rec = self._session.call_xenapi('network.get_record', network_ref) # Retrieve PIFs from network for pif_ref in network_rec['PIFs']: # Retrieve VLAN from PIF pif_rec = self._session.call_xenapi('PIF.get_record', pif_ref) pif_vlan = int(pif_rec['VLAN']) # Raise an exception if VLAN != vlan_num if pif_vlan != vlan_num: raise Exception(_( "PIF %(pif_rec['uuid'])s for network " "%(bridge)s has VLAN id %(pif_vlan)d. " "Expected %(vlan_num)d") % locals()) return network_ref
def create_vifs(self, vm_ref, network_info): """Creates vifs for an instance""" logging.debug(_("creating vif(s) for vm: |%s|"), vm_ref) # this function raises if vm_ref is not a vm_opaque_ref self._session.get_xenapi().VM.get_record(vm_ref) for device, (network, info) in enumerate(network_info): mac_address = info['mac'] bridge = network['bridge'] rxtx_cap = info.pop('rxtx_cap') network_ref = \ NetworkHelper.find_network_with_bridge(self._session, bridge) VMHelper.create_vif(self._session, vm_ref, network_ref, mac_address, device, rxtx_cap)
def plug(self, xenapi_session, vm_ref, instance, device, network, network_mapping): if network_mapping.get('should_create_vlan'): network_ref = self.ensure_vlan_bridge(xenapi_session, network) else: network_ref = NetworkHelper.find_network_with_bridge( xenapi_session, network['bridge']) rxtx_cap = network_mapping.pop('rxtx_cap') vif_rec = {} vif_rec['device'] = str(device) vif_rec['network'] = network_ref vif_rec['VM'] = vm_ref vif_rec['MAC'] = network_mapping['mac'] vif_rec['MTU'] = '1500' vif_rec['other_config'] = {} vif_rec['qos_algorithm_type'] = "ratelimit" if rxtx_cap else '' vif_rec['qos_algorithm_params'] = \ {"kbps": str(rxtx_cap * 1024)} if rxtx_cap else {} return vif_rec
def plug(self, xenapi_session, vm_ref, instance, device, network, network_mapping): # with OVS model, always plug into an OVS integration bridge # that is already created network_ref = NetworkHelper.find_network_with_bridge(xenapi_session, FLAGS.xenapi_ovs_integration_bridge) vif_rec = {} vif_rec['device'] = str(device) vif_rec['network'] = network_ref vif_rec['VM'] = vm_ref vif_rec['MAC'] = network_mapping['mac'] vif_rec['MTU'] = '1500' vif_rec['qos_algorithm_type'] = "" vif_rec['qos_algorithm_params'] = {} # OVS on the hypervisor monitors this key and uses it to # set the iface-id attribute vif_rec['other_config'] = \ {"nicira-iface-id": network_mapping['vif_uuid']} return vif_rec
def plug(self, xenapi_session, vm_ref, instance, device, network, network_mapping): # with OVS model, always plug into an OVS integration bridge # that is already created network_ref = NetworkHelper.find_network_with_bridge( xenapi_session, FLAGS.xenapi_ovs_integration_bridge) vif_rec = {} vif_rec['device'] = str(device) vif_rec['network'] = network_ref vif_rec['VM'] = vm_ref vif_rec['MAC'] = network_mapping['mac'] vif_rec['MTU'] = '1500' vif_rec['qos_algorithm_type'] = "" vif_rec['qos_algorithm_params'] = {} # OVS on the hypervisor monitors this key and uses it to # set the iface-id attribute vif_rec['other_config'] = \ {"nicira-iface-id": network_mapping['vif_uuid']} return vif_rec
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