Просмотр исходного кода

Propagate Windows user script errors

`powershell.exe -File` doesn't propagate the exit code of the
specified script.

As an alternative, we'll use '& $script; exit $LASTEXITCODE',
moving the execution policy and non-interactive parameters to
the "exec_ps_command" method.
Lucian Petrut 4 недель назад
Родитель
Сommit
54d435c486

+ 1 - 5
coriolis/osmorphing/osmount/windows.py

@@ -254,11 +254,7 @@ class WindowsMountTools(base.BaseOSMountTools):
             raise exception.CoriolisException(
             raise exception.CoriolisException(
                 "Failed to copy user script to target system.") from err
                 "Failed to copy user script to target system.") from err
 
 
-        cmd = ('$ErrorActionPreference = "Stop"; powershell.exe '
-               '-NonInteractive -ExecutionPolicy RemoteSigned '
-               '-File "%(script)s"') % {
-            "script": script_path,
-        }
+        cmd = f'& "{script_path}"; exit $LASTEXITCODE'
         try:
         try:
             out = self._conn.exec_ps_command(cmd)
             out = self._conn.exec_ps_command(cmd)
             LOG.debug("User script output: %s" % out)
             LOG.debug("User script output: %s" % out)

+ 1 - 3
coriolis/osmorphing/windows.py

@@ -402,9 +402,7 @@ class BaseWindowsMorphingTools(base.BaseOSMorphingTools):
             raise exception.CoriolisException(
             raise exception.CoriolisException(
                 "Failed to copy user script to target system.") from err
                 "Failed to copy user script to target system.") from err
 
 
-        cmd = ('$ErrorActionPreference = "Stop"; powershell.exe '
-               '-NonInteractive -ExecutionPolicy RemoteSigned '
-               '-File "%(script)s" "%(os_root_dir)s"') % {
+        cmd = ('& "%(script)s" "%(os_root_dir)s"; exit $LASTEXITCODE') % {
             "script": script_path,
             "script": script_path,
             "os_root_dir": self._os_root_dir,
             "os_root_dir": self._os_root_dir,
         }
         }

+ 2 - 2
coriolis/tests/integration/base.py

@@ -301,11 +301,11 @@ class ReplicaIntegrationTestBase(CoriolisIntegrationTestBase):
         # Create transfer replica.
         # Create transfer replica.
         # Use basename as instance name; real VM names do not contain slashes,
         # Use basename as instance name; real VM names do not contain slashes,
         # and some providers use the name as is in resource indentifiers.
         # and some providers use the name as is in resource indentifiers.
-        instance_name = os.path.basename(self._src_device)
+        self._instance_name = os.path.basename(self._src_device)
         self._transfer = self._create_transfer(
         self._transfer = self._create_transfer(
             self._src_endpoint.id,
             self._src_endpoint.id,
             self._dst_endpoint.id,
             self._dst_endpoint.id,
-            instances=[instance_name],
+            instances=[self._instance_name],
             destination_minion_pool_id=self._pool_id,
             destination_minion_pool_id=self._pool_id,
             source_environment={"block_device_path": self._src_device},
             source_environment={"block_device_path": self._src_device},
             destination_environment={"devices": [self._dst_device]},
             destination_environment={"devices": [self._dst_device]},

+ 2 - 2
coriolis/tests/integration/deployments/test_osmorphing.py

@@ -71,10 +71,10 @@ class OsMorphingDeploymentTest(integration_base.ReplicaIntegrationTestBase):
 
 
     def test_os_morphing_instance_script_basic_format(self):
     def test_os_morphing_instance_script_basic_format(self):
         expected_string = str(uuid.uuid4())
         expected_string = str(uuid.uuid4())
-        instance = self._src_device
         user_scripts = {
         user_scripts = {
             'instances': {
             'instances': {
-                instance: f"echo -n {expected_string} > $1/cookie\n\r"
+                self._instance_name: (
+                    f"echo -n {expected_string} > $1/cookie\n\r")
             }
             }
         }
         }
         deployment_kwargs = {
         deployment_kwargs = {

+ 3 - 5
coriolis/tests/osmorphing/test_windows.py

@@ -338,11 +338,9 @@ class BaseWindowsMorphingToolsTestCase(test_base.CoriolisBaseTestCase):
         mock_write_winrm_file.assert_called_once_with(
         mock_write_winrm_file.assert_called_once_with(
             self.conn, script_path, user_script)
             self.conn, script_path, user_script)
         self.conn.exec_ps_command.assert_called_once_with(
         self.conn.exec_ps_command.assert_called_once_with(
-            ('$ErrorActionPreference = "Stop"; powershell.exe '
-             '-NonInteractive -ExecutionPolicy RemoteSigned '
-             '-File "%(script)s" "%(os_root_dir)s"') % {
-                 "script": script_path,
-                 "os_root_dir": self.os_root_dir,
+            ('& "%(script)s" "%(os_root_dir)s"; exit $LASTEXITCODE') % {
+                "script": script_path,
+                "os_root_dir": self.os_root_dir,
             }
             }
         )
         )
 
 

+ 7 - 1
coriolis/tests/test_wsman.py

@@ -148,7 +148,13 @@ class WSManConnectionTestCase(test_base.CoriolisBaseTestCase):
         self.conn.exec_command.return_value = "std_out\n\n"
         self.conn.exec_command.return_value = "std_out\n\n"
         result = self.conn.exec_ps_command(self.cmd)
         result = self.conn.exec_ps_command(self.cmd)
         self.conn.exec_command.assert_called_once_with(
         self.conn.exec_command.assert_called_once_with(
-            "powershell.exe", ["-EncodedCommand", 'dABlAHMAdABfAGMAbQBkAA=='],
+            "powershell.exe",
+            [
+                "-EncodedCommand",
+                'dABlAHMAdABfAGMAbQBkAA==',
+                '-NonInteractive',
+                '-ExecutionPolicy', 'RemoteSigned',
+            ],
             timeout=None)
             timeout=None)
         self.assertEqual(result, "std_out")
         self.assertEqual(result, "std_out")
 
 

+ 8 - 1
coriolis/wsman.py

@@ -149,7 +149,14 @@ class WSManConnection(object):
         LOG.debug("Executing PS command: %s", cmd)
         LOG.debug("Executing PS command: %s", cmd)
         base64_cmd = base64.b64encode(cmd.encode('utf-16le')).decode()
         base64_cmd = base64.b64encode(cmd.encode('utf-16le')).decode()
         return self.exec_command(
         return self.exec_command(
-            "powershell.exe", ["-EncodedCommand", base64_cmd],
+            "powershell.exe",
+            [
+                "-EncodedCommand",
+                base64_cmd,
+                "-NonInteractive",
+                "-ExecutionPolicy",
+                "RemoteSigned",
+            ],
             timeout=timeout)[:-2]
             timeout=timeout)[:-2]
 
 
     def test_path(self, remote_path):
     def test_path(self, remote_path):