diff --git a/sysinv/sysinv/sysinv/sysinv/common/utils.py b/sysinv/sysinv/sysinv/sysinv/common/utils.py index 996816de3b..ff3f739862 100644 --- a/sysinv/sysinv/sysinv/sysinv/common/utils.py +++ b/sysinv/sysinv/sysinv/sysinv/common/utils.py @@ -3794,3 +3794,51 @@ def extract_rpm_package(rpm_package, target_dir): raise exception.SysinvException( "Error extracting rpm %s: %s" % (rpm_package, error), ) + + +def get_ostree_commit(ostree_repo): + repo_arg = "--repo=%s" % ostree_repo + + try: + refs = subprocess.run( + ["ostree", repo_arg, "refs"], + capture_output=True, + check=True, + text=True, + ) + + commit = subprocess.run( + ["ostree", repo_arg, "log", refs.stdout], + capture_output=True, + check=True, + text=True, + ) + except Exception as error: + raise exception.SysinvException( + "Error getting ostree commit: %s" % (error), + ) + + result = commit.stdout.split() + + if result[0] != "commit": + return None + + return result[1] + + +def checkout_ostree(ostree_repo, commit, target_dir, subpath): + repo_arg = "--repo=%s" % ostree_repo + path_arg = None + + if subpath: + path_arg = "--subpath=%s" % subpath + + try: + subprocess.run( + ["ostree", repo_arg, path_arg, "--union", "checkout", commit, target_dir], + check=True, + ) + except Exception as error: + raise exception.SysinvException( + "Error checkout ostree commit: %s" % (error), + ) diff --git a/sysinv/sysinv/sysinv/sysinv/loads/extract_files.py b/sysinv/sysinv/sysinv/sysinv/loads/extract_files.py index f7443c789d..25cd4098b7 100644 --- a/sysinv/sysinv/sysinv/sysinv/loads/extract_files.py +++ b/sysinv/sysinv/sysinv/sysinv/loads/extract_files.py @@ -24,6 +24,8 @@ class ExtractFiles(base.BaseLoadImport): if os_version == constants.OS_CENTOS: self._extract_centos_playbooks(load_version, target_dir) + elif os_version == constants.OS_DEBIAN: + self._extract_debian_playbooks(load_version, target_dir) def _extract_centos_playbooks(self, load_version, target_dir): package_name = "playbookconfig" @@ -48,3 +50,14 @@ class ExtractFiles(base.BaseLoadImport): for file_name in file_names: file_path = os.path.join(source_dir, file_name) shutil.move(file_path, target_dir) + + def _extract_debian_playbooks(self, load_version, target_dir): + ostree_repo = "/var/www/pages/feed/rel-%s/ostree_repo/" % load_version + repo_commit = utils.get_ostree_commit(ostree_repo) + + if not repo_commit: + raise exception.SysinvException( + "Commit ostree not found for repo: %s" % ostree_repo + ) + + utils.checkout_ostree(ostree_repo, repo_commit, target_dir, subpath=PLAYBOOKS_PATH) diff --git a/sysinv/sysinv/sysinv/sysinv/tests/common/test_utils.py b/sysinv/sysinv/sysinv/sysinv/tests/common/test_utils.py index d540a0ead9..d8001e2b97 100644 --- a/sysinv/sysinv/sysinv/sysinv/tests/common/test_utils.py +++ b/sysinv/sysinv/sysinv/sysinv/tests/common/test_utils.py @@ -335,3 +335,81 @@ class TestCommonUtils(base.TestCase): ) self.assertTrue(mock_subprocess.method_calls) + + @mock.patch("sysinv.common.utils.subprocess") + def test_get_ostree_commit(self, mock_subprocess): + commit = "c1bb601e1dc78b4a1ad7b687badd16edeb5ca59e28413902d1b3" + + refs_return = subprocess.CompletedProcess( + args="", + returncode=0, + stdout="starlingx", + stderr=None, + ) + + commit_return = subprocess.CompletedProcess( + args="", + returncode=0, + stdout=""" + commit c1bb601e1dc78b4a1ad7b687badd16edeb5ca59e28413902d1b3 + ContentChecksum: 4aacd1c71b056f8e28a8be27c508f21f62afba955 + Date: 2022-12-18 18:55:09 +0000 + + Commit-id: starlingx-intel-x86-64-20221218185325 + """, + stderr=None, + ) + + mock_subprocess.run.side_effect = [ + refs_return, + commit_return, + ] + + result = utils.get_ostree_commit("/tmp/ostree_repo") + + self.assertTrue(mock_subprocess.method_calls) + + self.assertEqual(result, commit) + + @mock.patch("sysinv.common.utils.subprocess") + def test_get_ostree_commit_without_commit(self, mock_subprocess): + refs_return = subprocess.CompletedProcess( + args="", + returncode=0, + stdout="starlingx", + stderr=None, + ) + + commit_return = subprocess.CompletedProcess( + args="", + returncode=0, + stdout="No metadata header found", + stderr=None, + ) + + mock_subprocess.run.side_effect = [ + refs_return, + commit_return, + ] + + result = utils.get_ostree_commit("/tmp/ostree_repo") + + self.assertTrue(mock_subprocess.method_calls) + + self.assertIsNone(result) + + @mock.patch("sysinv.common.utils.subprocess") + def test_get_ostree_commit_exception(self, mock_subprocess): + mock_subprocess.CalledProcessError = \ + subprocess.CalledProcessError + + mock_subprocess.run.side_effect = \ + subprocess.CalledProcessError(1, "Generic error") + + self.assertRaises( + exception.SysinvException, + utils.get_ostree_commit, + "/tmp/ostree_repo", + ) + + self.assertTrue(mock_subprocess.method_calls) diff --git a/sysinv/sysinv/sysinv/sysinv/tests/loads/test_extract_files.py b/sysinv/sysinv/sysinv/sysinv/tests/loads/test_extract_files.py index 078100fb8c..d4d948af8b 100644 --- a/sysinv/sysinv/sysinv/sysinv/tests/loads/test_extract_files.py +++ b/sysinv/sysinv/sysinv/sysinv/tests/loads/test_extract_files.py @@ -17,6 +17,11 @@ class TestExtractFiles(base.TestCase): self.mock_subprocess.return_value = mock.MagicMock() self.addCleanup(subprocess_patch.stop) + os_patch = \ + mock.patch("sysinv.loads.extract_files.os", mock.MagicMock()) + self.mock_os = os_patch.start() + self.addCleanup(os_patch.stop) + self.plugin = ExtractFiles() @@ -31,11 +36,6 @@ class TestExtractFilesCentos(TestExtractFiles): self.mock_utils_patch.listdir.return_value = ["playbookconfig"] self.addCleanup(utils_patch.stop) - os_patch = \ - mock.patch("sysinv.loads.extract_files.os", mock.MagicMock()) - self.mock_os = os_patch.start() - self.addCleanup(os_patch.stop) - shutil_patch = \ mock.patch("sysinv.loads.extract_files.shutil", mock.MagicMock()) self.mock_shutil = shutil_patch.start() @@ -77,3 +77,129 @@ class TestExtractFilesCentos(TestExtractFiles): self.assertTrue(self.mock_os.method_calls) self.assertTrue(self.mock_subprocess.method_calls) self.assertFalse(self.mock_shutil.method_calls) + + +@mock.patch.object(utils, "get_os_target", lambda x: constants.OS_DEBIAN) +class TestExtractFilesDebian(TestExtractFiles): + def test_extract_files_debian(self): + refs = subprocess.CompletedProcess( + args="", + returncode=0, + stdout="starlingx", + stderr=None, + ) + + commit = subprocess.CompletedProcess( + args="", + returncode=0, + stdout=""" + commit c1bb601e1dc78b4a1ad7b687badd16edeb5ca59e28413902d1b3 + ContentChecksum: 4aacd1c71b056f8e28a8be27c508f21f62afba955 + Date: 2022-12-18 18:55:09 +0000 + + Commit-id: starlingx-intel-x86-64-20221218185325 + """, + stderr=None, + ) + + result = subprocess.CompletedProcess( + args="", + returncode=0, + stdout=None, + stderr=None, + ) + + self.mock_subprocess.run.side_effect = [ + refs, + commit, + result, + ] + + self.plugin.extract_files("1.0") + + self.assertTrue(self.mock_os.method_calls) + self.assertTrue(self.mock_subprocess.method_calls) + + def test_extract_files_debian_without_commit(self): + refs = subprocess.CompletedProcess( + args="", + returncode=0, + stdout="", + stderr=None, + ) + + commit = subprocess.CompletedProcess( + args="", + returncode=1, + stdout="Usage: ostree log [OPTION...] REF", + stderr=None, + ) + + self.mock_subprocess.run.side_effect = [ + refs, + commit, + ] + + self.assertRaises( + exception.SysinvException, + self.plugin.extract_files, + "1.0", + ) + + self.assertTrue(self.mock_os.method_calls) + self.assertTrue(self.mock_subprocess.method_calls) + + def test_extract_files_debian_get_commit_error(self): + self.mock_subprocess.CalledProcessError = \ + subprocess.CalledProcessError + + self.mock_subprocess.run.side_effect = \ + subprocess.CalledProcessError(1, "Generic error") + + self.assertRaises( + exception.SysinvException, + self.plugin.extract_files, + "1.0", + ) + + self.assertTrue(self.mock_os.method_calls) + self.assertTrue(self.mock_subprocess.method_calls) + + def test_extract_files_debian_checkout_commit_error(self): + refs = subprocess.CompletedProcess( + args="", + returncode=0, + stdout="starlingx", + stderr=None, + ) + + commit = subprocess.CompletedProcess( + args="", + returncode=0, + stdout=""" + commit c1bb601e1dc78b4a1ad7b687badd16edeb5ca59e28413902d1b3 + ContentChecksum: 4aacd1c71b056f8e28a8be27c508f21f62afba955 + Date: 2022-12-18 18:55:09 +0000 + + Commit-id: starlingx-intel-x86-64-20221218185325 + """, + stderr=None, + ) + + self.mock_subprocess.run.side_effect = [ + refs, + commit, + subprocess.CalledProcessError(1, "error: Invalid refspec"), + ] + + self.mock_subprocess.CalledProcessError = \ + subprocess.CalledProcessError + + self.assertRaises( + exception.SysinvException, + self.plugin.extract_files, + "1.0", + ) + + self.assertTrue(self.mock_os.method_calls) + self.assertTrue(self.mock_subprocess.method_calls)