source: TOOLS/ConsoGENCMIP6/bin/conso_gencmip6.py @ 2850

Last change on this file since 2850 was 2850, checked in by labetoulle, 6 years ago

[consogencmip6] Change cpt parsing to reflect latest changes in ccc_myproject output

  • Property svn:executable set to *
File size: 11.8 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# this must come first
5from __future__ import print_function, unicode_literals, division
6
7# standard library imports
8from argparse import ArgumentParser
9import json
10import shutil
11import os
12import os.path
13import subprocess
14# import datetime as dt
15
16# Application library imports
17from libconso import *
18
19
20########################################
21def get_storedir(login):
22
23  print("get_storedir")
24
25  command = ["ccc_home", "-A", "-u", login]
26  try :
27    res = subprocess.check_output(command)
28    print("res", res)
29  except Exception as rc:
30    print("exception", rc)
31    res = None
32
33  return res.strip()
34
35
36########################################
37def get_dirsize(dirname):
38
39  command = ["du", "-sbh", dirname]
40  try :
41    res = subprocess.check_output(command)
42    res = res.split()[0]
43  except Exception as rc :
44    print(rc)
45    res = None
46
47  return res
48
49
50# ########################################
51# def get_dirlist(dirname):
52
53
54#   return output
55
56
57########################################
58def parse_myproject(filename, project_name):
59
60  project = {}
61  project["name"] = project_name
62  logins  = {}
63
64  if where_we_run() == "curie":
65    try :
66      res = subprocess.check_output("ccc_myproject")
67    except Exception as rc :
68      print(rc)
69      exit(1)
70    with open(os.path.join(DIR["DATA"], OUT["CCCMP"]), "w") as fileout:
71      fileout.write(res)
72
73  with open(filename, "r") as filein:
74    # Skip lines until we find project name.
75    # Then extract script date
76    for ligne in filein:
77      if "Accounting" in ligne and \
78          project["name"] in ligne:
79        today = ligne.split()[-1]
80        today = string_to_date(today)
81        project["machine"] = ligne.split()[5]
82        project["nodes"]   = ligne.split()[6]
83        break
84
85    # Skip until we find login title line
86    for ligne in filein:
87      if "Login" in ligne:
88        if "Account" in ligne:
89          fg_account = True
90        else:
91          fg_account = False
92        break
93
94    # Login list, until Subtotal or blank line
95    for ligne in filein:
96      if not ligne.strip() or \
97         "Subtotal" in ligne:
98        break
99      if fg_account:
100        login, account, conso = ligne.split()
101      else:
102        login, conso = ligne.split()
103      logins[login] = float(conso)
104
105    # Skip until we find consumed time (hours)
106    for ligne in filein:
107      if "Total" in ligne:
108        total = float(ligne.split()[-1])
109        break
110
111    # Skip until we find allocated time (hours)
112    for ligne in filein:
113      if "Allocated" in ligne:
114        project["alloc"] = float(ligne.split()[-1])
115        break
116
117    # Skip until we find theoratical use (%)
118    for ligne in filein:
119      if "Suggested use at this time" in ligne:
120        utheo = float(ligne.split()[-1].strip("%"))
121        break
122
123    # Skip until we find real use (%)
124    for ligne in filein:
125      if "Real use at this time" in ligne:
126        ureal = float(ligne.split()[-1].strip("%"))
127        break
128
129    # Skip until we find deadline
130    for ligne in filein:
131      if "Project deadline" in ligne:
132        project["deadline"] = ligne.split()[-1]
133        break
134
135  return project, logins, today, total, utheo, ureal
136
137
138########################################
139def write_param(filename, project):
140
141  if args.dryrun:
142    print(json.dumps(project, indent=2))
143  else:
144    with open(filename, "w") as fileout:
145      json.dump(project, fileout, indent=2)
146
147
148########################################
149def write_bilan(
150  filename, today, total, ureal, utheo,
151  runp_mean, penp_mean, runp_std, penp_std,
152  runf_mean, penf_mean, runf_std, penf_std
153):
154  """
155  Conso totale par jour
156  ---------------------
157  on garde le total, date en tete en accumulant dans le fichier :
158  OUT_CONSO_BILAN
159  """
160
161  fmt_str = (
162    "{:10s} {:12s} {:11s} {:11s} "
163    "{:14s} {:14s} {:14s} {:14s} "
164    "{:14s} {:14s} {:14s} {:14s} "
165    "\n"
166  )
167
168  title_str = fmt_str.format(
169    "date",
170    "conso(hours)",
171    "real_use(%)",
172    "theo_use(%)",
173    "runningP(core)",
174    "pendingP(core)",
175    "run_stdP(core)",
176    "pen_stdP(core)",
177    "runningF(core)",
178    "pendingF(core)",
179    "run_stdF(core)",
180    "pen_stdF(core)",
181  )
182
183  fmt_str = (
184    "{:%Y-%m-%d} {:12.2f} {:11.2f} {:11.2f} "
185    "{:14.2f} {:14.2f} {:14.2f} {:14.2f} "
186    "{:14.2f} {:14.2f} {:14.2f} {:14.2f} "
187    "\n"
188  )
189
190  result_str = fmt_str.format(
191    today,
192    total,
193    ureal,
194    utheo,
195    runp_mean,
196    penp_mean,
197    runp_std,
198    penp_std,
199    runf_mean,
200    penf_mean,
201    runf_std,
202    penf_std,
203  )
204
205  if args.dryrun:
206    print(title_str.strip())
207    print(result_str.strip())
208  else:
209    if not os.path.isfile(filename):
210      with open(filename, "w") as fileout:
211        fileout.write(title_str)
212    with open(filename, "a") as fileout:
213      fileout.write(result_str)
214
215
216########################################
217def write_utheo(filename, today, utheo):
218  """
219  Conso théorique par jour
220  ------------------------
221  OUT_CONSO_THEO
222  """
223
224  title_str  = "{:10s} {:11s}\n".format(
225                 "date",
226                 "theo_use(%)",
227               )
228  result_str = "{:%Y-%m-%d} {:11.2f}\n".format(
229                 today,
230                 utheo,
231               )
232
233  if args.dryrun:
234    print(title_str.strip())
235    print(result_str.strip())
236  else:
237    if not os.path.isfile(filename):
238      with open(filename, "w") as fileout:
239        fileout.write(title_str)
240    with open(filename, "a") as fileout:
241      fileout.write(result_str)
242
243
244########################################
245def write_login(filename, today, logins):
246  """
247  Conso par login (HOME)
248  ----------------------
249  on garde la trace de chaque login, date en tete, en remplacant
250  le fichier a chaque fois : OUT_CONSO_LOGIN
251  """
252
253  title_str  = "{:10s} {:10s} {:12s}\n".format(
254                 "date",
255                 "login",
256                 "conso(hours)",
257               )
258
259  with open(filename, "w") as fileout:
260    if args.dryrun:
261      print(title_str.strip())
262    else:
263      fileout.write(title_str)
264
265    for key in sorted(logins):
266      result_str = "{:%Y-%m-%d} {:10s} {:12.2f}\n".format(
267                     today,
268                     key,
269                     logins[key],
270                   )
271      if args.dryrun:
272        print(result_str.strip())
273      else:
274        fileout.write(result_str)
275
276
277########################################
278def write_store(filename, today, logins):
279  """
280  volume cree sur STORE
281  ---------------------
282  par login qui a consomme, en remplacant le fichier a chaque fois :
283  OUT_CONSO_STORE
284  """
285
286  items = (login for login, conso in logins.iteritems()
287                  if conso > 0.)
288
289  title_str = "{:10s} {:10s} {:>7s} {:s}\n".format(
290                "date",
291                "login",
292                "dirsize",
293                "dirname",
294              )
295
296  with open(filename, "w") as fileout:
297    if args.dryrun:
298      print(title_str.strip())
299    else:
300      fileout.write(title_str)
301
302    for login in items:
303      if args.verbose:
304        print(login)
305      storedir = get_storedir(login)
306      if not storedir:
307        print("storedir not found for {}".format(storedir))
308        break
309      igcm_out = os.path.join(storedir, "IGCM_OUT")
310
311      if not os.path.isdir(igcm_out):
312        print("no {}".format(igcm_out)) 
313        continue
314
315      dirlist = []
316      try:
317        dirlist = os.listdir(igcm_out)
318      except OSError as rc:
319        print("Error on os.listdir({}):\n{}".format(igcm_out, rc))
320
321      for dirname in dirlist:
322        result_str = "{:%Y-%m-%d} {:10s} {:>7s} {:s}\n".format(
323                       today,
324                       login,
325                       get_dirsize(os.path.join(igcm_out, dirname)),
326                       os.path.join(igcm_out, dirname)
327                     )
328
329        if args.dryrun or args.verbose:
330          print(result_str.strip())
331
332        if not args.dryrun:
333          fileout.write(result_str)
334
335
336########################################
337def save_files(file_list, today):
338
339  if not args.dryrun:
340    suffix = "{:%Y%m%d}".format(today)
341    for filename in file_list:
342      filein  = os.path.join(DIR["DATA"], filename)
343      if os.path.isfile(filein):
344        fileout = os.path.join(DIR["SAVEDATA"],
345                               "_".join((filename, suffix)))
346        shutil.copy(filein, fileout)
347
348
349########################################
350if __name__ == '__main__':
351
352  # Get arguments from command line
353  # ===============================
354  parser = ArgumentParser()
355  parser.add_argument("-v", "--verbose", action="store_true",
356                      help="Verbose mode")
357  parser.add_argument("-d", "--dryrun", action="store_true",
358                      help="dry run, no file produced")
359  parser.add_argument("-a", "--all", action="store_false",
360                      help="produce all files (default)")
361  parser.add_argument("-b", "--bilan", action="store_true",
362                      help="produce all files (default)")
363  parser.add_argument("-l", "--login", action="store_true",
364                      help="produce all files (default)")
365  parser.add_argument("-s", "--store", action="store_true",
366                      help="produce all files (default)")
367
368  args = parser.parse_args()
369  if args.verbose:
370    print(os.path.basename(__file__))
371    print(where_we_run())
372    print(args)
373
374  if args.bilan or args.login or args.store:
375    args.all = False
376
377  project_name, DIR, OUT = parse_config("bin/config.ini")
378
379  if args.verbose:
380    print(DIR["DATA"])
381    print(DIR["SAVEDATA"])
382
383  (project, logins, today, total, utheo, ureal) = parse_myproject(
384    os.path.join(DIR["DATA"], OUT["CCCMP"]),
385    project_name
386  )
387
388  if args.verbose:
389    print(today, utheo, ureal)
390    print(project)
391    print(logins)
392
393  # Produce files
394  # =============
395
396  # 1- Parametres du projet
397  # -----------------------
398  if args.verbose:
399    print("=> write_param")
400
401  write_param(os.path.join(DIR["DATA"], OUT["PARAM"]), project)
402
403  # 2- Conso totale par jour
404  # ------------------------
405
406  if args.verbose:
407    print("=> write_bilan")
408
409  file_jobs = get_last_file(
410      DIR["SAVEDATA"],
411      "{}_{:%Y%m%d}".format(OUT["JOBS"], today)
412  )
413  if args.verbose:
414    print(file_jobs)
415
416  run_mean = np.nan
417  pen_mean = np.nan
418  run_std  = np.nan
419  pen_std  = np.nan
420
421  if file_jobs:
422    try:
423      data = np.genfromtxt(
424        file_jobs,
425        skip_header=1,
426        converters={
427          0: string_to_datetime,
428          1: float,
429          2: float,
430        },
431        missing_values="nan",
432      )
433    except Exception as rc:
434      print("Problem with file {} :\n{}".format(file_jobs, rc))
435      exit(1)
436
437    run_mean = np.nanmean(
438        np.array([run for _, run, _ in data])
439    )
440    pen_mean = np.nanmean(
441        np.array([pen for _, _, pen in data])
442    )
443
444    run_std = np.nanstd(
445        np.array([run for _, run, _ in data])
446    )
447    pen_std = np.nanstd(
448        np.array([pen for _, _, pen in data])
449    )
450
451  if args.verbose:
452    print(run_mean, pen_mean, run_std, pen_std)
453
454  write_bilan(
455    os.path.join(DIR["DATA"], OUT["BILAN"]),
456    today,
457    total,
458    ureal,
459    utheo,
460    run_mean,
461    pen_mean,
462    run_std,
463    pen_std,
464    runf_mean,
465    penf_mean,
466    runf_std,
467    penf_std,
468  )
469
470  # 2b- Conso théorique par jour
471  # ----------------------------
472  if args.verbose:
473    print("=> write_utheo")
474
475  write_utheo(os.path.join(DIR["DATA"], OUT["UTHEO"]), today, utheo)
476
477  # 3- Conso par login (HOME)
478  # -------------------------
479  if args.verbose:
480    print("=> write_login")
481
482  write_login(os.path.join(DIR["DATA"], OUT["LOGIN"]), today, logins)
483
484  # 4- volume cree sur STORE
485  # ------------------------
486  if args.verbose:
487    print("=> write_store")
488
489  if where_we_run() == "curie":
490    write_store(os.path.join(DIR["DATA"], OUT["STORE"]), today, logins)
491
492  # Save files (on WORKDIR)
493  # =======================
494  if args.verbose:
495    print("=> Save files")
496  if not args.dryrun:
497    file_list = [
498        OUT["PARAM"],
499        OUT["BILAN"],
500        OUT["UTHEO"],
501        OUT["LOGIN"],
502        OUT["STORE"],
503        OUT["CCCMP"],
504    ]
505
506    save_files(file_list, today)
507
508  exit(0)
509
Note: See TracBrowser for help on using the repository browser.