Update enroll-init logic to allow retry
This update enables enroll-init to re-run even after a prior success, providing support for oam/passowrd reconfiguration following failures in later enrollment stages. Changes include: - Cloud-init cleanup is now deferred until the end of enrollment, enabling flexibility in the enroll-init step. - A new RVMC mode, 'eject_image_only', has been added to strictly eject an inserted image. This is invoked as part of the enroll-init playbook to eject the seed ISO, preventing cloud-config from being reapplied during reboots. This is necessary since cloud-init remains enabled until the enrollment concludes. Additionally, these changes have been made: - Replace incorrect admin_password with 'sysadmin_password' from the payload to reconfigure the sysadmin password. - Utilize the enroll-init playbook, separated from the install playbook (see dependent changes). Background: Cloud-init services were originally cleaned up immediately after a successful enroll-init (OAM and password reconfiguration) to: - Align with default cloud-init behavior: configuration applied once per instance. - Prevent unintended conflicts during the enrollment process with 'run-always' modules, such as an inserted seed ISO retriggering reconfiguration during later reboots. However, this caused a limitation where, if enrollment failed after a successful enroll-init, retries would skip enroll-init, necessitating manual intervention for oam/password if needed. Test Plan: 1. PASS: Verify enrollment without the admin field in the bootstrap values. Ensure semantic checks, and confirm 'sysadmin_password' is used for password reconfiguration. 2. PASS: Mount and validate the contents of the generated seed ISO. The cloud-config should no longer specify a cleanup script. 3. PASS: Run a remote install: Validate RVMC script output. The script should execute as before, the new code path should not be reached. 4. PASS: Validate enroll-init retries: - Induce failure in the enroll-init step. - Simulate a later stage enrollment failure after a successful enroll-init. Ensure OAM and password can be reconfigured during retries in all scenarios. 5. PASS: Verify that cloud-init remains enabled until the end of enrollment. Story: 2011100 Task: 51363 Depends-On: https://review.opendev.org/c/starlingx/ansible-playbooks/+/935519 Change-Id: I65bf2a28638c75930ba3f71f33267e42fb449b6c Signed-off-by: Salman Rana <salman.rana@windriver.com>
This commit is contained in:
parent
bdb6275ee2
commit
ba5f718276
@ -266,7 +266,7 @@ MANDATORY_ENROLL_INIT_VALUES = [
|
||||
"external_oam_subnet",
|
||||
"external_oam_gateway_address",
|
||||
"external_oam_floating_address",
|
||||
"admin_password",
|
||||
"sysadmin_password",
|
||||
"system_mode",
|
||||
"software_version",
|
||||
] + BMC_INSTALL_VALUES
|
||||
@ -309,6 +309,10 @@ ANSIBLE_SUBCLOUD_INSTALL_PLAYBOOK = (
|
||||
|
||||
ENROLL_INIT_SEED_ISO_NAME = "seed.iso"
|
||||
|
||||
ANSIBLE_SUBCLOUD_ENROLL_INIT_PLAYBOOK = (
|
||||
"/usr/share/ansible/stx-ansible/playbooks/enroll_init.yml"
|
||||
)
|
||||
|
||||
ANSIBLE_SUBCLOUD_ENROLL_PLAYBOOK = (
|
||||
"/usr/share/ansible/stx-ansible/playbooks/enroll_subcloud.yml"
|
||||
)
|
||||
|
@ -1747,6 +1747,24 @@ class VmcObject(object):
|
||||
self.redfish_obj.logout()
|
||||
self.logging_util.dlog1("Session : Closed")
|
||||
|
||||
def eject_image_only(self):
|
||||
"""Eject image only without any other iso related operations."""
|
||||
|
||||
self._redfish_client_connect()
|
||||
self._redfish_root_query()
|
||||
self._redfish_create_session()
|
||||
self._redfish_get_managers()
|
||||
self._redfish_get_systems_members()
|
||||
self._redfish_get_vm_url()
|
||||
self._redfish_load_vm_actions()
|
||||
self._redfish_eject_image()
|
||||
|
||||
self.logging_util.ilog("Done")
|
||||
|
||||
if self.redfish_obj is not None and self.session is True:
|
||||
self.redfish_obj.logout()
|
||||
self.logging_util.dlog1("Session : Closed")
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Methods to be called from rvmc module
|
||||
|
@ -153,12 +153,11 @@ class SubcloudEnrollmentInit(object):
|
||||
raise exceptions.EnrollInitExecutionFailed(reason=msg)
|
||||
|
||||
hashed_password = crypt.crypt(
|
||||
iso_values["admin_password"], crypt.mksalt(crypt.METHOD_SHA512)
|
||||
iso_values["sysadmin_password"], crypt.mksalt(crypt.METHOD_SHA512)
|
||||
)
|
||||
|
||||
enroll_utils = "/usr/local/bin/"
|
||||
reconfig_script = os.path.join(enroll_utils, "enroll-init-reconfigure")
|
||||
cleanup_script = os.path.join(enroll_utils, "enroll-init-cleanup")
|
||||
extern_oam_gw_ip = iso_values["external_oam_gateway_address"].split(",")[0]
|
||||
|
||||
reconfig_command = (
|
||||
@ -177,10 +176,7 @@ class SubcloudEnrollmentInit(object):
|
||||
f"{iso_values['external_oam_node_1_address'].split(',')[0]}"
|
||||
)
|
||||
|
||||
runcmd = [
|
||||
reconfig_command,
|
||||
cleanup_script,
|
||||
]
|
||||
runcmd = [reconfig_command]
|
||||
|
||||
user_data_file = os.path.join(path, "user-data")
|
||||
with open(user_data_file, "w") as f_out_user_data_file:
|
||||
|
@ -351,7 +351,7 @@ class SubcloudManager(manager.Manager):
|
||||
if state == "init":
|
||||
enroll_command = [
|
||||
"ansible-playbook",
|
||||
dccommon_consts.ANSIBLE_SUBCLOUD_INSTALL_PLAYBOOK,
|
||||
dccommon_consts.ANSIBLE_SUBCLOUD_ENROLL_INIT_PLAYBOOK,
|
||||
"-i",
|
||||
ansible_subcloud_inventory_file,
|
||||
"--limit",
|
||||
|
@ -4924,7 +4924,7 @@ class TestSubcloudEnrollment(BaseTestSubcloudManager):
|
||||
|
||||
self.iso_values = {
|
||||
"software_version": self.rel_version,
|
||||
"admin_password": "St8rlingX*",
|
||||
"sysadmin_password": "St8rlingX*",
|
||||
"bootstrap_interface": "enp2s1",
|
||||
"external_oam_floating_address": "10.10.10.2",
|
||||
"network_mask": "255.255.255.0",
|
||||
@ -4986,7 +4986,7 @@ class TestSubcloudEnrollment(BaseTestSubcloudManager):
|
||||
|
||||
# Test with incomplete iso_values, expect KeyError
|
||||
copied_dict = self.iso_values.copy()
|
||||
copied_dict.pop("admin_password")
|
||||
copied_dict.pop("sysadmin_password")
|
||||
|
||||
self.assertRaises(
|
||||
KeyError,
|
||||
|
@ -170,6 +170,12 @@ def parse_arguments():
|
||||
"--config_file", type=str, required=True, help="RVMC config file"
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--eject_image_only",
|
||||
action="store_true",
|
||||
help="Optional execution mode to strictly eject an inserted image",
|
||||
)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
@ -305,13 +311,22 @@ if __name__ == "__main__":
|
||||
logging_util.ilog("BMC IP Addr : %s" % target_object.ip)
|
||||
logging_util.ilog("Host Image : %s" % target_object.img)
|
||||
|
||||
excluded_operations = []
|
||||
if os.path.basename(target_object.img) == consts.ENROLL_INIT_SEED_ISO_NAME:
|
||||
# If the host image is a seed ISO,
|
||||
# the boot order should not be changed.
|
||||
excluded_operations = ["set_boot_override"]
|
||||
if args.eject_image_only:
|
||||
target_object.eject_image_only()
|
||||
else:
|
||||
excluded_operations = []
|
||||
# TODO(srana): Decouple this from ENROLL_INIT_SEED_ISO_NAME.
|
||||
# We should generalize the approach and pass the excluded operations
|
||||
# to the script for enrollment.
|
||||
if (
|
||||
os.path.basename(target_object.img)
|
||||
== consts.ENROLL_INIT_SEED_ISO_NAME
|
||||
):
|
||||
# If the host image is a seed ISO,
|
||||
# the boot order should not be changed.
|
||||
excluded_operations = ["set_boot_override"]
|
||||
|
||||
target_object.execute(excluded_operations)
|
||||
target_object.execute(excluded_operations)
|
||||
except eventlet.timeout.Timeout as e:
|
||||
if e is not script_timeout:
|
||||
raise
|
||||
|
Loading…
Reference in New Issue
Block a user