Skip to content
This repository was archived by the owner on Apr 27, 2022. It is now read-only.

Commit 03c12b7

Browse files
authored
Merge pull request #874 from naved001/network-connected-nodes
Show network now shows node and nic connected to network
2 parents 4b523e5 + f81274e commit 03c12b7

File tree

4 files changed

+124
-6
lines changed

4 files changed

+124
-6
lines changed

docs/rest_api.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ The result must contain the following fields:
200200
* "owner", the name of the project which created the network, or
201201
"admin", if it was created by an administrator.
202202
* "access", a list of projects that have access to the network or null if the network is public
203+
* "connected-nodes": nodes and list of nics connected to network
203204

204205
Response body (on success):
205206

@@ -208,13 +209,16 @@ Response body (on success):
208209
"channels": <chanel-id-list>,
209210
"owner": <project or "admin">,
210211
"access": <project(s) with access to the network/null>
212+
"connected-nodes": {"<node>": [<list of nics connected to network]}
211213
}
212214

213215
Authorization requirements:
214216

215217
* If the network is public, no special access is required.
216218
* Otherwise, access to a project in the "access" list or
217219
administrative access is required.
220+
* Admins and network owners can see all nodes connected to network; other users
221+
only see connected nodes that they have access to.
218222

219223
#### Channel Formats
220224

hil/api.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,6 @@ def _have_attachment(nic, query):
380380
model.NetworkAttachment.nic == nic,
381381
query,
382382
).first() is not None
383-
384383
auth_backend = get_auth_backend()
385384

386385
node = _must_find(model.Node, node)
@@ -895,6 +894,18 @@ def show_network(network):
895894
else:
896895
result['access'] = None
897896

897+
connected_nodes = {}
898+
for n in network.attachments:
899+
if auth_backend.have_project_access(network.owner) or \
900+
auth_backend.have_project_access(n.nic.owner.project):
901+
node, nic = n.nic.owner.label, n.nic.label
902+
# build a dictonary mapping a node to list of nics
903+
if node not in connected_nodes:
904+
connected_nodes[node] = [nic]
905+
else:
906+
connected_nodes[node].append(nic)
907+
result['connected-nodes'] = connected_nodes
908+
898909
return json.dumps(result, sort_keys=True)
899910

900911

tests/unit/api/main.py

Lines changed: 106 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
fail_on_log_warnings, additional_db, with_request_context, \
6262
network_create_simple, server_init
6363
from hil.network_allocator import get_network_allocator
64+
from hil.auth import get_auth_backend
6465
import pytest
6566
import json
6667
import uuid
@@ -80,7 +81,8 @@ def configure():
8081
'require_authentication': 'True',
8182
},
8283
'extensions': {
83-
'hil.ext.auth.null': '',
84+
'hil.ext.auth.null': None,
85+
'hil.ext.auth.mock': '',
8486
'hil.ext.switches.mock': '',
8587
'hil.ext.obm.ipmi': '',
8688
'hil.ext.obm.mock': '',
@@ -103,6 +105,12 @@ def configure():
103105
with_request_context = pytest.yield_fixture(with_request_context)
104106

105107

108+
@pytest.fixture
109+
def set_admin_auth():
110+
"""Set admin auth for all calls"""
111+
get_auth_backend().set_admin(True)
112+
113+
106114
@pytest.fixture
107115
def switchinit():
108116
"""Create a switch with one port"""
@@ -114,11 +122,21 @@ def switchinit():
114122
api.switch_register_port('sw0', PORTS[2])
115123

116124

125+
def new_node(name):
126+
"""Create a mock node named ``name``"""
127+
api.node_register(name, obm={
128+
"type": OBM_TYPE_MOCK,
129+
"host": "ipmihost",
130+
"user": "root",
131+
"password": "tapeworm"})
132+
133+
117134
default_fixtures = ['fail_on_log_warnings',
118135
'configure',
119136
'fresh_database',
120137
'server_init',
121-
'with_request_context']
138+
'with_request_context',
139+
'set_admin_auth']
122140

123141
pytestmark = pytest.mark.usefixtures(*default_fixtures)
124142

@@ -2436,7 +2454,8 @@ def test_show_network_simple(self):
24362454
'name': 'spiderwebs',
24372455
'owner': 'anvil-nextgen',
24382456
'access': ['anvil-nextgen'],
2439-
"channels": ["vlan/native", "vlan/40"]
2457+
"channels": ["vlan/native", "vlan/40"],
2458+
'connected-nodes': {},
24402459
}
24412460

24422461
def test_show_network_public(self):
@@ -2452,6 +2471,7 @@ def test_show_network_public(self):
24522471
'owner': 'admin',
24532472
'access': None,
24542473
'channels': ['vlan/native', 'vlan/432'],
2474+
'connected-nodes': {},
24552475
}
24562476

24572477
def test_show_network_provider(self):
@@ -2468,6 +2488,88 @@ def test_show_network_provider(self):
24682488
'owner': 'admin',
24692489
'access': ['anvil-nextgen'],
24702490
'channels': ['vlan/native', 'vlan/451'],
2491+
'connected-nodes': {},
2492+
}
2493+
2494+
def test_show_network_with_nodes(self, switchinit):
2495+
"""test the output when a node is connected to a network"""
2496+
auth = get_auth_backend()
2497+
2498+
# the following is done by an admin user called 'user'.
2499+
assert auth.get_user() is 'user'
2500+
assert auth.have_admin() is True
2501+
2502+
# register a node
2503+
new_node('node-anvil')
2504+
api.node_register_nic('node-anvil', 'eth0', 'DE:AD:BE:EF:20:14')
2505+
api.port_connect_nic('sw0', PORTS[2], 'node-anvil', 'eth0')
2506+
2507+
# create a project and a network owned by it. Also connect a node to it
2508+
api.project_create('anvil-nextgen')
2509+
api.project_connect_node('anvil-nextgen', 'node-anvil')
2510+
network_create_simple('spiderwebs', 'anvil-nextgen')
2511+
2512+
api.node_connect_network('node-anvil', 'eth0', 'spiderwebs')
2513+
deferred.apply_networking()
2514+
result = json.loads(api.show_network('spiderwebs'))
2515+
2516+
assert result == {
2517+
'name': 'spiderwebs',
2518+
'owner': 'anvil-nextgen',
2519+
'access': ['anvil-nextgen'],
2520+
"channels": ["vlan/native", "vlan/40"],
2521+
'connected-nodes': {'node-anvil': ['eth0']},
2522+
}
2523+
2524+
# register another node
2525+
new_node('node-pineapple')
2526+
api.node_register_nic('node-pineapple', 'eth0', 'DE:AD:BE:EF:20:14')
2527+
api.switch_register_port('sw0', PORTS[1])
2528+
api.port_connect_nic('sw0', PORTS[1], 'node-pineapple', 'eth0')
2529+
2530+
# create a new project and give it access to spiderwebs network, and
2531+
# then connect its node to the network.
2532+
api.project_create('pineapple')
2533+
api.network_grant_project_access('pineapple', 'spiderwebs')
2534+
api.project_connect_node('pineapple', 'node-pineapple')
2535+
2536+
api.node_connect_network('node-pineapple', 'eth0', 'spiderwebs')
2537+
deferred.apply_networking()
2538+
2539+
# switch to a different user and project
2540+
auth.set_user('spongebob')
2541+
project = api._must_find(model.Project, 'pineapple')
2542+
auth.set_project(project)
2543+
auth.set_admin(False)
2544+
2545+
result = json.loads(api.show_network('spiderwebs'))
2546+
2547+
# check that nodes not owned by this project aren't visible in output.
2548+
assert result == {
2549+
'name': 'spiderwebs',
2550+
'owner': 'anvil-nextgen',
2551+
'access': ['anvil-nextgen', 'pineapple'],
2552+
"channels": ["vlan/native", "vlan/40"],
2553+
'connected-nodes': {'node-pineapple': ['eth0']},
2554+
}
2555+
2556+
# switch to the network owner and then see the output
2557+
2558+
auth.set_user('user')
2559+
project = api._must_find(model.Project, 'anvil-nextgen')
2560+
auth.set_project(project)
2561+
auth.set_admin(False)
2562+
2563+
result = json.loads(api.show_network('spiderwebs'))
2564+
2565+
# all nodes should be visible now.
2566+
assert result == {
2567+
'name': 'spiderwebs',
2568+
'owner': 'anvil-nextgen',
2569+
'access': ['anvil-nextgen', 'pineapple'],
2570+
"channels": ["vlan/native", "vlan/40"],
2571+
'connected-nodes': {'node-pineapple': ['eth0'],
2572+
'node-anvil': ['eth0']},
24712573
}
24722574

24732575

@@ -2544,7 +2646,7 @@ def test_extension_list(self):
25442646
"""Test the list_active_extensions api call."""
25452647
result = json.loads(api.list_active_extensions())
25462648
assert result == [
2547-
'hil.ext.auth.null',
2649+
'hil.ext.auth.mock',
25482650
'hil.ext.network_allocators.vlan_pool',
25492651
'hil.ext.obm.ipmi',
25502652
'hil.ext.obm.mock',

tests/unit/client.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,8 @@ def test_network_show(self):
691691
u'access': [u'proj-01'],
692692
u'channels': [u'vlan/native', u'vlan/1001'],
693693
u'name': u'net-01',
694-
u'owner': u'proj-01'
694+
u'owner': u'proj-01',
695+
u'connected-nodes': {},
695696
}
696697

697698
def test_network_create(self):

0 commit comments

Comments
 (0)