From 8cba8d6d1d37a30eab470d3288b5ad4601d496b6 Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Mon, 4 Apr 2016 11:30:13 -0500 Subject: Add default global variables for licensing information --- lib/spack/spack/package.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'lib') diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index 8e6cf32954..6c7f550e00 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -374,6 +374,19 @@ class Package(object): if not hasattr(self, 'list_depth'): self.list_depth = 1 + # Set default licensing information + if not hasattr(self, 'license_required'): + self.license_required = False + + if not hasattr(self, 'license_files'): + self.license_files = [] + + if not hasattr(self, 'license_vars'): + self.license_vars = [] + + if not hasattr(self, 'license_url'): + self.license_url = None + # Set up some internal variables for timing. self._fetch_time = 0.0 self._total_time = 0.0 -- cgit v1.2.3-60-g2f50 From 1b997f10a8f650810bb2363e8adb73794dfc740b Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Mon, 4 Apr 2016 15:12:27 -0500 Subject: Add set_up_license function --- lib/spack/spack/package.py | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'lib') diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index 6c7f550e00..ff757296f3 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -957,6 +957,10 @@ class Package(object): self._total_time = time.time() - start_time build_time = self._total_time - self._fetch_time + # Set up license information + if self.license_required: + self.set_up_license() + tty.msg("Successfully installed %s" % self.name, "Fetch: %s. Build: %s. Total: %s." % (_hms(self._fetch_time), _hms(build_time), @@ -1006,6 +1010,79 @@ class Package(object): raise InstallError( "Install failed for %s. Nothing was installed!" % self.name) + + 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: + # Use the first file listed in license_files + license_path = self.prefix + '/' + self.license_files[0] + self.write_license_file(license_path) + # Open up file in user's favorite $EDITOR for editing + spack.editor(license_path) + tty.msg("Added license file %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): + # Use the first file listed in license_files + license = open(license_path, 'w') + + license.write("""\ +# A license is required to use %s. +# +# The recommended solution is to store your license key in this file. +# By default, %s searches the following file(s) for a license key +# (relative to the installation prefix): +# +#\t%s +# +""" % (self.name, self.name, self.name, '\n#\t'.join(self.license_files))) + + if self.license_vars: + license.write("""\ +# Alternatively, use one of the following environment variable(s): +# +#\t%s +# +# If you choose to store your license in a non-standard location, you may +# set one of these variable(s) to the full pathname to the license file, or +# port@host if you store your license keys on a dedicated license server. +# You will likely want to set this variable in a module file so that it +# gets loaded every time someone tries to use %s. +# +""" % ('\n#\t'.join(self.license_vars), self.name)) + + if self.license_url: + license.write("""\ +# For further information on how to acquire a license, please refer to: +#\t%s +# +""" % self.license_url) + + license.write("""\ +# You may enter your license below. + +""") + + license.close() + + def do_install_dependencies(self, **kwargs): # Pass along paths of dependencies here for dep in self.spec.dependencies.values(): -- cgit v1.2.3-60-g2f50 From 5cb45c253eec4377d3da33863fbbdd2c16def6d9 Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Mon, 4 Apr 2016 15:20:56 -0500 Subject: Bug fix --- lib/spack/spack/package.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index ff757296f3..7648a2f863 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -1052,7 +1052,7 @@ class Package(object): # #\t%s # -""" % (self.name, self.name, self.name, '\n#\t'.join(self.license_files))) +""" % (self.name, self.name, '\n#\t'.join(self.license_files))) if self.license_vars: license.write("""\ -- cgit v1.2.3-60-g2f50 From b63d11d5b0dece2c4e063b3ac5dc4658ab585fd9 Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Mon, 4 Apr 2016 15:25:53 -0500 Subject: Formatting consistency --- lib/spack/spack/package.py | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index 7648a2f863..6d425c3dc7 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -1071,6 +1071,7 @@ class Package(object): if self.license_url: license.write("""\ # For further information on how to acquire a license, please refer to: +# #\t%s # """ % self.license_url) -- cgit v1.2.3-60-g2f50 From 6906911e85f5df504ef0a039ac510822eafc3643 Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Tue, 5 Apr 2016 11:00:55 -0500 Subject: Allow license files to use different symbols for comments --- lib/spack/spack/package.py | 72 +++++++++++++++---------- var/spack/repos/builtin/packages/nag/package.py | 13 ++++- var/spack/repos/builtin/packages/pgi/package.py | 1 + 3 files changed, 56 insertions(+), 30 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index 6d425c3dc7..322cf502a6 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -378,6 +378,9 @@ class Package(object): if not hasattr(self, 'license_required'): self.license_required = False + if not hasattr(self, 'license_comment'): + self.license_comment = '#' + if not hasattr(self, 'license_files'): self.license_files = [] @@ -1040,46 +1043,59 @@ class Package(object): def write_license_file(self, license_path): - # Use the first file listed in license_files + """Writes empty license file. + + Comments give suggestions on alternative methods of installing + a license.""" + + comment = self.license_comment license = open(license_path, 'w') license.write("""\ -# A license is required to use %s. -# -# The recommended solution is to store your license key in this file. -# By default, %s searches the following file(s) for a license key -# (relative to the installation prefix): -# -#\t%s -# -""" % (self.name, self.name, '\n#\t'.join(self.license_files))) +{0} A license is required to use {1}. +{0} +{0} The recommended solution is to store your license key in this file. +{0} By default, {1} searches the following file(s) for a license key +{0} (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)) if self.license_vars: license.write("""\ -# Alternatively, use one of the following environment variable(s): -# -#\t%s -# -# If you choose to store your license in a non-standard location, you may -# set one of these variable(s) to the full pathname to the license file, or -# port@host if you store your license keys on a dedicated license server. -# You will likely want to set this variable in a module file so that it -# gets loaded every time someone tries to use %s. -# -""" % ('\n#\t'.join(self.license_vars), self.name)) +{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)) if self.license_url: license.write("""\ -# For further information on how to acquire a license, please refer to: -# -#\t%s -# -""" % self.license_url) +{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("""\ -# You may enter your license below. +{0} You may enter your license below. -""") +""".format(comment)) license.close() diff --git a/var/spack/repos/builtin/packages/nag/package.py b/var/spack/repos/builtin/packages/nag/package.py index 840b79c66b..c6c33ecad5 100644 --- a/var/spack/repos/builtin/packages/nag/package.py +++ b/var/spack/repos/builtin/packages/nag/package.py @@ -5,17 +5,26 @@ class Nag(Package): """The NAG Fortran Compiler.""" homepage = "http://www.nag.com/nagware/np.asp" - version('6.1', '1e29d9d435b7ccc2842a320150b28ba4', - url='http://www.nag.com/downloads/impl/npl6a61na_amd64.tgz') + version('6.1', '1e29d9d435b7ccc2842a320150b28ba4') + version('6.0', '3fa1e7f7b51ef8a23e6c687cdcad9f96') # Licensing license_required = True + license_comment = '!' license_files = ['lib/nag.key', 'lib/nag.licence', 'lib/nagware.licence'] license_vars = ['NAG_KUSARI_FILE'] license_url = 'http://www.nag.com/doc/inun/np61/lin-mac/klicence.txt' + + def url_for_version(self, version): + # TODO: url and checksum are architecture dependent + # TODO: We currently only support x86_64 + return 'http://www.nag.com/downloads/impl/npl6a%sna_amd64.tgz' % \ + str(version).replace('.', '') + + def install(self, spec, prefix): # Set installation directories os.environ['INSTALL_TO_BINDIR'] = prefix.bin diff --git a/var/spack/repos/builtin/packages/pgi/package.py b/var/spack/repos/builtin/packages/pgi/package.py index 649c7dbee2..095569a2a9 100644 --- a/var/spack/repos/builtin/packages/pgi/package.py +++ b/var/spack/repos/builtin/packages/pgi/package.py @@ -27,6 +27,7 @@ class Pgi(Package): # Licensing license_required = True + license_comment = '#' license_files = ['license.dat'] license_vars = ['PGROUPD_LICENSE_FILE', 'LM_LICENSE_FILE'] license_url = 'http://www.pgroup.com/doc/pgiinstall.pdf' -- cgit v1.2.3-60-g2f50 From 2a11cb8b7606721d0cbe2763eca680dcef328acd Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Fri, 15 Apr 2016 15:04:16 -0500 Subject: Use global licenses with local symlinks --- lib/spack/spack/package.py | 65 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index 322cf502a6..3feec90ddb 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -898,6 +898,11 @@ class Package(object): 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: @@ -960,9 +965,9 @@ class Package(object): self._total_time = time.time() - start_time build_time = self._total_time - self._fetch_time - # Set up license information - if self.license_required: - self.set_up_license() + # 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." % @@ -1014,16 +1019,38 @@ class Package(object): "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 local_license_symlink(self): + """Returns the path where a local license file is searched for.""" + if not self.license_files: + return + return join_path(self.prefix, 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: - # Use the first file listed in license_files - license_path = self.prefix + '/' + self.license_files[0] - self.write_license_file(license_path) - # Open up file in user's favorite $EDITOR for editing - spack.editor(license_path) - tty.msg("Added license file %s" % license_path) + 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: @@ -1045,12 +1072,17 @@ class Package(object): def write_license_file(self, license_path): """Writes empty license file. - Comments give suggestions on alternative methods of installing - a license.""" + 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} @@ -1065,6 +1097,7 @@ class Package(object): license.write("{0}\n".format(comment)) + # Environment variables if self.license_vars: license.write("""\ {0} Alternatively, use one of the following environment variable(s): @@ -1084,6 +1117,7 @@ class Package(object): {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: @@ -1100,6 +1134,15 @@ class Package(object): license.close() + def symlink_license(self): + """Create a local symlink that points to the global license file.""" + target = self.global_license_file() + link_name = self.local_license_symlink() + 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(): -- cgit v1.2.3-60-g2f50 From 8bcb812529eb62f1afad089dda02ea6cf6eb01cf Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Tue, 19 Apr 2016 12:28:50 -0500 Subject: Allow multiple license symlinks --- lib/spack/spack/package.py | 26 ++++++++++--------------- var/spack/repos/builtin/packages/nag/package.py | 4 +--- 2 files changed, 11 insertions(+), 19 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index 3feec90ddb..504e1fc3bb 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -1029,13 +1029,6 @@ class Package(object): os.path.basename(self.license_files[0])) - def local_license_symlink(self): - """Returns the path where a local license file is searched for.""" - if not self.license_files: - return - return join_path(self.prefix, self.license_files[0]) - - def set_up_license(self): """Prompt the user, letting them know that a license is required.""" @@ -1086,9 +1079,9 @@ class Package(object): license.write("""\ {0} A license is required to use {1}. {0} -{0} The recommended solution is to store your license key in this file. -{0} By default, {1} searches the following file(s) for a license key -{0} (relative to the installation prefix): +{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)) @@ -1135,12 +1128,13 @@ class Package(object): def symlink_license(self): - """Create a local symlink that points to the global license file.""" - target = self.global_license_file() - link_name = self.local_license_symlink() - if os.path.exists(target): - os.symlink(target, link_name) - tty.msg("Added local symlink %s to global license file" % link_name) + """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): diff --git a/var/spack/repos/builtin/packages/nag/package.py b/var/spack/repos/builtin/packages/nag/package.py index c6c33ecad5..d6ffe35171 100644 --- a/var/spack/repos/builtin/packages/nag/package.py +++ b/var/spack/repos/builtin/packages/nag/package.py @@ -11,9 +11,7 @@ class Nag(Package): # Licensing license_required = True license_comment = '!' - license_files = ['lib/nag.key', - 'lib/nag.licence', - 'lib/nagware.licence'] + license_files = ['lib/nag.key'] license_vars = ['NAG_KUSARI_FILE'] license_url = 'http://www.nag.com/doc/inun/np61/lin-mac/klicence.txt' -- cgit v1.2.3-60-g2f50 From 19f4b27fd2b6986e236738de394738a9935c2abf Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Mon, 9 May 2016 11:30:31 -0500 Subject: Add documentation for packaging of licensed software --- lib/spack/docs/packaging_guide.rst | 121 +++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) (limited to 'lib') diff --git a/lib/spack/docs/packaging_guide.rst b/lib/spack/docs/packaging_guide.rst index 1b7941ab24..65ff08d5c8 100644 --- a/lib/spack/docs/packaging_guide.rst +++ b/lib/spack/docs/packaging_guide.rst @@ -703,6 +703,127 @@ Fetching a revision Subversion branches are handled as part of the directory structure, so you can check out a branch or tag by changing the ``url``. + +.. _license: + +Licensed software +------------------------------------------ + +In order to install licensed software, Spack needs to know a few more +details about a package. The following class attributes should be defined. + +``license_required`` +~~~~~~~~~~~~~~~~~~~~~ + +Boolean. If set to ``True``, this software requires a license. If set to +``False``, all of the following attributes will be ignored. Defaults to +``False``. + +``license_comment`` +~~~~~~~~~~~~~~~~~~~~~ + +String. Contains the symbol used by the license manager to denote a comment. +Defaults to ``#``. + +``license_files`` +~~~~~~~~~~~~~~~~~~~~~ + +List of strings. These are files that the software searches for when +looking for a license. All file paths must be relative to the installation +directory. More complex packages like Intel may require multiple +licenses for individual components. Defaults to the empty list. + +``license_vars`` +~~~~~~~~~~~~~~~~~~~~~ + +List of strings. Environment variables that can be set to tell the software +where to look for a license if it is not in the usual location. Defaults +to the empty list. + +``license_url`` +~~~~~~~~~~~~~~~~~~~~~ + +String. A URL pointing to license setup instructions for the software. +Defaults to the empty string. + +For example, let's take a look at the package for the PGI compilers. + +.. code-block:: python + + # Licensing + license_required = True + license_comment = '#' + license_files = ['license.dat'] + license_vars = ['PGROUPD_LICENSE_FILE', 'LM_LICENSE_FILE'] + license_url = 'http://www.pgroup.com/doc/pgiinstall.pdf' + +As you can see, PGI requires a license. Its license manager, FlexNet, uses +the ``#`` symbol to denote a comment. It expects the license file to be +named ``license.dat`` and to be located directly in the installation prefix. +If you would like the installation file to be located elsewhere, simply set +``PGROUPD_LICENSE_FILE`` or ``LM_LICENSE_FILE`` after installation. For +further instructions on installation and licensing, see the URL provided. + +Let's walk through a sample PGI installation to see exactly what Spack is +and isn't capable of. Since PGI does not provide a download URL, it must +be downloaded manually. It can either be added to a mirror or located in +the current directory when ``spack install pgi`` is run. See :ref:`mirrors` +for instructions on setting up a mirror. + +After running ``spack install pgi``, the first thing that will happen is +Spack will create a global license file located at +``$SPACK_ROOT/etc/spack/licenses/pgi/license.dat``. It will then open up the +file using the editor set in ``$EDITOR``, or vi if unset. It will look like +this: + +.. code-block:: + + # A license is required to use pgi. + # + # The recommended solution is to store your license key in this global + # license file. After installation, the following symlink(s) will be + # added to point to this file (relative to the installation prefix): + # + # license.dat + # + # Alternatively, use one of the following environment variable(s): + # + # PGROUPD_LICENSE_FILE + # LM_LICENSE_FILE + # + # If you choose to store your license in a non-standard location, you may + # set one of these variable(s) to the full pathname to the license file, or + # port@host if you store your license keys on a dedicated license server. + # You will likely want to set this variable in a module file so that it + # gets loaded every time someone tries to use pgi. + # + # For further information on how to acquire a license, please refer to: + # + # http://www.pgroup.com/doc/pgiinstall.pdf + # + # You may enter your license below. + +You can add your license directly to this file, or tell FlexNet to use a +license stored on a separate license server. Here is an example that +points to a license server called licman1: + +.. code-block:: + + SERVER licman1.mcs.anl.gov 00163eb7fba5 27200 + USE_SERVER + +If your package requires the license to install, you can reference the +location of this global license using ``Package.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 +will automatically detect and reuse the already existing global license. + +If the software you are trying to package doesn't rely on license files, +Spack will print a warning message, letting the user know that they +need to set an environment variable or pointing them to installation +documentation. + .. _patching: Patches -- cgit v1.2.3-60-g2f50 From ee7ec4fa66aed5bcbdb97fddf2303b3debab5c4e Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Tue, 10 May 2016 15:43:24 -0500 Subject: Move all licensing support to pre/post_install hooks --- lib/spack/docs/packaging_guide.rst | 2 +- lib/spack/spack/hooks/licensing.py | 135 ++++++++++++++++++++++++++++++++++++ lib/spack/spack/package.py | 137 +++---------------------------------- 3 files changed, 147 insertions(+), 127 deletions(-) create mode 100644 lib/spack/spack/hooks/licensing.py (limited to 'lib') diff --git a/lib/spack/docs/packaging_guide.rst b/lib/spack/docs/packaging_guide.rst index 65ff08d5c8..650e0ee3b2 100644 --- a/lib/spack/docs/packaging_guide.rst +++ b/lib/spack/docs/packaging_guide.rst @@ -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 diff --git a/lib/spack/spack/hooks/licensing.py b/lib/spack/spack/hooks/licensing.py new file mode 100644 index 0000000000..56f7b6daa5 --- /dev/null +++ b/lib/spack/spack/hooks/licensing.py @@ -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) diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index 504e1fc3bb..17d92fdf79 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -397,6 +397,17 @@ class Package(object): 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 @@ class Package(object): """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 @@ class Package(object): 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 @@ class Package(object): "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(): -- cgit v1.2.3-60-g2f50 From 5879f8207fe005a485c09a3d8802493455ba16ac Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Tue, 10 May 2016 16:40:46 -0500 Subject: Flake8 formatting changes --- lib/spack/spack/hooks/licensing.py | 6 +++-- .../builtin/packages/allinea-forge/package.py | 3 +-- .../builtin/packages/allinea-reports/package.py | 8 +++---- var/spack/repos/builtin/packages/nag/package.py | 5 ++-- var/spack/repos/builtin/packages/pgi/package.py | 27 ++++++++++++++-------- 5 files changed, 28 insertions(+), 21 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/hooks/licensing.py b/lib/spack/spack/hooks/licensing.py index 56f7b6daa5..99521c8356 100644 --- a/lib/spack/spack/hooks/licensing.py +++ b/lib/spack/spack/hooks/licensing.py @@ -46,7 +46,7 @@ def set_up_license(pkg): # 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)) + (pkg.name, pkg.license_url)) # If all else fails, you're on your own else: @@ -132,4 +132,6 @@ def symlink_license(pkg): 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) + tty.msg("Added local symlink %s to global license file" % + link_name) + diff --git a/var/spack/repos/builtin/packages/allinea-forge/package.py b/var/spack/repos/builtin/packages/allinea-forge/package.py index 1f757039a6..fa88b450be 100644 --- a/var/spack/repos/builtin/packages/allinea-forge/package.py +++ b/var/spack/repos/builtin/packages/allinea-forge/package.py @@ -1,5 +1,6 @@ from spack import * + class AllineaForge(Package): """Allinea Forge is the complete toolsuite for software development - with everything needed to debug, profile, optimize, edit and build C, C++ and @@ -17,13 +18,11 @@ class AllineaForge(Package): license_vars = ['ALLINEA_LICENCE_FILE', 'ALLINEA_LICENSE_FILE'] license_url = 'http://www.allinea.com/user-guide/forge/Installation.html' - def url_for_version(self, version): # TODO: add support for other architectures/distributions url = "http://content.allinea.com/downloads/" return url + "allinea-forge-%s-Redhat-6.0-x86_64.tar" % version - def install(self, spec, prefix): textinstall = which('textinstall.sh') textinstall('--accept-licence', prefix) diff --git a/var/spack/repos/builtin/packages/allinea-reports/package.py b/var/spack/repos/builtin/packages/allinea-reports/package.py index 526d51c688..0099e6e64c 100644 --- a/var/spack/repos/builtin/packages/allinea-reports/package.py +++ b/var/spack/repos/builtin/packages/allinea-reports/package.py @@ -1,9 +1,11 @@ from spack import * + class AllineaReports(Package): """Allinea Performance Reports are the most effective way to characterize - and understand the performance of HPC application runs. One single-page HTML - report elegantly answers a range of vital questions for any HPC site""" + and understand the performance of HPC application runs. One single-page + HTML report elegantly answers a range of vital questions for any HPC site + """ homepage = "http://www.allinea.com/products/allinea-performance-reports" @@ -16,13 +18,11 @@ class AllineaReports(Package): license_vars = ['ALLINEA_LICENCE_FILE', 'ALLINEA_LICENSE_FILE'] license_url = 'http://www.allinea.com/user-guide/reports/Installation.html' - def url_for_version(self, version): # TODO: add support for other architectures/distributions url = "http://content.allinea.com/downloads/" return url + "allinea-reports-%s-Redhat-6.0-x86_64.tar" % version - def install(self, spec, prefix): textinstall = which('textinstall.sh') textinstall('--accept-licence', prefix) diff --git a/var/spack/repos/builtin/packages/nag/package.py b/var/spack/repos/builtin/packages/nag/package.py index d6ffe35171..df7344d37a 100644 --- a/var/spack/repos/builtin/packages/nag/package.py +++ b/var/spack/repos/builtin/packages/nag/package.py @@ -1,6 +1,7 @@ from spack import * import os + class Nag(Package): """The NAG Fortran Compiler.""" homepage = "http://www.nag.com/nagware/np.asp" @@ -15,13 +16,11 @@ class Nag(Package): license_vars = ['NAG_KUSARI_FILE'] license_url = 'http://www.nag.com/doc/inun/np61/lin-mac/klicence.txt' - def url_for_version(self, version): # TODO: url and checksum are architecture dependent # TODO: We currently only support x86_64 return 'http://www.nag.com/downloads/impl/npl6a%sna_amd64.tgz' % \ - str(version).replace('.', '') - + str(version).replace('.', '') def install(self, spec, prefix): # Set installation directories diff --git a/var/spack/repos/builtin/packages/pgi/package.py b/var/spack/repos/builtin/packages/pgi/package.py index 095569a2a9..8a067a43f1 100644 --- a/var/spack/repos/builtin/packages/pgi/package.py +++ b/var/spack/repos/builtin/packages/pgi/package.py @@ -1,6 +1,7 @@ from spack import * import os + class Pgi(Package): """PGI optimizing multi-core x64 compilers for Linux, MacOS & Windows with support for debugging and profiling of local MPI processes. @@ -18,12 +19,18 @@ class Pgi(Package): version('16.3', '618cb7ddbc57d4e4ed1f21a0ab25f427') - variant('network', default=True, description="Perform a network install") - variant('single', default=False, description="Perform a single system install") - variant('nvidia', default=False, description="Enable installation of optional NVIDIA components, such as CUDA") - variant('amd', default=False, description="Enable installation of optional AMD components") - variant('java', default=False, description="Enable installation of Java Runtime Environment") - variant('mpi', default=False, description="Enable installation of Open MPI") + variant('network', default=True, + description="Perform a network install") + variant('single', default=False, + description="Perform a single system install") + variant('nvidia', default=False, + description="Enable installation of optional NVIDIA components") + variant('amd', default=False, + description="Enable installation of optional AMD components") + variant('java', default=False, + description="Enable installation of Java Runtime Environment") + variant('mpi', default=False, + description="Enable installation of Open MPI") # Licensing license_required = True @@ -32,7 +39,6 @@ class Pgi(Package): license_vars = ['PGROUPD_LICENSE_FILE', 'LM_LICENSE_FILE'] license_url = 'http://www.pgroup.com/doc/pgiinstall.pdf' - def install(self, spec, prefix): # Enable the silent installation feature os.environ['PGI_SILENT'] = "true" @@ -41,12 +47,13 @@ class Pgi(Package): if '+network' in spec and '~single' in spec: os.environ['PGI_INSTALL_TYPE'] = "network" - os.environ['PGI_INSTALL_LOCAL_DIR'] = "%s/%s/share_objects" % (prefix, self.version) + os.environ['PGI_INSTALL_LOCAL_DIR'] = "%s/%s/share_objects" % \ + (prefix, self.version) elif '+single' in spec and '~network' in spec: os.environ['PGI_INSTALL_TYPE'] = "single" else: - msg = 'You must choose either a network install or a single system install.\n' - msg += 'You cannot choose both.' + msg = 'You must choose either a network install or a single ' + msg += 'system install.\nYou cannot choose both.' raise RuntimeError(msg) if '+nvidia' in spec: -- cgit v1.2.3-60-g2f50 From c043275f1b83e54ad00355fdae255aa11a2d03e1 Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Wed, 11 May 2016 11:46:41 -0500 Subject: Final flake8 changes --- lib/spack/spack/hooks/licensing.py | 1 - lib/spack/spack/package.py | 8 ++------ .../builtin/packages/allinea-forge/package.py | 8 ++++---- .../builtin/packages/allinea-reports/package.py | 8 ++++---- var/spack/repos/builtin/packages/nag/package.py | 8 ++++---- var/spack/repos/builtin/packages/pgi/package.py | 22 +++++++++++----------- 6 files changed, 25 insertions(+), 30 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/hooks/licensing.py b/lib/spack/spack/hooks/licensing.py index 99521c8356..31f15cc3e9 100644 --- a/lib/spack/spack/hooks/licensing.py +++ b/lib/spack/spack/hooks/licensing.py @@ -134,4 +134,3 @@ def symlink_license(pkg): os.symlink(target, link_name) tty.msg("Added local symlink %s to global license file" % link_name) - diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index 17d92fdf79..8f8eb6db64 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -407,7 +407,6 @@ class Package(object): 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: @@ -1021,7 +1020,6 @@ class Package(object): raise InstallError( "Install failed for %s. Nothing was installed!" % self.name) - def do_install_dependencies(self, **kwargs): # Pass along paths of dependencies here for dep in self.spec.dependencies.values(): @@ -1349,11 +1347,9 @@ class Package(object): def rpath(self): """Get the rpath this package links with, as a list of paths.""" rpaths = [self.prefix.lib, self.prefix.lib64] - rpaths.extend(d.prefix.lib - for d in self.spec.traverse(root=False) + rpaths.extend(d.prefix.lib for d in self.spec.traverse(root=False) if os.path.isdir(d.prefix.lib)) - rpaths.extend(d.prefix.lib64 - for d in self.spec.traverse(root=False) + rpaths.extend(d.prefix.lib64 for d in self.spec.traverse(root=False) if os.path.isdir(d.prefix.lib64)) return rpaths diff --git a/var/spack/repos/builtin/packages/allinea-forge/package.py b/var/spack/repos/builtin/packages/allinea-forge/package.py index fa88b450be..e5bd62dd70 100644 --- a/var/spack/repos/builtin/packages/allinea-forge/package.py +++ b/var/spack/repos/builtin/packages/allinea-forge/package.py @@ -13,10 +13,10 @@ class AllineaForge(Package): # Licensing license_required = True - license_comment = '#' - license_files = ['licences/Licence'] - license_vars = ['ALLINEA_LICENCE_FILE', 'ALLINEA_LICENSE_FILE'] - license_url = 'http://www.allinea.com/user-guide/forge/Installation.html' + license_comment = '#' + license_files = ['licences/Licence'] + license_vars = ['ALLINEA_LICENCE_FILE', 'ALLINEA_LICENSE_FILE'] + license_url = 'http://www.allinea.com/user-guide/forge/Installation.html' def url_for_version(self, version): # TODO: add support for other architectures/distributions diff --git a/var/spack/repos/builtin/packages/allinea-reports/package.py b/var/spack/repos/builtin/packages/allinea-reports/package.py index 0099e6e64c..7b11e681f5 100644 --- a/var/spack/repos/builtin/packages/allinea-reports/package.py +++ b/var/spack/repos/builtin/packages/allinea-reports/package.py @@ -13,10 +13,10 @@ class AllineaReports(Package): # Licensing license_required = True - license_comment = '#' - license_files = ['licences/Licence'] - license_vars = ['ALLINEA_LICENCE_FILE', 'ALLINEA_LICENSE_FILE'] - license_url = 'http://www.allinea.com/user-guide/reports/Installation.html' + license_comment = '#' + license_files = ['licences/Licence'] + license_vars = ['ALLINEA_LICENCE_FILE', 'ALLINEA_LICENSE_FILE'] + license_url = 'http://www.allinea.com/user-guide/reports/Installation.html' def url_for_version(self, version): # TODO: add support for other architectures/distributions diff --git a/var/spack/repos/builtin/packages/nag/package.py b/var/spack/repos/builtin/packages/nag/package.py index df7344d37a..af893d3db0 100644 --- a/var/spack/repos/builtin/packages/nag/package.py +++ b/var/spack/repos/builtin/packages/nag/package.py @@ -11,10 +11,10 @@ class Nag(Package): # Licensing license_required = True - license_comment = '!' - license_files = ['lib/nag.key'] - license_vars = ['NAG_KUSARI_FILE'] - license_url = 'http://www.nag.com/doc/inun/np61/lin-mac/klicence.txt' + license_comment = '!' + license_files = ['lib/nag.key'] + license_vars = ['NAG_KUSARI_FILE'] + license_url = 'http://www.nag.com/doc/inun/np61/lin-mac/klicence.txt' def url_for_version(self, version): # TODO: url and checksum are architecture dependent diff --git a/var/spack/repos/builtin/packages/pgi/package.py b/var/spack/repos/builtin/packages/pgi/package.py index 8a067a43f1..8dc6453469 100644 --- a/var/spack/repos/builtin/packages/pgi/package.py +++ b/var/spack/repos/builtin/packages/pgi/package.py @@ -15,29 +15,29 @@ class Pgi(Package): set up a mirror, see http://software.llnl.gov/spack/mirrors.html""" homepage = "http://www.pgroup.com/" - url = "file://%s/pgi-16.3.tar.gz" % os.getcwd() + url = "file://%s/pgi-16.3.tar.gz" % os.getcwd() version('16.3', '618cb7ddbc57d4e4ed1f21a0ab25f427') variant('network', default=True, - description="Perform a network install") + description="Perform a network install") variant('single', default=False, - description="Perform a single system install") + description="Perform a single system install") variant('nvidia', default=False, - description="Enable installation of optional NVIDIA components") + description="Enable installation of optional NVIDIA components") variant('amd', default=False, - description="Enable installation of optional AMD components") + description="Enable installation of optional AMD components") variant('java', default=False, - description="Enable installation of Java Runtime Environment") + description="Enable installation of Java Runtime Environment") variant('mpi', default=False, - description="Enable installation of Open MPI") + description="Enable installation of Open MPI") # Licensing license_required = True - license_comment = '#' - license_files = ['license.dat'] - license_vars = ['PGROUPD_LICENSE_FILE', 'LM_LICENSE_FILE'] - license_url = 'http://www.pgroup.com/doc/pgiinstall.pdf' + license_comment = '#' + license_files = ['license.dat'] + license_vars = ['PGROUPD_LICENSE_FILE', 'LM_LICENSE_FILE'] + license_url = 'http://www.pgroup.com/doc/pgiinstall.pdf' def install(self, spec, prefix): # Enable the silent installation feature -- cgit v1.2.3-60-g2f50