f45b786c921dbd0be985d44e3618ee4157b7bc4b
[deliverable/lttng-ivc.git] / lttng_ivc / utils / ProjectFactory.py
1 import os
2 import logging
3 import yaml
4 import pickle
5
6 import lttng_ivc.utils.project as Project
7 import lttng_ivc.settings as Settings
8
9 from lttng_ivc.utils.utils import sha256_checksum
10
11 _logger = logging.getLogger('project.factory')
12 _project_constructor = {
13 'babeltrace': Project.Babeltrace,
14 'lttng-modules': Project.Lttng_modules,
15 'lttng-tools': Project.Lttng_tools,
16 'lttng-ust': Project.Lttng_ust,
17 }
18
19 __projects_cache = {}
20
21 _project_py_checksum = sha256_checksum(Settings.project_py_file_location)
22
23 _markers = None
24 with open(Settings.run_configuration_file, 'r') as stream:
25 # This is voluntary static across calls, no need to perform this
26 # every time.
27 _markers = yaml.load(stream)
28
29
30 def get_fresh(label, tmpdir):
31 if label not in _markers:
32 # TODO: specialized exception, handle it caller-side so the caller
33 # can decide to skip or fail test.
34 raise Exception('Label is no present')
35 marker = _markers[label]
36 constructor = _project_constructor[marker['project']]
37 path = marker['path']
38 sha1 = marker['sha1']
39 return constructor(label, path, sha1, tmpdir)
40
41
42 def _validate_pickle(pickle, label):
43 _logger.debug("Checking validate for {} {}".format(pickle,
44 label))
45 if pickle._py_file_checksum != _project_py_checksum:
46 _logger.warn("Project py file changed".format(pickle.label,
47 label))
48 return False
49
50 if pickle.label != label:
51 _logger.warn("Label {} and {} are not the same".format(pickle.label,
52 label))
53 return False
54 if pickle.sha1 != _markers[label]['sha1']:
55 _logger.warn("Sha1 {} and {} are not the same".format(pickle.sha1,
56 _markers[label]['sha1']))
57 return False
58
59 deps = _markers[label]['deps']
60 if len(deps) != len(pickle.dependencies):
61 _logger.warn("Len {} and {} are not the same".format(len(deps),
62 len(pickle.dependencies)))
63 return False
64 for dep in deps:
65 if dep not in pickle.dependencies:
66 _logger.warn("Dep {} is not in {}".format(dep,
67 pickle.dependencies))
68 return False
69 else:
70 _logger.debug("Calling validate {} {}".format(pickle.dependencies[dep],
71 dep))
72 valid = _validate_pickle(pickle.dependencies[dep], dep)
73 if not valid:
74 return False
75 return True
76
77
78 def get_precook(label):
79 """
80 Retrieve a precooked immutable projects from a cache if present
81 otherwise the project is built, installed and cached for future access.
82 """
83 if label not in _markers:
84 # TODO: specialized exception, handle it caller-side so the caller
85 # can decide to skip or fail test.
86 raise Exception('Label is no present')
87 marker = _markers[label]
88 constructor = _project_constructor[marker['project']]
89 path = marker['path']
90 sha1 = marker['sha1']
91 deps = marker['deps']
92
93 # Cache path for the label
94 cache_path = os.path.join(Settings.projects_cache_folder, label)
95 pickle_path = os.path.join(cache_path, label+".pickle")
96
97 # Check if Pickle Rick is present and valid. If so return it asap.
98 if os.path.exists(pickle_path):
99 with open(pickle_path, 'rb') as pickle_file:
100 pickled = pickle.load(pickle_file)
101 if _validate_pickle(pickled, label):
102 return pickled
103 else:
104 pickled.cleanup()
105 _logger.warn("Pickle for {} is invalid. Rebuilding".format(label))
106
107 project = constructor(label, path, sha1, cache_path)
108
109 for dep in deps:
110 obj_dep = get_precook(dep)
111 project.dependencies[dep] = obj_dep
112
113 project.autobuild()
114 project._immutable = True
115 with open(pickle_path, 'wb') as pickle_file:
116 pickle.dump(project, pickle_file)
117
118 return project
This page took 0.044894 seconds and 4 git commands to generate.