def _select_machine(self, context, instance): inst_type = instance_types.get_instance_type(instance['instance_type_id']) bmm_found = None reuse = False # create a non autocommit session session = get_session_dodai(False) session.begin() try: bmms = db.bmm_get_all_by_instance_type(context, inst_type["name"], session) if instance["availability_zone"] == "resource_pool": #Add a machine to resource pool. for bmm in bmms: if bmm["availability_zone"] != "resource_pool": continue if bmm["status"] != "inactive": continue bmm_found = bmm break else: for bmm in bmms: if bmm["availability_zone"] != "resource_pool": continue if bmm["status"] != "active": continue instance_ref = db.instance_get(context, bmm["instance_id"]) if instance_ref["image_ref"] != instance["image_ref"]: continue bmm_found = bmm reuse = True break if not bmm_found: for bmm in bmms: if bmm["status"] == "used" or bmm["status"] == "processing": continue bmm_found = bmm reuse = False break if bmm_found: db.bmm_update(context, bmm_found["id"], {"status": "processing"}, session) except Exception as ex: LOG.exception(ex) session.rollback() raise exception.BareMetalMachineUnavailable() session.commit() if bmm_found: return bmm_found, reuse raise exception.BareMetalMachineUnavailable()
def spawn(self, context, instance, network_info=None, block_device_info=None): """ Create a new instance/VM/domain on the virtualization platform. Once this successfully completes, the instance should be running (power_state.RUNNING). If this fails, any partial instance should be completely cleaned up, and the virtualization platform should be in the state that it was before this call began. :param context: security context :param instance: Instance object as returned by DB layer. This function should use the data there to guide the creation of the new instance. :param network_info: :py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info` :param block_device_info: """ LOG.debug("spawn") instance_zone, cluster_name, vlan_id, create_cluster = self._parse_zone(instance["availability_zone"]) # update instances table bmm, reuse = self._select_machine(context, instance) instance["display_name"] = bmm["name"] instance["availability_zone"] = instance_zone db.instance_update(context, instance["id"], {"display_name": bmm["name"], "availability_zone": instance_zone}) if vlan_id: db.bmm_update(context, bmm["id"], {"availability_zone": cluster_name, "vlan_id": vlan_id, "service_ip": None}) if instance_zone == "resource_pool": self._install_machine(context, instance, bmm, cluster_name, vlan_id) else: self._update_ofc(bmm, cluster_name) if bmm["instance_id"]: db.instance_destroy(context, bmm["instance_id"]) if reuse: db.bmm_update(context, bmm["id"], {"status": "used", "instance_id": instance["id"]}) else: self._install_machine(context, instance, bmm, cluster_name, vlan_id) if instance["key_data"]: self._inject_key(bmm["pxe_ip"], str(instance["key_data"]))
def destroy(self, context, instance, network_info, cleanup=True): """Destroy (shutdown and delete) the specified instance. If the instance is not found (for example if networking failed), this function should still succeed. It's probably a good idea to log a warning in that case. :param instance: Instance object as returned by DB layer. :param network_info: :py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info` :param cleanup: """ LOG.debug("destroy") bmm = db.bmm_get_by_instance_id(context, instance["id"]) db.bmm_update(context, bmm["id"], {"status": "processing"}) mac = self._get_pxe_mac(bmm) # update ofc self._update_ofc_for_destroy(context, bmm) db.bmm_update(context, bmm["id"], { "vlan_id": None, "availability_zone": "resource_pool" }) # begin to delete os self._cp_template( "delete.sh", self._get_cobbler_instance_path(instance, "delete.sh"), { "INSTANCE_ID": instance["id"], "COBBLER": FLAGS.cobbler, "MONITOR_PORT": FLAGS.dodai_monitor_port }) self._cp_template( "pxeboot_action", self._get_pxe_boot_file(mac), { "INSTANCE_ID": instance["id"], "COBBLER": FLAGS.cobbler, "PXE_MAC": bmm["pxe_mac"], "ACTION": "delete" }) self._reboot_or_power_on(bmm["ipmi_ip"]) # wait until starting to delete os while self._get_state(context, instance) != "deleted": greenthread.sleep(20) LOG.debug("Wait until data of instance %s was deleted." % instance["id"]) utils.execute("rm", "-rf", self._get_cobbler_instance_path(instance)) # update db db.bmm_update(context, bmm["id"], { "instance_id": None, "service_ip": None }) return db.bmm_get(context, bmm["id"])
def destroy(self, context, instance, network_info, cleanup=True): """Destroy (shutdown and delete) the specified instance. If the instance is not found (for example if networking failed), this function should still succeed. It's probably a good idea to log a warning in that case. :param instance: Instance object as returned by DB layer. :param network_info: :py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info` :param cleanup: """ LOG.debug("destroy") bmm = db.bmm_get_by_instance_id(context, instance["id"]) db.bmm_update(context, bmm["id"], {"status": "processing"}) mac = self._get_pxe_mac(bmm) # update ofc self._update_ofc_for_destroy(context, bmm) db.bmm_update(context, bmm["id"], {"vlan_id": None, "availability_zone": "resource_pool"}) # begin to delete os self._cp_template("delete.sh", self._get_cobbler_instance_path(instance, "delete.sh"), {"INSTANCE_ID": instance["id"], "COBBLER": FLAGS.cobbler, "MONITOR_PORT": FLAGS.dodai_monitor_port}) self._cp_template("pxeboot_action", self._get_pxe_boot_file(mac), {"INSTANCE_ID": instance["id"], "COBBLER": FLAGS.cobbler, "PXE_MAC": bmm["pxe_mac"], "ACTION": "delete"}) self._reboot_or_power_on(bmm["ipmi_ip"]) # wait until starting to delete os while self._get_state(context, instance) != "deleted": greenthread.sleep(20) LOG.debug("Wait until data of instance %s was deleted." % instance["id"]) utils.execute("rm", "-rf", self._get_cobbler_instance_path(instance)); # update db db.bmm_update(context, bmm["id"], {"instance_id": None, "service_ip": None}) return db.bmm_get(context, bmm["id"])
def _install_machine(self, context, instance, bmm, cluster_name, vlan_id, update_instance=False): db.bmm_update(context, bmm["id"], {"instance_id": instance["id"]}) mac = self._get_pxe_mac(bmm) # fetch image image_base_path = self._get_cobbler_image_path() if not os.path.exists(image_base_path): utils.execute('mkdir', '-p', image_base_path) image_path = self._get_cobbler_image_path(instance) if not os.path.exists(image_path): image_meta = images.fetch(context, instance["image_ref"], image_path, instance["user_id"], instance["project_id"]) else: image_meta = images.show(context, instance["image_ref"]) image_type = "server" image_name = image_meta["name"] or image_meta["properties"]["image_location"] if image_name.find("dodai-deploy") == -1: image_type = "node" # begin to install os pxe_ip = bmm["pxe_ip"] or "None" pxe_mac = bmm["pxe_mac"] or "None" storage_ip = bmm["storage_ip"] or "None" storage_mac = bmm["storage_mac"] or "None" service_mac1 = bmm["service_mac1"] or "None" service_mac2 = bmm["service_mac2"] or "None" instance_path = self._get_cobbler_instance_path(instance) if not os.path.exists(instance_path): utils.execute('mkdir', '-p', instance_path) self._cp_template("create.sh", self._get_cobbler_instance_path(instance, "create.sh"), {"INSTANCE_ID": instance["id"], "IMAGE_ID": instance["image_ref"], "COBBLER": FLAGS.cobbler, "HOST_NAME": bmm["name"], "STORAGE_IP": storage_ip, "STORAGE_MAC": storage_mac, "PXE_IP": pxe_ip, "PXE_MAC": pxe_mac, "SERVICE_MAC1": bmm["service_mac1"], "SERVICE_MAC2": bmm["service_mac2"], "IMAGE_TYPE": image_type, "MONITOR_PORT": FLAGS.dodai_monitor_port, "ROOT_SIZE": FLAGS.dodai_partition_root_gb, "SWAP_SIZE": FLAGS.dodai_partition_swap_gb, "EPHEMERAL_SIZE": FLAGS.dodai_partition_ephemeral_gb, "KDUMP_SIZE": FLAGS.dodai_partition_kdump_gb}) self._cp_template("pxeboot_action", self._get_pxe_boot_file(mac), {"INSTANCE_ID": instance["id"], "COBBLER": FLAGS.cobbler, "PXE_MAC": pxe_mac, "ACTION": "create"}) LOG.debug("Reboot or power on.") self._reboot_or_power_on(bmm["ipmi_ip"]) # wait until starting to install os while self._get_state(context, instance) != "install": greenthread.sleep(20) LOG.debug("Wait until begin to install instance %s." % instance["id"]) self._cp_template("pxeboot_start", self._get_pxe_boot_file(mac), {}) # wait until starting to reboot while self._get_state(context, instance) != "install_reboot": greenthread.sleep(20) LOG.debug("Wait until begin to reboot instance %s after os has been installed." % instance["id"]) power_manager = PowerManager(bmm["ipmi_ip"]) power_manager.soft_off() while power_manager.status() == "on": greenthread.sleep(20) LOG.debug("Wait unit the instance %s shuts down." % instance["id"]) power_manager.on() # wait until installation of os finished while self._get_state(context, instance) != "installed": greenthread.sleep(20) LOG.debug("Wait until instance %s installation finished." % instance["id"]) if cluster_name == "resource_pool": status = "active" else: status = "used" db.bmm_update(context, bmm["id"], {"status": status}) if update_instance: db.instance_update(context, instance["id"], {"vm_state": vm_states.ACTIVE})
def _select_machine(self, context, instance): inst_type = instance_types.get_instance_type( instance['instance_type_id']) bmm_found = None reuse = False # create a non autocommit session session = get_session_dodai(False) session.begin() try: bmms = db.bmm_get_all_by_instance_type(context, inst_type["name"], session) if instance[ "availability_zone"] == "resource_pool": #Add a machine to resource pool. for bmm in bmms: if bmm["availability_zone"] != "resource_pool": continue if bmm["status"] != "inactive": continue bmm_found = bmm break else: for bmm in bmms: if bmm["availability_zone"] != "resource_pool": continue if bmm["status"] != "active": continue instance_ref = db.instance_get(context, bmm["instance_id"]) if instance_ref["image_ref"] != instance["image_ref"]: continue bmm_found = bmm reuse = True break if not bmm_found: for bmm in bmms: if bmm["status"] == "used" or bmm[ "status"] == "processing": continue bmm_found = bmm reuse = False break if bmm_found: db.bmm_update(context, bmm_found["id"], {"status": "processing"}, session) except Exception as ex: LOG.exception(ex) session.rollback() raise exception.BareMetalMachineUnavailable() session.commit() if bmm_found: return bmm_found, reuse raise exception.BareMetalMachineUnavailable()
def _install_machine(self, context, instance, bmm, cluster_name, vlan_id, update_instance=False): db.bmm_update(context, bmm["id"], {"instance_id": instance["id"]}) mac = self._get_pxe_mac(bmm) # fetch image image_base_path = self._get_cobbler_image_path() if not os.path.exists(image_base_path): utils.execute('mkdir', '-p', image_base_path) image_path = self._get_cobbler_image_path(instance) if not os.path.exists(image_path): image_meta = images.fetch(context, instance["image_ref"], image_path, instance["user_id"], instance["project_id"]) else: image_meta = images.show(context, instance["image_ref"]) image_type = "server" image_name = image_meta["name"] or image_meta["properties"][ "image_location"] if image_name.find("dodai-deploy") == -1: image_type = "node" # begin to install os pxe_ip = bmm["pxe_ip"] or "None" pxe_mac = bmm["pxe_mac"] or "None" storage_ip = bmm["storage_ip"] or "None" storage_mac = bmm["storage_mac"] or "None" service_mac1 = bmm["service_mac1"] or "None" service_mac2 = bmm["service_mac2"] or "None" instance_path = self._get_cobbler_instance_path(instance) if not os.path.exists(instance_path): utils.execute('mkdir', '-p', instance_path) self._cp_template( "create.sh", self._get_cobbler_instance_path(instance, "create.sh"), { "INSTANCE_ID": instance["id"], "IMAGE_ID": instance["image_ref"], "COBBLER": FLAGS.cobbler, "HOST_NAME": bmm["name"], "STORAGE_IP": storage_ip, "STORAGE_MAC": storage_mac, "PXE_IP": pxe_ip, "PXE_MAC": pxe_mac, "SERVICE_MAC1": bmm["service_mac1"], "SERVICE_MAC2": bmm["service_mac2"], "IMAGE_TYPE": image_type, "MONITOR_PORT": FLAGS.dodai_monitor_port, "ROOT_SIZE": FLAGS.dodai_partition_root_gb, "SWAP_SIZE": FLAGS.dodai_partition_swap_gb, "EPHEMERAL_SIZE": FLAGS.dodai_partition_ephemeral_gb, "KDUMP_SIZE": FLAGS.dodai_partition_kdump_gb }) self._cp_template( "pxeboot_action", self._get_pxe_boot_file(mac), { "INSTANCE_ID": instance["id"], "COBBLER": FLAGS.cobbler, "PXE_MAC": pxe_mac, "ACTION": "create" }) LOG.debug("Reboot or power on.") self._reboot_or_power_on(bmm["ipmi_ip"]) # wait until starting to install os while self._get_state(context, instance) != "install": greenthread.sleep(20) LOG.debug("Wait until begin to install instance %s." % instance["id"]) self._cp_template("pxeboot_start", self._get_pxe_boot_file(mac), {}) # wait until starting to reboot while self._get_state(context, instance) != "install_reboot": greenthread.sleep(20) LOG.debug( "Wait until begin to reboot instance %s after os has been installed." % instance["id"]) power_manager = PowerManager(bmm["ipmi_ip"]) power_manager.soft_off() while power_manager.status() == "on": greenthread.sleep(20) LOG.debug("Wait unit the instance %s shuts down." % instance["id"]) power_manager.on() # wait until installation of os finished while self._get_state(context, instance) != "installed": greenthread.sleep(20) LOG.debug("Wait until instance %s installation finished." % instance["id"]) if cluster_name == "resource_pool": status = "active" else: status = "used" db.bmm_update(context, bmm["id"], {"status": status}) if update_instance: db.instance_update(context, instance["id"], {"vm_state": vm_states.ACTIVE})
def spawn(self, context, instance, network_info=None, block_device_info=None): """ Create a new instance/VM/domain on the virtualization platform. Once this successfully completes, the instance should be running (power_state.RUNNING). If this fails, any partial instance should be completely cleaned up, and the virtualization platform should be in the state that it was before this call began. :param context: security context :param instance: Instance object as returned by DB layer. This function should use the data there to guide the creation of the new instance. :param network_info: :py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info` :param block_device_info: """ LOG.debug("spawn") instance_zone, cluster_name, vlan_id, create_cluster = self._parse_zone( instance["availability_zone"]) # update instances table bmm, reuse = self._select_machine(context, instance) instance["display_name"] = bmm["name"] instance["availability_zone"] = instance_zone db.instance_update(context, instance["id"], { "display_name": bmm["name"], "availability_zone": instance_zone }) if vlan_id: db.bmm_update( context, bmm["id"], { "availability_zone": cluster_name, "vlan_id": vlan_id, "service_ip": None }) if instance_zone == "resource_pool": self._install_machine(context, instance, bmm, cluster_name, vlan_id) else: self._update_ofc(bmm, cluster_name) if bmm["instance_id"]: db.instance_destroy(context, bmm["instance_id"]) if reuse: db.bmm_update(context, bmm["id"], { "status": "used", "instance_id": instance["id"] }) else: self._install_machine(context, instance, bmm, cluster_name, vlan_id) if instance["key_data"]: self._inject_key(bmm["pxe_ip"], str(instance["key_data"]))