2022-12-16 05:31:40 -06:00
#!/usr/bin/env python3
import os
import re
import sys
import stat
import argparse
import tempfile
import subprocess as sp
from urllib import request
from urllib.error import HTTPError
2024-10-15 11:20:40 -04:00
rocprofsys_version = "@ROCPROFSYS_VERSION@"
2024-12-10 14:35:02 -05:00
rocprofsys_git_tag = "@ROCPROFSYS_GIT_TAG@"
2022-12-16 05:31:40 -06:00
_rocm_path = os . environ . get ( "ROCM_PATH" , "/opt/rocm" )
_rocm_version = None
def get_rocm_version ( rocm_hint ):
global _rocm_path
global _rocm_version
if rocm_hint is not None and rocm_hint is not True :
if rocm_hint . replace ( "." , "0" ) . isnumeric ():
_rocm_version = rocm_hint
else :
_rocm_path = rocm_hint
def _parse_version ( _v ):
return re . split ( r "[ \\ .-]" , _v ) if _v is not None else None
_version = _parse_version ( _rocm_version )
for fname in [
"version" ,
"version-dev" ,
"version-hip-libraries" ,
"version-hiprt" ,
"version-hiprt-devel" ,
"version-hip-sdk" ,
"version-libs" ,
"version-utils" ,
]:
if _version is not None and len ( _version ) > 0 :
break
_fname = os . path . join ( _rocm_path , ".info" , fname )
if os . path . exists ( _fname ):
with open ( _fname , "r" ) as f :
_version = _parse_version ( f . readlines ()[ 0 ] . strip ( " \n " ))
if _version is not None and len ( _version ) > 0 :
_major = int ( _version [ 0 ])
_minor = int ( _version [ 1 ]) if len ( _version ) >= 2 else 0
_rocm_version = f " { _major } . { _minor } "
return "-ROCm- {} " . format (( 10000 * _major ) + ( 100 * _minor ))
return None
def get_os_info ( os_distrib , os_version ):
_os_info = {}
with open ( "/etc/os-release" , "r" ) as f :
for line in [ _v . strip () for _v in f . readlines ()]:
2023-03-16 14:50:32 -05:00
if "=" not in line :
continue
2022-12-16 05:31:40 -06:00
_key , _data = line . split ( "=" , 1 )
_os_info [ _key ] = _data . strip ( '"' )
2023-04-13 02:14:35 -05:00
def _parse_version ( _v ):
_version = re . split ( r "[ \\ .-]" , _v )
return (
" {} . {} " . format ( _version [ 0 ], _version [ 1 ])
if len ( _version ) > 1
else " {} " . format ( _version [ 0 ])
)
2022-12-16 05:31:40 -06:00
if os_distrib is None or os_distrib == "auto" :
2023-04-13 02:14:35 -05:00
if "ubuntu" in _os_info [ "ID" ]:
2022-12-16 05:31:40 -06:00
os_distrib = "ubuntu"
2023-04-13 02:14:35 -05:00
elif "opensuse" in _os_info [ "ID" ]:
2022-12-16 05:31:40 -06:00
os_distrib = "opensuse"
2023-04-13 02:14:35 -05:00
elif "rhel" in _os_info [ "ID" ]:
2023-03-08 00:19:29 -06:00
os_distrib = "rhel"
2023-04-13 02:14:35 -05:00
elif "centos" in _os_info [ "ID" ]:
2023-03-08 00:19:29 -06:00
os_distrib = "rhel"
2023-04-13 02:14:35 -05:00
elif "rockylinux" in _os_info [ "ID" ]:
os_distrib = "rhel"
elif "debian" in _os_info [ "ID" ]:
os_distrib = "ubuntu"
if "debian" in _os_info [ "ID" ] and os_version is None :
_debian_version = float ( _parse_version ( _os_info [ "VERSION_ID" ]))
if _debian_version >= 11.0 :
os_version = "20.04"
else :
os_version = "18.04"
elif "fedora" in _os_info [ "ID" ]:
2023-03-08 00:19:29 -06:00
os_distrib = "rhel"
2023-04-13 02:14:35 -05:00
# fedora has different versioning system so fallback to 8.7
if os_version is None :
os_version = "8.7"
2022-12-16 05:31:40 -06:00
else :
2023-04-13 02:14:35 -05:00
# if we don't have an exact match, check ID_LIKE
if "ID_LIKE" not in _os_info . keys ():
_os_info [ "ID_LIKE" ] = _os_info [ "ID" ]
if "debian" in _os_info [ "ID_LIKE" ]:
os_distrib = "ubuntu"
if os_version is None :
2024-07-10 22:07:44 -04:00
# fallback on 20.04 if ID is not ubuntu but debian-like
os_version = "20.04"
2023-04-13 02:14:35 -05:00
elif "suse" in _os_info [ "ID_LIKE" ]:
os_distrib = "opensuse"
# fallback on 15.3 if ID is not opensuse but suse-like
if os_version is None :
os_version = "15.3"
elif "rhel" in _os_info [ "ID_LIKE" ] or "centos" in _os_info [ "ID_LIKE" ]:
os_distrib = "rhel"
if os_version is None :
os_version = "8.7"
else :
raise RuntimeError (
"Unknown ID_LIKE value in /etc/os-release: {} " . format (
_os_info [ "ID_LIKE" ]
)
)
elif os_distrib == "centos" :
2023-03-08 00:19:29 -06:00
os_distrib = "rhel"
2023-04-13 02:14:35 -05:00
# uses same versioning system
elif os_distrib == "fedora" :
os_distrib = "rhel"
if os_version is None :
# fedora has different versioning system so fallback to 8.7
os_version = "8.7"
2022-12-16 05:31:40 -06:00
if os_version is None :
os_version = _parse_version ( _os_info [ "VERSION_ID" ])
return ( os_distrib , os_version )
def print_log ( * args , ** kwargs ):
sys . stdout . flush ()
sys . stderr . flush ()
sys . stderr . write ( "### " )
sys . stderr . write ( * args , ** kwargs )
sys . stderr . write ( " \n " )
sys . stderr . flush ()
def run ( * args , ** kwargs ):
print_log ( "Executing: {} \n " . format ( " " . join ( * args )))
sp . run ( * args , ** kwargs , check = True )
sys . stderr . write ( " \n " )
if __name__ == "__main__" :
parser = argparse . ArgumentParser ()
parser . add_argument (
"--version" ,
2024-10-15 11:20:40 -04:00
help = "Print ROCm Systems Profiler version which will be installed" ,
2022-12-16 05:31:40 -06:00
action = "store_true" ,
)
parser . add_argument (
2024-10-21 14:58:30 -04:00
"-p" , "--prefix" , help = "Installation prefix" , type = str , default = "/opt/rocprofiler-systems"
2022-12-16 05:31:40 -06:00
)
parser . add_argument (
"-i" ,
"--interactive" ,
help = "Prompt to accept the license and include/exclude subdirectory" ,
action = "store_true" ,
)
parser . add_argument (
"-D" ,
"--download-path" ,
help = "Download directory (default: temporary directory)" ,
type = str ,
default = None ,
)
parser . add_argument (
"-d" ,
"--os-distrib" ,
help = "Target OS distribution" ,
type = str ,
default = None ,
2023-03-08 00:19:29 -06:00
choices = ( "auto" , "ubuntu" , "opensuse" , "rhel" , "centos" , "fedora" ),
2022-12-16 05:31:40 -06:00
)
parser . add_argument (
"-v" , "--os-version" , help = "Target OS version" , type = str , default = None
)
parser . add_argument (
"-k" ,
"--keep-download" ,
help = "Do not delete downloaded file as installation" ,
action = "store_true" ,
)
parser . add_argument (
"--rocm" ,
2024-10-15 11:20:40 -04:00
help = "Install ROCm Systems Profiler with ROCm support. Accepts either a ROCm version (e.g. '6.2') or the root path to the ROCm install containing .info/version* file(s) (e.g. /opt/rocm if /opt/rocm/.info/version exists). If no argument is provided, the ROCm version will attempted to be deduced from $ENV {ROCM_PATH} /.info/version" ,
2022-12-16 05:31:40 -06:00
nargs = "?" ,
default = None ,
const = True ,
metavar = "VERSION or ROCM_PATH with .info/version file(s)" ,
)
# right now, only valid set of extensions are: papi + ompt + python3
# in the future, this might change, e.g. MPI variants
parser . add_argument (
"-e" ,
"--extensions" ,
2024-10-15 11:20:40 -04:00
help = "ROCm Systems Profiler extensions, e.g. PAPI, OMPT, and Python3" ,
2022-12-16 05:31:40 -06:00
nargs = "*" ,
default = ( "papi" , "ompt" , "python3" ),
choices = ( "papi" , "ompt" , "python3" ),
)
args = parser . parse_args ()
if args . version :
2024-10-15 11:20:40 -04:00
print ( f "ROCm Systems Profiler { rocprofsys_version } " )
2022-12-16 05:31:40 -06:00
sys . exit ( 0 )
os_distrib , os_version = get_os_info ( args . os_distrib , args . os_version )
rocm_version = get_rocm_version ( args . rocm ) if args . rocm is not None else ""
extensions = ""
if "papi" in args . extensions :
extensions += "-PAPI"
if "ompt" in args . extensions :
extensions += "-OMPT"
if "python3" in args . extensions :
extensions += "-Python3"
if rocm_version is None :
raise RuntimeError (
f "Error! ROCm version could not be determined from { _rocm_path } /.info/version*. Please provide a ROCm version or the root path to the ROCm install containing the .info directory, e.g. '--rocm 5.4' or '--rocm /path/to/rocm/install'"
)
2024-10-15 11:20:40 -04:00
script = f "rocprofiler-systems- { rocprofsys_version } - { os_distrib } - { os_version }{ rocm_version }{ extensions } .sh"
2024-12-10 14:35:02 -05:00
url = f "https://github.com/ROCm/rocprofiler-systems/releases/download/ { rocprofsys_git_tag } / { script } "
2022-12-16 05:31:40 -06:00
download_dir = (
2024-10-15 11:20:40 -04:00
tempfile . mkdtemp ( prefix = "rocprof-sys-install-" )
2022-12-16 05:31:40 -06:00
if args . download_path is None
else args . download_path
)
install_script = os . path . join ( download_dir , script )
try :
if not os . path . exists ( download_dir ):
print_log ( f "Creating download directory: { download_dir } ..." )
os . makedirs ( download_dir )
print_log ( f "Downloading { url } ..." )
try :
response = request . urlretrieve ( url , install_script )
except HTTPError as e :
print_log ( f "" )
print_log ( f "Error: { e } " )
print_log ( f "" )
print_log ( f "Error: Installer script download from { url } failed!" )
if args . rocm is not None :
print_log (
f "There may not be a pre-built installer for ROCm version { _rocm_version } "
)
sys . exit ( - 1 )
if os . path . exists ( install_script ):
print_log ( f "Download completed: { install_script } " )
else :
raise RuntimeError ( f "Download completed but { install_script } does not exist" )
os . chmod ( install_script , stat . S_IRWXU )
if not os . path . exists ( args . prefix ):
print_log ( f "Creating directory: { args . prefix } ..." )
os . makedirs ( args . prefix )
install_args = (
[ "--exclude-subdir" , "--skip-license" ] if not args . interactive else []
)
2024-10-15 11:20:40 -04:00
print_log ( f "Installing ROCm Systems Profiler to { args . prefix } ..." )
2022-12-16 05:31:40 -06:00
run ([ install_script , f "--prefix= { args . prefix } " ] + install_args )
print_log (
2024-10-15 11:20:40 -04:00
f "ROCm Systems Profiler v { rocprofsys_version } installation to { args . prefix } succeeded!"
2022-12-16 05:31:40 -06:00
)
finally :
if not args . keep_download :
print_log ( f "Removing install script { install_script } ..." )
os . remove ( install_script )
# remove the directory if it is a temporary directory
if args . download_path is None :
print_log ( f "Removing temporary directory { download_dir } ..." )
os . rmdir ( download_dir )