Licensing information
[deliverable/lttng-ivc.git] / lttng_ivc / utils / utils.py
CommitLineData
efdd48db
JR
1# Copyright (c) 2017 Jonathan Rajotte-Julien <jonathan.rajotte-julien@efficios.com>
2#
3# Permission is hereby granted, free of charge, to any person obtaining a copy
4# of this software and associated documentation files (the "Software"), to deal
5# in the Software without restriction, including without limitation the rights
6# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7# copies of the Software, and to permit persons to whom the Software is
8# furnished to do so, subject to the following conditions:
9#
10# The above copyright notice and this permission notice shall be included in all
11# copies or substantial portions of the Software.
12#
13# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19# SOFTWARE.
20
a028c28a 21import signal
cb87ff89 22import hashlib
bde0c540
JR
23import os
24import time
74eb7096
JR
25import socket
26
8fefa4a3 27from lxml import etree
74eb7096 28from contextlib import closing
a028c28a 29
8fefa4a3 30
85a9e11c
JR
31def line_count(file_path):
32 line_count = 0
33 with open(file_path) as f:
34 for line in f:
35 line_count += 1
36 return line_count
a028c28a
JR
37
38
cb87ff89
JR
39def sha256_checksum(filename, block_size=65536):
40 sha256 = hashlib.sha256()
41 with open(filename, 'rb') as f:
42 for block in iter(lambda: f.read(block_size), b''):
43 sha256.update(block)
44 return sha256.hexdigest()
45
46
bde0c540
JR
47# TODO: timeout as a parameter or Settings
48# TODO: Custom exception
49def wait_for_file(path):
50 i = 0
51 timeout = 60
52 while not os.path.exists(path):
53 time.sleep(1)
54 i = i + 1
55 if i > timeout:
56 raise Exception("File still does not exists. Timeout expired")
57
58
59# TODO: find better exception
60def create_empty_file(path):
61 if os.path.exists(path):
62 raise Exception("Path already exist")
63 open(path, 'w').close()
64
65
a028c28a
JR
66def __dummy_sigusr1_handler():
67 pass
68
69
31565289 70def sessiond_spawn(runtime, opt_args=""):
74eb7096 71 agent_port = find_free_port()
29cf55b3 72 previous_handler = signal.signal(signal.SIGUSR1, __dummy_sigusr1_handler)
31565289
JR
73 cmd = "lttng-sessiond -vvv --verbose-consumer -S --agent-tcp-port {}".format(agent_port)
74 cmd = " ".join([cmd, opt_args])
75 sessiond = runtime.spawn_subprocess(cmd)
29cf55b3
JR
76 signal.sigtimedwait({signal.SIGUSR1}, 60)
77 previous_handler = signal.signal(signal.SIGUSR1, previous_handler)
78 return sessiond
79
80
04f8cce0
JR
81def relayd_spawn(runtime, url="localhost"):
82 """
83 Return a tuple (relayd_uuid, ctrl_port, data_port, live_port)
84 """
85 ports = find_multiple_free_port(3)
86 data_port = ports.pop()
87 ctrl_port = ports.pop()
88 live_port = ports.pop()
89
90 base_cmd = "lttng-relayd -vvv"
91 data_string = "-D tcp://{}:{}".format(url, data_port)
92 ctrl_string = "-C tcp://{}:{}".format(url, ctrl_port)
93 live_string = "-L tcp://{}:{}".format(url, live_port)
94
95 cmd = " ".join([base_cmd, data_string, ctrl_string, live_string])
96 relayd = runtime.spawn_subprocess(cmd)
97
98 # Synchronization based on verbosity since no -S is available for
99 # lttng-relayd yet.
100 log_path = runtime.get_subprocess_stderr_path(relayd)
101
102 # TODO: Move to settings.
103 ready_cue = "Listener accepting live viewers connections"
104 # TODO: Move to settings.
105 timeout = 60
106 ready = False
107 for i in range(timeout):
108 if file_contains(log_path, ready_cue):
109 ready = True
110 break
111 time.sleep(1)
112
113 if not ready:
114 # Cleanup is performed by runtime
115 raise Exception("Relayd readyness timeout expired")
116
117 return (relayd, ctrl_port, data_port, live_port)
118
119
74eb7096
JR
120def find_free_port():
121 # There is no guarantee that the port will be free at runtime but should be
122 # good enough
123 with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
124 s.bind(('', 0))
125 return s.getsockname()[1]
29cf55b3 126
f4711e68 127
04f8cce0
JR
128def find_multiple_free_port(number):
129 """
130 Return a list of supposedly free port
131 """
132 assert(number >= 0)
133 ports = []
134 while(len(ports) != number):
135 port = find_free_port()
136 if port in ports:
137 continue
138 ports.append(port)
139 return ports
140
141
8fefa4a3
JR
142def file_contains(file_path, list_of_string):
143 with open(file_path, 'r') as f:
144 for line in f:
f4711e68
JR
145 for s in list_of_string:
146 if s in line:
147 return True
2094d672
JR
148
149
150def find_dir(root, name):
151 """
152 Returns the absolute path or None.
153 """
154 abs_path = None
155 for base, dirs, files in os.walk(root):
156 for tmp in dirs:
2094d672
JR
157 if tmp.endswith(name):
158 abs_path = os.path.abspath(os.path.join(base, tmp))
159 return abs_path
8fefa4a3
JR
160
161
816f8cc1
JR
162def find_file(root, name):
163 """
164 Returns the absolute path or None.
165 """
816f8cc1
JR
166 abs_path = None
167 for base, dirs, files in os.walk(root):
168 for tmp in files:
169 if tmp.endswith(name):
170 abs_path = os.path.abspath(os.path.join(base, tmp))
816f8cc1
JR
171 return abs_path
172
173
174def validate(xml_path, xsd_path):
175
176 xmlschema_doc = etree.parse(xsd_path)
177 xmlschema = etree.XMLSchema(xmlschema_doc)
178
179 xml_doc = etree.parse(xml_path)
180 result = xmlschema.validate(xml_doc)
181
182 return result
183
8fefa4a3
JR
184def xpath_query(xml_file, xpath):
185 """
186 Return a list of xml node corresponding to the xpath. The list can be of lenght
187 zero.
188 """
189 with open(xml_file, 'r') as f:
190 tree = etree.parse(f)
191 root = tree.getroot()
192 # Remove all namespace
193 # https://stackoverflow.com/questions/18159221/remove-namespace-and-prefix-from-xml-in-python-using-lxml
194 for elem in root.getiterator():
195 if not hasattr(elem.tag, 'find'):
196 continue
197 i = elem.tag.find('}')
198 if i >= 0:
199 elem.tag = elem.tag[i+1:]
200
201 return root.xpath(xpath)
This page took 0.030884 seconds and 5 git commands to generate.