def test_ensure_legal_operations(): """Test to ensure that ensure_legal_operations works as expected""" # create a project and a network api.project_create('anvil-nextgen') network_create_simple('hammernet', 'anvil-nextgen') network_create_simple('pineapple', 'anvil-nextgen') # register a switch of type dellnos9 and add a port to it api.switch_register('s3048', type=SWITCH_TYPE, username="******", password="******", hostname="switchname", interface_type="GigabitEthernet") api.switch_register_port('s3048', '1/3') switch = api.get_or_404(model.Switch, 's3048') # register a ndoe and a nic api.node_register( node='compute-01', obmd={ 'uri': 'http://obmd.example.com', 'admin_token': 'secret', }, ) api.project_connect_node('anvil-nextgen', 'compute-01') api.node_register_nic('compute-01', 'eth0', 'DE:AD:BE:EF:20:14') nic = api.get_or_404(model.Nic, 'eth0') api.port_connect_nic('s3048', '1/3', 'compute-01', 'eth0') # connecting a trunked network wihtout having a native should fail. # call the method directly and test the API too. with pytest.raises(BlockedError): switch.ensure_legal_operation(nic, 'connect', 'vlan/1212') with pytest.raises(BlockedError): api.node_connect_network('compute-01', 'eth0', 'hammernet', 'vlan/40') # doing these operations in the correct order, that is native network first # and then trunked, should work. api.node_connect_network('compute-01', 'eth0', 'hammernet', 'vlan/native') mock_networking_action() api.node_connect_network('compute-01', 'eth0', 'pineapple', 'vlan/41') mock_networking_action() # removing these networks in the wrong order should not work. with pytest.raises(BlockedError): switch.ensure_legal_operation(nic, 'detach', 'vlan/native') with pytest.raises(BlockedError): api.node_detach_network('compute-01', 'eth0', 'hammernet') # removing networks in the right order should work api.node_detach_network('compute-01', 'eth0', 'pineapple') mock_networking_action() api.node_detach_network('compute-01', 'eth0', 'hammernet') mock_networking_action() db.session.close()
def test_many_http_queries(): """Put a few objects in the db, then bombard the api with queries. This is intended to shake out problems like the resource leak discussed in issue #454. """ # NOTE: Now that the session is managed by Flask-SQLAlchemy, failures here # are unlikely to be regressions of the issue that #454 fixed; we're no # longer managing the lifecycle of the session ourselves. It's not obvious # that this is more than clutter now, but let's not be too trigger happy # about deleting tests. with rest.app.test_request_context(): rest.init_auth() api.node_register('node-99', obm={ "type": "http://schema.massopencloud.org/haas/v0/obm/ipmi", "host": "ipmihost", "user": "******", "password": "******"}) api.node_register('node-98', obm={ "type": "http://schema.massopencloud.org/haas/v0/obm/ipmi", "host": "ipmihost", "user": "******", "password": "******"}) api.node_register('node-97', obm={ "type": "http://schema.massopencloud.org/haas/v0/obm/ipmi", "host": "ipmihost", "user": "******", "password": "******"}) api.node_register_nic('node-99', 'eth0', 'DE:AD:BE:EF:20:14') api.node_register_nic('node-98', 'eth0', 'DE:AD:BE:EF:20:15') api.node_register_nic('node-97', 'eth0', 'DE:AD:BE:EF:20:16') api.project_create('anvil-nextgen') api.project_create('anvil-legacy') api.project_connect_node('anvil-nextgen', 'node-99') api.project_connect_node('anvil-legacy', 'node-98') client = rest.app.test_client() def _show_nodes(path): """Helper for the loop below. This does a GET on path, which must return a json list of names of nodes. It will then query the state of each node. If any request does not return 200 or has a body which is not valid json, the test will fail. """ resp = client.get(path) assert resp.status_code == 200 for node in json.loads(resp.get_data()): resp = client.get('/nodes/%s' % node) assert resp.status_code == 200 # At least make sure the body parses: json.loads(resp.get_data()) for _i in range(100): _show_nodes('/nodes/free') resp = client.get('/projects') assert resp.status_code == 200 for project in json.loads(resp.get_data()): _show_nodes('/project/%s/nodes' % project)
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 test_many_http_queries(): """Put a few objects in the db, then bombard the api with queries. This is intended to shake out problems like the resource leak discussed in issue #454. """ # NOTE: Now that the session is managed by Flask-SQLAlchemy, failures here # are unlikely to be regressions of the issue that #454 fixed; we're no # longer managing the lifecycle of the session ourselves. It's not obvious # that this is more than clutter now, but let's not be too trigger happy # about deleting tests. with rest.app.test_request_context(): rest.init_auth() api.node_register('node-99', obm={ "type": "http://schema.massopencloud.org/haas/v0/obm/ipmi", "host": "ipmihost", "user": "******", "password": "******"}) api.node_register('node-98', obm={ "type": "http://schema.massopencloud.org/haas/v0/obm/ipmi", "host": "ipmihost", "user": "******", "password": "******"}) api.node_register('node-97', obm={ "type": "http://schema.massopencloud.org/haas/v0/obm/ipmi", "host": "ipmihost", "user": "******", "password": "******"}) api.node_register_nic('node-99', 'eth0', 'DE:AD:BE:EF:20:14') api.node_register_nic('node-98', 'eth0', 'DE:AD:BE:EF:20:15') api.node_register_nic('node-97', 'eth0', 'DE:AD:BE:EF:20:16') api.project_create('anvil-nextgen') api.project_create('anvil-legacy') api.project_connect_node('anvil-nextgen', 'node-99') api.project_connect_node('anvil-legacy', 'node-98') client = rest.app.test_client() def _show_nodes(path): """Helper for the loop below. This does a GET on path, which must return a json list of names of nodes. It will then query the state of each node. If any request does not return 200 or has a body which is not valid json, the test will fail. """ resp = client.get(path) assert resp.status_code == 200 for node in json.loads(resp.get_data()): resp = client.get('/nodes/%s' % node) assert resp.status_code == 200 # At least make sure the body parses: json.loads(resp.get_data()) for i in range(100): _show_nodes('/nodes/free') resp = client.get('/projects') assert resp.status_code == 200 for project in json.loads(resp.get_data()): _show_nodes('/project/%s/nodes' % project)
def mock_node(obmd_cfg): """Register a node wth obmd & hil. returns the node's label. The node will be attached to a project called 'anvil-nextgen'. """ obmd_uri = 'http://localhost' + obmd_cfg['ListenAddr'] + '/node/node-99' # register a node with obmd: requests.put( obmd_uri, auth=('admin', obmd_cfg['AdminToken']), data=json.dumps({ "type": "mock", "info": { "addr": "10.0.0.4", "NumWrites": 0, }, })) # and then with hil: api.node_register( node='node-99', obmd={ 'uri': obmd_uri, 'admin_token': obmd_cfg['AdminToken'], }, ) # Create a project, and attach the node. api.project_create('anvil-nextgen') api.project_connect_node('anvil-nextgen', 'node-99') return 'node-99'
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 test_project_detach_node_maintenance(self, maintenance_proj_init): """Test that project_detach_node removes the node from the project. Note that the maintenance server has a fake url. We expect it to fail during the connection.""" api.project_create('anvil-nextgen') new_node('node-99') api.project_connect_node('anvil-nextgen', 'node-99') # Should raise error due to arbitrary POST url: with pytest.raises(LoggedWarningError): api.project_detach_node('anvil-nextgen', 'node-99') maintenance_proj = api.get_or_404(model.Project, 'maintenance') node = api.get_or_404(model.Node, 'node-99') assert node.project == maintenance_proj
def test_enable_disable_obm(obmd_cfg): """Test enabling and disabling the obm of a node via the api.""" obmd_uri = 'http://localhost' + obmd_cfg['ListenAddr'] + '/node/node-99' # register a node with obmd: requests.put( obmd_uri, auth=('admin', obmd_cfg['AdminToken']), data=json.dumps({ "type": "ipmi", "info": { "addr": "10.0.0.4", "user": "******", "pass": "******", }, })) # and then with hil: api.node_register( node='node-99', obm={ "type": 'http://schema.massopencloud.org/haas/v0/obm/mock', "host": "ipmihost", "user": "******", "password": "******", }, obmd={ 'uri': obmd_uri, 'admin_token': obmd_cfg['AdminToken'], }, ) # Then create a project, and attach the node. api.project_create('anvil-nextgen') api.project_connect_node('anvil-nextgen', 'node-99') # now the test proper: # First, enable the obm api.node_enable_disable_obm('node-99', enabled=True) # Obm is enabled; we shouldn't be able to detach the node: with pytest.raises(errors.BlockedError): api.project_detach_node('anvil-nextgen', 'node-99') # ...so disable it first: api.node_enable_disable_obm('node-99', enabled=False) # ...and then it should work: api.project_detach_node('anvil-nextgen', 'node-99')
def collect_nodes(self): """Add 4 available nodes with nics to the project. If there are not enough nodes, this will rais an api.AllocationError. """ free_nodes = Node.query.filter_by(project_id=None).all() nodes = [] for node in free_nodes: if len(node.nics) > 0: api.project_connect_node('anvil-nextgen', node.label) nodes.append(node) if len(nodes) >= 4: break # If there are not enough nodes with nics, raise an exception if len(nodes) < 4: raise api.AllocationError( ('At least 4 nodes with at least ' + '1 NIC are required for this test. Only %d node(s) were ' + 'provided.') % len(nodes)) return nodes