def create_pending_actions_db(): """Create database objects including a pending NetworkingAction. The first version of this function was used to create the dump 'pending-networking-actions.sql'. """ # At a minimum we need a project, node, nic, switch, port, and network: api.project_create('runway') api.node_register( 'node-1', obm={ 'type': MOCK_OBM_TYPE, 'user': '******', 'host': 'host', 'password': '******', }, ) api.node_register_nic('node-1', 'pxe', 'de:ad:be:ef:20:16') api.switch_register('sw0', type=MOCK_SWITCH_TYPE, username='******', hostname='host', password='******', ) api.switch_register_port('sw0', 'gi1/0/4') api.port_connect_nic('sw0', 'gi1/0/4', 'node-1', 'pxe') api.project_connect_node('runway', 'node-1') api.network_create('runway_pxe', 'runway', 'runway', '') # Queue up a networking action. Importantly, we do *not* call # deferred.apply_networking, as that would flush the action and # remove it from the database. api.node_connect_network('node-1', 'pxe', 'runway_pxe')
def create_pending_actions_db(): """Create database objects including a pending NetworkingAction. The first version of this function was used to create the dump 'pending-networking-actions.sql'. """ # At a minimum we need a project, node, nic, switch, port, and network: api.project_create('runway') api.node_register( 'node-1', obm={ 'type': MOCK_OBM_TYPE, 'user': '******', 'host': 'host', 'password': '******', }, ) api.node_register_nic('node-1', 'pxe', 'de:ad:be:ef:20:16') api.switch_register( 'sw0', type=MOCK_SWITCH_TYPE, username='******', hostname='host', password='******', ) api.switch_register_port('sw0', 'gi1/0/4') api.port_connect_nic('sw0', 'gi1/0/4', 'node-1', 'pxe') api.project_connect_node('runway', 'node-1') api.network_create('runway_pxe', 'runway', 'runway', '') # Queue up a networking action. Importantly, we do *not* call # deferred.apply_networking, as that would flush the action and # remove it from the database. api.node_connect_network('node-1', 'pxe', 'runway_pxe')
def network_create_simple(network, project): """Create a simple project-owned network. This is a shorthand for the network_create API call, that defaults parameters to the most common case---namely, that the network is owned by a project, has access only by that project, and uses an allocated underlying net_id. Note that this is the only valid set of parameters for a network that belongs to a project. The test-suite uses this extensively, for tests that don't care about more complicated features of networks. """ api.network_create(network, project, project, "")
def test_create_network_with_id_outside_pool(self): # create an admin owned network api.network_create('hammernet', 'admin', '', 1511) # administrators should be able to make different networks with the # same network id api.network_create('starfish', 'admin', '', 1511) network = api._must_find(model.Network, 'starfish') net_id = int(network.network_id) assert network.allocated is False assert net_id == 1511
def test_create_network_with_id_outside_pool(self): """Test creation of networks whose ID is not in the pool.""" # create an admin owned network api.network_create('hammernet', 'admin', '', 1511) # administrators should be able to make different networks with the # same network id api.network_create('starfish', 'admin', '', 1511) network = api.get_or_404(model.Network, 'starfish') net_id = int(network.network_id) assert network.allocated is False assert net_id == 1511
def test_vlanid_for_admin_network(): """ Test for valid vlanID for administrator-owned networks. """ # create a network with a string vlan id with pytest.raises(errors.BadArgumentError): api.network_create('hammernet', 'admin', '', 'yes') # create a network with a vlanid>4096 with pytest.raises(errors.BadArgumentError): api.network_create('nailnet', 'admin', '', '5023') # create a netowrk with a vlanid<1 with pytest.raises(errors.BadArgumentError): api.network_create('nailnet', 'admin', '', '-2')
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 test_create_network_with_id_from_pool(self): """Test creation of networks with IDs from the pool.""" api.project_create('nuggets') # create a project owned network and get its network_id api.network_create('hammernet', 'nuggets', 'nuggets', '') network = api._must_find(model.Network, 'hammernet') net_id = int(network.network_id) assert network.allocated is True # create an admin owned network with net_id from pool api.network_create('nailnet', 'admin', '', 103) network = api._must_find(model.Network, 'nailnet') assert network.allocated is True # creating a network with the same network id should raise an error with pytest.raises(errors.BlockedError): api.network_create('redbone', 'admin', '', 103) with pytest.raises(errors.BlockedError): api.network_create('starfish', 'admin', '', net_id) # free the network ids by deleting the networks api.network_delete('hammernet') api.network_delete('nailnet') api._assert_absent(model.Network, 'hammernet') api._assert_absent(model.Network, 'nailnet') # after deletion we should be able to create admin networks with those # network_ids api.network_create('redbone', 'admin', '', 103) network = api._must_find(model.Network, 'redbone') assert int(network.network_id) == 103 api.network_create('starfish', 'admin', '', net_id) network = api._must_find(model.Network, 'starfish') assert int(network.network_id) == net_id
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 test_create_network_with_id_from_pool(self): """Test creation of networks with IDs from the pool.""" api.project_create('nuggets') # create a project owned network and get its network_id api.network_create('hammernet', 'nuggets', 'nuggets', '') network = api.get_or_404(model.Network, 'hammernet') net_id = int(network.network_id) assert network.allocated is True # create an admin owned network with net_id from pool api.network_create('nailnet', 'admin', '', 103) network = api.get_or_404(model.Network, 'nailnet') assert network.allocated is True # creating a network with the same network id should raise an error with pytest.raises(errors.BlockedError): api.network_create('redbone', 'admin', '', 103) with pytest.raises(errors.BlockedError): api.network_create('starfish', 'admin', '', net_id) # free the network ids by deleting the networks api.network_delete('hammernet') api.network_delete('nailnet') api.absent_or_conflict(model.Network, 'hammernet') api.absent_or_conflict(model.Network, 'nailnet') # after deletion we should be able to create admin networks with those # network_ids api.network_create('redbone', 'admin', '', 103) network = api.get_or_404(model.Network, 'redbone') assert int(network.network_id) == 103 api.network_create('starfish', 'admin', '', net_id) network = api.get_or_404(model.Network, 'starfish') assert int(network.network_id) == net_id