6
6
# option. This file may not be copied, modified, or distributed
7
7
# except according to those terms.
8
8
9
+ import os
10
+
9
11
import llnl .util .tty as tty
10
12
11
13
from ramble .application import ApplicationBase , ApplicationError
@@ -44,13 +46,19 @@ class SpackApplication(ApplicationBase):
44
46
def __init__ (self , file_path ):
45
47
super ().__init__ (file_path )
46
48
self ._setup_phases = [
49
+ 'create_spack_env' ,
47
50
'install_software' ,
48
51
'get_inputs' ,
49
52
'make_experiments'
50
53
]
51
54
52
55
self ._analyze_phases = ['analyze_experiments' ]
53
56
self ._archive_phases = ['archive_experiments' ]
57
+ self ._mirror_phases = [
58
+ 'mirror_inputs' ,
59
+ 'create_spack_env' ,
60
+ 'mirror_software'
61
+ ]
54
62
55
63
self .application_class = 'SpackApplication'
56
64
@@ -84,39 +92,43 @@ def _add_expand_vars(self, expander):
84
92
except ramble .spack_runner .RunnerError as e :
85
93
tty .die (e )
86
94
87
- def _install_software (self , workspace , expander ):
88
- import os
95
+ def _extract_specs (self , workspace , expander , spec_name , app_name ):
96
+ """Build a list of all specs which the named spec requires
97
+
98
+ Traverse a spec and all of its dependencies to extract a list
99
+ of specs
100
+ """
101
+ spec_list = []
102
+ spec = workspace .get_named_spec (spec_name , app_name )
103
+ if 'dependencies' in spec :
104
+ for dep in spec ['dependencies' ]:
105
+ spec_list .extend (
106
+ self ._extract_specs (workspace ,
107
+ expander ,
108
+ dep , app_name ))
109
+ spec ['application_name' ] = app_name
110
+ spec_list .append ((spec_name , spec ))
111
+ return spec_list
112
+
113
+ def _create_spack_env (self , workspace , expander ):
114
+ """Create the spack environment for this experiment
115
+
116
+ Extract all specs this experiment uses, and write the spack environment
117
+ file for it.
118
+ """
89
119
90
120
# See if we cached this already, and if so return
91
121
namespace = expander .spec_namespace
92
122
if not namespace :
93
123
raise ApplicationError ('Ramble spec_namespace is set to None.' )
94
124
95
- cache_tupl = ('spack' , namespace )
125
+ cache_tupl = ('spack-env ' , namespace )
96
126
if workspace .check_cache (cache_tupl ):
97
127
tty .debug ('{} already in cache.' .format (cache_tupl ))
98
128
return
99
129
else :
100
130
workspace .add_to_cache (cache_tupl )
101
131
102
- def extract_specs (workspace , expander , spec_name , app_name ):
103
- """Build a list of all specs the named spec requires
104
-
105
- Traverse a spec and all of its dependencies to extract a list
106
- of specs
107
- """
108
- spec_list = []
109
- spec = workspace .get_named_spec (spec_name , app_name )
110
- if 'dependencies' in spec :
111
- for dep in spec ['dependencies' ]:
112
- spec_list .extend (
113
- extract_specs (workspace ,
114
- expander ,
115
- dep , app_name ))
116
- spec ['application_name' ] = app_name
117
- spec_list .append ((spec_name , spec ))
118
- return spec_list
119
-
120
132
try :
121
133
runner = ramble .spack_runner .SpackRunner (dry_run = workspace .dry_run )
122
134
@@ -145,8 +157,8 @@ def extract_specs(workspace, expander, spec_name, app_name):
145
157
runner .add_spec (workspace .spec_string (mpi_spec ,
146
158
use_custom_specifier = True ))
147
159
148
- pkg_specs = extract_specs (workspace , expander , name ,
149
- app_context )
160
+ pkg_specs = self . _extract_specs (workspace , expander , name ,
161
+ app_context )
150
162
for pkg_name , pkg_info in pkg_specs :
151
163
if pkg_name not in added_specs :
152
164
added_specs [pkg_name ] = True
@@ -170,20 +182,44 @@ def extract_specs(workspace, expander, spec_name, app_name):
170
182
'defined in ramble.yaml' )
171
183
172
184
runner .concretize ()
185
+
186
+ except ramble .spack_runner .RunnerError as e :
187
+ tty .die (e )
188
+
189
+ def _install_software (self , workspace , expander ):
190
+ """Install application's software using spack"""
191
+
192
+ # See if we cached this already, and if so return
193
+ namespace = expander .spec_namespace
194
+ if not namespace :
195
+ raise ApplicationError ('Ramble spec_namespace is set to None.' )
196
+
197
+ cache_tupl = ('spack-install' , namespace )
198
+ if workspace .check_cache (cache_tupl ):
199
+ tty .debug ('{} already in cache.' .format (cache_tupl ))
200
+ return
201
+ else :
202
+ workspace .add_to_cache (cache_tupl )
203
+
204
+ try :
205
+ runner = ramble .spack_runner .SpackRunner (dry_run = workspace .dry_run )
206
+ runner .set_env (expander .expand_var ('{spack_env}' ))
207
+
208
+ runner .activate ()
173
209
runner .install ()
174
210
211
+ app_context = expander .expand_var ('{spec_name}' )
175
212
for name , spec_info in \
176
213
workspace .all_application_specs (app_context ):
177
- if 'mpi' in spec_info and \
178
- spec_info ['mpi' ] not in mpi_added :
214
+ if 'mpi' in spec_info :
179
215
mpi_spec = workspace .get_named_spec (spec_info ['mpi' ],
180
216
'mpi_library' )
181
217
spec_str = workspace .spec_string (mpi_spec )
182
218
package_path = runner .get_package_path (spec_str )
183
219
expander .set_package_path (name , package_path )
184
220
185
- pkg_specs = extract_specs (workspace , expander , name ,
186
- app_context )
221
+ pkg_specs = self . _extract_specs (workspace , expander , name ,
222
+ app_context )
187
223
for pkg_name , pkg_info in pkg_specs :
188
224
spec = workspace ._build_spec_dict (pkg_info ,
189
225
app_name = app_context )
@@ -194,3 +230,61 @@ def extract_specs(workspace, expander, spec_name, app_name):
194
230
195
231
except ramble .spack_runner .RunnerError as e :
196
232
tty .die (e )
233
+
234
+ def _mirror_software (self , workspace , expander ):
235
+ """Mirror software source for this experiment using spack"""
236
+ import re
237
+
238
+ # See if we cached this already, and if so return
239
+ namespace = expander .spec_namespace
240
+ if not namespace :
241
+ raise ApplicationError ('Ramble spec_namespace is set to None.' )
242
+
243
+ cache_tupl = ('spack-mirror' , namespace )
244
+ if workspace .check_cache (cache_tupl ):
245
+ tty .debug ('{} already in cache.' .format (cache_tupl ))
246
+ return
247
+ else :
248
+ workspace .add_to_cache (cache_tupl )
249
+
250
+ try :
251
+ runner = ramble .spack_runner .SpackRunner (dry_run = workspace .dry_run )
252
+ runner .set_env (expander .expand_var ('{spack_env}' ))
253
+
254
+ runner .activate ()
255
+
256
+ mirror_output = runner .mirror_environment (workspace ._software_mirror_path )
257
+
258
+ present = 0
259
+ added = 0
260
+ failed = 0
261
+
262
+ present_regex = re .compile (r'\s+(?P<num>[0-9]+)\s+already present' )
263
+ present_match = present_regex .search (mirror_output )
264
+ if present_match :
265
+ present = int (present_match .group ('num' ))
266
+
267
+ added_regex = re .compile (r'\s+(?P<num>[0-9]+)\s+added' )
268
+ added_match = added_regex .search (mirror_output )
269
+ if added_match :
270
+ added = int (added_match .group ('num' ))
271
+
272
+ failed_regex = re .compile (r'\s+(?P<num>[0-9]+)\s+failed to fetch.' )
273
+ failed_match = failed_regex .search (mirror_output )
274
+ if failed_match :
275
+ failed = int (failed_match .group ('num' ))
276
+
277
+ added_start = len (workspace ._software_mirror_stats .new )
278
+ for i in range (added_start , added_start + added ):
279
+ workspace ._software_mirror_stats .new [i ] = i
280
+
281
+ present_start = len (workspace ._software_mirror_stats .present )
282
+ for i in range (present_start , present_start + present ):
283
+ workspace ._software_mirror_stats .present [i ] = i
284
+
285
+ error_start = len (workspace ._software_mirror_stats .errors )
286
+ for i in range (error_start , error_start + failed ):
287
+ workspace ._software_mirror_stats .errors .add (i )
288
+
289
+ except ramble .spack_runner .RunnerError as e :
290
+ tty .die (e )
0 commit comments