log = logging.getLogger(__name__)
-def set_priority():
+def set_priority(interface):
# create a priority queueing discipline
- return ['sudo', 'tc', 'qdisc', 'add', 'dev', 'eno1', 'root', 'handle', '1:', 'prio']
+ return ['sudo', 'tc', 'qdisc', 'add', 'dev', interface, 'root', 'handle', '1:', 'prio']
-def show_tc():
+def show_tc(interface):
# shows tc device present
- return ['sudo', 'tc', 'qdisc', 'show', 'dev', 'eno1']
+ return ['sudo', 'tc', 'qdisc', 'show', 'dev', interface]
-def del_tc():
+def del_tc(interface):
- return ['sudo', 'tc', 'qdisc', 'del', 'dev', 'eno1', 'root']
+ return ['sudo', 'tc', 'qdisc', 'del', 'dev', interface, 'root']
-def cmd_prefix():
+def cmd_prefix(interface):
# prepare command to set delay
- cmd1 = ['sudo', 'tc', 'qdisc', 'add', 'dev', 'eno1', 'parent',
+ cmd1 = ['sudo', 'tc', 'qdisc', 'add', 'dev', interface, 'parent',
'1:1', 'handle', '2:', 'netem', 'delay']
# prepare command to change delay
- cmd2 = ['sudo', 'tc', 'qdisc', 'replace', 'dev', 'eno1', 'root', 'netem', 'delay']
+ cmd2 = ['sudo', 'tc', 'qdisc', 'replace', 'dev', interface, 'root', 'netem', 'delay']
# prepare command to apply filter to the matched ip/host
- cmd3 = ['sudo', 'tc', 'filter', 'add', 'dev', 'eno1',
+ cmd3 = ['sudo', 'tc', 'filter', 'add', 'dev', interface,
'parent', '1:0', 'protocol', 'ip', 'pref', '55',
'handle', '::55', 'u32', 'match', 'ip', 'dst']
return cmd1, cmd2, cmd3
-def static_delay(remote, host, delay):
+def static_delay(remote, host, interface, delay):
""" Sets a constant delay between two hosts to emulate network delays using tc qdisc and netem"""
- set_delay, change_delay, set_ip = cmd_prefix()
+ set_delay, change_delay, set_ip = cmd_prefix(interface)
ip = socket.gethostbyname(host.hostname)
- r = remote.run(args=show_tc(), stdout=StringIO())
+ r = remote.run(args=show_tc(interface), stdout=StringIO())
if r.stdout.getvalue().strip().find('refcnt') == -1:
# call set_priority() func to create priority queue
# if not already created(indicated by -1)
log.info('Create priority queue')
- remote.run(args=set_priority())
+ remote.run(args=set_priority(interface))
# set static delay, with +/- 5ms jitter with normal distribution as default
log.info('Setting delay to %s' % delay)
log.info('Delay set on %s' % remote)
set_ip.extend(['%s' % ip, 'flowid', '2:1'])
remote.run(args=set_ip)
- remote.run(args=show_tc(), stdout=StringIO())
+ remote.run(args=show_tc(interface), stdout=StringIO())
else:
# if the device is already created, only change the delay
log.info('Setting delay to %s' % delay)
change_delay.extend(['%s' % delay, '5ms', 'distribution', 'normal'])
remote.run(args=change_delay)
- remote.run(args=show_tc(), stdout=StringIO())
+ remote.run(args=show_tc(interface), stdout=StringIO())
-def variable_delay(remote, host, delay_range=[]):
+def variable_delay(remote, host, interface, delay_range=[]):
""" Vary delay between two values"""
- set_delay, change_delay, set_ip = cmd_prefix()
+ set_delay, change_delay, set_ip = cmd_prefix(interface)
ip = socket.gethostbyname(host.hostname)
delay1 = delay_range[0]
delay2 = delay_range[1]
- r = remote.run(args=show_tc(), stdout=StringIO())
+ r = remote.run(args=show_tc(interface), stdout=StringIO())
if r.stdout.getvalue().strip().find('refcnt') == -1:
# call set_priority() func to create priority queue
# if not already created(indicated by -1)
- remote.run(args=set_priority())
+ remote.run(args=set_priority(interface))
# set variable delay
log.info('Setting varying delay')
log.info('Delay set on %s' % remote)
set_ip.extend(['%s' % ip, 'flowid', '2:1'])
remote.run(args=set_ip)
- remote.run(args=show_tc(), stdout=StringIO())
+ remote.run(args=show_tc(interface), stdout=StringIO())
else:
# if the device is already created, only change the delay
log.info('Setting varying delay')
change_delay.extend(['%s' % delay1, '%s' % delay2])
remote.run(args=change_delay)
- remote.run(args=show_tc(), stdout=StringIO())
+ remote.run(args=show_tc(interface), stdout=StringIO())
-def delete_dev(remote):
+def delete_dev(remote, interface):
""" Delete the qdisc if present"""
log.info('Delete tc')
- r = remote.run(args=show_tc(), stdout=StringIO())
+ r = remote.run(args=show_tc(interface), stdout=StringIO())
if r.stdout.getvalue().strip().find('refcnt') != -1:
- remote.run(args=del_tc())
+ remote.run(args=del_tc(interface))
class Toggle:
stop_event = gevent.event.Event()
- def __init__(self, remote, host, interval):
+ def __init__(self, remote, host, interface, interval):
self.remote = remote
self.host = host
self.interval = interval
+ self.interface = interface
self.ip = socket.gethostbyname(self.host.hostname)
def packet_drop(self):
""" Drop packets to the remote ip specified"""
- _, _, set_ip = cmd_prefix()
+ _, _, set_ip = cmd_prefix(self.interface)
- r = self.remote.run(args=show_tc(), stdout=StringIO())
+ r = self.remote.run(args=show_tc(self.interface), stdout=StringIO())
if r.stdout.getvalue().strip().find('refcnt') == -1:
- self.remote.run(args=set_priority())
+ self.remote.run(args=set_priority(self.interface))
# packet drop to specific ip
log.info('Drop all packets to %s' % self.host)
set_ip.extend(['%s' % self.ip, 'action', 'drop'])
self.stop_event.wait(timeout=self.interval)
# if qdisc exist,delete it.
try:
- delete_dev(self.remote)
+ delete_dev(self.remote, self.interface)
log.info('link up')
except SSHException as e:
log.debug('Failed to run command')
"""
- netem:
clients: [c1.rgw.0]
+ iface: eno1
dst_client: [c2.rgw.1]
delay: 10ms
- netem:
clients: [c1.rgw.0]
+ iface: eno1
dst_client: [c2.rgw.1]
delay_range: [10ms, 20ms] # (min, max)
- netem:
clients: [rgw.1, mon.0]
+ iface: eno1
dst_client: [c2.rgw.1]
link_toggle_interval: 10 # no unit mentioned. By default takes seconds.
- netem:
clients: [rgw.1, mon.0]
+ iface: eno1
link_recover: true
if config.get('dst_client') is not None:
dst = config.get('dst_client')
(host,) = ctx.cluster.only(dst).remotes.iterkeys()
- ctx.netem.host = host
for role in config.get('clients', None):
(remote,) = ctx.cluster.only(role).remotes.iterkeys()
ctx.netem.remote = remote
if config.get('delay', False):
- static_delay(remote, host, config.get('delay'))
+ static_delay(remote, host, config.get('iface'), config.get('delay'))
if config.get('delay_range', False):
- variable_delay(remote, host, config.get('delay_range'))
+ variable_delay(remote, host, config.get('iface'), config.get('delay_range'))
if config.get('link_toggle_interval', False):
log.info('Toggling link for %s' % config.get('link_toggle_interval'))
global toggle
- toggle = Toggle(remote, host, config.get('link_toggle_interval'))
+ toggle = Toggle(remote, host, config.get('iface'), config.get('link_toggle_interval'))
ctx.netem.toggle = toggle
toggle.begin()
if config.get('link_recover', False):
toggle.end()
log.info('sleeping')
time.sleep(config.get('link_toggle_interval'))
- delete_dev(ctx.netem.remote)
+ delete_dev(ctx.netem.remote, config.get('iface'))
try:
ctx.netem.toggle.end()
for role in config.get('clients'):
(remote,) = ctx.cluster.only(role).remotes.iterkeys()
- delete_dev(remote)
+ delete_dev(remote, config.get('iface'))