Salome HOME
[bos #32522][EDF] SALOME on Demand. Added unified check if an extension installed...
[modules/kernel.git] / bin / SalomeOnDemandTK / extension_unpacker.py
1 #!/usr/bin/env python3
2 # -*- coding:utf-8 -*-
3 # Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
4 #
5 # Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
6 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
7 #
8 # This library is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Lesser General Public
10 # License as published by the Free Software Foundation; either
11 # version 2.1 of the License, or (at your option) any later version.
12 #
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 # Lesser General Public License for more details.
17 #
18 # You should have received a copy of the GNU Lesser General Public
19 # License along with this library; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21 #
22 # See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #
24
25 #  File   : extension_unpacker.py
26 #  Author : Konstantin Leontev, Open Cascade
27 #
28 #  @package SalomeOnDemandTK
29 #  @brief Set of utility to unpack SALOME python extensions.
30
31 """Set of utility to unpack SALOME python extensions.
32 """
33
34 import tarfile
35 import os
36 import sys
37 import json
38 from traceback import format_exc
39
40 from .extension_utilities import logger, \
41     DFILE_EXT, ARCFILE_EXT, EXTDEPENDSON_KEY, EXTCOMPONENT_KEY, \
42     isvalid_filename, isvalid_dirname, ext_info_bykey, set_selext_env, get_app_root, \
43     check_if_installed
44
45
46 def unpack_salomex(salome_root, salomex):
47     """
48     Unpack a given salome extension archive into SALOME install root.
49
50     Args:
51         salome_root - path to SALOME install root directory.
52         salomex - a given salomex file to unpack.
53
54     Returns:
55         True if an ext was successfully unpacked.
56     """
57
58     logger.debug('Starting unpack a salome extension file')
59
60     # Check if provided filenames are valid
61     if  not isvalid_dirname(salome_root) or \
62         not isvalid_filename(salomex, ARCFILE_EXT):
63         return False
64
65     # Check if the given extension is already installed
66     salome_ext_name, _ = os.path.splitext(os.path.basename(salomex))
67     _, salomexc = check_if_installed(salome_root, salome_ext_name)
68     if salomexc:
69         logger.debug('To reinstall an extension you need to remove it first!')
70         return False
71
72     try:
73         with tarfile.open(salomex) as ext:
74
75             # Read a list of dependencies, so let's check if they are present in salome_root
76             logger.debug('Try to read %s.%s file...', salome_ext_name, DFILE_EXT)
77             salomexd_mem = ext.getmember(salome_ext_name + '.' + DFILE_EXT)
78             salomexd_file = ext.extractfile(salomexd_mem)
79             salomexd_content = json.load(salomexd_file)
80
81             logger.debug('Check dependencies...')
82             if EXTDEPENDSON_KEY in salomexd_content and salomexd_content[EXTDEPENDSON_KEY]:
83                 depends_on = salomexd_content[EXTDEPENDSON_KEY]
84
85                 # Check every module if it's in the salome_root
86                 for depends in depends_on:
87                     depends_filename = os.path.join(salome_root, depends + '.' + DFILE_EXT)
88                     if not os.path.isfile(depends_filename):
89                         logger.error('Cannot find %s for a module that extension depends on!',
90                             depends_filename)
91                         return False
92
93             # Unpack archive in the salome_root
94             logger.debug('Extract all the files into %s...', salome_root)
95             ext.extractall(salome_root)
96
97             logger.debug('SALOME extension %s was installed.', salome_ext_name)
98
99     except (OSError, KeyError):
100         logger.error(format_exc())
101         return False
102
103     return True
104
105
106 def install_salomex(salomex):
107     """
108     Install a given salome extension into SALOME_APPLICATION_DIR.
109
110     Args:
111         salomex - a given salomex file to unpack.
112
113     Returns:
114         A list of components to be activated later or None if the function failed.
115     """
116
117     logger.debug('Starting install a salome extension from %s', salomex)
118
119     # Check if we have the salome root path
120     app_root = os.environ.get('SALOME_APPLICATION_DIR', '')
121     if not app_root:
122         # It should be set on the app start, but leave it here to run as a standalone script
123         logger.warning(
124             'Env var SALOME_APPLICATION_DIR is not set! Try to set it going up from cur location.')
125         app_root = get_app_root()
126
127     # Unpack an archive
128     if not unpack_salomex(app_root, salomex):
129         return None
130
131     # Set up an environment
132     # It's not clear at the moment what to do if it fails
133     ext_name, _ = os.path.splitext(os.path.basename(salomex))
134     set_selext_env(app_root, ext_name)
135
136     # Get components to activate later
137     components = ext_info_bykey(app_root, ext_name, EXTCOMPONENT_KEY)
138
139     return components if components else []
140
141
142 if __name__ == '__main__':
143     if len(sys.argv) == 3:
144         arg_1, arg_2 = sys.argv[1:] # pylint: disable=unbalanced-tuple-unpacking
145         unpack_salomex(arg_1, arg_2)
146     elif len(sys.argv) == 2:
147         install_salomex(sys.argv[1])
148     else:
149         logger.error('You must provide all the arguments!')
150         logger.info(unpack_salomex.__doc__)