32 self.
_lock = threading.Lock()
40 except Exception
as e:
47 return tuple(self.
_pool.values())
51 item = self.
_pool[key]
56 def delete(self, key, ignore_missing=False):
59 subject = self.
_pool.pop(key)
61 if not ignore_missing:
69 except Exception
as e:
70 self.
_pool[key] = subject
73 def _create(self, subject):
74 raise NotImplementedError
76 def _delete(self, subject):
77 raise NotImplementedError
79 def key(self, subject):
80 raise NotImplementedError
87 def key(self, subject):
90 def _create(self, subject):
91 tag = self.
key(subject)
95 kind=
'vlan', ifname=ifname, vlan_id=tag,
99 iface = ip.interfaces[ifname].ro
101 ifname, index=iface.index, vlan_tag=tag))
105 def _delete(self, subject):
106 tag = self.
key(subject)
108 with self.
get_ipdb().interfaces[ifname]
as iface:
113 return 'vlan.{}'.
format(tag)
120 def _create(self, subject):
122 if subject.iface
is None:
125 name = subject.iface.get_ipdb_key()
126 with self.
get_ipdb().interfaces[name]
as iface:
127 iface.add_ip(subject.address, mask=subject.prefix)
130 def _delete(self, subject):
131 name = subject.iface.get_ipdb_key()
132 with self.
get_ipdb().interfaces[name]
as iface:
133 iface.del_ip(subject.address, mask=subject.prefix)
135 def _check_collision(self, subject):
136 network = subject.network
137 for address
in self.
_pool.values():
138 if not address.network.overlaps(network):
152 if proc.poll()
is None:
159 with open(str(path),
'rt')
as stream:
160 out.append(stream.read())
162 if not filter(bool, out):
168 def _create(self, subject):
174 raise ValueError(
'Unsupported payload {!r}'.
format(subject))
177 def _delete(self, subject):
183 except FileNotFoundError:
187 for attempt
in range(3):
188 if subject.proc.poll()
is not None:
190 subject.proc.terminate()
195 if e.errno != errno.ESRCH:
201 subject.bind_address.free_port(subject.bind_port)
203 def _create_consumer(self, subject):
204 subject.bind_port = subject.bind_address.alloc_port()
209 '--bind={}'.
format(subject.bind_address.address),
210 '--port={}'.
format(subject.bind_port)]
213 def _create_producer(self, subject):
214 bandwidth = subject.bandwidth * 1024
215 if subject.burst_pkt:
216 bandwidth =
'{}/{}'.
format(bandwidth, subject.burst_pkt)
220 '--client={}'.
format(subject.remote_address.address),
221 '--port={}'.
format(subject.remote_address.port),
222 '--bandwidth={}'.
format(bandwidth),
223 '--time={}'.
format(subject.time),
231 'ip',
'netns',
'exec', self.context.make_network_namespace_name(),
232 'iperf3',
'--json',
'--interval=1']
233 if subject.bind_address
is not None:
234 cmd.append(
'--bind={}'.
format(subject.bind_address.address))
240 proc = subprocess.Popen(cmd, stdout=report, stderr=err)
242 subject.set_proc(proc)
243 self.context.children.add(proc)
246 return self.context.
path(
'{}.json'.
format(subject.idnr))
249 return self.context.
path(
'{}.err'.
format(subject.idnr))
258 report = json.loads(stdout)
259 except (ValueError, TypeError)
as e:
262 stderr +=
'-+' * 30 +
'-\n' 263 stderr +=
'Can\'t decode iperf3 output: {}\n'.
format(e)
264 stderr +=
'Raw iperf3 output stats on next line\n' 266 return report, stderr
def run_iperf(self, subject, cmd)
def __init__(self, context)
def __init__(self, context)
def delete(self, key, ignore_missing=False)
def get_report(self, key)
def _check_collision(self, subject)
def create(self, subject)
def _delete(self, subject)
def make_error_file_name(self, subject)
def make_cmd_common_part(self, subject)
def _create(self, subject)
def make_report_file_name(self, subject)
def _create_producer(self, subject)
def _create_consumer(self, subject)