pymtt
 All Classes Namespaces Files Functions Variables Groups
OMPI_Snapshot.py
Go to the documentation of this file.
1 # -*- coding: utf-8; tab-width: 4; indent-tabs-mode: f; python-indent: 4 -*-
2 #
3 # Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
4 # Copyright (c) 2017-2018 Los Alamos National Security, LLC. All rights
5 # reserved.
6 # $COPYRIGHT$
7 #
8 # Additional copyrights may follow
9 #
10 # $HEADER$
11 #
12 
13 from __future__ import print_function
14 from future import standard_library
15 standard_library.install_aliases()
16 import os
17 from urllib.parse import urlparse
18 from FetchMTTTool import *
19 from distutils.spawn import find_executable
20 import requests
21 import sys
22 
23 ## @addtogroup Tools
24 # @{
25 # @addtogroup Fetch
26 # @section OMPI_Snapshot
27 # Plugin for getting software via OMPI Nightly tarballs
28 # @param url URL to access the OMPI nightly tarball (e.g. https://www.open-mpi.org/nightly/v2.x)
29 # @param version_file optional file containing name of most recent tarball version tested
30 # @param mpi_name optional name for the OMPI snapshot tarball
31 # @}
33 
34  def __init__(self):
35  # initialise parent class
36  FetchMTTTool.__init__(self)
37  self.activated = False
38  # track the repos we have processed so we
39  # don't do them multiple times
40  self.done = {}
41  self.options = {}
42  self.options['url'] = (None, "URL to access the repository")
43  self.options['version_file'] = (None, "File containing name of most recent tarball version tested")
44  self.options['mpi_name'] = (None, "Name of OMPI tarball being tested")
45  return
46 
47  def activate(self):
48  if not self.activated:
49  # use the automatic procedure from IPlugin
50  IPlugin.activate(self)
51  return
52 
53  def deactivate(self):
54  IPlugin.deactivate(self)
55  return
56 
57  def print_name(self):
58  return "OMPI_Snapshot"
59 
60  def print_options(self, testDef, prefix):
61  lines = testDef.printOptions(self.options)
62  for line in lines:
63  print(prefix + line)
64  return
65 
66  def execute(self, log, keyvals, testDef):
67  testDef.logger.verbose_print("OMP_Snapshot Execute")
68  # parse any provided options - these will override the defaults
69  cmds = {}
70  testDef.parseOptions(log, self.options, keyvals, cmds)
71  # check that they gave us a URL
72  try:
73  if cmds['url'] is not None:
74  url = cmds['url']
75  except KeyError:
76  log['status'] = 1
77  log['stderr'] = "No repository URL was provided"
78  return
79  testDef.logger.verbose_print("Download OMPI url " + url)
80  # get the tarball snapshot name, e.g. v2.x-201711210241-e92a637
81  snapshot_url = url + '/latest_snapshot.txt'
82  try:
83  snapshot_req = requests.get(snapshot_url)
84 # Assumes the error is HTTPError
85 # Then raise HTTP status error response
86  snapshot_req.raise_for_status()
87  except requests.exceptions.HTTPError as error:
88  testDef.logger.verbose_print("HTTP Error: ",error)
89  log['status'] = 1
90  log['stderr'] = "HTTP error"
91  sys.exit(-1)
92  except requests.exceptions.ConnectionError as connection_error:
93  testDef.logger.verbose_print("Error connecting: ", connection_error)
94  log['status'] = 1
95  log['stderr'] = "Error connecting"
96  sys.exit(-1)
97  except requests.exceptions.Timeout:
98  testDef.logger.verbose_print("Timeout error ")
99  log['status'] = 1
100  log['stderr'] = "Timeout error"
101  sys.exit(-1)
102  except requests.exceptions.RequestException as base_class_error:
103  testDef.logger.verbose_print("An error occured: ", base_class_error)
104  log['status'] = 1
105  log['stderr'] = "An error occured"
106  sys.exit(-1)
107 
108  # check to see if we have already processed this tarball
109  try:
110  if self.options['version_file'] is not None:
111  if os.path.exists(cmds['version_file']):
112  try:
113  f = open(cmds['version_file'], 'r')
114  last_version = f.readline().strip()
115  f.close()
116  if last_version == snapshot_req.text.strip():
117  log['status'] = 1
118  log['stderr'] = "No new tarballs to test"
119  # track that we serviced this one
120  return
121  except IOError:
122  log['status'] = 1
123  log['stderr'] = "An error occurred reading version file: " + cmds['version_file']
124  testDef.logger.verbose_print("An error occurred reading version file: " + cmds['version_file'])
125  return
126  else:
127  testDef.logger.verbose_print("Version file does not exist")
128  pass
129  except KeyError:
130  pass
131 
132  # build the tarball name, using a base and then full name
133  tarball_base_name = 'openmpi-' + snapshot_req.text.strip()
134  tarball_name = tarball_base_name + '.tar.gz'
135  download_url = url + '/' + tarball_name
136 
137  try:
138  if self.done[tarball_base_name] is not None:
139  log['status'] = self.done[tarball_base_name][0]
140  log['location'] = self.done[tarball_base_name][1]
141  return
142  except KeyError:
143  pass
144  # now look for the executable in our path
145  if not find_executable("curl"):
146  log['status'] = 1
147  log['stderr'] = "curl command not found"
148  return
149 
150  # record our current location
151  cwd = os.getcwd()
152 
153  dst = os.path.join(testDef.options['scratchdir'], log['section'].replace(":","_"))
154  try:
155  if not os.path.exists(dst): os.mkdir(dst)
156  except:
157  log['status'] = 1
158  log['stderr'] = "Unable to create " + dst
159  return
160 
161  # change to the scratch directory
162  os.chdir(dst)
163  # see if this software has already been cloned
164  if os.path.exists(tarball_base_name):
165  if not os.path.isdir(tarball_base_name):
166  log['status'] = 1
167  log['stderr'] = "Cannot update requested OMPI tarball as a file of that name already exists".format(tarball_base_name)
168  # track that we serviced this one
169  self.done.append((tarball_base_name, 1))
170  return
171  # move to that location
172  os.chdir(tarball_base_name)
173  # if they want us to leave it as-is, then we are done
174  try:
175  if cmds['asis']:
176  status = 0
177  stdout = None
178  stderr = None
179  except KeyError:
180  pass
181  else:
182  # download the tarball - TODO probably need to do a try on these
183  testDef.logger.verbose_print("downloading tarball " + tarball_name + "url: " + download_url)
184  status, stdout, stderr, _ = testDef.execmd.execute(None, ["curl", "-o", tarball_name, download_url], testDef)
185  if 0 != status:
186  log['status'] = 1
187  log['stderr'] = "download for tarball " + tarball_name + "url: " + download_url + "FAILED"
188  return
189  # untar the tarball
190  testDef.logger.verbose_print("untarring tarball " + tarball_name)
191  status, stdout, stderr, _ = testDef.execmd.execute(None, ["tar", "-zxf", tarball_name], testDef)
192  if 0 != status:
193  log['status'] = 1
194  log['stderr'] = "untar of tarball " + tarball_name + "FAILED"
195  return
196  # update version file if we're using one
197  try:
198  if self.options['version_file'] is not None:
199  try:
200  f = open(cmds['version_file'], 'w')
201  print(snapshot_req.text.strip(), file=f);
202  except:
203  log['status'] = 1
204  log['stderr'] = "Failed to update version file"
205  testDef.logger.verbose_print("Failed to update version file")
206  return
207  except KeyError:
208  pass
209  # move into the resulting directory
210  os.chdir(tarball_base_name)
211  # record the result
212  log['status'] = status
213  log['stdout'] = stdout
214  log['stderr'] = stderr
215  log['mpi_info'] = {'name' : cmds['mpi_name'], 'version' : snapshot_req.text.strip()}
216  testDef.logger.verbose_print("setting mpi_info to " + str(log.get('mpi_info')))
217 
218  # log our absolute location so others can find it
219  log['location'] = os.getcwd()
220  # track that we serviced this one
221  self.done[tarball_base_name] = (status, log['location'])
222  # change back to the original directory
223  os.chdir(cwd)
224 
225  return