def test_get_port_networks(self, switch): """Test the get_port_networks method""" with requests_mock.mock() as mock: PORT1 = model.Port(label=INTERFACE1, switch=switch) PORT2 = model.Port(label=INTERFACE2, switch=switch) PORT3 = model.Port(label=INTERFACE3, switch=switch) mock.get(switch._construct_url(INTERFACE1, suffix='trunk'), text=TRUNK_NATIVE_VLAN_RESPONSE_WITH_VLANS) mock.get(switch._construct_url(INTERFACE2, suffix='trunk'), text=TRUNK_NATIVE_VLAN_RESPONSE_NO_VLANS) mock.get(switch._construct_url(INTERFACE3, suffix='trunk'), text=TRUNK_VLAN_RESPONSE) response = switch.get_port_networks([PORT1, PORT2, PORT3]) assert response == { PORT1: [('vlan/native', '10'), ('vlan/4001', '4001'), ('vlan/4025', '4025')], PORT2: [('vlan/native', '10')], PORT3: [('vlan/1', '1'), ('vlan/4001', '4001'), ('vlan/4004', '4004'), ('vlan/4025', '4025'), ('vlan/4050', '4050')] }
def test_apply_networking(switch, network, fresh_database): '''Test to validate apply_networking commits actions incrementally This test verifies that the apply_networking() function in hil/deferred.py incrementally commits actions, which ensures that any error on an action will not require a complete rerun of the prior actions (e.g. if an error is thrown on the 3rd action, the 1st and 2nd action will have already been committed) The test also verifies that if a new networking action fails, then the old networking actions in the queue were commited. ''' nic = [] actions = [] # initialize 3 nics and networking actions for i in range(0, 3): interface = 'gi1/0/%d' % (i) nic.append(new_nic(str(i))) nic[i].port = model.Port(label=interface, switch=switch) actions.append( model.NetworkingAction(nic=nic[i], new_network=network, channel='vlan/native', type='modify_port')) # this makes the last action invalid for the test switch because the switch # raises an error when the networking action is of type revert port. actions[2] = model.NetworkingAction(nic=nic[2], new_network=None, channel='', type='revert_port') for action in actions: db.session.add(action) db.session.commit() with pytest.raises(RevertPortError): deferred.apply_networking() # close the session opened by `apply_networking` when `handle_actions` # fails; without this the tests would just stall (when using postgres) db.session.close() local_db = new_db() pending_action = local_db.session \ .query(model.NetworkingAction) \ .order_by(model.NetworkingAction.id).one_or_none() current_count = local_db.session \ .query(model.NetworkingAction).count() local_db.session.delete(pending_action) local_db.session.commit() local_db.session.close() # test that there's only pending action in the queue and it is of type # revert_port assert current_count == 1 assert pending_action.type == 'revert_port'
def switch_register_port(switch, port): """Register a port on a switch. If the port already exists, a DuplicateError will be raised. """ get_auth_backend().require_admin() switch = _must_find(model.Switch, switch) _assert_absent_n(switch, model.Port, port) port = model.Port(port, switch) db.session.add(port) db.session.commit()
def switch_register_port(switch, port): """Register a port on a switch. If the port already exists, a DuplicateError will be raised. """ get_auth_backend().require_admin() switch = get_or_404(model.Switch, switch) absent_child_or_conflict(switch, model.Port, port) switch.validate_port_name(port) port = model.Port(port, switch) db.session.add(port) db.session.commit()
def test_modify_port(self, switch, nic, network): """Test the modify_port method""" # Create a port on the switch and connect it to the nic port = model.Port(label=INTERFACE1, switch=switch) port.nic = nic # Test action to set a network as native action_native = model.NetworkingAction(type='modify_port', nic=nic, new_network=network, channel='vlan/native') with requests_mock.mock() as mock: url_switch = switch._construct_url(INTERFACE1) mock.post(url_switch) url_mode = switch._construct_url(INTERFACE1, suffix='mode') mock.put(url_mode) url_tag = switch._construct_url(INTERFACE1, suffix='trunk/tag/native-vlan') mock.delete(url_tag) url_trunk = switch._construct_url(INTERFACE1, suffix='trunk') mock.put(url_trunk) switch.modify_port(action_native.nic.port.label, action_native.channel, action_native.new_network.network_id) assert mock.called assert mock.call_count == 4 assert mock.request_history[0].text == SWITCHPORT_PAYLOAD assert mock.request_history[1].text == TRUNK_PAYLOAD assert mock.request_history[3].text == TRUNK_NATIVE_PAYLOAD # Test action to remove a native network action_rm_native = model.NetworkingAction(type='modify_port', nic=nic, new_network=None, channel='vlan/native') with requests_mock.mock() as mock: url_native = switch._construct_url(INTERFACE1, suffix='trunk/native-vlan') mock.delete(url_native) switch.modify_port(action_rm_native.nic.port.label, action_rm_native.channel, None) assert mock.called assert mock.call_count == 1 # Test action to add a vlan action_vlan = model.NetworkingAction(type='modify_port', nic=nic, new_network=network, channel='vlan/102') with requests_mock.mock() as mock: url_switch = switch._construct_url(INTERFACE1) mock.post(url_switch) url_mode = switch._construct_url(INTERFACE1, suffix='mode') mock.put(url_mode) url_trunk = switch._construct_url(INTERFACE1, suffix='trunk/allowed/vlan') mock.put(url_trunk) switch.modify_port(action_vlan.nic.port.label, action_vlan.channel, action_vlan.new_network.network_id) assert mock.called assert mock.call_count == 3 assert mock.request_history[0].text == SWITCHPORT_PAYLOAD assert mock.request_history[1].text == TRUNK_PAYLOAD assert mock.request_history[2].text == TRUNK_VLAN_PAYLOAD # Test action to remove a vlan action_rm_vlan = model.NetworkingAction(type='modify_port', nic=nic, new_network=None, channel='vlan/102') with requests_mock.mock() as mock: url_trunk = switch._construct_url(INTERFACE1, suffix='trunk/allowed/vlan') mock.put(url_trunk) switch.modify_port(action_rm_vlan.nic.port.label, action_rm_vlan.channel, None) assert mock.called assert mock.call_count == 1 assert mock.request_history[0].text == TRUNK_REMOVE_VLAN_PAYLOAD
def test_apply_networking(switch, network, fresh_database): '''Test to validate apply_networking commits actions incrementally This test verifies that the apply_networking() function in hil/deferred.py incrementally commits actions, which ensures that any error on an action will not require a complete rerun of the prior actions (e.g. if an error is thrown on the 3rd action, the 1st and 2nd action will have already been committed) The test also verifies that if a new networking action fails, then the old networking actions in the queue were commited. ''' nic = [] actions = [] # initialize 3 nics and networking actions for i in range(0, 2): interface = 'gi1/0/%d' % (i) nic.append(new_nic(str(i))) nic[i].port = model.Port(label=interface, switch=switch) unique_id = str(uuid.uuid4()) actions.append( model.NetworkingAction(nic=nic[i], new_network=network, channel='vlan/native', type='modify_port', uuid=unique_id, status='PENDING')) # Create another aciton of type revert_port. This action is invalid for the # test switch because the switch raises an error when the networking action # is of type revert port. unique_id = str(uuid.uuid4()) nic.append(new_nic('2')) nic[2].port = model.Port(label=interface, switch=switch) actions.append( model.NetworkingAction(nic=nic[2], new_network=None, uuid=unique_id, channel='', status='PENDING', type='revert_port')) # get some nic attributes before we close this db session. nic2_label = nic[2].label nic2_node = nic[2].owner.label for action in actions: db.session.add(action) db.session.commit() # simple check to ensure that right number of actions are added. total_count = db.session.query(model.NetworkingAction).count() assert total_count == 3 deferred.apply_networking() # close the session opened by `apply_networking` when `handle_actions` # fails; without this the tests would just stall (when using postgres) db.session.close() local_db = new_db() errored_action = local_db.session \ .query(model.NetworkingAction) \ .order_by(model.NetworkingAction.id).filter_by(status='ERROR') \ .one_or_none() # Count the number of actions with different statuses error_count = local_db.session \ .query(model.NetworkingAction).filter_by(status='ERROR').count() pending_count = local_db.session \ .query(model.NetworkingAction).filter_by(status='PENDING').count() done_count = local_db.session \ .query(model.NetworkingAction).filter_by(status='DONE').count() # test that there's only 1 action that errored out in the queue and that it # is of type revert_port assert error_count == 1 assert errored_action.type == 'revert_port' assert pending_count == 0 assert done_count == 2 local_db.session.commit() local_db.session.close() # add another action on a nic with a previously failed action. api.network_create('corsair', 'admin', '', '105') api.node_connect_network(nic2_node, nic2_label, 'corsair') # the api call should delete the errored action on that nic, and a new # pending action should appear. local_db = new_db() errored_action = local_db.session \ .query(model.NetworkingAction) \ .order_by(model.NetworkingAction.id).filter_by(status='ERROR') \ .one_or_none() pending_action = local_db.session \ .query(model.NetworkingAction) \ .order_by(model.NetworkingAction.id).filter_by(status='PENDING') \ .one_or_none() assert errored_action is None assert pending_action is not None local_db.session.commit() local_db.session.close()
def create_bigint_db(): """Create database objects used in 'after-PK-bigint.sql'""" from hil.ext.switches.n3000 import DellN3000 from hil.ext.switches.dell import PowerConnect55xx from hil.ext.switches.brocade import Brocade from hil.ext.switches.nexus import Nexus from hil.ext.switches.mock import MockSwitch from hil.ext.obm.ipmi import Ipmi from hil.ext.obm.mock import MockObm from hil.ext.auth.database import User from hil.ext.auth import database as dbauth with app.app_context(): db.session.add( DellN3000(label='sw-n3000', hostname='host', username='******', password='******', dummy_vlan='5', type=DellN3000.api_name)) dell1 = PowerConnect55xx(label='sw-dell', hostname='host', username='******', password='******', type=PowerConnect55xx.api_name) db.session.add(dell1) db.session.add( Nexus(label='sw-nexus', hostname='host', username='******', password='******', dummy_vlan='5', type=Nexus.api_name)) db.session.add( Brocade(label='sw-brocade', hostname='host', username='******', password='******', interface_type='4', type=Brocade.api_name)) db.session.add( MockSwitch(label='sw0', hostname='host', username='******', password='******', type=MockSwitch.api_name)) proj = model.Project(label='runway') db.session.add(proj) headnode1 = model.Headnode(label='runway_headnode', project=proj, base_img='image1') db.session.add(headnode1) db.session.add(model.Hnic(label='hnic1', headnode=headnode1)) ipmi = Ipmi(host='host', user='******', password='******') db.session.add(ipmi) mock_obm = MockObm(host='host', user='******', password='******') db.session.add(mock_obm) node1 = model.Node(label='node-1', obm=ipmi) db.session.add(node1) db.session.add( model.Metadata(label='meta', value="it is a true value", node=node1)) network1 = model.Network(owner=None, access=[proj], allocated=False, network_id="networking network", label='hil wireless') db.session.add(network1) nic1 = model.Nic(node=node1, label='pxe', mac_addr='ff:ff:ff:ff:ff:fe') model.Port(label='A fine port', switch=dell1) db.session.add(nic1) db.session.add( model.NetworkAttachment(nic=nic1, network_id=1, channel='vlan/100')) db.session.add( model.NetworkingAction(type='modify_port', nic=nic1, new_network=network1, channel='vlan/100')) jim = User(label='jim', password='******', is_admin=True) db.session.add(jim) local.auth = dbauth.User.query.filter_by(label='jim').one() dbauth.user_add_project('jim', 'runway') db.session.commit() # Original password is "pass" db.session.query(User).get(1).hashed_password = \ ('$6$rounds=656000$iTyrApYTUhMx4b4g$YcaMExV' 'YtS0ut2yXWrT64OggFpE4lLg12QsAuyMA3YKX6Czth' 'XeisA47dJZW9GwU2q2CTIVrsbpxAVT64Pih2/') db.session.commit()