Move all licensing support to pre/post_install hooks
This commit is contained in:
parent
19f4b27fd2
commit
ee7ec4fa66
@ -813,7 +813,7 @@ points to a license server called licman1:
|
||||
USE_SERVER
|
||||
|
||||
If your package requires the license to install, you can reference the
|
||||
location of this global license using ``Package.global_license_file()``.
|
||||
location of this global license using ``self.global_license_file``.
|
||||
After installation, symlinks for all of the files given in
|
||||
``license_files`` will be created, pointing to this global license.
|
||||
If you install a different version or variant of the package, Spack
|
||||
|
135
lib/spack/spack/hooks/licensing.py
Normal file
135
lib/spack/spack/hooks/licensing.py
Normal file
@ -0,0 +1,135 @@
|
||||
import os
|
||||
|
||||
import spack
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.filesystem import join_path
|
||||
|
||||
|
||||
def pre_install(pkg):
|
||||
"""This hook handles global license setup for licensed software."""
|
||||
if pkg.license_required:
|
||||
set_up_license(pkg)
|
||||
|
||||
|
||||
def set_up_license(pkg):
|
||||
"""Prompt the user, letting them know that a license is required.
|
||||
|
||||
For packages that rely on license files, a global license file is
|
||||
created and opened for editing.
|
||||
|
||||
For packages that rely on environment variables to point to a
|
||||
license, a warning message is printed.
|
||||
|
||||
For all other packages, documentation on how to set up a license
|
||||
is printed."""
|
||||
|
||||
# If the license can be stored in a file, create one
|
||||
if pkg.license_files:
|
||||
license_path = pkg.global_license_file
|
||||
if not os.path.exists(license_path):
|
||||
# Create a new license file
|
||||
write_license_file(pkg, license_path)
|
||||
# Open up file in user's favorite $EDITOR for editing
|
||||
spack.editor(license_path)
|
||||
tty.msg("Added global license file %s" % license_path)
|
||||
else:
|
||||
# Use already existing license file
|
||||
tty.msg("Found already existing license %s" % license_path)
|
||||
|
||||
# If not a file, what about an environment variable?
|
||||
elif pkg.license_vars:
|
||||
tty.warn("A license is required to use %s. Please set %s to the "
|
||||
"full pathname to the license file, or port@host if you"
|
||||
" store your license keys on a dedicated license server" %
|
||||
(pkg.name, ' or '.join(pkg.license_vars)))
|
||||
|
||||
# If not a file or variable, suggest a website for further info
|
||||
elif pkg.license_url:
|
||||
tty.warn("A license is required to use %s. See %s for details" %
|
||||
(pkg.name, pkg.license_url))
|
||||
|
||||
# If all else fails, you're on your own
|
||||
else:
|
||||
tty.warn("A license is required to use %s" % pkg.name)
|
||||
|
||||
|
||||
def write_license_file(pkg, license_path):
|
||||
"""Writes empty license file.
|
||||
|
||||
Comments give suggestions on alternative methods of
|
||||
installing a license."""
|
||||
|
||||
comment = pkg.license_comment
|
||||
|
||||
# Global license directory may not already exist
|
||||
if not os.path.exists(os.path.dirname(license_path)):
|
||||
os.makedirs(os.path.dirname(license_path))
|
||||
license = open(license_path, 'w')
|
||||
|
||||
# License files
|
||||
license.write("""\
|
||||
{0} A license is required to use {1}.
|
||||
{0}
|
||||
{0} The recommended solution is to store your license key in this global
|
||||
{0} license file. After installation, the following symlink(s) will be
|
||||
{0} added to point to this file (relative to the installation prefix):
|
||||
{0}
|
||||
""".format(comment, pkg.name))
|
||||
|
||||
for filename in pkg.license_files:
|
||||
license.write("{0}\t{1}\n".format(comment, filename))
|
||||
|
||||
license.write("{0}\n".format(comment))
|
||||
|
||||
# Environment variables
|
||||
if pkg.license_vars:
|
||||
license.write("""\
|
||||
{0} Alternatively, use one of the following environment variable(s):
|
||||
{0}
|
||||
""".format(comment))
|
||||
|
||||
for var in pkg.license_vars:
|
||||
license.write("{0}\t{1}\n".format(comment, var))
|
||||
|
||||
license.write("""\
|
||||
{0}
|
||||
{0} If you choose to store your license in a non-standard location, you may
|
||||
{0} set one of these variable(s) to the full pathname to the license file, or
|
||||
{0} port@host if you store your license keys on a dedicated license server.
|
||||
{0} You will likely want to set this variable in a module file so that it
|
||||
{0} gets loaded every time someone tries to use {1}.
|
||||
{0}
|
||||
""".format(comment, pkg.name))
|
||||
|
||||
# Documentation
|
||||
if pkg.license_url:
|
||||
license.write("""\
|
||||
{0} For further information on how to acquire a license, please refer to:
|
||||
{0}
|
||||
{0}\t{1}
|
||||
{0}
|
||||
""".format(comment, pkg.license_url))
|
||||
|
||||
license.write("""\
|
||||
{0} You may enter your license below.
|
||||
|
||||
""".format(comment))
|
||||
|
||||
license.close()
|
||||
|
||||
|
||||
def post_install(pkg):
|
||||
"""This hook symlinks local licenses to the global license for
|
||||
licensed software."""
|
||||
if pkg.license_required:
|
||||
symlink_license(pkg)
|
||||
|
||||
|
||||
def symlink_license(pkg):
|
||||
"""Create local symlinks that point to the global license file."""
|
||||
target = pkg.global_license_file
|
||||
for filename in pkg.license_files:
|
||||
link_name = join_path(pkg.prefix, filename)
|
||||
if os.path.exists(target):
|
||||
os.symlink(target, link_name)
|
||||
tty.msg("Added local symlink %s to global license file" % link_name)
|
@ -397,6 +397,17 @@ def __init__(self, spec):
|
||||
if self.is_extension:
|
||||
spack.repo.get(self.extendee_spec)._check_extendable()
|
||||
|
||||
@property
|
||||
def global_license_file(self):
|
||||
"""Returns the path where a global license file should be stored."""
|
||||
if not self.license_files:
|
||||
return
|
||||
spack_root = ancestor(__file__, 4)
|
||||
global_license_dir = join_path(spack_root, 'etc', 'spack', 'licenses')
|
||||
return join_path(global_license_dir, self.name,
|
||||
os.path.basename(self.license_files[0]))
|
||||
|
||||
|
||||
@property
|
||||
def version(self):
|
||||
if not self.spec.versions.concrete:
|
||||
@ -899,10 +910,6 @@ def build_process():
|
||||
"""Forked for each build. Has its own process and python
|
||||
module space set up by build_environment.fork()."""
|
||||
|
||||
# Set up a global license if one is required
|
||||
if self.license_required:
|
||||
self.set_up_license()
|
||||
|
||||
start_time = time.time()
|
||||
if not fake:
|
||||
if not skip_patch:
|
||||
@ -965,10 +972,6 @@ def build_process():
|
||||
self._total_time = time.time() - start_time
|
||||
build_time = self._total_time - self._fetch_time
|
||||
|
||||
# Symlink local license to global license if one is required
|
||||
if self.license_required and self.license_files:
|
||||
self.symlink_license()
|
||||
|
||||
tty.msg("Successfully installed %s" % self.name,
|
||||
"Fetch: %s. Build: %s. Total: %s." %
|
||||
(_hms(self._fetch_time), _hms(build_time),
|
||||
@ -1019,124 +1022,6 @@ def check_paths(path_list, filetype, predicate):
|
||||
"Install failed for %s. Nothing was installed!" % self.name)
|
||||
|
||||
|
||||
def global_license_file(self):
|
||||
"""Returns the path where a global license file should be stored."""
|
||||
if not self.license_files:
|
||||
return
|
||||
spack_root = ancestor(__file__, 4)
|
||||
global_license_dir = join_path(spack_root, 'etc', 'spack', 'licenses')
|
||||
return join_path(global_license_dir, self.name,
|
||||
os.path.basename(self.license_files[0]))
|
||||
|
||||
|
||||
def set_up_license(self):
|
||||
"""Prompt the user, letting them know that a license is required."""
|
||||
|
||||
# If the license can be stored in a file, create one
|
||||
if self.license_files:
|
||||
license_path = self.global_license_file()
|
||||
if not os.path.exists(license_path):
|
||||
# Create a new license file
|
||||
self.write_license_file(license_path)
|
||||
# Open up file in user's favorite $EDITOR for editing
|
||||
spack.editor(license_path)
|
||||
tty.msg("Added global license file %s" % license_path)
|
||||
else:
|
||||
# Use already existing license file
|
||||
tty.msg("Found already existing license %s" % license_path)
|
||||
|
||||
# If not a file, what about an environment variable?
|
||||
elif self.license_vars:
|
||||
tty.warn("A license is required to use %s. Please set %s to the "
|
||||
"full pathname to the license file, or port@host if you"
|
||||
" store your license keys on a dedicated license server" %
|
||||
(self.name, ' or '.join(self.license_vars)))
|
||||
|
||||
# If not a file or variable, suggest a website for further info
|
||||
elif self.license_url:
|
||||
tty.warn("A license is required to use %s. See %s for details" %
|
||||
(self.name, self.license_url))
|
||||
|
||||
# If all else fails, you're on your own
|
||||
else:
|
||||
tty.warn("A license is required to use %s" % self.name)
|
||||
|
||||
|
||||
def write_license_file(self, license_path):
|
||||
"""Writes empty license file.
|
||||
|
||||
Comments give suggestions on alternative methods of
|
||||
installing a license."""
|
||||
|
||||
comment = self.license_comment
|
||||
|
||||
# Global license directory may not already exist
|
||||
if not os.path.exists(os.path.dirname(license_path)):
|
||||
os.makedirs(os.path.dirname(license_path))
|
||||
license = open(license_path, 'w')
|
||||
|
||||
# License files
|
||||
license.write("""\
|
||||
{0} A license is required to use {1}.
|
||||
{0}
|
||||
{0} The recommended solution is to store your license key in this global
|
||||
{0} license file. After installation, the following symlink(s) will be
|
||||
{0} added to point to this file (relative to the installation prefix):
|
||||
{0}
|
||||
""".format(comment, self.name))
|
||||
|
||||
for filename in self.license_files:
|
||||
license.write("{0}\t{1}\n".format(comment, filename))
|
||||
|
||||
license.write("{0}\n".format(comment))
|
||||
|
||||
# Environment variables
|
||||
if self.license_vars:
|
||||
license.write("""\
|
||||
{0} Alternatively, use one of the following environment variable(s):
|
||||
{0}
|
||||
""".format(comment))
|
||||
|
||||
for var in self.license_vars:
|
||||
license.write("{0}\t{1}\n".format(comment, var))
|
||||
|
||||
license.write("""\
|
||||
{0}
|
||||
{0} If you choose to store your license in a non-standard location, you may
|
||||
{0} set one of these variable(s) to the full pathname to the license file, or
|
||||
{0} port@host if you store your license keys on a dedicated license server.
|
||||
{0} You will likely want to set this variable in a module file so that it
|
||||
{0} gets loaded every time someone tries to use {1}.
|
||||
{0}
|
||||
""".format(comment, self.name))
|
||||
|
||||
# Documentation
|
||||
if self.license_url:
|
||||
license.write("""\
|
||||
{0} For further information on how to acquire a license, please refer to:
|
||||
{0}
|
||||
{0}\t{1}
|
||||
{0}
|
||||
""".format(comment, self.license_url))
|
||||
|
||||
license.write("""\
|
||||
{0} You may enter your license below.
|
||||
|
||||
""".format(comment))
|
||||
|
||||
license.close()
|
||||
|
||||
|
||||
def symlink_license(self):
|
||||
"""Create local symlinks that point to the global license file."""
|
||||
target = self.global_license_file()
|
||||
for filename in self.license_files:
|
||||
link_name = join_path(self.prefix, filename)
|
||||
if os.path.exists(target):
|
||||
os.symlink(target, link_name)
|
||||
tty.msg("Added local symlink %s to global license file" % link_name)
|
||||
|
||||
|
||||
def do_install_dependencies(self, **kwargs):
|
||||
# Pass along paths of dependencies here
|
||||
for dep in self.spec.dependencies.values():
|
||||
|
Loading…
Reference in New Issue
Block a user