Skip to content

Commit bbdf26e

Browse files
first-boot scripts: allow specifying a file name
1 parent e8c892b commit bbdf26e

5 files changed

Lines changed: 66 additions & 13 deletions

File tree

coriolis/osmorphing/base.py

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,13 @@
5858
run_scripts /usr/lib/coriolis/firstboot/user
5959
6060
if [ $first_error -eq 0 ]; then
61-
echo "All the scripts completed successfully, creating /var/lib/coriolis/firstboot-complete"
61+
echo "All the scripts completed successfully."
62+
echo "Creating /var/lib/coriolis/firstboot-complete"
6263
mkdir -p /var/lib/coriolis
6364
touch /var/lib/coriolis/firstboot-complete
6465
else
65-
echo "One of the scripts failed, won't create /var/lib/coriolis/firstboot-complete"
66+
echo "One of the scripts failed."
67+
echo "Won't create /var/lib/coriolis/firstboot-complete"
6668
fi
6769
6870
exit $first_error
@@ -168,8 +170,23 @@ def register_firstboot_script(
168170
self,
169171
script: str,
170172
index: int = 0,
171-
user_provided=True,
173+
user_provided: bool = True,
174+
script_filename: str | None = None,
172175
):
176+
"""Register a script to be executed during the first replica boot.
177+
178+
:param script: the script content
179+
:param index: script execution index (0-99), used as a script filename
180+
prefix. The scripts will be executed in alphabetic order,
181+
the Coriolis scripts first and then user provided scripts
182+
afterwards.
183+
:param user_provider: whether this is a Coriolis internal script
184+
(executed first) or user provided script.
185+
:param script_filename: optional script filename. The index parameter
186+
will be ignored when explicitly specifying
187+
the filename. Coriolis internal scripts should
188+
specify a filename to facilitate debugging.
189+
"""
173190
pass
174191

175192
@abc.abstractmethod
@@ -796,18 +813,24 @@ def register_firstboot_script(
796813
self,
797814
script: str,
798815
index: int = 0,
799-
user_provided=True,
816+
user_provided: bool = True,
817+
script_filename: str | None = None,
800818
):
801-
if len(script) == 0:
819+
820+
if not script:
802821
LOG.debug("Empty first-boot script, skipping...")
803822
return
804823

805824
if user_provided:
806825
script_dir = "/usr/lib/coriolis/firstboot/user"
807826
else:
808827
script_dir = "/usr/lib/coriolis/firstboot/service"
809-
unique_id = str(uuid.uuid4()).split("-")[0]
810-
script_path = os.path.join(script_dir, f"{index:02d}-{unique_id}.sh")
828+
829+
if not script_filename:
830+
unique_id = str(uuid.uuid4()).split("-")[0]
831+
script_filename = f"{index:02d}-{unique_id}.sh"
832+
833+
script_path = os.path.join(script_dir, script_filename)
811834

812835
self._exec_cmd_chroot(f"mkdir -p {script_dir}")
813836
self._write_file_sudo(script_path, script)

coriolis/osmorphing/windows.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -733,9 +733,10 @@ def register_firstboot_script(
733733
self,
734734
script: str,
735735
index: int = 0,
736-
user_provided=True,
736+
user_provided: bool = True,
737+
script_filename: str | None = None,
737738
):
738-
if len(script) == 0:
739+
if not script:
739740
LOG.debug("Empty first-boot script, skipping...")
740741
return
741742

@@ -752,9 +753,10 @@ def register_firstboot_script(
752753

753754
cbslinit_base_dir = self._get_cbslinit_base_dir()
754755
script_dir = self._get_cbslinit_scripts_dir(cbslinit_base_dir)
755-
unique_id = str(uuid.uuid4()).split("-")[0]
756-
script_path = os.path.join(
757-
script_dir, f"{index:02d}-{unique_id}.ps1")
756+
if not script_filename:
757+
unique_id = str(uuid.uuid4()).split("-")[0]
758+
script_filename = f"{index:02d}-{unique_id}.ps1"
759+
script_path = os.path.join(script_dir, script_filename)
758760

759761
self._conn.exec_ps_command(f"mkdir -Force {script_dir}")
760762
utils.write_winrm_file(

coriolis/tests/integration/deployments/test_osmorphing.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,9 @@ def test_os_morphing_global_script_first_boot(self):
184184
first_boot_script_path)
185185
if payload == first_boot_script:
186186
found = True
187+
if payload == "should-not-get-executed":
188+
raise AssertionError(
189+
"Linux instance contains Windows script.")
187190

188191
if not found:
189192
raise AssertionError(

coriolis/tests/osmorphing/test_manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def setUp(self):
3131
},
3232
{
3333
"phase": constants.PHASE_REPLICA_FIRST_BOOT,
34-
"payload": "fist-boot-script",
34+
"payload": "first-boot-script",
3535
},
3636
]
3737

coriolis/tests/osmorphing/test_windows.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -964,3 +964,28 @@ def test_register_firstboot_script(self, mock_uuid, mock_write_winrm_file):
964964
self.morphing_tools._conn,
965965
"C:\\Cloudbase-Init\\LocalScripts/61-37c27abd.ps1",
966966
mock_script)
967+
968+
@mock.patch.object(windows.utils, 'write_winrm_file')
969+
@mock.patch("uuid.uuid4")
970+
def test_register_firstboot_script_explicit_fname(
971+
self,
972+
mock_uuid,
973+
mock_write_winrm_file,
974+
):
975+
mock_uuid.return_value = "37c27abd-85ff-4cb8-8d31-4e7067e145ab"
976+
mock_script = "mock-script"
977+
script_filename = "test-filename.ps1"
978+
979+
self.morphing_tools.register_firstboot_script(
980+
mock_script,
981+
index=10,
982+
user_provided=True,
983+
script_filename=script_filename,
984+
)
985+
986+
self.morphing_tools._conn.exec_ps_command.assert_called_once_with(
987+
"mkdir -Force C:\\Cloudbase-Init\\LocalScripts")
988+
mock_write_winrm_file.assert_called_once_with(
989+
self.morphing_tools._conn,
990+
f"C:\\Cloudbase-Init\\LocalScripts/{script_filename}",
991+
mock_script)

0 commit comments

Comments
 (0)