Implement /NetworkDriver.CreateNetwork
This patch replaces the mocked version of /NetworkDriver.CreateNetwork with the actual Neutron call. The unit test for the endpoint is also implemented. Change-Id: I58517069470f1689d486e6a96a094f0dac959116 Signed-off-by: Taku Fukushima <f.tac.mac@gmail.com>
This commit is contained in:
parent
50b9f430bc
commit
4b7dde26ea
@ -10,12 +10,24 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
|
||||
from flask import jsonify
|
||||
from flask import request
|
||||
from neutronclient.neutron import client
|
||||
|
||||
from kuryr import app
|
||||
from kuryr.constants import SCHEMA
|
||||
|
||||
|
||||
OS_URL = os.environ.get('OS_URL', 'http://127.0.0.1:9696/')
|
||||
OS_TOKEN = os.environ.get('OS_TOKEN', '9999888877776666')
|
||||
|
||||
# TODO(tfukushima): Retrieve configuration info from a config file.
|
||||
app.neutron = client.Client('2.0', endpoint_url=OS_URL, token=OS_TOKEN)
|
||||
app.neutron.format = 'json'
|
||||
|
||||
|
||||
@app.route('/Plugin.Activate', methods=['POST'])
|
||||
def plugin_activate():
|
||||
return jsonify(SCHEMA['PLUGIN_ACTIVATE'])
|
||||
@ -23,6 +35,35 @@ def plugin_activate():
|
||||
|
||||
@app.route('/NetworkDriver.CreateNetwork', methods=['POST'])
|
||||
def network_driver_create_network():
|
||||
"""Creates a new Neutron Network which name is the given NetworkID.
|
||||
|
||||
This function takes the following JSON data and delegates the actual
|
||||
network creation to the Neutron client. libnetwork's NetworkID is used as
|
||||
the name of Network in Neutron. ::
|
||||
|
||||
{
|
||||
"NetworkID": string,
|
||||
"Options": {
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
See the following link for more details about the spec:
|
||||
|
||||
https://github.com/docker/libnetwork/blob/master/docs/remote.md#create-network # noqa
|
||||
"""
|
||||
json_data = request.get_json(force=True)
|
||||
|
||||
app.logger.debug("Received JSON data {0} for /NetworkDriver.CreateNetwork"
|
||||
.format(json_data))
|
||||
# TODO(tfukushima): Add a validation of the JSON data for the network.
|
||||
neutron_network_name = json_data['NetworkID']
|
||||
|
||||
network = app.neutron.create_network(
|
||||
{'network': {'name': neutron_network_name, "admin_state_up": True}})
|
||||
|
||||
app.logger.info("Created a new network with name {0} successfully: {1}"
|
||||
.format(neutron_network_name, network))
|
||||
return jsonify(SCHEMA['SUCCESS'])
|
||||
|
||||
|
||||
|
@ -10,12 +10,12 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslotest import base
|
||||
from neutronclient.tests.unit.test_cli20 import CLITestV20Base
|
||||
|
||||
from kuryr import app
|
||||
|
||||
|
||||
class TestCase(base.BaseTestCase):
|
||||
class TestCase(CLITestV20Base):
|
||||
"""Test case base class for all unit tests."""
|
||||
|
||||
def setUp(self):
|
||||
@ -23,6 +23,7 @@ class TestCase(base.BaseTestCase):
|
||||
app.config['DEBUG'] = True
|
||||
app.config['TESTING'] = True
|
||||
self.app = app.test_client()
|
||||
self.app.neutron = self.client
|
||||
|
||||
|
||||
class TestKuryrBase(TestCase):
|
||||
@ -30,9 +31,12 @@ class TestKuryrBase(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestKuryrBase, self).setUp()
|
||||
self.app.neutron.format = 'json'
|
||||
|
||||
def tearDown(self):
|
||||
super(TestKuryrBase, self).tearDown()
|
||||
self.mox.VerifyAll()
|
||||
self.mox.UnsetStubs()
|
||||
|
||||
|
||||
class TestKuryrFailures(TestKuryrBase):
|
||||
|
@ -10,9 +10,13 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import hashlib
|
||||
import random
|
||||
|
||||
from ddt import ddt, data, unpack
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from kuryr import app
|
||||
from kuryr.constants import SCHEMA
|
||||
from kuryr.tests.base import TestKuryrBase
|
||||
|
||||
@ -36,7 +40,6 @@ class TestKuryr(TestKuryrBase):
|
||||
- POST /NetworkDriver.Leave
|
||||
"""
|
||||
@data(('/Plugin.Activate', SCHEMA['PLUGIN_ACTIVATE']),
|
||||
('/NetworkDriver.CreateNetwork', SCHEMA['SUCCESS']),
|
||||
('/NetworkDriver.DeleteNetwork', SCHEMA['SUCCESS']),
|
||||
('/NetworkDriver.CreateEndpoint', SCHEMA['CREATE_ENDPOINT']),
|
||||
('/NetworkDriver.EndpointOperInfo', SCHEMA['ENDPOINT_OPER_INFO']),
|
||||
@ -48,3 +51,41 @@ class TestKuryr(TestKuryrBase):
|
||||
response = self.app.post(endpoint)
|
||||
decoded_json = jsonutils.loads(response.data)
|
||||
self.assertEqual(expected, decoded_json)
|
||||
|
||||
def test_network_driver_create_network(self):
|
||||
docker_network_id = hashlib.sha256(
|
||||
str(random.getrandbits(256))).hexdigest()
|
||||
self.mox.StubOutWithMock(app.neutron, "create_network")
|
||||
fake_request = {
|
||||
"network": {
|
||||
"name": docker_network_id,
|
||||
"admin_state_up": True
|
||||
}
|
||||
}
|
||||
# The following fake response is retrieved from the Neutron doc:
|
||||
# http://developer.openstack.org/api-ref-networking-v2.html#createNetwork # noqa
|
||||
fake_response = {
|
||||
"network": {
|
||||
"status": "ACTIVE",
|
||||
"subnets": [],
|
||||
"name": docker_network_id,
|
||||
"admin_state_up": True,
|
||||
"tenant_id": "9bacb3c5d39d41a79512987f338cf177",
|
||||
"router:external": False,
|
||||
"segments": [],
|
||||
"shared": False,
|
||||
"id": "4e8e5957-649f-477b-9e5b-f1f75b21c03c"
|
||||
}
|
||||
}
|
||||
app.neutron.create_network(fake_request).AndReturn(fake_response)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
data = {'NetworkID': docker_network_id, 'Options': {}}
|
||||
response = self.app.post('/NetworkDriver.CreateNetwork',
|
||||
content_type='application/json',
|
||||
data=jsonutils.dumps(data))
|
||||
|
||||
self.assertEqual(200, response.status_code)
|
||||
decoded_json = jsonutils.loads(response.data)
|
||||
self.assertEqual(SCHEMA['SUCCESS'], decoded_json)
|
||||
|
61
kuryr/tests/test_kuryr_network.py
Normal file
61
kuryr/tests/test_kuryr_network.py
Normal file
@ -0,0 +1,61 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import hashlib
|
||||
import random
|
||||
|
||||
from neutronclient.common.exceptions import Unauthorized
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from kuryr import app
|
||||
from kuryr.tests.base import TestKuryrFailures
|
||||
|
||||
|
||||
class TestKuryrNetworkFailures(TestKuryrFailures):
|
||||
"""Unittests for checking if Kuryr handles the failures for the networks.
|
||||
|
||||
This test covers error responses listed in the spec:
|
||||
http://developer.openstack.org/api-ref-networking-v2-ext.html#createProviderNetwork # noqa
|
||||
"""
|
||||
|
||||
def _create_network_with_exception(self, network_name, ex):
|
||||
self.mox.StubOutWithMock(app.neutron, "create_network")
|
||||
fake_bad_request_without_name = {
|
||||
"network": {
|
||||
"name": network_name,
|
||||
"admin_state_up": True
|
||||
}
|
||||
}
|
||||
app.neutron.create_network(
|
||||
fake_bad_request_without_name).AndRaise(ex)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
def _invoke_create_request(self, network_name):
|
||||
data = {'NetworkID': network_name, 'Options': {}}
|
||||
response = self.app.post('/NetworkDriver.CreateNetwork',
|
||||
content_type='application/json',
|
||||
data=jsonutils.dumps(data))
|
||||
return response
|
||||
|
||||
def test_create_network_unauthorized(self):
|
||||
docker_network_id = hashlib.sha256(
|
||||
str(random.getrandbits(256))).hexdigest()
|
||||
self._create_network_with_exception(
|
||||
docker_network_id, Unauthorized())
|
||||
|
||||
response = self._invoke_create_request(docker_network_id)
|
||||
|
||||
self.assertEqual(401, response.status_code)
|
||||
decoded_json = jsonutils.loads(response.data)
|
||||
self.assertTrue('Err' in decoded_json)
|
||||
self.assertEqual(
|
||||
{'Err': 'Unauthorized: bad credentials.'}, decoded_json)
|
@ -36,8 +36,9 @@ def make_json_app(import_name, **kwargs):
|
||||
@app.errorhandler(NeutronClientException)
|
||||
def make_json_error(ex):
|
||||
response = jsonify({"Err": str(ex)})
|
||||
response.status_code = (ex.code
|
||||
if isinstance(ex, HTTPException)
|
||||
response.status_code = (ex.code if isinstance(ex, HTTPException)
|
||||
else ex.status_code
|
||||
if isinstance(ex, NeutronClientException)
|
||||
else 500)
|
||||
content_type = 'application/vnd.docker.plugins.v1+json; charset=utf-8'
|
||||
response.headers['Content-Type'] = content_type
|
||||
|
Loading…
Reference in New Issue
Block a user