(self, upgrade=False, downgrade=False)
| 718 | return True |
| 719 | |
| 720 | def _install_pkgs(self, upgrade=False, downgrade=False): |
| 721 | if downgrade: |
| 722 | self.install_previous(downgrade=downgrade) |
| 723 | return True |
| 724 | pkg = None |
| 725 | if platform.is_windows() and self.file_ext: |
| 726 | for p in self.pkgs: |
| 727 | if p.endswith(self.file_ext): |
| 728 | pkg = str(pathlib.Path(p).resolve()) |
| 729 | break |
| 730 | if pkg is None: |
| 731 | pkg = str(pathlib.Path(self.pkgs[0]).resolve()) |
| 732 | if platform.is_windows(): |
| 733 | if upgrade: |
| 734 | self.root = self.install_dir.parent |
| 735 | self.bin_dir = self.install_dir |
| 736 | self.ssm_bin = self.install_dir / "ssm.exe" |
| 737 | self._ensure_windows_services_stopped() |
| 738 | time.sleep(3) |
| 739 | if pkg.endswith("exe"): |
| 740 | log.info("Installing: %s", str(pkg)) |
| 741 | ret = self.proc.run( |
| 742 | str(pkg), |
| 743 | "/start-minion=0", |
| 744 | "/S", |
| 745 | _timeout=self.installer_timeout, |
| 746 | ) |
| 747 | self._check_retcode(ret) |
| 748 | elif pkg.endswith("msi"): |
| 749 | log.info("Installing: %s", str(pkg)) |
| 750 | # self.proc.run always makes the command a list even when shell |
| 751 | # is true, meaning shell being true will never work correctly. |
| 752 | msi_cmd = f'msiexec.exe /qn /i "{pkg}" /norestart START_MINION=""' |
| 753 | ret = subprocess.run( |
| 754 | msi_cmd, |
| 755 | shell=True, # nosec |
| 756 | check=False, |
| 757 | ) |
| 758 | log.info("MSI returncode: %s", ret.returncode) |
| 759 | assert ret.returncode in [0, 3010] |
| 760 | |
| 761 | if upgrade: |
| 762 | # MSI major upgrades with mismatched component GUIDs can |
| 763 | # remove files that should be kept. Running a repair |
| 764 | # ensures all files from the new product are on disk. |
| 765 | repair_cmd = f'msiexec.exe /qn /fa "{pkg}" /norestart' |
| 766 | repair_ret = subprocess.run( |
| 767 | repair_cmd, |
| 768 | shell=True, # nosec |
| 769 | check=False, |
| 770 | ) |
| 771 | log.info("MSI repair returncode: %s", repair_ret.returncode) |
| 772 | else: |
| 773 | log.error("Invalid package: %s", pkg) |
| 774 | return False |
| 775 | |
| 776 | log.debug("Removing installed salt-minion service") |
| 777 | self.proc.run(str(self.ssm_bin), "stop", "salt-minion", "confirm") |
no test coverage detected