Completed
Push — develop ( 84fb58...03de07 )
by
unknown
01:12
created

detect_scheduling_sys()   F

Complexity

Conditions 9

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 1 Features 0
Metric Value
cc 9
c 4
b 1
f 0
dl 0
loc 33
rs 3
1
import sys
2
import os
3
from subprocess import Popen, PIPE, check_output
0 ignored issues
show
Unused Code introduced by
Unused PIPE imported from subprocess
Loading history...
Unused Code introduced by
Unused Popen imported from subprocess
Loading history...
4
import time
5
import uuid
6
from fabric.api import env, run, cd, get, hide, settings, remote_tunnel, show
0 ignored issues
show
Configuration introduced by
The import fabric.api could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
Unused Code introduced by
Unused remote_tunnel imported from fabric.api
Loading history...
Unused Code introduced by
Unused cd imported from fabric.api
Loading history...
Unused Code introduced by
Unused show imported from fabric.api
Loading history...
7
from fabric.tasks import execute
0 ignored issues
show
Configuration introduced by
The import fabric.tasks could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
8
from fabric.decorators import with_settings
0 ignored issues
show
Configuration introduced by
The import fabric.decorators could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
9
from datetime import timedelta
10
from os.path import join as pj
11
12
from jinja2 import Environment, FileSystemLoader
0 ignored issues
show
Configuration introduced by
The import jinja2 could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
13
14
JOB_SCHEDULERS = ('SGE', 'SLURM', 'LSF',
15
                  'PBS', 'TORQUE', 'MAUI', 'LOADLEVELER')
16
17
scheduler = None
18
job_db = None
19
20
21
def get_data(filename):
22
    packagedir = os.path.dirname(__file__)
23
    dirname = pj(packagedir, '..', 'share', 'MyCluster')
24
    fullname = os.path.join(dirname, filename)
25
    # Need to check if file exists as
26
    # share location may also be sys.prefix/share
27
    if not os.path.isfile(fullname):
28
        dirname = pj(sys.prefix, 'share', 'MyCluster')
29
        fullname = os.path.join(dirname, filename)
30
31
    return fullname
32
33
34
def load_template(template_name):
35
    env = Environment(loader=FileSystemLoader(os.path.join(os.path.dirname(__file__), 'templates')))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (100/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Comprehensibility Bug introduced by
env is re-defining a name which is already available in the outer-scope (previously defined on line 6).

It is generally a bad practice to shadow variables from the outer-scope. In most cases, this is done unintentionally and might lead to unexpected behavior:

param = 5

class Foo:
    def __init__(self, param):   # "param" would be flagged here
        self.param = param
Loading history...
36
    return env.get_template(template_name)
37
38
39
def detect_scheduling_sys():
40
41
    # Test for SLURM
42
    if os.getenv('SLURMHOME') is not None:
43
        return my_import('mycluster.slurm')
44
45
    try:
46
        line = check_output(['scontrol', 'ping'])
47
        if line.split('(')[0] == 'Slurmctld':
48
            return my_import('mycluster.slurm')
49
    except:
0 ignored issues
show
Coding Style Best Practice introduced by
General except handlers without types should be used sparingly.

Typically, you would use general except handlers when you intend to specifically handle all types of errors, f.e. when logging. Otherwise, such general error handlers can mask errors in your application that you want to know of.

Loading history...
50
        pass
51
52
    # Test for PBS
53
    try:
54
        line = check_output(['pbsnodes', '-a'])
55
        return my_import('mycluster.pbs')
56
    except:
0 ignored issues
show
Coding Style Best Practice introduced by
General except handlers without types should be used sparingly.

Typically, you would use general except handlers when you intend to specifically handle all types of errors, f.e. when logging. Otherwise, such general error handlers can mask errors in your application that you want to know of.

Loading history...
57
        pass
58
59
    # Test for SGE
60
    if os.getenv('SGE_CLUSTER_NAME') is not None:
61
        return my_import('mycluster.sge')
62
63
    # Test for lsf
64
    try:
65
        line = check_output('lsid')
66
        if line.split(' ')[0] == 'Platform' or line.split(' ')[0] == 'IBM':
67
            return my_import('mycluster.lsf')
68
    except:
0 ignored issues
show
Coding Style Best Practice introduced by
General except handlers without types should be used sparingly.

Typically, you would use general except handlers when you intend to specifically handle all types of errors, f.e. when logging. Otherwise, such general error handlers can mask errors in your application that you want to know of.

Loading history...
69
        pass
70
71
    return None
72
73
74
def queues():
75
    if scheduler is not None:
76
        return scheduler.queues()
77
    else:
78
        return []
79
80
def accounts():
81
    if scheduler is not None:
82
        return scheduler.accounts()
83
    else:
84
        return []
85
86
87
def remote_sites():
88
    if job_db is not None:
89
        return job_db.remote_site_db
90
    else:
91
        return []
92
93
94
@with_settings(warn_only=True)
95
def remote_cmd():
96
    output_file = '~/.mycluster/' + str(uuid.uuid4())
97
    with hide('output', 'running', 'warnings'), settings(warn_only=True):
98
        run('mycluster -p >' + output_file, pty=False)
99
        import StringIO
0 ignored issues
show
Configuration introduced by
The import StringIO could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
100
        contents = StringIO.StringIO()
101
        get(output_file, contents)
102
        # operate on 'contents' like a file object here, e.g. 'print
103
        return contents.getvalue()
104
105
106
def remote_job_list(site):
107
    env.use_ssh_config = True
108
    return execute(remote_cmd, hosts=[site])
109
110
111
def print_timedelta(td):
112
    if (td.days > 0):
0 ignored issues
show
Unused Code Coding Style introduced by
There is an unnecessary parenthesis after if.
Loading history...
113
        if td.days > 1:
114
            out = str(td).replace(" days, ", ":")
115
        else:
116
            out = str(td).replace(" day, ", ":")
117
    else:
118
        out = "0:" + str(td)
119
    outAr = out.split(':')
120
    outAr = ["%02d" % (int(float(x))) for x in outAr]
121
    out = ":".join(outAr)
122
    return out
123
124
125
def get_timedelta(date_str):
126
    # Returns timedelta object from string in [DD-[hh:]]mm:ss format
127
    days = 0
128
    hours = 0
129
    minutes = 0
130
    seconds = 0
131
132
    if date_str.count('-') == 1:
133
        days = int(date_str.split('-')[0])
134
        date_str = date_str.partition('-')[2]
135
    if date_str.count(':') == 2:
136
        hours = int(date_str.split(':')[0])
137
        date_str = date_str.partition(':')[2]
138
139
    try:
140
        minutes = int(date_str.split(':')[0])
141
        seconds = int(date_str.split(':')[1])
142
    except:
0 ignored issues
show
Coding Style Best Practice introduced by
General except handlers without types should be used sparingly.

Typically, you would use general except handlers when you intend to specifically handle all types of errors, f.e. when logging. Otherwise, such general error handlers can mask errors in your application that you want to know of.

Loading history...
143
        pass
144
145
    return timedelta(days=days,
146
                     hours=hours,
147
                     minutes=minutes,
148
                     seconds=seconds
149
                     )
150
151
152
def get_stats_time(stats):
153
154
    wallclock = '-' if 'wallclock' not in stats else stats['wallclock']
155
    wallclock_delta = None
156
    cputime_delta = None
157
    if wallclock != '-':
158
        try:
159
            wallclock_delta = wallclock
160
            wallclock = print_timedelta(wallclock_delta)
161
        except:
0 ignored issues
show
Coding Style Best Practice introduced by
General except handlers without types should be used sparingly.

Typically, you would use general except handlers when you intend to specifically handle all types of errors, f.e. when logging. Otherwise, such general error handlers can mask errors in your application that you want to know of.

Loading history...
162
            pass
163
    cputime = '-' if 'cpu' not in stats else stats['cpu']
164
    if cputime != '-':
165
        try:
166
            cputime_delta = cputime
167
            cputime = print_timedelta(cputime_delta)
168
        except:
0 ignored issues
show
Coding Style Best Practice introduced by
General except handlers without types should be used sparingly.

Typically, you would use general except handlers when you intend to specifically handle all types of errors, f.e. when logging. Otherwise, such general error handlers can mask errors in your application that you want to know of.

Loading history...
169
            pass
170
171
    time_ratio = None
172
    if cputime_delta and wallclock_delta:
173
        time_ratio = (float(cputime_delta.total_seconds()) /
174
                      wallclock_delta.total_seconds())
175
176
    return cputime, wallclock, time_ratio
177
178
179
def printjobs(num_lines):
180
    print('User name: {0} {1}'.format(job_db.user_db['user'].first_name,
181
                                      job_db.user_db['user'].last_name))
182
    jobs = job_list()
183
    print('     | {0:^10} | {1:^10} |\
184
          {2:^10} | {3:^12} | {4:^12} |\
185
          {5:^5} | {6:^20} | {7:50}'.format('Job ID',
186
                                            'Status',
187
                                            'NTasks',
188
                                            'CPU Time',
189
                                            'Wallclock',
190
                                            'Util %',
191
                                            'Job Name',
192
                                            'Job Dir',)
193
          )
194
    for i, j in enumerate(jobs):
195
        job_id = jobs[j].job_id
196
        status = jobs[j].status
197
        # queue = jobs[j].queue
198
        # site_name = job_db.queue_db[queue].site_name
199
        # scheduler_type = job_db.site_db[site_name].scheduler_type
200
        cputime, wallclock, time_ratio = get_stats_time(jobs[j].stats)
201
        efficiency = '-'
202
        if time_ratio:
203
            try:
204
                efficiency = (time_ratio / (int(jobs[j].num_tasks) *
205
                              int(jobs[j].threads_per_task)) * 100.0)
206
                efficiency = '{:.1f}'.format(efficiency)
207
            except:
0 ignored issues
show
Coding Style Best Practice introduced by
General except handlers without types should be used sparingly.

Typically, you would use general except handlers when you intend to specifically handle all types of errors, f.e. when logging. Otherwise, such general error handlers can mask errors in your application that you want to know of.

Loading history...
208
                pass
209
210
        if status == 'completed':
211
            print('{0:4} | {1:^10} |\
212
                  {2:^10} | {3:^10} |\
213
                  {4:^12} | {5:^12} |\
214
                  {6:^5} | {7:^20} | {8:50}'.format(i + 1,
215
                                                    job_id,
216
                                                    status,
217
                                                    str(jobs[j].num_tasks) +
218
                                                    ' (' +
219
                                                    str(jobs[j].threads_per_task) +
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (83/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
220
                                                    ')',
221
                                                    cputime,
222
                                                    wallclock,
223
                                                    efficiency,
224
                                                    jobs[j].job_name,
225
                                                    jobs[j].job_dir)
226
                  )
227
        elif status == 'running':
228
            stats = scheduler.running_stats(job_id)
229
            cputime, wallclock, time_ratio = get_stats_time(stats)
230
            efficiency = '-'
231
            if time_ratio:
232
                try:
233
                    efficiency = (time_ratio / (int(jobs[j].num_tasks) *
234
                                  int(jobs[j].threads_per_task)) * 100.0)
235
                    efficiency = '{:.1f}'.format(efficiency)
236
                except:
0 ignored issues
show
Coding Style Best Practice introduced by
General except handlers without types should be used sparingly.

Typically, you would use general except handlers when you intend to specifically handle all types of errors, f.e. when logging. Otherwise, such general error handlers can mask errors in your application that you want to know of.

Loading history...
237
                    pass
238
            print('{0:4} | {1:^10} | {2:^10} |\
239
                   {3:^10} | {4:^12} | {5:^12} |\
240
                   {6:^5} | {7:^20} | {8:50}'.format(i + 1,
241
                                                     job_id,
242
                                                     status,
243
                                                     str(jobs[j].num_tasks) +
244
                                                     ' (' +
245
                                                     str(jobs[j].threads_per_task) +
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (84/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
246
                                                     ')',
247
                                                     cputime,
248
                                                     wallclock,
249
                                                     efficiency,
250
                                                     jobs[j].job_name,
251
                                                     jobs[j].job_dir)
252
                  )
253
        else:
254
            print('{0:4} | {1:^10} | {2:^10} |\
255
                   {3:^10} | {4:^12} | {5:^12} |\
256
                   {6:^5} | {7:^20} | {8:50}'.format(i + 1,
257
                                                     job_id,
258
                                                     status,
259
                                                     str(jobs[j].num_tasks) +
260
                                                     ' (' +
261
                                                     str(jobs[j].threads_per_task) +
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (84/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
262
                                                     ')',
263
                                                     '-',
264
                                                     '-',
265
                                                     efficiency,
266
                                                     jobs[j].job_name,
267
                                                     jobs[j].job_dir)
268
                  )
269
270
    remotes = remote_sites()
271
    for i, j in enumerate(remotes):
272
        print('Remote Site: ' + remotes[j].name)
273
        remote_list = remote_job_list(remotes[j].user + '@' + remotes[j].name)
274
        for r in remote_list:
275
            print(remote_list[r])
276
277
278
def print_queue_info():
279
    print('{0:25} | {1:^15} | {2:^15} | {3:^15} |\
280
           {4:^15} | {5:^15}'.format('Queue Name', 'Node Max Task',
281
                                     'Node Max Thread', 'Node Max Memory',
282
                                     'Max Task', 'Available Task'))
283
    for q in queues():
284
        try:
285
            nc = scheduler.node_config(q)
286
            tpn = scheduler.tasks_per_node(q)
287
            avail = scheduler.available_tasks(q)
288
        except:
0 ignored issues
show
Coding Style Best Practice introduced by
General except handlers without types should be used sparingly.

Typically, you would use general except handlers when you intend to specifically handle all types of errors, f.e. when logging. Otherwise, such general error handlers can mask errors in your application that you want to know of.

Loading history...
289
            nc = None
290
            tpn = None
291
            avail = None
292
        print('{0:25} | {1:^15} | {2:^15} |\
293
               {3:^15} | {4:^15} | {5:^15}'.format(q, tpn,
294
                                                   nc['max thread'],
295
                                                   nc['max memory'],
296
                                                   avail['max tasks'],
297
                                                   avail['available']))
298
299
300
def create_submit(queue_id, script_name=None, **kwargs):
301
302
    if job_db is not None:
303
        if 'user_email' not in kwargs:
304
            email = job_db.user_db['user'].email
305
            if email != 'unknown':
306
                kwargs['user_email'] = email
307
308
    if scheduler is not None:
309
        script = scheduler.create_submit(queue_id, **kwargs)
310
311
        if script_name is not None:
312
            import os.path
0 ignored issues
show
Comprehensibility Bug introduced by
os is re-defining a name which is already available in the outer-scope (previously defined on line 2).

It is generally a bad practice to shadow variables from the outer-scope. In most cases, this is done unintentionally and might lead to unexpected behavior:

param = 5

class Foo:
    def __init__(self, param):   # "param" would be flagged here
        self.param = param
Loading history...
313
            if not os.path.isfile(script_name):
314
                with open(script_name, 'w') as f:
315
                    f.write(script)
316
            else:
317
                print('Warning file: {0} already exists.\
318
                       Please choose a different name'.format(script_name))
319
        return script
320
    else:
321
        print('Warning job scheduler not detected')
322
        return None
323
324
325
def submit(script_name, immediate, depends=None):
326
327
    if scheduler is None:
328
        return None
329
330
    job_id = -1
331
    import os.path
0 ignored issues
show
Comprehensibility Bug introduced by
os is re-defining a name which is already available in the outer-scope (previously defined on line 2).

It is generally a bad practice to shadow variables from the outer-scope. In most cases, this is done unintentionally and might lead to unexpected behavior:

param = 5

class Foo:
    def __init__(self, param):   # "param" would be flagged here
        self.param = param
Loading history...
332
    if os.path.isfile(script_name):
333
        job_id = scheduler.submit(script_name, immediate, depends)
334
        if job_id is not None:
335
            print('Job submitted with ID {0}'.format(job_id))
336
        if job_db is not None and job_id is not None:
337
            from persist import Job
0 ignored issues
show
Configuration introduced by
The import persist could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
338
            job = Job(job_id, time.time())
339
            with open(script_name, 'r') as f:
340
                for line in f:
341
                    if line.split('=')[0] == 'export NUM_TASKS':
342
                        job.num_tasks = line.split('=')[1].strip()
343
                    if line.split('=')[0] == 'export TASKS_PER_NODE':
344
                        job.tasks_per_node = line.split('=')[1].strip()
345
                    if line.split('=')[0] == 'export THREADS_PER_TASK':
346
                        job.threads_per_task = line.split('=')[1].strip()
347
                    if line.split('=')[0] == 'export NUM_NODES':
348
                        job.num_nodes = line.split('=')[1].strip()
349
                    if line.split('=')[0] == 'export MYCLUSTER_QUEUE':
350
                        job.queue = line.split('=')[1].strip()
351
                    if line.split('=')[0] == 'export MYCLUSTER_JOB_NAME':
352
                        job.job_name = line.split('=')[1].strip()
353
354
            job.script_name = script_name
355
            job.job_dir = os.path.dirname(os.path.abspath(script_name))
356
            job_db.add_job(job)
357
            job_db.add_queue(job.queue, scheduler.name())
358
    else:
359
        print('Error file: {0} does not exist.'.format(script_name))
360
361
    return job_id
362
363
364
def delete(job_id):
365
    # Add check
366
    job = job_db.get(job_id)
367
    site_name = job.queue.site_name
368
    scheduler_type = job_db.site_db[site_name].scheduler_type
369
370
    if (scheduler.name() == site_name and
371
       scheduler.scheduler_type() == scheduler_type):
372
        scheduler.delete(job_id)
373
    else:
374
        print('JobID: ' + str(job_id) + ' not found at current site')
375
376
377
def add_remote(remote_site):
378
    if job_db is not None:
379
        job_db.add_remote(remote_site)
380
381
382
def export(job_id):
383
    pass
384
385
386
def job_list():
387
    if job_db is not None:
388
        return job_db.job_db
389
    return []
390
391
392
def get_job(job_id):
393
    if job_db is not None:
394
        return job_db.get(job_id)
395
    return None
396
397
398
def my_import(name):
399
    mod = __import__(name)
400
    components = name.split('.')
401
    for comp in components[1:]:
402
        mod = getattr(mod, comp)
403
    return mod
404
405
406
def get_directory():
407
    from os.path import expanduser
408
    home = expanduser("~")
409
    directory = home + '/.mycluster/'
410
    return directory
411
412
413
def create_directory():
414
    directory = get_directory()
415
    if not os.path.exists(directory):
416
        os.makedirs(directory)
417
        return True
418
    else:
419
        return False
420
421
422
def create_db():
423
    global job_db
424
    try:
425
        from persist import JobDB
0 ignored issues
show
Configuration introduced by
The import persist could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
426
        job_db = JobDB()
427
    except Exception as e:
428
        print('Database failed to initialise. Error Message: ' + str(e))
429
430
    return job_db
431
432
433
def update_db():
434
    try:
435
        if scheduler is not None:
436
            status_dict = scheduler.status()
437
            jobs = job_list()
438
            for j in jobs:
439
                if jobs[j].status != 'completed':
440
                    job_id = jobs[j].job_id
441
                    if job_id in status_dict:
442
                        state = status_dict[job_id]
443
                        if state == 'r':
444
                            jobs[j].update_status('running')
445
                    else:
446
                        jobs[j].update_status('completed')
447
                        jobs[j].update_stats(scheduler.job_stats(job_id))
448
    except Exception as e:
449
        print('Database failed to update. Error Message: ' + str(e))
450
451
452
def sysscribe_update(job_id):
453
    if job_db is not None:
454
        from sysscribe import system
0 ignored issues
show
Configuration introduced by
The import sysscribe could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
455
        job_db.get(job_id).update_sysscribe(system.system_dict())
456
457
458
def email_update(email):
459
    if job_db is not None:
460
        job_db.user_db['user'].update_email(email)
461
462
463
def firstname_update(name):
464
    if job_db is not None:
465
        job_db.user_db['user'].firstname(name)
466
467
468
def lastname_update(name):
469
    if job_db is not None:
470
        job_db.user_db['user'].lastname(name)
471
472
473
def get_user():
474
    if job_db is not None:
475
        return (job_db.user_db['user'].first_name + ' ' +
476
                job_db.user_db['user'].last_name)
477
    else:
478
        return 'unknown'
479
480
481
def get_email():
482
    if job_db is not None:
483
        return job_db.user_db['user'].email
484
    else:
485
        return 'unknown'
486
487
488
def get_site():
489
    return 'unknown'
490
491
492
def appname_update(job_id, appname):
493
    if job_db is not None:
494
        job_db.get(job_id).appname(appname)
495
496
497
def appdata_update(job_id, appdata):
498
    if job_db is not None:
499
        job_db.get(job_id).appdata(appdata)
500
501
502
def init(silent=False):
503
    global scheduler
504
    scheduler = detect_scheduling_sys()
505
    created = create_directory()
506
    if create_db() is not None:
507
        update_db()
508
509
    if not silent:
510
        print('MyCluster Initialisation Info')
511
        print('-----------------------------')
512
        print('Local database in: ' + get_directory())
513
        print('User: ' + get_user())
514
        print('Email: ' + get_email())
515
        if not scheduler:
516
            print('Local job scheduler: None')
517
        else:
518
            print('Local job scheduler: ' + scheduler.scheduler_type())
519
            print('Site name: ' + get_site())
520
        print('')
521