class PhysicalConnection(driver.ComputeDriver): """Physical hypervisor driver""" def _get_dhcp_hosts(self, context): """Get network's hosts config in dhcp-host format.""" hosts = [] for ph in self._get_phy_hosts(context): ip = db.phy_pxe_ip_get_by_phy_host_id(context, ph.id) if ip: hosts.append(_host_dhcp(ph.pxe_mac_address, "phyhost-%s" % ph.id, ip.address)) return '\n'.join(hosts) def __init__(self): LOG.info(_("Physical driver __init__")) if not FLAGS.physical_deploy_kernel: raise exception.NovaException('physical_deploy_kernel is not defined') if not FLAGS.physical_deploy_ramdisk: raise exception.NovaException('physical_deploy_ramdisk is not defined') self._vif_driver = utils.import_object(FLAGS.physical_vif_driver) if FLAGS.physical_enable_firewall: self._firewall_driver = QuantumFilterFirewall() else: self._firewall_driver = DisabledQuantumFilterFirewall() @classmethod def instance(cls): if not hasattr(cls, '_instance'): cls._instance = cls() return cls._instance def init_host(self, host): return def list_instances(self): l = [] ctx = nova_context.get_admin_context() for i in self._get_phy_hosts(ctx): if i.instance: l.append(i.instance.name) return l def list_instances_detail(self): l = [] ctx = nova_context.get_admin_context() for i in self._get_phy_hosts(ctx): if i.instance: pm = _get_ipmi(i.ipmi_address, i.ipmi_user, i.ipmi_password) ps = power_state.SHUTOFF if pm.is_power_on(): ps = power_state.RUNNING ii = driver.InstanceInfo(i.instance.name, ps) l.append(ii) return l def _get_phy_hosts(self, context): service = db.service_get_by_host_and_topic(context, FLAGS.host, "compute") if not service: LOG.warn("Could not get service_get_by_host_and_topic host=%s topic=%s", FLAGS.host, "compute") return [] phy_hosts = db.phy_host_get_all(context) hosts = [] for i in phy_hosts: if i.service_id == service.id: hosts.append(i) return hosts def _get_phy_host_by_instance_id(self, instance_id): ctx = nova_context.get_admin_context() for i in self._get_phy_hosts(ctx): if not i.instance: continue try: if i.instance.id == instance_id: return i except exception.InstanceNotFound: continue return None def _get_phy_host_by_instance_name(self, instance_name): ctx = nova_context.get_admin_context() for i in self._get_phy_hosts(ctx): if not i.instance: continue try: if i.instance.name == instance_name: return i except exception.InstanceNotFound: continue return None def _find_suitable_phy_host(self, context, instance): result = None for i in self._get_phy_hosts(context): if i.instance_id: continue if i.registration_status != 'done': continue if i.cpus < instance.vcpus: continue if i.memory_mb < instance.memory_mb: continue if result == None: result = i else: if i.cpus < result.cpus: result = i elif i.cpus == result.cpus and i.memory_mb < result.memory_mb: result = i return result def spawn(self, context, instance, image_meta, network_info=None, block_device_info=None): LOG.debug("spawn:") LOG.debug("instance=%s", instance.__dict__) LOG.debug("image_meta=%s", image_meta) LOG.debug("network_info=%s", network_info) LOG.debug("block_device_info=%s", block_device_info) # TODO: handle block devices host = self._find_suitable_phy_host(context, instance) if not host: LOG.info("no suitable physical host found") raise NoSuitablePhyHost() db.phy_host_update(context, host['id'], {'instance_id': instance['id'], 'task_state' : physical_states.BUILDING, }) nics_in_order = [] pifs = db.phy_interface_get_all_by_phy_host_id(context, host['id']) for pif in pifs: nics_in_order.append(pif['address']) if pif.vif_uuid: db.phy_interface_set_vif_uuid(context, pif.id, None) nics_in_order.append(host['pxe_mac_address']) image_root = os.path.join(FLAGS.instances_path, instance['name']) tftp_root = FLAGS.physical_tftp_root os.mkdir(image_root) if FLAGS.physical_pxe_vlan_per_host: parent_interface = FLAGS.physical_pxe_parent_interface pxe_ip_id = db.phy_pxe_ip_associate(context, host.id) pxe_ip = db.phy_pxe_ip_get(context, pxe_ip_id) vlan_num = host.pxe_vlan_id server_address = pxe_ip.server_address client_address = pxe_ip.address tftp_root = os.path.join(tftp_root, str(instance['id'])) pxe_interface = vlan.ensure_vlan(vlan_num, parent_interface) from nova.network import linux_net chain = 'phy-%s' % pxe_interface iptables = linux_net.iptables_manager iptables.ipv4['filter'].add_chain(chain) iptables.ipv4['filter'].add_rule('INPUT', '-i %s -j $%s' % (pxe_interface, chain)) iptables.ipv4['filter'].add_rule(chain, '--proto udp --sport=68 --dport=67 -j ACCEPT') iptables.ipv4['filter'].add_rule(chain, '-s %s -j ACCEPT' % client_address) iptables.ipv4['filter'].add_rule(chain, '-j DROP') iptables.apply() #execute('ip', 'address', # 'add', server_address, # 'peer', client_address, # 'dev', pxe_interface, # run_as_root=True) #execute('ip', 'link', 'set', pxe_interface, 'up', run_as_root=True) execute('ip', 'address', 'add', server_address + '/24', 'dev', pxe_interface, run_as_root=True) execute('ip', 'route', 'add', client_address, 'scope', 'host', 'dev', pxe_interface, run_as_root=True) os.mkdir(tftp_root) shutil.copyfile(FLAGS.physical_pxelinux_path, os.path.join(tftp_root, 'pxelinux.0')) os.mkdir(os.path.join(tftp_root, 'pxelinux.cfg')) pxe.start_pxe_server(interface=pxe_interface, tftp_root=tftp_root, client_address=client_address, pid_path=_dnsmasq_pid_path(pxe_interface), lease_path=_dnsmasq_lease_path(pxe_interface)) self.plug_vifs(instance, network_info) ifcfgs = [] if_num = -1 for (network,mapping) in network_info: LOG.debug("mapping['mac'] = %s", mapping['mac']) if_num += 1 device = "eth%d" % if_num pif = db.phy_interface_get_by_vif_uuid(context, mapping['vif_uuid']) if not pif: LOG.warn("vif_uuid:%s dose not associated to pif, unexpectedly", mapping['vif_uuid']) continue ifcfg = _build_ifcfg_string_from_mapping(device, pif.address, mapping) if FLAGS.physical_use_unsafe_vlan and mapping['should_create_vlan'] and network.get('vlan'): ifcfg += "," + network['vlan'] LOG.debug("ifcfg: %s", ifcfg) ifcfgs.append(ifcfg) self._firewall_driver.setup_basic_filtering(instance, network_info) self._firewall_driver.update_instance_filter(instance, network_info) ami_id = str(image_meta['id']) aki_id = str(instance['kernel_id']) ari_id = str(instance['ramdisk_id']) deploy_aki_id = FLAGS.physical_deploy_kernel deploy_ari_id = FLAGS.physical_deploy_ramdisk image_target = os.path.join(image_root, ami_id) kernel_target = os.path.join(tftp_root, aki_id) ramdisk_target = os.path.join(tftp_root, ari_id) deploy_kernel_target = os.path.join(tftp_root, deploy_aki_id) deploy_ramdisk_target = os.path.join(tftp_root, deploy_ari_id) LOG.debug("fetching image id=%s target=%s", ami_id, image_target) self._cache_image_x(context=context, target=image_target, image_id=ami_id, user_id=instance['user_id'], project_id=instance['project_id']) LOG.debug("injecting to image id=%s target=%s", ami_id, image_target) self._inject_to_image(image_target, instance, network_info, nics_in_order) LOG.debug("fetching kernel id=%s target=%s", aki_id, kernel_target) self._cache_image_x(context=context, image_id=aki_id, target=kernel_target, user_id=instance['user_id'], project_id=instance['project_id']) LOG.debug("fetching ramdisk id=%s target=%s", ari_id, ramdisk_target) self._cache_image_x(context=context, image_id=ari_id, target=ramdisk_target, user_id=instance['user_id'], project_id=instance['project_id']) LOG.debug("fetching deploy_kernel id=%s target=%s", aki_id, kernel_target) self._cache_image_x(context=context, image_id=deploy_aki_id, target=deploy_kernel_target, user_id=instance['user_id'], project_id=instance['project_id']) LOG.debug("fetching deploy_ramdisk id=%s target=%s", ari_id, ramdisk_target) self._cache_image_x(context=context, image_id=deploy_ari_id, target=deploy_ramdisk_target, user_id=instance['user_id'], project_id=instance['project_id']) LOG.debug("fetching images all done") pxe_config_path = os.path.join(tftp_root, 'pxelinux.cfg', "01-" + host.pxe_mac_address.replace(":", "-").lower()) root_mb = instance['root_gb'] * 1024 inst_type_id = instance['instance_type_id'] inst_type = instance_types.get_instance_type(inst_type_id) swap_mb = inst_type['swap'] if swap_mb < 1024: swap_mb = 1024 deployment_key = _random_alnum(32) deployment_id = db.phy_deployment_create(context, deployment_key, image_target, pxe_config_path, root_mb, swap_mb) # 'default deploy' will be replaced to 'default boot' by phy_deploy_work pxeconf = "default deploy\n" pxeconf += "\n" pxeconf += "label deploy\n" pxeconf += "kernel %s\n" % deploy_aki_id pxeconf += "append" pxeconf += " initrd=%s" % deploy_ari_id pxeconf += " selinux=0" pxeconf += " disk=cciss/c0d0,sda,hda" pxeconf += " iscsi_target_iqn=iqn-%s" % str(instance['uuid']) pxeconf += " deployment_id=%s" % deployment_id pxeconf += " deployment_key=%s" % deployment_key pxeconf += "\n" pxeconf += "ipappend 3\n" pxeconf += "\n" pxeconf += "label boot\n" pxeconf += "kernel %s\n" % aki_id pxeconf += "append" pxeconf += " initrd=%s" % ari_id # ${ROOT} will be replaced to UUID=... by phy_deploy_work pxeconf += " root=${ROOT} ro" pxeconf += "\n" pxeconf += "\n" f = open(pxe_config_path, 'w') f.write(pxeconf) f.close() if not host.ipmi_address: LOG.warn("Since ipmi_address is empty, power_off_on is not performed") LOG.debug("power on") pm = _get_ipmi(host.ipmi_address, host.ipmi_user, host.ipmi_password) state = pm.power_off() self._update_physical_state(context, host, instance, state) state = pm.power_on() self._update_physical_state(context, host, instance, state) if FLAGS.physical_console: (out,err) = execute(FLAGS.physical_console, '--ipmi_address=%s' % host.ipmi_address, '--ipmi_user=%s' % host.ipmi_user, '--ipmi_password=%s' % host.ipmi_password, '--terminal_port=%s' % host.terminal_port, '--pidfile=%s' % _console_pidfile(host.id), run_as_root=True) LOG.debug("physical_console: out=%s", out) LOG.debug("physical_console: err=%s", err) def reboot(self, instance, network_info): host = self._get_phy_host_by_instance_id(instance.id) if not host: raise exception.InstanceNotFound(instance_id=instance.id) ctx = nova_context.get_admin_context() pm = _get_ipmi(host.ipmi_address, host.ipmi_user, host.ipmi_password) state = pm.power_off() self._update_physical_state(ctx, host, instance, state) state = pm.power_on() self._update_physical_state(ctx, host, instance, state) def get_host_ip_addr(self): return None def rescue(self, context, instance, callback, network_info): pass def unrescue(self, instance, callback, network_info): pass def poll_rescued_instances(self, timeout): pass def destroy(self, instance, network_info, block_device_info=None): LOG.debug("destroy: instance=%s", instance.__dict__) ctx = nova_context.get_admin_context() host = self._get_phy_host_by_instance_id(instance.id) if not host: LOG.warning("Instance:id='%s' not found" % instance.id) return pm = _get_ipmi(host.ipmi_address, host.ipmi_user, host.ipmi_password) state = pm.power_off() self._update_physical_state(ctx, host, None, state) self._firewall_driver.unfilter_instance(instance, network_info=network_info) for (network, mapping) in network_info: self._vif_driver.unplug(instance, network, mapping) image_root = os.path.join(FLAGS.instances_path, str(instance['id'])) shutil.rmtree(image_root, ignore_errors=True) tftp_root = FLAGS.physical_tftp_root if FLAGS.physical_pxe_vlan_per_host: vlan_num = host.pxe_vlan_id pxe_interface = 'vlan%d' % vlan_num tftp_root = tftp_root + '/' + str(instance.id) dnsmasq_pid = _dnsmasq_pid(pxe_interface) if dnsmasq_pid: execute(FLAGS.physical_kill_dnsmasq_path, str(dnsmasq_pid), run_as_root=True) _unlink_without_raise(_dnsmasq_pid_path(pxe_interface)) _unlink_without_raise(_dnsmasq_lease_path(pxe_interface)) execute('ip', 'link', 'set', pxe_interface, 'down', run_as_root=True) execute('vconfig', 'rem', pxe_interface, run_as_root=True) shutil.rmtree(tftp_root, ignore_errors=True) from nova.network import linux_net chain = 'phy-%s' % pxe_interface iptables = linux_net.iptables_manager iptables.ipv4['filter'].remove_chain(chain) iptables.apply() else: pxe_config_path = os.path.join(tftp_root, "pxelinux.cfg", "01-" + host.pxe_mac_address.replace(":", "-").lower()) _unlink_without_raise(pxe_config_path) db.phy_pxe_ip_disassociate(ctx, host.id) console_pid = _console_pid(host.id) if console_pid: execute('kill', str(console_pid), run_as_root=True, check_exit_code=[0,1]) _unlink_without_raise(_console_pidfile(host.id)) def _create_iscsi_export_tgtadm(self, path, tid, iqn): LOG.debug("_create_iscsi_export_tgtadm: %s", locals()) utils.execute('tgtadm', '--lld', 'iscsi', '--mode', 'target', '--op', 'new', '--tid', tid, '--targetname', iqn, run_as_root=True) utils.execute('tgtadm', '--lld', 'iscsi', '--mode', 'logicalunit', '--op', 'new', '--tid', tid, '--lun', '1', '--backing-store', path, run_as_root=True) def _allow_iscsi_tgtadm(self, tid, address): LOG.debug("_allow_iscsi_tgtadm: %s", locals()) utils.execute('tgtadm', '--lld', 'iscsi', '--mode', 'target', '--op', 'bind', '--tid', tid, '--initiator-address', address, run_as_root=True) def _delete_iscsi_export_tgtadm(self, tid): LOG.debug("_delete_iscsi_export_tgtadm: %s", locals()) try: utils.execute('tgtadm', '--lld', 'iscsi', '--mode', 'logicalunit', '--op', 'delete', '--tid', tid, '--lun', '1', run_as_root=True) except: pass try: utils.execute('tgtadm', '--lld', 'iscsi', '--mode', 'target', '--op', 'delete', '--tid', tid, run_as_root=True) except: pass # check if tid is deleted # If tid is deleted (or has been deleted) tgtadm returns with status==22. execute('tgtadm', '--lld', 'iscsi', '--mode', 'target', '--op', 'show', '--tid', tid, check_exit_code=22, run_as_root=True) def _volume_id_from_device_path(self, device_path): import re m = re.search(r':volume-([0-9A-Fa-f]+)', device_path) if m: return int(m.group(1), 16) return None def attach_volume(self, instance_name, device_path, mountpoint): LOG.info("attach_volume: instance_name=%s device_path=%s mountpoint=%s", instance_name,device_path,mountpoint) i = self._get_phy_host_by_instance_name(instance_name) if not i: raise exception.InstanceNotFound(instance_id=instance_name) ctx = nova_context.get_admin_context() pxe_ip = db.phy_pxe_ip_get_by_phy_host_id(ctx, i.id) if not pxe_ip: if not FLAGS.physical_use_unsafe_iscsi: raise exception.Error("No fixed PXE IP is associated to phy_instance:%s" % instance_name) volume_id = self._volume_id_from_device_path(device_path) tid = volume_id mpstr = mountpoint.replace('/', '.').strip('.') iqn = 'iqn.2010-10.org.openstack:%s-%s' % (tid, mpstr) self._create_iscsi_export_tgtadm(device_path, tid, iqn) if pxe_ip: self._allow_iscsi_tgtadm(tid, pxe_ip.address) else: # unsafe self._allow_iscsi_tgtadm(tid, 'ALL') return True def _volume_id_from_instance_name_and_mountpoint(self, instance_name, mountpoint): ctx = nova_context.get_admin_context() phy_host = self._get_phy_host_by_instance_name(instance_name) if not phy_host: return None for vol in db.volume_get_all_by_instance(ctx, phy_host.instance.id): if vol.mountpoint == mountpoint: return vol.id return None @exception.wrap_exception() def detach_volume(self, instance_name, mountpoint): LOG.info("detach_volume: instance_name=%s mountpoint=%s", instance_name,mountpoint) tid = self._volume_id_from_instance_name_and_mountpoint(instance_name, mountpoint) if not tid: LOG.warn("cannot find volume for instance_name=%s and mountpoint=%s", instance_name, mountpoint) return self._delete_iscsi_export_tgtadm(tid) def get_info(self, instance): h = self._get_phy_host_by_instance_id(instance['id']) if not h: raise exception.InstanceNotFound(instance_id=instance['id']) pm = _get_ipmi(h.ipmi_address, h.ipmi_user, h.ipmi_password) ps = power_state.SHUTOFF if pm.is_power_on(): ps = power_state.RUNNING LOG.debug("power_state=%s", ps) return {'state': ps, 'max_mem': h['memory_mb'], 'mem': h['memory_mb'], 'num_cpu': h['cpus'], 'cpu_time': 0} def get_diagnostics(self, instance_name): i = self._get_phy_host_by_instance_name(instance_name) if not i: raise exception.InstanceNotFound(instance_id=instance_name) return {} def list_disks(self, instance_name): i = self._get_phy_host_by_instance_name(instance_name) if not i: raise exception.InstanceNotFound(instance_id=instance_name) return ['A_DISK'] def list_interfaces(self, instance_name): i = self._get_phy_host_by_instance_name(instance_name) if not i: raise exception.InstanceNotFound(instance_id=instance_name) return ['A_VIF'] def block_stats(self, instance_name, disk_id): i = self._get_phy_host_by_instance_name(instance_name) if not i: raise exception.InstanceNotFound(instance_id=instance_name) return [0L, 0L, 0L, 0L, None] def interface_stats(self, instance_name, iface_id): i = self._get_phy_host_by_instance_name(instance_name) if not i: raise exception.InstanceNotFound(instance_id=instance_name) return [0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L] def get_console_output(self, instance): return 'FAKE CONSOLE\xffOUTPUT' def get_ajax_console(self, instance): return {'token': 'FAKETOKEN', 'host': 'fakeajaxconsole.com', 'port': 6969} def get_vnc_console(self, instance): return {'token': 'FAKETOKEN', 'host': 'fakevncconsole.com', 'port': 6969} def get_console_pool_info(self, console_type): return {'address': '127.0.0.1', 'username': '******', 'password': '******'} def refresh_security_group_rules(self, security_group_id): self._firewall_driver.refresh_security_group_rules(security_group_id) return True def refresh_security_group_members(self, security_group_id): self._firewall_driver.refresh_security_group_members(security_group_id) return True def refresh_provider_fw_rules(self): self._firewall_driver.refresh_provider_fw_rules() pass def _sum_phy_hosts(self, ctxt): vcpus = 0 vcpus_used = 0 memory_mb = 0 memory_mb_used = 0 local_gb = 0 local_gb_used = 0 for i in self._get_phy_hosts(ctxt): if i.registration_status != 'done': continue vcpus += i.cpus memory_mb += i.memory_mb local_gb += i.local_gb dic = {'vcpus': vcpus, 'memory_mb': memory_mb, 'local_gb': local_gb, 'vcpus_used': vcpus_used, 'memory_mb_used': memory_mb_used, 'local_gb_used': local_gb_used, } return dic def _max_phy_resouces(self, ctxt): max_cpus = 0 max_memory_mb = 0 max_local_gb = 0 for i in self._get_phy_hosts(ctxt): if i.registration_status != 'done' or i.instance_id: continue #put prioirty to memory size. You can use CPU and HDD, if you change the following line. if max_memory_mb > i.memory_mb: max_memory_mb = i.momory_mb max_cpus = i.cpus max_local_gb = i.max_local_gb dic = {'vcpus': max_cpus, 'memory_mb': max_memory_mb, 'local_gb': max_local_gb, 'vcpus_used': 0, 'memory_mb_used': 0, 'local_gb_used': 0, } return dic def update_available_resource(self, ctxt, host): """Updates compute manager resource info on ComputeNode table. This method is called when nova-coompute launches, and whenever admin executes "nova-manage service update_resource". :param ctxt: security context :param host: hostname that compute manager is currently running """ dic = self._max_phy_resouces(ctxt) #dic = self._sum_phy_hosts(ctxt) dic['hypervisor_type'] = 'physical' dic['hypervisor_version'] = 1 dic['cpu_info'] = 'physical cpu' try: service_ref = db.service_get_all_compute_by_host(ctxt, host)[0] except exception.NotFound: raise exception.ComputeServiceUnavailable(host=host) dic['service_id'] = service_ref['id'] compute_node_ref = service_ref['compute_node'] if not compute_node_ref: LOG.info(_('Compute_service record created for %s ') % host) db.compute_node_create(ctxt, dic) else: LOG.info(_('Compute_service record updated for %s ') % host) db.compute_node_update(ctxt, compute_node_ref[0]['id'], dic) def ensure_filtering_rules_for_instance(self, instance_ref, network_info): self._firewall_driver.setup_basic_filtering(instance_ref, network_info) self._firewall_driver.update_instance_filter(instance_ref, network_info) def unfilter_instance(self, instance_ref, network_info): self._firewall_driver.unfilter_instance(instance_ref, network_info=network_info) def test_remove_vm(self, instance_name): """ Removes the named VM, as if it crashed. For testing""" LOG.info(_("test_remove_vm: instance_name=%s") % (instance_name)) raise exception.InstanceNotFound(instance_id=instance_name) def _get_host_stats(self): dic = self._max_phy_resouces(nova_context.get_admin_context()) memory_total = dic['memory_mb'] * 1024 * 1024 memory_free = (dic['memory_mb'] - dic['memory_mb_used']) * 1024 * 1024 disk_total = dic['local_gb'] * 1024 * 1024 * 1024 disk_used = dic['local_gb_used'] * 1024 * 1024 * 1024 return { 'host_name-description': 'baremetal ' + FLAGS.host, 'host_hostname': FLAGS.host, 'host_memory_total': memory_total, 'host_memory_overhead': 0, 'host_memory_free': memory_free, 'host_memory_free_computed': memory_free, 'host_other_config': {}, # 'host_ip_address': '192.168.1.109', # 'host_cpu_info': {}, 'disk_available': disk_total - disk_used, 'disk_total': disk_total, 'disk_used': disk_used, # 'host_uuid': 'cedb9b39-9388-41df-8891-c5c9a0c0fe5f', 'host_name_label': FLAGS.host, 'type': 'physical', } def update_host_status(self): LOG.info(_("update_host_status:")) return self._get_host_stats() def get_host_stats(self, refresh=False): LOG.info(_("get_host_stats: refresh=%s") % (refresh)) return self._get_host_stats() def host_power_action(self, host, action): """Reboots, shuts down or powers up the host.""" LOG.info(_("host_power_action: host=%s action=%s") % (host, action)) pass def set_host_enabled(self, host, enabled): """Sets the specified host's ability to accept new instances.""" LOG.info(_("set_host_enabled: host=%s enabled=%s") % (host, enabled)) pass def _fetch_image(self, context, target, image_id, user_id, project_id): """Grab image and optionally attempt to resize it""" images.fetch_to_raw(context, image_id, target, user_id, project_id) def _cache_image_x(self, context, target, image_id, user_id, project_id): """Grab image and optionally attempt to resize it""" if not os.path.exists(target): self._fetch_image(context, target, image_id, user_id, project_id) def plug_vifs(self, instance, network_info): """Plugin VIFs into networks.""" LOG.debug("plug_vifs: %s", locals()) for (network, mapping) in network_info: self._vif_driver.plug(instance, network, mapping) def _update_physical_state(self, context, host, instance, state): instance_id = None if instance: instance_id = instance.id db.phy_host_update(context, host.id, {'instance_id': instance_id, 'task_state' : state, }) def _inject_to_image(self, target, inst, network_info, nics_in_order): # For now, we assume that if we're not using a kernel, we're using a # partitioned disk image where the target partition is the first # partition target_partition = None if not inst['kernel_id']: target_partition = "1" # rename nics to be in order LOG.debug("injecting persisitent net") rules = "" i = 0 for hwaddr in nics_in_order: rules += 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="%s", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth%d"\n' % (hwaddr,i) i += 1 disk.inject_files(target, [ ('/etc/udev/rules.d/70-persistent-net.rules', rules) ], partition=target_partition, use_cow=False) bootif_name = "eth%d" % (i-1) if inst['key_data']: key = str(inst['key_data']) else: key = None net = "" nets = [] ifc_template = open(FLAGS.injected_network_template).read() ifc_num = -1 have_injected_networks = False for (network_ref, mapping) in network_info: ifc_num += 1 # always inject #if not network_ref['injected']: # continue have_injected_networks = True address = mapping['ips'][0]['ip'] netmask = mapping['ips'][0]['netmask'] address_v6 = None gateway_v6 = None netmask_v6 = None if FLAGS.use_ipv6: address_v6 = mapping['ip6s'][0]['ip'] netmask_v6 = mapping['ip6s'][0]['netmask'] gateway_v6 = mapping['gateway_v6'] net_info = {'name': 'eth%d' % ifc_num, 'address': address, 'netmask': netmask, 'gateway': mapping['gateway'], 'broadcast': mapping['broadcast'], 'dns': ' '.join(mapping['dns']), 'address_v6': address_v6, 'gateway_v6': gateway_v6, 'netmask_v6': netmask_v6, 'hwaddress': mapping['mac']} nets.append(net_info) if have_injected_networks: _late_load_cheetah() net = str(Template(ifc_template, searchList=[{'interfaces': nets, 'use_ipv6': FLAGS.use_ipv6}])) net += "\n" net += "auto %s\n" % bootif_name net += "iface %s inet dhcp\n" % bootif_name if FLAGS.physical_inject_password: admin_password = inst.get('admin_pass') else: admin_password = None metadata = inst.get('metadata') if any((key, net, metadata, admin_password)): inst_name = inst['name'] img_id = inst.image_ref for injection in ('metadata', 'key', 'net', 'admin_password'): if locals()[injection]: LOG.info(_('instance %(inst_name)s: injecting ' '%(injection)s into image %(img_id)s'), locals(), instance=inst) try: disk.inject_data(target, key, net, metadata, admin_password, partition=target_partition, use_cow=False) except Exception as e: # This could be a windows image, or a vmdk format disk LOG.warn(_('instance %(inst_name)s: ignoring error injecting' ' data into image %(img_id)s (%(e)s)') % locals(), instance=inst)