def test_run(self): """Test vring.""" dns = {'xxx.xx.com': '1.1.1.1', 'yyy.xx.com': '2.2.2.2'} socket.gethostbyname.side_effect = lambda hostname: dns[hostname] mock_discovery = treadmill.discovery.Discovery(None, 'a.a', None) treadmill.discovery.Discovery.iteritems.return_value = [ ('foo:tcp0', 'xxx.xx.com:12345'), ('foo:tcp1', 'xxx.xx.com:23456'), ('foo:tcp2', 'xxx.xx.com:34567'), ('bla:tcp0', 'yyy.xx.com:54321'), ] vring.run('ring_0', { 'tcp0': 10000, 'tcp1': 11000 }, ['tcp0'], mock_discovery) # Ignore all but tcp0 endpoints. # # Ignore tcp2 as it is not listed in the port map. treadmill.iptables.add_dnat_rule.assert_has_calls([ mock.call(('1.1.1.1', 10000, '1.1.1.1', '12345'), chain='ring_0'), mock.call(('2.2.2.2', 10000, '2.2.2.2', '54321'), chain='ring_0'), ]) treadmill.iptables.add_dnat_rule.reset() treadmill.discovery.Discovery.iteritems.return_value = [ ('foo:tcp0', 'xxx.xx.com:12345'), ('foo:tcp1', 'xxx.xx.com:23456'), ('foo:tcp2', 'xxx.xx.com:34567'), ('bla:tcp0', 'yyy.xx.com:54321'), ('foo:tcp0', None), ] vring.run('ring_0', { 'tcp0': 10000, 'tcp1': 11000 }, ['tcp0'], mock_discovery) treadmill.iptables.add_dnat_rule.assert_has_calls([ mock.call(('1.1.1.1', 10000, '1.1.1.1', '12345'), chain='ring_0'), mock.call(('2.2.2.2', 10000, '2.2.2.2', '54321'), chain='ring_0'), ]) # Check the rule is removed for foo:tcp0 endpoint. treadmill.iptables.delete_dnat_rule.assert_has_calls([ mock.call(('1.1.1.1', 10000, '1.1.1.1', '12345'), chain='ring_0') ])
def test_run_with_skip(self): """Test vring.""" dns = {'xxx.xx.com': '1.1.1.1', 'yyy.xx.com': '2.2.2.2'} socket.gethostbyname.side_effect = lambda hostname: dns[hostname] mock_discovery = treadmill.discovery.Discovery(None, 'a.a', None) treadmill.discovery.Discovery.iteritems.return_value = [ ('proid.foo#123:tcp:tcp_ep', 'xxx.xx.com:12345'), ('proid.foo#123:udp:udp_ep', 'xxx.xx.com:23456'), ('proid.foo#123:tcp:other_tcp_ep', 'xxx.xx.com:34567'), ('proid.bla#123:tcp:tcp_ep', 'yyy.xx.com:54321'), ] vring.run('ring_0', { 'tcp_ep': 10000, 'udp_ep': 11000 }, ['tcp_ep', 'udp_ep'], mock_discovery, skip=['yyy.xx.com']) # Ignore all but tcp0 endpoints. # # Ignore tcp2 as it is not listed in the port map. self.assertEquals(treadmill.iptables.add_dnat_rule.call_count, 2) treadmill.iptables.add_dnat_rule.assert_has_calls([ mock.call(treadmill.firewall.DNATRule('tcp', '1.1.1.1', 10000, '1.1.1.1', 12345), chain='ring_0'), mock.call(treadmill.firewall.DNATRule('udp', '1.1.1.1', 11000, '1.1.1.1', 23456), chain='ring_0'), ], any_order=True) self.assertEquals(treadmill.iptables.add_snat_rule.call_count, 2) treadmill.iptables.add_snat_rule.assert_has_calls([ mock.call(treadmill.firewall.SNATRule('tcp', '1.1.1.1', 12345, '1.1.1.1', 10000), chain='ring_0'), mock.call(treadmill.firewall.SNATRule('udp', '1.1.1.1', 23456, '1.1.1.1', 11000), chain='ring_0'), ], any_order=True)
def vring_cmd(approot, manifest): """Run vring manager.""" context.GLOBAL.zk.conn.add_listener(zkutils.exit_on_disconnect) tm_env = appenv.AppEnvironment(approot) app = yaml.load(stream=manifest) with lc.LogContext(_LOGGER, app['name'], lc.ContainerAdapter) as log: # TODO(boysson): Remove all validation from here. utils.validate(app, [('vring', True, dict)]) ring = app['vring'] utils.validate(ring, [('rules', True, list), ('cells', True, list)]) if context.GLOBAL.cell not in ring['cells']: log.critical('cell %s not listed in vring.', context.GLOBAL.cell) sys.exit(-1) rules = ring['rules'] for rule in rules: utils.validate(rule, [('pattern', True, str), ('endpoints', True, list)]) # Create translation for endpoint name to expected port #. routing = {} for endpoint in app.get('endpoints', []): routing[endpoint['name']] = { 'port': endpoint['port'], 'proto': endpoint['proto'] } # Check that all ring endpoints are listed in the manifest. vring_endpoints = set() for rule in rules: for rule_endpoint in rule['endpoints']: if rule_endpoint not in routing: log.critical( 'vring references non-existing endpoint: [%s]', rule_endpoint) sys.exit(-1) vring_endpoints.add(rule_endpoint) # TODO: discovery is limited to one rule for now. if len(rules) != 1: log.critical('(TODO): multiple rules are not supported.') sys.exit(-1) pattern = rules[0]['pattern'] app_unique_name = appcfg.manifest_unique_name(app) app_discovery = discovery.Discovery(context.GLOBAL.zk.conn, pattern, '*') app_discovery.sync() # Restore default signal mask disabled by python spawning new # thread for Zk connection. # # TODO: should this be done as part of ZK connect? for sig in range(1, signal.NSIG): try: signal.signal(sig, signal.SIG_DFL) except RuntimeError: pass vring.run( routing, vring_endpoints, app_discovery, tm_env.rules, app['network']['vip'], app_unique_name, )
def vring_cmd(approot, manifest): """Run vring manager.""" context.GLOBAL.zk.conn.add_listener(zkutils.exit_on_disconnect) tm_env = appenv.AppEnvironment(approot) with io.open(manifest, 'r') as fd: app = json.load(fd) with lc.LogContext(_LOGGER, app['name'], lc.ContainerAdapter) as log: # TODO(boysson): Remove all validation from here. utils.validate(app, [('vring', True, dict)]) ring = app['vring'] utils.validate(ring, [('rules', True, list), ('cells', True, list)]) if context.GLOBAL.cell not in ring['cells']: log.critical('cell %s not listed in vring.', context.GLOBAL.cell) sys.exit(-1) rules = ring['rules'] for rule in rules: utils.validate(rule, [('pattern', True, str), ('endpoints', True, list)]) # Create translation for endpoint name to expected port #. routing = {} for endpoint in app.get('endpoints', []): routing[endpoint['name']] = { 'port': endpoint['port'], 'proto': endpoint['proto'] } # Check that all ring endpoints are listed in the manifest. vring_endpoints = set() for rule in rules: for rule_endpoint in rule['endpoints']: if rule_endpoint not in routing: log.critical( 'vring references non-existing endpoint: [%s]', rule_endpoint) sys.exit(-1) vring_endpoints.add(rule_endpoint) patterns = [rule['pattern'] for rule in rules] app_discovery = discovery.Discovery(context.GLOBAL.zk.conn, patterns, '*') app_discovery.sync() # Restore default signal mask disabled by python spawning new # thread for Zk connection. # # TODO: should this be done as part of ZK connect? utils.restore_signals() app_unique_name = appcfg.manifest_unique_name(app) vring.run( routing, vring_endpoints, app_discovery, tm_env.rules, app['network']['vip'], app_unique_name, )
def test_run(self): """Test vring.""" dns = { 'xxx.xx.com': '1.1.1.1', 'yyy.xx.com': '2.2.2.2', 'zzz.xx.com': '3.3.3.3', } def _mock_gethostbyname(hostname): res = dns.get(hostname, None) if res is not None: return res raise socket.gaierror(-2, 'Name or service not known') socket.gethostbyname.side_effect = _mock_gethostbyname treadmill.sysinfo.hostname.return_value = 'zzz.xx.com' mock_discovery = treadmill.discovery.Discovery(None, 'a.a', None) mock_rulemgr = treadmill.rulefile.RuleMgr('/test', '/owners') treadmill.discovery.Discovery.iteritems.return_value = [ ('proid.foo#123:tcp:tcp_ep', 'xxx.xx.com:12345'), ('proid.foo#123:udp:udp_ep', 'xxx.xx.com:23456'), ('proid.foo#123:tcp:other_tcp_ep', 'xxx.xx.com:34567'), ('proid.foo#124:tcp:tcp_ep', 'zzz.xx.com:12345'), ('proid.foo#124:udp:udp_ep', 'zzz.xx.com:23456'), ('proid.foo#124:tcp:other_tcp_ep', 'zzz.xx.com:34567'), ('proid.foo#666:tcp:tcp_ep', 'bad:12345'), ('proid.foo#666:udp:udp_ep', 'bad:23456'), ('proid.foo#666:tcp:other_tcp_ep', 'zzz.xx.com:34567'), ('proid.foo#125:tcp:tcp_ep', 'yyy.xx.com:45678'), ('proid.foo#125:udp:udp_ep', 'yyy.xx.com:56789'), ('proid.foo#125:tcp:other_tcp_ep', 'yyy.xx.com:34567'), ] vring.run( { 'tcp_ep': { 'port': 10000, 'proto': 'tcp', }, 'udp_ep': { 'port': 11000, 'proto': 'udp' }, }, ['tcp_ep', 'udp_ep'], mock_discovery, mock_rulemgr, '192.168.7.7', 'proid.foo#124') # Ignore all but tcp0 endpoints. # # Ignore tcp2 as it is not listed in the port map. mock_rulemgr.create_rule.assert_has_calls([ mock.call(chain=treadmill.iptables.VRING_DNAT, rule=treadmill.firewall.DNATRule(proto='tcp', src_ip='192.168.7.7', dst_ip='3.3.3.3', dst_port=10000, new_ip='192.168.7.7', new_port=10000), owner='proid.foo#124'), mock.call(chain=treadmill.iptables.VRING_DNAT, rule=treadmill.firewall.DNATRule(proto='udp', src_ip='192.168.7.7', dst_ip='3.3.3.3', dst_port=11000, new_ip='192.168.7.7', new_port=11000), owner='proid.foo#124'), mock.call(chain=treadmill.iptables.VRING_DNAT, rule=treadmill.firewall.DNATRule(proto='tcp', src_ip='192.168.7.7', dst_ip='1.1.1.1', dst_port=10000, new_ip='1.1.1.1', new_port=12345), owner='proid.foo#124'), mock.call(chain=treadmill.iptables.VRING_SNAT, rule=treadmill.firewall.SNATRule(proto='tcp', src_ip='1.1.1.1', src_port=12345, dst_ip='192.168.7.7', new_ip='1.1.1.1', new_port=10000), owner='proid.foo#124'), mock.call(chain=treadmill.iptables.VRING_DNAT, rule=treadmill.firewall.DNATRule(proto='udp', src_ip='192.168.7.7', dst_ip='1.1.1.1', dst_port=11000, new_ip='1.1.1.1', new_port=23456), owner='proid.foo#124'), mock.call(chain=treadmill.iptables.VRING_SNAT, rule=treadmill.firewall.SNATRule(proto='udp', src_ip='1.1.1.1', src_port=23456, dst_ip='192.168.7.7', new_ip='1.1.1.1', new_port=11000), owner='proid.foo#124'), mock.call(chain=treadmill.iptables.VRING_DNAT, rule=treadmill.firewall.DNATRule( proto='tcp', src_ip='192.168.7.7', dst_ip='2.2.2.2', dst_port=10000, new_ip='2.2.2.2', new_port=45678, ), owner='proid.foo#124'), mock.call(chain=treadmill.iptables.VRING_SNAT, rule=treadmill.firewall.SNATRule(proto='tcp', src_ip='2.2.2.2', src_port=45678, dst_ip='192.168.7.7', new_ip='2.2.2.2', new_port=10000), owner='proid.foo#124'), mock.call(chain=treadmill.iptables.VRING_DNAT, rule=treadmill.firewall.DNATRule( proto='udp', src_ip='192.168.7.7', dst_ip='2.2.2.2', dst_port=11000, new_ip='2.2.2.2', new_port=56789, ), owner='proid.foo#124'), mock.call(chain=treadmill.iptables.VRING_SNAT, rule=treadmill.firewall.SNATRule(proto='udp', src_ip='2.2.2.2', src_port=56789, dst_ip='192.168.7.7', new_ip='2.2.2.2', new_port=11000), owner='proid.foo#124'), ], any_order=True) self.assertEqual(mock_rulemgr.create_rule.call_count, 10) mock_rulemgr.create_rule.reset_mock() ############ treadmill.discovery.Discovery.iteritems.return_value = [ ('proid.foo#123:tcp:tcp_ep', 'xxx.xx.com:12345'), ('proid.foo#123:udp:udp_ep', 'xxx.xx.com:23456'), ('proid.foo#123:tcp:other_tcp_ep', 'xxx.xx.com:34567'), ('proid.foo#124:tcp:tcp_ep', 'zzz.xx.com:12345'), ('proid.foo#124:udp:udp_ep', 'zzz.xx.com:23456'), ('proid.foo#124:tcp:other_tcp_ep', 'zzz.xx.com:34567'), ('proid.foo#123:tcp:tcp_ep', None), ('proid.foo#123:udp:udp_ep', None), ('proid.foo#123:tcp:other_tcp_ep', None), ('proid.foo#125:tcp:tcp_ep', None), ('proid.foo#125:udp:udp_ep', None), ('proid.foo#125:tcp:other_tcp_ep', None), ] vring.run( { 'tcp_ep': { 'port': 10000, 'proto': 'tcp', }, 'udp_ep': { 'port': 11000, 'proto': 'udp' }, }, ['tcp_ep', 'udp_ep'], mock_discovery, mock_rulemgr, '192.168.7.7', 'proid.foo#124') mock_rulemgr.create_rule.assert_has_calls([ mock.call(chain=treadmill.iptables.VRING_DNAT, rule=treadmill.firewall.DNATRule(proto='tcp', src_ip='192.168.7.7', dst_ip='3.3.3.3', dst_port=10000, new_ip='192.168.7.7', new_port=10000), owner='proid.foo#124'), mock.call(chain=treadmill.iptables.VRING_DNAT, rule=treadmill.firewall.DNATRule(proto='udp', src_ip='192.168.7.7', dst_ip='3.3.3.3', dst_port=11000, new_ip='192.168.7.7', new_port=11000), owner='proid.foo#124'), mock.call(chain=treadmill.iptables.VRING_DNAT, rule=treadmill.firewall.DNATRule(proto='tcp', src_ip='192.168.7.7', dst_ip='1.1.1.1', dst_port=10000, new_ip='1.1.1.1', new_port=12345), owner='proid.foo#124'), mock.call(chain=treadmill.iptables.VRING_SNAT, rule=treadmill.firewall.SNATRule(proto='tcp', src_ip='1.1.1.1', src_port=12345, dst_ip='192.168.7.7', new_ip='1.1.1.1', new_port=10000), owner='proid.foo#124'), mock.call(chain=treadmill.iptables.VRING_DNAT, rule=treadmill.firewall.DNATRule(proto='udp', src_ip='192.168.7.7', dst_ip='1.1.1.1', dst_port=11000, new_ip='1.1.1.1', new_port=23456), owner='proid.foo#124'), mock.call(chain=treadmill.iptables.VRING_SNAT, rule=treadmill.firewall.SNATRule(proto='udp', src_ip='1.1.1.1', src_port=23456, dst_ip='192.168.7.7', new_ip='1.1.1.1', new_port=11000), owner='proid.foo#124'), ], any_order=True) self.assertEqual(mock_rulemgr.create_rule.call_count, 6) # Check the rule is removed for foo#123 but not foo#125. mock_rulemgr.unlink_rule.assert_has_calls([ mock.call(chain=treadmill.iptables.VRING_DNAT, rule=treadmill.firewall.DNATRule(proto='tcp', src_ip='192.168.7.7', dst_ip='1.1.1.1', dst_port=10000, new_ip='1.1.1.1', new_port=12345), owner='proid.foo#124'), mock.call(chain=treadmill.iptables.VRING_SNAT, rule=treadmill.firewall.SNATRule(proto='tcp', src_ip='1.1.1.1', src_port=12345, dst_ip='192.168.7.7', new_ip='1.1.1.1', new_port=10000), owner='proid.foo#124'), mock.call(chain=treadmill.iptables.VRING_DNAT, rule=treadmill.firewall.DNATRule(proto='udp', src_ip='192.168.7.7', dst_ip='1.1.1.1', dst_port=11000, new_ip='1.1.1.1', new_port=23456), owner='proid.foo#124'), mock.call(chain=treadmill.iptables.VRING_SNAT, rule=treadmill.firewall.SNATRule(proto='udp', src_ip='1.1.1.1', src_port=23456, dst_ip='192.168.7.7', new_ip='1.1.1.1', new_port=11000), owner='proid.foo#124'), ], any_order=True) self.assertEqual(mock_rulemgr.unlink_rule.call_count, 4)