source: TOOLS/ConsoGENCI/trunk/bin/libconso.py @ 2783

Last change on this file since 2783 was 2783, checked in by labetoulle, 6 years ago
  • Run everything (DB inserts + plots) from single bash script
  • Change exit codes (unsigned in bash, so no negative values...) :
    • 0: everything was ok;
    • 1: nothing done, 'cause nothing to do => ok;
    • >= 2: error.
  • DB access now needs password
  • plot_bilan: added date of production and plotted range to image
  • Cleaning (useless comments, ...)
File size: 10.7 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# ==================================================================== #
5# Author: Sonia Labetoulle                                             #
6# Contact: sonia.labetoulle _at_ ipsl.jussieu.fr                       #
7# Created: 2016                                                        #
8# History:                                                             #
9# Modification:                                                        #
10# ==================================================================== #
11
12# this must come first
13from __future__ import print_function, unicode_literals, division
14
15# standard library imports
16import socket
17import os
18import os.path
19import glob
20import subprocess
21import datetime as dt
22import numpy as np
23import ConfigParser as cp
24
25# Application library imports
26
27
28########################################################################
29def dods_cp(img_out, img_name, DODS):
30  """
31  """
32  if not DODS["DIR"]:
33    print("DODS directory not defined")
34    return
35
36  # .. Copy pdf file to dods server ..
37  # ==================================
38  command = [
39    "scp",
40    img_out,
41    "{}@{}:{}".format(
42      DODS["USER"],
43      DODS["SERVER"],
44      os.path.join(DODS["DIR"], "pdf", img_name + ".pdf")
45    )
46  ]
47  print(command)
48  try :
49    subprocess.call(command)
50  except Exception as rc :
51    print("Error in scp for {}:\n{}".format(command, rc))
52
53  # .. Convert pdf to temporary png ..
54  # ==================================
55  img_png = img_out.replace(".pdf", ".png")
56  command = ["convert", "-density", "200", img_out, img_png]
57
58  print(command)
59  try :
60    subprocess.call(command)
61  except Exception as rc :
62    print("Error in convert for {}:\n{}".format(img_out, rc))
63
64  # .. Copy png file to dods server ..
65  # ==================================
66  command = [
67    "scp",
68    img_png,
69    "{}@{}:{}".format(
70      DODS["USER"],
71      DODS["SERVER"],
72      os.path.join(DODS["DIR"], "img", img_name + ".png")
73    )
74  ]
75
76  print(command)
77  try :
78    subprocess.call(command)
79  except Exception as rc :
80    print("Error in scp for {}:\n{}".format(command, rc))
81
82  # .. Delete temporary png file ..
83  # ===============================
84  try:
85    os.remove(img_png)
86  except Exception as rc:
87    print("Could not remove {}:\n{}".format(img_png, rc))
88
89  return
90
91
92########################################################################
93def parse_config(filename):
94
95  DIR = {}
96  DODS = {}
97
98  config = cp.ConfigParser(allow_no_value=True)
99  config.optionxform = str
100  config.read(filename)
101
102  for section in ("projet", "directories"):
103    if not config.has_section(section):
104      print(
105        "Missing section {} in {}, we stop".format(section, filename)
106      )
107      exit(9)
108
109  # ... Project name ...
110  # --------------------
111  section = "projet"
112  option  = "name"
113  # project_name = config.get(section, option)
114
115  # ... Common directories ...
116  # --------------------------
117  section = "directories"
118  for option in config.options(section):
119    DIR[option] = config.get(section, option)
120
121    if DIR[option] and not os.path.isdir(DIR[option]):
122      print("mkdir {}".format(DIR[option]))
123      try :
124        os.makedirs(DIR[option])
125      except Exception as rc :
126        print("Could not create {}:\n{}".format(DIR[option], rc))
127
128  # .. DODS configuration ...
129  # -------------------------
130  section = "dods"
131  for option in config.options(section):
132    DODS[option] = config.get(section, option)
133
134  return (DIR, DODS)
135
136
137########################################################################
138def string_to_percent(x):
139  """
140  """
141  return float(x.strip("%"))/100.
142
143
144########################################################################
145def string_to_size_unit(x):
146  """
147  """
148  if unicode(x).isdecimal():
149    x = x + "o"
150
151  (size, unit) = (float(x[:-1]), x[-1])
152
153  return SizeUnit(size, unit)
154
155
156########################################################################
157def string_to_float(x):
158  """
159  """
160  return float(x.strip("h"))
161
162
163########################################################################
164def string_to_date(ssaammjj, fmt="%Y%m%d"):
165  """
166  """
167  fmts = ["%Y%m%d", "%Y-%m-%d", "%Y_%m_%d"]
168
169  for fmt in fmts:
170    try:
171      res = dt.datetime.strptime(ssaammjj, fmt)
172    except Exception:
173      pass
174    else:
175      break
176
177  return res.date()
178
179
180########################################################################
181def string_to_datetime(string, fmt="%Y-%m-%d-%H:%M"):
182  """
183  """
184  return dt.datetime.strptime(string, fmt)
185
186
187########################################################################
188def where_we_run():
189
190  res = ""
191  if "curie" in socket.getfqdn():
192    res = "curie"
193  elif "ipsl" in socket.getfqdn():
194    res = "ipsl"
195  else:
196    res = "default"
197
198  return res
199
200
201########################################################################
202def get_last_file(dir_data, pattern):
203  """
204  """
205  current_dir = os.getcwd()
206  os.chdir(dir_data)
207  filename = pattern + "*"
208  file_list = glob.glob(os.path.join(dir_data, filename))
209  if file_list:
210    res = sorted(file_list)[-1]
211  else:
212    res = None
213  os.chdir(current_dir)
214  return res
215
216
217########################################################################
218def get_input_files(dir_data, file_list):
219  """
220  """
221  res = []
222
223  for filename in file_list:
224    res.append(get_last_file(dir_data, filename))
225
226  if None in res:
227    print("\nMissing one or more input files, we stop.")
228    for f_in, f_out in zip(file_list, res):
229      print("=> {}: {}".format(f_in, f_out))
230    exit(9)
231
232  return res
233
234
235########################################################################
236def plot_save(img_out, title):
237  """
238  """
239  from matplotlib.backends.backend_pdf import PdfPages
240
241  dpi = 200.
242
243  dirname = os.path.dirname(img_out)
244  if not os.path.isdir(dirname):
245    print("mkdir {}".format(dirname))
246    try :
247      os.makedirs(dirname)
248    except Exception as rc :
249      print("Could not create {}:\n{}".format(dirname, rc))
250
251  with PdfPages(img_out) as pdf:
252    pdf.savefig(dpi=dpi)
253
254    # ... pdf file's metadata ...
255    # ---------------------------
256    d = pdf.infodict()
257    d["Title"]   = title
258    d["Author"]  = os.path.basename(__file__)
259
260    # d["Subject"] = (
261    #   "Time spent over specific commands during create_ts "
262    #   "jobs at IDRIS and four configurations at TGCC"
263    # )
264    # d["Keywords"] = "bench create_ts TGCC IDRIS ncrcat"
265    # d["CreationDate"] = dt.datetime(2009, 11, 13)
266    # d["ModDate"] = dt.datetime.today()
267
268
269########################################################################
270class AllocItem(object):
271
272  #---------------------------------------------------------------------
273  def __init__(
274    self,
275    alloc_id,
276    machine,
277    node_type,
278    start_date,
279    end_date,
280    alloc
281  ):
282
283    self.alloc_id   = alloc_id
284    self.machine    = machine
285    self.node_type  = node_type
286    self.start_date = start_date
287    self.end_date   = end_date
288    self.alloc      = alloc
289
290    delta = self.end_date - self.start_date
291    self.days = delta.days + 1
292
293    self.daily_conso = self.alloc / self.days
294
295  #---------------------------------------------------------------------
296  def __repr__(self):
297    return "{} ({:%Y%m%d}/{:%Y%m%d}): {}".format(
298      self.machine,
299      self.start_date,
300      self.end_date,
301      self.alloc,
302    )
303
304
305########################################################################
306class Project(object):
307
308  #---------------------------------------------------------------------
309  def __init__(self, project_name, center):
310    self.project = project_name
311    self.centre = center
312    self.alloc_items = []
313
314  #---------------------------------------------------------------------
315  def __repr__(self):
316    return "{}/{}: {}".format(
317      self.project,
318      self.centre,
319      self.alloc_items,
320    )
321
322  #---------------------------------------------------------------------
323  def add_alloc(
324    self,
325    alloc_id,
326    machine,
327    node_type,
328    start_date,
329    end_date,
330    alloc
331  ):
332
333    alloc_item = AllocItem(
334      alloc_id,
335      machine,
336      node_type,
337      start_date,
338      end_date,
339      alloc
340    )
341
342    self.alloc_items.append(alloc_item)
343
344    self.start_date = min(
345      [item.start_date for item in self.alloc_items]
346    )
347    self.end_date = max(
348      [item.end_date for item in self.alloc_items]
349    )
350
351    self.alloc = sum(
352      [item.alloc for item in self.alloc_items]
353    )
354    self.max_daily_conso = max(
355      [item.daily_conso for item in self.alloc_items]
356    )
357
358    self.days = sum(
359      [item.days for item in self.alloc_items]
360    )
361
362    self.nb_alloc = len(self.alloc_items)
363
364  #---------------------------------------------------------------------
365  def get_theo_eq(self, dates):
366
367    # x0 = 0
368    y0 = 0.
369
370    for item in self.alloc_items:
371      yi = y0
372      yf = y0 + item.alloc / self.alloc
373
374      if item.start_date.date() in dates:
375        xi = dates.index(item.start_date.date())
376      else:
377        xi = 0
378
379      if item.end_date.date() in dates:
380        xf = dates.index(item.end_date.date())
381      else:
382        xf = len(dates) + 1
383
384      m = np.array([[xi, 1.], [xf+1, 1.]])
385      n = np.array([yi, yf])
386
387      try:
388        polynome = np.poly1d(np.linalg.solve(m, n))
389      except np.linalg.linalg.LinAlgError:
390        print("error poly")
391        item.theo_eq = None
392      else:
393        item.theo_eq = polynome
394        item.xi = xi
395        item.xf = xf
396        item.yi = yi
397        item.yf = yf
398
399      y0 = yf
400
401  #---------------------------------------------------------------------
402  def fill_data(self, row):
403    # self.id = row["id"]
404    # self.machine = row["machine"]
405    # self.node = row["node_type"]
406    # self.start_date = row["start_date"]
407    # self.end_date = row["end_date"]
408    # self.alloc = row["total_hrs"]
409
410    delta = self.end_date - self.start_date
411    self.days = delta.days + 1
412
413
414########################################################################
415class SizeUnit(object):
416  #---------------------------------------------------------------------
417  def __init__(self, size, unit):
418    self.size = size
419    self.unit = unit
420
421  #---------------------------------------------------------------------
422  def __repr__(self):
423    return "{:6.2f}{}o".format(self.size, self.unit)
424
425  #---------------------------------------------------------------------
426  def convert_size(self, unit_out):
427    """
428    """
429    prefixes = ["o", "K", "M", "G", "T", "P", "H"]
430
431    if not self.size or \
432       self.unit == unit_out:
433      size_out = self.size
434    else:
435      idx_deb = prefixes.index(self.unit)
436      idx_fin = prefixes.index(unit_out)
437      size_out = self.size
438      for i in xrange(abs(idx_fin-idx_deb)):
439        if idx_fin > idx_deb:
440          size_out = size_out / 1024
441        else:
442          size_out = size_out * 1024
443
444    return SizeUnit(size_out, unit_out)
445
446
447########################################################################
448if __name__ == '__main__':
449  pass
Note: See TracBrowser for help on using the repository browser.