Merge "Add support of nova network for share-networks API and DB"
This commit is contained in:
commit
f396a2ce1a
|
@ -45,6 +45,7 @@ SHARE_NETWORK_ATTRS = (
|
||||||
'user_id',
|
'user_id',
|
||||||
'created_at',
|
'created_at',
|
||||||
'updated_at',
|
'updated_at',
|
||||||
|
'nova_net_id',
|
||||||
'neutron_net_id',
|
'neutron_net_id',
|
||||||
'neutron_subnet_id',
|
'neutron_subnet_id',
|
||||||
'network_type',
|
'network_type',
|
||||||
|
@ -208,6 +209,23 @@ class ShareNetworkController(wsgi.Controller):
|
||||||
'detail')
|
'detail')
|
||||||
return self._get_share_networks(req)
|
return self._get_share_networks(req)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _verify_no_mutually_exclusive_data(share_network, update_data=None):
|
||||||
|
update_data = update_data or dict()
|
||||||
|
neutron_net_id = (
|
||||||
|
share_network.get('neutron_net_id') or
|
||||||
|
update_data.get('neutron_net_id'))
|
||||||
|
neutron_subnet_id = (
|
||||||
|
share_network.get('neutron_subnet_id') or
|
||||||
|
update_data.get('neutron_subnet_id'))
|
||||||
|
nova_net_id = (
|
||||||
|
share_network.get('nova_net_id') or
|
||||||
|
update_data.get('nova_net_id'))
|
||||||
|
if nova_net_id and (neutron_net_id or neutron_subnet_id):
|
||||||
|
msg = _("Neutron net data and Nova net data are mutually "
|
||||||
|
"exclusive. Only one of these are allowed at a time.")
|
||||||
|
raise exc.HTTPBadRequest(explanation=msg)
|
||||||
|
|
||||||
@wsgi.serializers(xml=ShareNetworkTemplate)
|
@wsgi.serializers(xml=ShareNetworkTemplate)
|
||||||
def update(self, req, id, body):
|
def update(self, req, id, body):
|
||||||
"""Update specified share network."""
|
"""Update specified share network."""
|
||||||
|
@ -224,6 +242,7 @@ class ShareNetworkController(wsgi.Controller):
|
||||||
|
|
||||||
update_values = body[RESOURCE_NAME]
|
update_values = body[RESOURCE_NAME]
|
||||||
|
|
||||||
|
self._verify_no_mutually_exclusive_data(share_network, update_values)
|
||||||
if share_network['share_servers']:
|
if share_network['share_servers']:
|
||||||
for value in update_values:
|
for value in update_values:
|
||||||
if value not in ['name', 'description']:
|
if value not in ['name', 'description']:
|
||||||
|
@ -254,6 +273,7 @@ class ShareNetworkController(wsgi.Controller):
|
||||||
|
|
||||||
values = body[RESOURCE_NAME]
|
values = body[RESOURCE_NAME]
|
||||||
values['project_id'] = context.project_id
|
values['project_id'] = context.project_id
|
||||||
|
self._verify_no_mutually_exclusive_data(values)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
reservations = QUOTAS.reserve(context, share_networks=1)
|
reservations = QUOTAS.reserve(context, share_networks=1)
|
||||||
|
|
|
@ -43,6 +43,7 @@ class ViewBuilder(common.ViewBuilder):
|
||||||
'updated_at': share_network.get('updated_at'),
|
'updated_at': share_network.get('updated_at'),
|
||||||
'neutron_net_id': share_network.get('neutron_net_id'),
|
'neutron_net_id': share_network.get('neutron_net_id'),
|
||||||
'neutron_subnet_id': share_network.get('neutron_subnet_id'),
|
'neutron_subnet_id': share_network.get('neutron_subnet_id'),
|
||||||
|
'nova_net_id': share_network.get('nova_net_id'),
|
||||||
'network_type': share_network.get('network_type'),
|
'network_type': share_network.get('network_type'),
|
||||||
'segmentation_id': share_network.get('segmentation_id'),
|
'segmentation_id': share_network.get('segmentation_id'),
|
||||||
'cidr': share_network.get('cidr'),
|
'cidr': share_network.get('cidr'),
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
# Copyright 2015 Mirantis Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
"""add_nova_net_id_column_to_share_networks
|
||||||
|
|
||||||
|
Revision ID: 17115072e1c3
|
||||||
|
Revises: 38e632621e5a
|
||||||
|
Create Date: 2015-02-05 18:07:19.062995
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '17115072e1c3'
|
||||||
|
down_revision = '38e632621e5a'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.add_column(
|
||||||
|
'share_networks',
|
||||||
|
sa.Column('nova_net_id', sa.String(36), nullable=True))
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.drop_column('share_networks', 'nova_net_id')
|
|
@ -326,6 +326,7 @@ class ShareNetwork(BASE, ManilaBase):
|
||||||
deleted = Column(String(36), default='False')
|
deleted = Column(String(36), default='False')
|
||||||
project_id = Column(String(36), nullable=False)
|
project_id = Column(String(36), nullable=False)
|
||||||
user_id = Column(String(36), nullable=False)
|
user_id = Column(String(36), nullable=False)
|
||||||
|
nova_net_id = Column(String(36), nullable=True)
|
||||||
neutron_net_id = Column(String(36), nullable=True)
|
neutron_net_id = Column(String(36), nullable=True)
|
||||||
neutron_subnet_id = Column(String(36), nullable=True)
|
neutron_subnet_id = Column(String(36), nullable=True)
|
||||||
network_type = Column(String(32), nullable=True)
|
network_type = Column(String(32), nullable=True)
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import ddt
|
||||||
import mock
|
import mock
|
||||||
from oslo_db import exception as db_exception
|
from oslo_db import exception as db_exception
|
||||||
from oslo_utils import timeutils
|
from oslo_utils import timeutils
|
||||||
|
@ -74,6 +75,7 @@ fake_sn_with_ss_shortened = {
|
||||||
QUOTAS = quota.QUOTAS
|
QUOTAS = quota.QUOTAS
|
||||||
|
|
||||||
|
|
||||||
|
@ddt.ddt
|
||||||
class ShareNetworkAPITest(test.TestCase):
|
class ShareNetworkAPITest(test.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -110,6 +112,64 @@ class ShareNetworkAPITest(test.TestCase):
|
||||||
self.assertFalse('network_allocations' in view)
|
self.assertFalse('network_allocations' in view)
|
||||||
self.assertFalse('security_services' in view)
|
self.assertFalse('security_services' in view)
|
||||||
|
|
||||||
|
@ddt.data(
|
||||||
|
{'nova_net_id': 'fake_nova_net_id'},
|
||||||
|
{'neutron_net_id': 'fake_neutron_net_id'},
|
||||||
|
{'neutron_subnet_id': 'fake_neutron_subnet_id'},
|
||||||
|
{'neutron_net_id': 'fake', 'neutron_subnet_id': 'fake'})
|
||||||
|
def test_create_valid_cases(self, data):
|
||||||
|
data.update({'user_id': 'fake_user_id'})
|
||||||
|
body = {share_networks.RESOURCE_NAME: data}
|
||||||
|
result = self.controller.create(self.req, body)
|
||||||
|
data.pop('user_id', None)
|
||||||
|
for k, v in data.items():
|
||||||
|
self.assertIn(data[k], result['share_network'][k])
|
||||||
|
|
||||||
|
@ddt.data(
|
||||||
|
{'nova_net_id': 'foo', 'neutron_net_id': 'bar'},
|
||||||
|
{'nova_net_id': 'foo', 'neutron_subnet_id': 'quuz'},
|
||||||
|
{'nova_net_id': 'foo', 'neutron_net_id': 'bar',
|
||||||
|
'neutron_subnet_id': 'quuz'})
|
||||||
|
def test_create_invalid_cases(self, data):
|
||||||
|
data.update({'user_id': 'fake_user_id'})
|
||||||
|
body = {share_networks.RESOURCE_NAME: data}
|
||||||
|
self.assertRaises(
|
||||||
|
webob_exc.HTTPBadRequest, self.controller.create, self.req, body)
|
||||||
|
|
||||||
|
@ddt.data(
|
||||||
|
{'nova_net_id': 'fake_nova_net_id'},
|
||||||
|
{'neutron_net_id': 'fake_neutron_net_id'},
|
||||||
|
{'neutron_subnet_id': 'fake_neutron_subnet_id'},
|
||||||
|
{'neutron_net_id': 'fake', 'neutron_subnet_id': 'fake'})
|
||||||
|
def test_update_valid_cases(self, data):
|
||||||
|
body = {share_networks.RESOURCE_NAME: {'user_id': 'fake_user'}}
|
||||||
|
created = self.controller.create(self.req, body)
|
||||||
|
|
||||||
|
body = {share_networks.RESOURCE_NAME: data}
|
||||||
|
result = self.controller.update(
|
||||||
|
self.req, created['share_network']['id'], body)
|
||||||
|
|
||||||
|
for k, v in data.items():
|
||||||
|
self.assertIn(data[k], result['share_network'][k])
|
||||||
|
|
||||||
|
self._check_share_network_view(
|
||||||
|
result[share_networks.RESOURCE_NAME],
|
||||||
|
result['share_network'])
|
||||||
|
|
||||||
|
@ddt.data(
|
||||||
|
{'nova_net_id': 'foo', 'neutron_net_id': 'bar'},
|
||||||
|
{'nova_net_id': 'foo', 'neutron_subnet_id': 'quuz'},
|
||||||
|
{'nova_net_id': 'foo', 'neutron_net_id': 'bar',
|
||||||
|
'neutron_subnet_id': 'quuz'})
|
||||||
|
def test_update_invalid_cases(self, data):
|
||||||
|
body = {share_networks.RESOURCE_NAME: {'user_id': 'fake_user'}}
|
||||||
|
created = self.controller.create(self.req, body)
|
||||||
|
body = {share_networks.RESOURCE_NAME: data}
|
||||||
|
self.assertRaises(
|
||||||
|
webob_exc.HTTPBadRequest,
|
||||||
|
self.controller.update,
|
||||||
|
self.req, created['share_network']['id'], body)
|
||||||
|
|
||||||
def test_create_nominal(self):
|
def test_create_nominal(self):
|
||||||
with mock.patch.object(db_api,
|
with mock.patch.object(db_api,
|
||||||
'share_network_create',
|
'share_network_create',
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
# Copyright (c) 2015 Mirantis, Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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 ddt
|
||||||
|
|
||||||
|
from manila.api.views import share_networks
|
||||||
|
from manila import test
|
||||||
|
|
||||||
|
|
||||||
|
@ddt.ddt
|
||||||
|
class ViewBuilderTestCase(test.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(ViewBuilderTestCase, self).setUp()
|
||||||
|
self.builder = share_networks.ViewBuilder()
|
||||||
|
|
||||||
|
def test__collection_name(self):
|
||||||
|
self.assertEqual('share_networks', self.builder._collection_name)
|
||||||
|
|
||||||
|
@ddt.data(
|
||||||
|
{'id': 'fake_sn_id', 'name': 'fake_sn_name'},
|
||||||
|
{'id': 'fake_sn_id', 'name': 'fake_sn_name', 'fake_extra_key': 'foo'},
|
||||||
|
)
|
||||||
|
def test_build_share_network(self, sn):
|
||||||
|
expected_keys = (
|
||||||
|
'id', 'name', 'project_id', 'created_at', 'updated_at',
|
||||||
|
'neutron_net_id', 'neutron_subnet_id', 'nova_net_id',
|
||||||
|
'network_type', 'segmentation_id', 'cidr', 'ip_version',
|
||||||
|
'description')
|
||||||
|
|
||||||
|
result = self.builder.build_share_network(sn)
|
||||||
|
|
||||||
|
self.assertEqual(1, len(result))
|
||||||
|
self.assertIn('share_network', result)
|
||||||
|
self.assertEqual(sn['id'], result['share_network']['id'])
|
||||||
|
self.assertEqual(sn['name'], result['share_network']['name'])
|
||||||
|
self.assertEqual(len(expected_keys), len(result['share_network']))
|
||||||
|
for key in expected_keys:
|
||||||
|
self.assertIn(key, result['share_network'])
|
||||||
|
|
||||||
|
@ddt.data(
|
||||||
|
[],
|
||||||
|
[dict(id='fake_id',
|
||||||
|
name='fake_name',
|
||||||
|
project_id='fake_project_id',
|
||||||
|
created_at='fake_created_at',
|
||||||
|
updated_at='fake_updated_at',
|
||||||
|
neutron_net_id='fake_neutron_net_id',
|
||||||
|
neutron_subnet_id='fake_neutron_subnet_id',
|
||||||
|
nova_net_id='fake_nova_net_id',
|
||||||
|
network_type='fake_network_type',
|
||||||
|
segmentation_id='fake_segmentation_id',
|
||||||
|
cidr='fake_cidr',
|
||||||
|
ip_version='fake_ip_version',
|
||||||
|
description='fake_description'),
|
||||||
|
dict(id='fake_id2', name='fake_name2')],
|
||||||
|
)
|
||||||
|
def test_build_share_networks_with_details(self, share_networks):
|
||||||
|
expected = []
|
||||||
|
for share_network in share_networks:
|
||||||
|
expected.append(dict(
|
||||||
|
id=share_network.get('id'),
|
||||||
|
name=share_network.get('name'),
|
||||||
|
project_id=share_network.get('project_id'),
|
||||||
|
created_at=share_network.get('created_at'),
|
||||||
|
updated_at=share_network.get('updated_at'),
|
||||||
|
neutron_net_id=share_network.get('neutron_net_id'),
|
||||||
|
neutron_subnet_id=share_network.get('neutron_subnet_id'),
|
||||||
|
nova_net_id=share_network.get('nova_net_id'),
|
||||||
|
network_type=share_network.get('network_type'),
|
||||||
|
segmentation_id=share_network.get('segmentation_id'),
|
||||||
|
cidr=share_network.get('cidr'),
|
||||||
|
ip_version=share_network.get('ip_version'),
|
||||||
|
description=share_network.get('description')))
|
||||||
|
expected = {'share_networks': expected}
|
||||||
|
|
||||||
|
result = self.builder.build_share_networks(share_networks, True)
|
||||||
|
|
||||||
|
self.assertEqual(expected, result)
|
||||||
|
|
||||||
|
@ddt.data(
|
||||||
|
[],
|
||||||
|
[{'id': 'foo', 'name': 'bar'}],
|
||||||
|
[{'id': 'id1', 'name': 'name1'}, {'id': 'id2', 'name': 'name2'}],
|
||||||
|
[{'id': 'id1', 'name': 'name1'},
|
||||||
|
{'id': 'id2', 'name': 'name2', 'fake': 'I should not be returned'}],
|
||||||
|
)
|
||||||
|
def test_build_share_networks_without_details(self, share_networks):
|
||||||
|
expected = []
|
||||||
|
for share_network in share_networks:
|
||||||
|
expected.append(dict(
|
||||||
|
id=share_network.get('id'), name=share_network.get('name')))
|
||||||
|
expected = {'share_networks': expected}
|
||||||
|
|
||||||
|
result = self.builder.build_share_networks(share_networks, False)
|
||||||
|
|
||||||
|
self.assertEqual(expected, result)
|
Loading…
Reference in New Issue