Skip to content

Commit 469dc3c

Browse files
committed
Update packman
1 parent 2ac45fd commit 469dc3c

File tree

4 files changed

+94
-19
lines changed

4 files changed

+94
-19
lines changed

tools/packman/bootstrap/configure.bat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
:: See the License for the specific language governing permissions and
1313
:: limitations under the License.
1414

15-
set PM_PACKMAN_VERSION=7.15.1
15+
set PM_PACKMAN_VERSION=7.24.4
1616

1717
:: Specify where packman command is rooted
1818
set PM_INSTALL_PATH=%~dp0..

tools/packman/bootstrap/install_package.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
import os
2020
import stat
2121
import time
22-
from typing import Any, Callable
22+
import hashlib
23+
from typing import Any, Callable, Union
2324

2425

2526
RENAME_RETRY_COUNT = 100
@@ -130,7 +131,24 @@ def rename_folder_with_retry(staging_dir: StagingDirectory, folder_name):
130131
)
131132

132133

133-
def install_package(package_path, install_path):
134+
def generate_sha256_for_file(file_path: Union[str, os.PathLike]) -> str:
135+
"""Returns the SHA-256 hex digest for the file at `file_path`"""
136+
hash = hashlib.sha256()
137+
# Read the file in binary mode and update the hash object with data
138+
with open(file_path, "rb") as file:
139+
for chunk in iter(lambda: file.read(4096), b""):
140+
hash.update(chunk)
141+
return hash.hexdigest()
142+
143+
144+
def install_common_module(package_path, install_path):
145+
COMMON_SHA256 = "ef974608cf903f39dbd3f22b3e26c15a1dd21f6e71d05c1510dcf423128cd7a4"
146+
package_sha256 = generate_sha256_for_file(package_path)
147+
if package_sha256 != COMMON_SHA256:
148+
raise RuntimeError(
149+
f"Package at '{package_path}' must have a sha256 of '{COMMON_SHA256}' "
150+
f"but was found to have '{package_sha256}'"
151+
)
134152
staging_path, version = os.path.split(install_path)
135153
with StagingDirectory(staging_path) as staging_dir:
136154
output_folder = staging_dir.get_temp_folder_path()
@@ -151,4 +169,4 @@ def install_package(package_path, install_path):
151169
for exec_path in paths_list:
152170
if os.path.normcase(os.path.normpath(exec_path)) == target_path_np_nc:
153171
raise RuntimeError(f"packman will not install to executable path '{exec_path}'")
154-
install_package(sys.argv[1], target_path_np)
172+
install_common_module(sys.argv[1], target_path_np)

tools/packman/packman

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ else
2424
PM_CURL_SILENT="-s -S"
2525
PM_WGET_QUIET="--quiet"
2626
fi
27-
PM_PACKMAN_VERSION=7.15.1
27+
export PM_PACKMAN_VERSION=7.24.4
2828

2929
# This is necessary for newer macOS
3030
if [ `uname` == 'Darwin' ]; then
@@ -60,17 +60,49 @@ if [ ! -d "$PM_PACKAGES_ROOT" ]; then
6060
mkdir -p -m a+rwx "$PM_PACKAGES_ROOT"
6161
fi
6262

63+
execute_with_retry()
64+
{
65+
# Don't exit on error, we need to handle them
66+
set +e
67+
68+
local CMD="$1"
69+
local MAX_TRIES=4
70+
local DELAY=2
71+
local TRIES=0
72+
local exit_code
73+
74+
while [ $TRIES -lt $MAX_TRIES ]
75+
do
76+
((TRIES++))
77+
eval $CMD
78+
exit_code=$?
79+
if [ $exit_code -eq 0 ]; then
80+
return 0
81+
fi
82+
83+
if [ $TRIES -lt $MAX_TRIES ]; then
84+
echo "Attempt $TRIES failed. Retrying in $DELAY seconds ..."
85+
sleep $DELAY
86+
DELAY=$((DELAY * DELAY))
87+
echo "Retrying ..."
88+
fi
89+
done
90+
91+
echo "Command failed after $MAX_TRIES attempts: $CMD"
92+
return $exit_code
93+
}
94+
6395
fetch_file_from_s3()
6496
{
65-
SOURCE=$1
66-
SOURCE_URL=http://bootstrap.packman.nvidia.com/$SOURCE
67-
TARGET=$2
97+
local SOURCE=$1
98+
local SOURCE_URL=http://bootstrap.packman.nvidia.com/$SOURCE
99+
local TARGET=$2
68100
echo "Fetching $SOURCE from bootstrap.packman.nvidia.com ..."
101+
local CMD="curl -o $TARGET $SOURCE_URL $PM_CURL_SILENT"
69102
if command -v wget >/dev/null 2>&1; then
70-
wget $PM_WGET_QUIET -O$TARGET $SOURCE_URL
71-
else
72-
curl -o $TARGET $SOURCE_URL $PM_CURL_SILENT
103+
CMD="wget $PM_WGET_QUIET -O$TARGET $SOURCE_URL"
73104
fi
105+
execute_with_retry "$CMD"
74106
}
75107

76108
generate_temp_file_name()

tools/packman/packmanconf.py

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
1-
# Use this file to bootstrap packman into your Python environment (3.7.x). Simply
1+
# Copyright 2021-2024 NVIDIA CORPORATION
2+
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Use this file to bootstrap packman into your Python environment. Simply
216
# add the path by doing sys.insert to where packmanconf.py is located and then execute:
317
#
418
# >>> import packmanconf
@@ -32,11 +46,16 @@ def init():
3246
>>> import packmanapi
3347
>>> packmanapi.set_verbosity_level(packmanapi.VERBOSITY_HIGH)
3448
"""
35-
major = sys.version_info[0]
36-
minor = sys.version_info[1]
37-
if major != 3 or minor != 10:
49+
major = sys.version_info.major
50+
minor = sys.version_info.minor
51+
patch = sys.version_info.micro
52+
if major == 3 and (minor == 10 or (minor == 11 and patch <= 2)):
53+
# we are good
54+
pass
55+
else:
3856
raise RuntimeError(
39-
f"This version of packman requires Python 3.10.x, but {major}.{minor} was provided"
57+
f"This version of packman requires Python 3.10.0 up to 3.11.2, "
58+
f"but {major}.{minor}.{patch} was provided"
4059
)
4160
conf_dir = os.path.dirname(os.path.abspath(__file__))
4261
os.environ["PM_INSTALL_PATH"] = conf_dir
@@ -79,7 +98,13 @@ def get_module_dir(conf_dir, packages_root: str, version: str) -> str:
7998
tf = tempfile.NamedTemporaryFile(delete=False)
8099
target_name = tf.name
81100
tf.close()
82-
url = f"http://bootstrap.packman.nvidia.com/packman-common@{version}.zip"
101+
# Using http here and not https is by design. Unfortunately SSL keeps getting revised
102+
# which breaks old clients when servers are forced to upgrade to newer version of TLS
103+
# and refuse to downgrade when asked. Instead of relying on SSL for transport security
104+
# packman does SHA256 verification of the downloaded package in the `install_package`
105+
# method. We therefore inform SonarQube to stop complaining about the line below.
106+
# See issue #367 for more detail.
107+
url = f"http://bootstrap.packman.nvidia.com/packman-common@{version}.zip" # NOSONAR
83108
print(f"Downloading '{url}' ...")
84109
import urllib.request
85110

@@ -90,7 +115,7 @@ def get_module_dir(conf_dir, packages_root: str, version: str) -> str:
90115
script_path = os.path.join(conf_dir, "bootstrap", "install_package.py")
91116
ip = SourceFileLoader("install_package", script_path).load_module()
92117
print("Unpacking ...")
93-
ip.install_package(target_name, module_dir)
118+
ip.install_common_module(target_name, module_dir)
94119
os.unlink(tf.name)
95120
return module_dir
96121

@@ -101,7 +126,7 @@ def get_version(conf_dir: str):
101126
path += ".sh"
102127
with open(path, "rt", encoding="utf8") as launch_file:
103128
for line in launch_file.readlines():
104-
if line.startswith("PM_PACKMAN_VERSION"):
129+
if "PM_PACKMAN_VERSION" in line:
105130
_, value = line.split("=")
106131
return value.strip()
107132
raise RuntimeError(f"Unable to find 'PM_PACKMAN_VERSION' in '{path}'")

0 commit comments

Comments
 (0)