Server-side NIC selection for the collector
This commit is contained in:
111
tests/test_plugins/test_collector_network_interfaces.py
Normal file
111
tests/test_plugins/test_collector_network_interfaces.py
Normal file
@@ -0,0 +1,111 @@
|
||||
"""Which NIC becomes the PC's address, and what happens to the others.
|
||||
|
||||
The bay used to choose. It cannot: it does not know the site's addressing. A
|
||||
CMM whose Marvell AQtion 10Gbit link to its controller sits on 100.0.0.1
|
||||
reported THAT as the PC's address - the link carries a default route too - and
|
||||
the corporate address was never sent at all, so ShopDB could not show it even
|
||||
as a second row.
|
||||
|
||||
The bay now reports every NIC and takes no view. These pin the server side.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from shopdb.core.models import Asset, AssetType, Communication, CommunicationType
|
||||
|
||||
KEY = 'network-key'
|
||||
CORP = '10.48.255.210'
|
||||
MACHINE_LINK = '100.0.0.1'
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def collector_key(app):
|
||||
old = app.config.get('COLLECTOR_API_KEY')
|
||||
app.config['COLLECTOR_API_KEY'] = KEY
|
||||
yield KEY
|
||||
app.config['COLLECTOR_API_KEY'] = old
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def rig(db):
|
||||
if not AssetType.query.filter_by(assettype='computer').first():
|
||||
db.session.add(AssetType(assettype='computer'))
|
||||
if not CommunicationType.query.filter_by(comtype='IP').first():
|
||||
db.session.add(CommunicationType(comtype='IP'))
|
||||
db.session.commit()
|
||||
|
||||
|
||||
def _report(client, key, hostname, interfaces):
|
||||
return client.post('/api/collector/computers',
|
||||
json={'hostname': hostname, 'interfaces': interfaces},
|
||||
headers={'X-API-Key': key})
|
||||
|
||||
|
||||
def _comms(hostname):
|
||||
asset = Asset.query.filter_by(assetnumber=hostname).first()
|
||||
return Communication.query.filter_by(assetid=asset.assetid).all()
|
||||
|
||||
|
||||
BENS_CMM = [
|
||||
{'ipaddress': MACHINE_LINK, 'macaddress': 'AA:BB:CC:00:00:01',
|
||||
'adaptername': 'Marvell AQtion 10Gbit Network Adapter', 'isdefaultroute': True},
|
||||
{'ipaddress': CORP, 'macaddress': 'AA:BB:CC:00:00:02',
|
||||
'adaptername': 'Intel I219-LM', 'isdefaultroute': True},
|
||||
]
|
||||
|
||||
|
||||
def test_both_addresses_are_recorded(client, db, rig, collector_key):
|
||||
"""The one that is not primary must still EXIST. It used to be discarded."""
|
||||
_report(client, collector_key, 'CMM01', BENS_CMM)
|
||||
addresses = {c.ipaddress for c in _comms('CMM01')}
|
||||
assert addresses == {MACHINE_LINK, CORP}
|
||||
|
||||
|
||||
def test_the_configured_range_decides_the_primary(client, db, rig, collector_key):
|
||||
"""With the site's range named, the machine link cannot win."""
|
||||
from shopdb.core.models import Setting
|
||||
Setting.set('collector_corporate_ranges', '10.48.0.0/16',
|
||||
valuetype='string', category='computers')
|
||||
db.session.commit()
|
||||
|
||||
_report(client, collector_key, 'CMM02', BENS_CMM)
|
||||
primary = [c for c in _comms('CMM02') if c.isprimary]
|
||||
assert len(primary) == 1
|
||||
assert primary[0].ipaddress == CORP
|
||||
|
||||
|
||||
def test_exactly_one_primary_even_when_both_claim_a_default_route(
|
||||
client, db, rig, collector_key):
|
||||
"""Ben's CMM: two NICs, both routing. Ambiguous, but never two primaries."""
|
||||
_report(client, collector_key, 'CMM03', BENS_CMM)
|
||||
assert sum(1 for c in _comms('CMM03') if c.isprimary) == 1
|
||||
|
||||
|
||||
def test_a_second_checkin_does_not_duplicate_rows(client, db, rig, collector_key):
|
||||
"""Keyed on the MAC, so the same NIC updates rather than accumulating."""
|
||||
_report(client, collector_key, 'CMM04', BENS_CMM)
|
||||
_report(client, collector_key, 'CMM04', BENS_CMM)
|
||||
assert len(_comms('CMM04')) == 2
|
||||
|
||||
|
||||
def test_an_address_moving_to_another_nic_follows_the_mac(
|
||||
client, db, rig, collector_key):
|
||||
"""A MAC outlives an address, which is why it is the key."""
|
||||
_report(client, collector_key, 'CMM05', BENS_CMM)
|
||||
moved = [dict(entry) for entry in BENS_CMM]
|
||||
moved[1]['ipaddress'] = '10.48.255.211'
|
||||
_report(client, collector_key, 'CMM05', moved)
|
||||
|
||||
rows = _comms('CMM05')
|
||||
assert len(rows) == 2, 'a changed address must not mint a second row'
|
||||
assert '10.48.255.211' in {c.ipaddress for c in rows}
|
||||
|
||||
|
||||
def test_an_older_bay_sending_one_address_still_works(client, db, rig, collector_key):
|
||||
"""Bays run whatever collector they were imaged with."""
|
||||
client.post('/api/collector/computers',
|
||||
json={'hostname': 'CMM06', 'ipaddress': CORP},
|
||||
headers={'X-API-Key': collector_key})
|
||||
rows = _comms('CMM06')
|
||||
assert len(rows) == 1
|
||||
assert rows[0].ipaddress == CORP and rows[0].isprimary
|
||||
Reference in New Issue
Block a user