コード例 #1
0
    def update_graph():
        weights = [
            lb.get_dip_weight(POOL_HANDLE, ip, p)
            for (ip, p) in sorted(server_IPs.keys())
        ]
        loads = yield all_results(
            [server.callRemote('get_load', loadavg) for server in servers])
        conns = yield all_results(
            [server.callRemote('get_conn_count') for server in servers])
        now = (datetime.now() - demo_start).total_seconds()

        data = [now] + weights + loads + conns
        with open('./data.tsv', 'a') as f:
            f.write('{}\n'.format('\t'.join([str(x) for x in data])))
            f.flush()
コード例 #2
0
def test_dont_drop(remote_module, p4run):
    lb, client, server1 = yield all_results([
        LoadBalancer.get_initialised('s1', topology_db_file=p4run.topo_path),
        remote_module('myutils.client', host='h3'),
        remote_module('myutils.server', 8001, host='h1'),
    ])
    server1_ip, server2_ip = [p4run.topo.get_host_ip(h) for h in ('h1', 'h2')]

    pool_handle = yield lb.add_pool('10.0.0.1', 8000)
    print(' --------- v1: {server1} ---------')
    yield lb.add_dip(pool_handle, server1_ip, 8001)
    yield lb.commit()
    yield client.callRemote('start_echo_clients', '10.0.0.1', 8000, count=5)
    time.sleep(0.5)  # make sure the clients have connected
    print(' --------- v2: {server2} ---------')
    yield lb.rm_dip(pool_handle, server1_ip, 8001)
    yield lb.add_dip(pool_handle, server2_ip, 8001)
    yield lb.commit()
    time.sleep(0.5)  # give it time to notice the breakage, if any

    # test #1: this does not explode :D -- this would throw if something bad happened to the connections
    yield client.callRemote('close_all_connections')

    nconns = yield server1.callRemote('get_conn_count')
    assert nconns == 5
コード例 #3
0
def test_connections_break(remote_module, p4run):
    """
    Tests that connections break when the pool changes. Exists to avoid false positives.

    Same as `l4_loadbalancer/keep_connections_test.py:test_old_versions`,
    but uses the unversioned thing and expects it to fail."""
    lb, client, server1, server2 = yield all_results([
        LoadBalancerUnversioned.get_initialised('s1', topology_db_file=p4run.topo_path),
        remote_module('myutils.client', host='h3'),
        remote_module('myutils.server', 8001, host='h1'),
        remote_module('myutils.server', 8001, host='h2'),
    ])
    yield sleep(0.5)
    server1_ip, server2_ip = [p4run.topo.get_host_ip(h) for h in ('h1', 'h2')]

    pool_handle = yield lb.add_pool('10.0.0.1', 8000)
    print(' --------- create a pool with server1 ---------')
    yield lb.add_dip(pool_handle, server1_ip, 8001)
    yield client.callRemote('start_echo_clients', '10.0.0.1', 8000, count=5)
    yield sleep(0.5)  # make sure the clients have connected
    print(' --------- break it: change the pool ---------')
    yield lb.rm_dip(pool_handle, server1_ip, 8001)
    yield lb.add_dip(pool_handle, server2_ip, 8001)
    yield sleep(0.5)  # give time to notice the breakage

    with pytest.raises(pb.RemoteError) as excinfo:
        # this should throw a ConnectionLost, because we broke the connections
        yield client.callRemote('close_all_connections')
    assert 'ConnectionLost' in str(excinfo)
コード例 #4
0
 def adjust_weights(self):
     for pool, dips_ in self.pool_hashes.items():
         dips = sorted(dips_.keys())
         loads = yield all_results(
             [defer.maybeDeferred(self.get_metrics, *dip) for dip in dips])
         wanted = self.normalise(self.metrics_to_weights(loads))
         for (dip, dport), w in zip(dips, wanted):
             yield self.set_dip_weight(pool, dip, dport, w)
     yield self.commit()
コード例 #5
0
 def prefill_mac_table(self):
     # * MAC associations to hosts
     ds = []
     for h in self.topo.get_hosts_connected_to(self.sw_name):
         mac = self.topo.get_host_mac(h)
         port = self.topo.node_to_node_port_num(self.sw_name, h)
         ds.append(
             self.controller.table_add("mac", "forward", [mac],
                                       [str(port)]))
     yield all_results(ds)
コード例 #6
0
def test_echo_client(remote_module):
    client, server = yield all_results([
        remote_module('myutils.client', host=None),
        remote_module('myutils.server', 8000, host=None),
    ])
    yield client.callRemote('start_echo_clients', 'localhost', 8000, count=5)
    yield sleep(0.5)  # make sure the clients have connected
    yield client.callRemote('close_all_connections')

    nconns1 = yield server.callRemote('get_conn_count')
    assert nconns1 == 5
コード例 #7
0
def test_add_dip(remote_module, p4run):
    print(' --------- prepare server, client, and loadbalancer ---------')
    client, server, lb = yield all_results([
        remote_module('myutils.client', host='h1'),
        remote_module('myutils.server', 8001, host='h2'),
        LoadBalancer.get_initialised('s1', topology_db_file=p4run.topo_path),
    ])
    print(' --------- set up the pool ---------')
    pool_h = yield lb.add_pool('10.0.0.1', 8000)
    yield lb.add_dip(pool_h, p4run.topo.get_host_ip('h2'), 8001)
    print(' --------- check that it worked ---------')
    yield client.callRemote('make_connections', '10.0.0.1', 8000, count=47)
    num_conns = yield server.callRemote('get_conn_count')
    print('{}/47 connections successful'.format(num_conns))
    assert num_conns == 47
コード例 #8
0
def test_equal_balancing(remote_module, p4run):
    NUM_CONNS = 1000
    TOLERANCE = 0.8

    pools = {
        ('10.0.0.1', 8000): [('h1', 8001), ('h2', 8002), ('h3', 8003)],
        ('10.0.0.1', 7000): [('h1', 7000)]
    }

    # create pools
    lb = yield LoadBalancer.get_initialised('s1',
                                            topology_db_file=p4run.topo_path)
    for vip, dips in pools.items():
        pool_h = yield lb.add_pool(*vip)
        for dip in dips:
            yield lb.add_dip(pool_h, p4run.topo.get_host_ip(dip[0]), dip[1])

    print(' ----- vips + inverse: -----')
    pprint(lb.vips.data)
    pprint(lb.vips_inverse.data)
    print(' ----- dips + inverse: -----')
    pprint(lb.dips.data)
    pprint(lb.dips_inverse.data)

    # run the servers
    servers = {}  # vip => [server remote]
    for vip, dips in pools.items():
        servers[vip] = []
        server_ds = []
        for dip in dips:
            dhost, dport = dip
            server_ds.append(remote_module('myutils.server', dport,
                                           host=dhost))
        servers[vip] = yield all_results(server_ds)

    # run the client
    client = yield remote_module('myutils.client', host='h4')
    for vip in pools:
        yield client.callRemote('make_connections', *vip, count=NUM_CONNS)

    # check the servers' connection counts
    for vip, dips in pools.items():
        expected_conns = TOLERANCE * NUM_CONNS / len(dips)
        for server in servers[vip]:
            num_conns = yield server.callRemote('get_conn_count')
            assert num_conns >= expected_conns, "[FLAKY] distribution should be approximately uniform"
コード例 #9
0
def test_rm_dip(remote_module, p4run):
    print(' --------- prepare server, client, and loadbalancer ---------')
    client, server, lb = yield all_results([
        remote_module('myutils.client', host='h1'),
        remote_module('myutils.server', 8001, host='h2'),
        LoadBalancer.get_initialised('s1', topology_db_file=p4run.topo_path),
    ])
    print(' --------- set up the pool ---------')
    pool_h = yield lb.add_pool('10.0.0.1', 8000)
    yield lb.add_dip(pool_h, p4run.topo.get_host_ip('h3'),
                     8001)  # will remove this later
    yield lb.add_dip(pool_h, p4run.topo.get_host_ip('h2'), 8001)
    yield lb.rm_dip(pool_h, p4run.topo.get_host_ip('h3'), 8001)  # tadaaa :D
    print(' ----- dips: -----')
    pprint(lb.dips.data)
    print(' --------- check that it worked ---------')
    yield client.callRemote('make_connections', '10.0.0.1', 8000, count=47)
    num_conns = yield server.callRemote('get_conn_count')
    assert num_conns == 47, "everything should go to h2 because h3 was removed"
コード例 #10
0
def test_rollover_active_conns(remote_module, p4run):
    lb, client1, client2, server1, server2 = yield all_results([
        LoadBalancer.get_initialised('s1', topology_db_file=p4run.topo_path),
        remote_module('myutils.client', host='h3'),
        remote_module('myutils.client', host='h4'),
        remote_module('myutils.server', 8001, host='h1'),
        remote_module('myutils.server', 8001, host='h2'),
    ])
    server1_ip, server2_ip = [p4run.topo.get_host_ip(h) for h in ('h1', 'h2')]

    pool_handle = yield lb.add_pool('10.0.0.1', 8000)

    for i in range(5):
        print(' --------- v1: server1 ---------')
        yield lb.add_dip(pool_handle, server1_ip, 8001)
        yield lb.commit()
        yield client1.callRemote('start_echo_clients',
                                 '10.0.0.1',
                                 8000,
                                 count=5)
        yield sleep(0.5)  # make sure the clients have connected
        print(' --------- v2: server2 ---------')
        yield lb.rm_dip(pool_handle, server1_ip, 8001)
        yield lb.add_dip(pool_handle, server2_ip, 8001)
        # roll over the version => eat old pending tables
        for i in range(5):
            yield lb.commit()
        yield client2.callRemote('start_echo_clients',
                                 '10.0.0.1',
                                 8000,
                                 count=3)
        yield sleep(0.5)  # give it time to notice the breakage, if any

        # this would throw if something bad happened to the connections
        yield client1.callRemote('close_all_connections')
        yield client2.callRemote('close_all_connections')

        yield check_conn_count(server1, 5)
        yield check_conn_count(server2, 3)

        yield lb.rm_dip(pool_handle, server2_ip,
                        8001)  # clean up before next iteration
コード例 #11
0
def test_direct_conn(remote_module, p4run):
    print(' --------- prepare server, client, and loadbalancer ---------')
    client, server, lb = yield all_results([
        remote_module('myutils.client', host='h1'),
        remote_module('myutils.server', 8000, host='h2'),
        LoadBalancer.get_initialised('s1', topology_db_file=p4run.topo_path),
    ])
    print(
        " --------- add a random pool: unused, just to make sure it doesn't mess things up ---------"
    )
    pool_h = yield lb.add_pool('10.0.0.1', 4700)
    yield lb.add_dip(pool_h, p4run.topo.get_host_ip('h1'), 4700)
    yield lb.add_dip(pool_h, p4run.topo.get_host_ip('h2'), 4700)
    yield lb.commit()
    print(' --------- check that it worked ---------')
    yield client.callRemote('make_connections',
                            p4run.topo.get_host_ip('h2'),
                            8000,
                            count=47)
    num_conns = yield server.callRemote('get_conn_count')
    assert num_conns == 47
コード例 #12
0
ファイル: main.py プロジェクト: Williamren97/sdn-loadbalancer
def demo(reactor):
    lines = WaitForLines()
    stdio.StandardIO(lines)

    ##### Preparation #######################################################

    # These are our servers.
    server_hosts = [
        # host, port, num CPUs
        ('h1', 9000, 1),
        ('h1', 9001, 2),
        ('h2', 9002, 4),
        ('h2', 9003, 8),
    ]

    # Run the server and client programs and get a "remote control" to them.
    servers = yield all_results([
        remote_module('myutils.server', port, ncpus, host=host)
        for host, port, ncpus in server_hosts
    ])
    clients = yield all_results([
        remote_module('myutils.client', host='h3'),
        remote_module('myutils.client', host='h4'),
    ])

    # Build an (ip, port) => server remote dict to use later.
    topo = Topology('./topology.db')
    server_IPs = {(topo.get_host_ip(h), p): remote
                  for (h, p, _), remote in zip(server_hosts, servers)}

    # Teach my load balancer controller how to get load from the servers.
    # In real life I could be e.g. SSHing into the servers, or using my
    # monitoring infrastructure.
    def get_load(ip, port):
        return server_IPs[(ip, port)].callRemote('get_load', 20)

    def set_weights(loads):
        return [1.0 / load for load in loads]

    # And start the controller.
    lb = yield MetricsLoadBalancer.get_initialised(
        's1', get_metrics=get_load, metrics_to_weights=set_weights)

    # Create a server pool on the loadbalancer.
    pool_handle = yield lb.add_pool('10.0.0.1', 8000)
    for ip, port in server_IPs.keys():
        yield lb.add_dip(pool_handle, ip, port)
    yield lb.commit()

    ##### Now the fun begins ################################################

    setup_graph(server_IPs, lb, 10)

    print('---------------- press Enter to start clients -----------------')
    yield lines.line_received

    @defer.inlineCallbacks
    def client0():
        """Client 0 will send long-running requests: closes after 10 seconds."""
        print('client0 running')
        yield clients[0].callRemote('start_echo_clients',
                                    '10.0.0.1',
                                    8000,
                                    count=4)
        yield sleep(10)
        yield clients[0].callRemote('close_all_connections')

    @defer.inlineCallbacks
    def client1():
        """Client 1 will send bursts of short connections (2s)."""
        print('client1 running')
        yield clients[1].callRemote('start_echo_clients',
                                    '10.0.0.1',
                                    8000,
                                    count=20)
        yield sleep(2)
        yield clients[1].callRemote('close_all_connections')

    # Run client0 every 13 seconds.
    task.LoopingCall(client0).start(13)

    # Run client1 every 4 seconds.
    task.LoopingCall(client1).start(3)

    print(
        '---------------- press Enter to start adjusting weights ----------------'
    )
    yield lines.line_received

    lb.start_loop()