Merge "Handle network is already created in DB"
This commit is contained in:
commit
8d431f596e
@ -389,6 +389,11 @@ class NetworkNotFound(HTTPNotFound):
|
|||||||
class NetworkAlreadyExists(ResourceExists):
|
class NetworkAlreadyExists(ResourceExists):
|
||||||
message = _("A network with %(field)s %(value)s already exists.")
|
message = _("A network with %(field)s %(value)s already exists.")
|
||||||
|
|
||||||
|
def __init__(self, field, value):
|
||||||
|
self.field = field
|
||||||
|
self.value = value
|
||||||
|
super(NetworkAlreadyExists, self).__init__(field=field, value=value)
|
||||||
|
|
||||||
|
|
||||||
class PortNotFound(HTTPNotFound):
|
class PortNotFound(HTTPNotFound):
|
||||||
message = _("Neutron port %(port)s could not be found.")
|
message = _("Neutron port %(port)s could not be found.")
|
||||||
|
@ -1081,6 +1081,28 @@ def get_network_by_uuid(context, network_uuid):
|
|||||||
return _get_dbdriver_instance().get_network_by_uuid(context, network_uuid)
|
return _get_dbdriver_instance().get_network_by_uuid(context, network_uuid)
|
||||||
|
|
||||||
|
|
||||||
|
@profiler.trace("db")
|
||||||
|
def list_networks(context, filters=None, limit=None, marker=None,
|
||||||
|
sort_key=None, sort_dir=None):
|
||||||
|
"""List matching networks.
|
||||||
|
|
||||||
|
Return a list of the specified columns for all networks that match
|
||||||
|
the specified filters.
|
||||||
|
|
||||||
|
:param context: The security context
|
||||||
|
:param filters: Filters to apply. Defaults to None.
|
||||||
|
:param limit: Maximum number of networks to return.
|
||||||
|
:param marker: the last item of the previous page; we return the next
|
||||||
|
result set.
|
||||||
|
:param sort_key: Attribute by which results should be sorted.
|
||||||
|
:param sort_dir: Direction in which results should be sorted.
|
||||||
|
(asc, desc)
|
||||||
|
:returns: A list of tuples of the specified columns.
|
||||||
|
"""
|
||||||
|
return _get_dbdriver_instance().list_networks(
|
||||||
|
context, filters, limit, marker, sort_key, sort_dir)
|
||||||
|
|
||||||
|
|
||||||
@profiler.trace("db")
|
@profiler.trace("db")
|
||||||
def update_network(context, uuid, values):
|
def update_network(context, uuid, values):
|
||||||
"""Update properties of a network.
|
"""Update properties of a network.
|
||||||
|
@ -1250,6 +1250,19 @@ class Connection(object):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def _add_networks_filters(self, query, filters):
|
||||||
|
filter_names = ['name', 'neutron_net_id', 'project_id', 'user_id']
|
||||||
|
return self._add_filters(query, models.Network, filters=filters,
|
||||||
|
filter_names=filter_names)
|
||||||
|
|
||||||
|
def list_networks(self, context, filters=None, limit=None,
|
||||||
|
marker=None, sort_key=None, sort_dir=None):
|
||||||
|
query = model_query(models.Network)
|
||||||
|
query = self._add_project_filters(context, query)
|
||||||
|
query = self._add_networks_filters(query, filters)
|
||||||
|
return _paginate_query(models.Network, limit, marker,
|
||||||
|
sort_key, sort_dir, query)
|
||||||
|
|
||||||
def create_network(self, context, values):
|
def create_network(self, context, values):
|
||||||
# ensure defaults are present for new networks
|
# ensure defaults are present for new networks
|
||||||
if not values.get('uuid'):
|
if not values.get('uuid'):
|
||||||
|
@ -118,7 +118,15 @@ class KuryrNetwork(network.Network):
|
|||||||
# which will guarantee only one request can create the network in here
|
# which will guarantee only one request can create the network in here
|
||||||
# (and call docker.create_network later) if there are concurrent
|
# (and call docker.create_network later) if there are concurrent
|
||||||
# requests on creating networks for the same neutron net.
|
# requests on creating networks for the same neutron net.
|
||||||
network.create(self.context)
|
try:
|
||||||
|
network.create(self.context)
|
||||||
|
except exception.NetworkAlreadyExists as e:
|
||||||
|
if e.field == 'neutron_net_id':
|
||||||
|
network = objects.Network.list(
|
||||||
|
self.context,
|
||||||
|
filters={'neutron_net_id': network.neutron_net_id})[0]
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
LOG.debug("Calling docker.create_network to create network %s, "
|
LOG.debug("Calling docker.create_network to create network %s, "
|
||||||
"ipam_options %s, options %s", name, ipam_options, options)
|
"ipam_options %s, options %s", name, ipam_options, options)
|
||||||
|
@ -75,6 +75,25 @@ class Network(base.ZunPersistentObject, base.ZunObject):
|
|||||||
db_network = dbapi.create_network(context, values)
|
db_network = dbapi.create_network(context, values)
|
||||||
self._from_db_object(self, db_network)
|
self._from_db_object(self, db_network)
|
||||||
|
|
||||||
|
@base.remotable_classmethod
|
||||||
|
def list(cls, context, limit=None, marker=None,
|
||||||
|
sort_key=None, sort_dir=None, filters=None):
|
||||||
|
"""Return a list of Network objects.
|
||||||
|
|
||||||
|
:param context: Security context.
|
||||||
|
:param limit: maximum number of resources to return in a single result.
|
||||||
|
:param marker: pagination marker for large data sets.
|
||||||
|
:param sort_key: column to sort results by.
|
||||||
|
:param sort_dir: direction to sort. "asc" or "desc".
|
||||||
|
:param filters: filters when list networks.
|
||||||
|
:returns: a list of :class:`Network` object.
|
||||||
|
|
||||||
|
"""
|
||||||
|
db_networks = dbapi.list_networks(
|
||||||
|
context, limit=limit, marker=marker, sort_key=sort_key,
|
||||||
|
sort_dir=sort_dir, filters=filters)
|
||||||
|
return Network._from_db_object_list(db_networks, cls, context)
|
||||||
|
|
||||||
@base.remotable
|
@base.remotable
|
||||||
def save(self, context=None):
|
def save(self, context=None):
|
||||||
"""Save updates to this Network.
|
"""Save updates to this Network.
|
||||||
|
@ -10,8 +10,12 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from oslo_utils import uuidutils
|
||||||
|
import six
|
||||||
|
|
||||||
from zun.common import exception
|
from zun.common import exception
|
||||||
import zun.conf
|
import zun.conf
|
||||||
|
from zun.db import api as dbapi
|
||||||
from zun.tests.unit.db import base
|
from zun.tests.unit.db import base
|
||||||
from zun.tests.unit.db import utils
|
from zun.tests.unit.db import utils
|
||||||
|
|
||||||
@ -36,3 +40,16 @@ class DbNetworkTestCase(base.DbTestCase):
|
|||||||
'A network with neutron_net_id 456.*'):
|
'A network with neutron_net_id 456.*'):
|
||||||
utils.create_test_network(context=self.context,
|
utils.create_test_network(context=self.context,
|
||||||
neutron_net_id='456')
|
neutron_net_id='456')
|
||||||
|
|
||||||
|
def test_list_networks(self):
|
||||||
|
uuids = []
|
||||||
|
for i in range(1, 6):
|
||||||
|
network = utils.create_test_network(
|
||||||
|
uuid=uuidutils.generate_uuid(),
|
||||||
|
context=self.context,
|
||||||
|
neutron_net_id=uuidutils.generate_uuid(),
|
||||||
|
name='network' + str(i))
|
||||||
|
uuids.append(six.text_type(network['uuid']))
|
||||||
|
res = dbapi.list_networks(self.context)
|
||||||
|
res_uuids = [r.uuid for r in res]
|
||||||
|
self.assertEqual(sorted(uuids), sorted(res_uuids))
|
||||||
|
@ -194,6 +194,36 @@ class KuryrNetworkTestCase(base.TestCase):
|
|||||||
'neutron.net.shared': 'False',
|
'neutron.net.shared': 'False',
|
||||||
'neutron.subnet.uuid': 'fake-subnet-id'})
|
'neutron.subnet.uuid': 'fake-subnet-id'})
|
||||||
|
|
||||||
|
@mock.patch.object(Network, 'create')
|
||||||
|
@mock.patch.object(Network, 'save')
|
||||||
|
@mock.patch.object(Network, 'list')
|
||||||
|
@mock.patch('zun.network.neutron.NeutronAPI')
|
||||||
|
def test_create_network_already_exist(
|
||||||
|
self, mock_neutron_api_cls, mock_list, mock_save, mock_create):
|
||||||
|
mock_neutron_api_cls.return_value = self.network_api.neutron_api
|
||||||
|
name = 'test_kuryr_network'
|
||||||
|
neutron_net_id = 'fake-net-id'
|
||||||
|
mock_create.side_effect = exception.NetworkAlreadyExists(
|
||||||
|
field='neutron_net_id', value=neutron_net_id)
|
||||||
|
with mock.patch.object(self.network_api.docker, 'create_network',
|
||||||
|
return_value={'Id': 'docker-net'}
|
||||||
|
) as mock_create_network:
|
||||||
|
network = self.network_api.create_network(name, neutron_net_id)
|
||||||
|
self.assertEqual('docker-net', network.network_id)
|
||||||
|
mock_list.assert_called_once_with(
|
||||||
|
self.context, filters={'neutron_net_id': neutron_net_id})
|
||||||
|
mock_create_network.assert_called_once_with(
|
||||||
|
name=name,
|
||||||
|
driver='kuryr',
|
||||||
|
enable_ipv6=False,
|
||||||
|
ipam={'Config': [{'Subnet': '10.5.0.0/16', 'Gateway': '10.5.0.1'}],
|
||||||
|
'Driver': 'kuryr',
|
||||||
|
'Options': {'neutron.net.shared': 'False',
|
||||||
|
'neutron.subnet.uuid': 'fake-subnet-id'}},
|
||||||
|
options={'neutron.net.uuid': 'fake-net-id',
|
||||||
|
'neutron.net.shared': 'False',
|
||||||
|
'neutron.subnet.uuid': 'fake-subnet-id'})
|
||||||
|
|
||||||
def test_remove_network(self):
|
def test_remove_network(self):
|
||||||
network_name = 'c02afe4e-8350-4263-8078'
|
network_name = 'c02afe4e-8350-4263-8078'
|
||||||
self.network_api.remove_network(network_name)
|
self.network_api.remove_network(network_name)
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
|
from testtools.matchers import HasLength
|
||||||
|
|
||||||
from zun import objects
|
from zun import objects
|
||||||
from zun.tests.unit.db import base
|
from zun.tests.unit.db import base
|
||||||
from zun.tests.unit.db import utils
|
from zun.tests.unit.db import utils
|
||||||
@ -53,3 +55,13 @@ class TestNetworkObject(base.DbTestCase):
|
|||||||
uuid,
|
uuid,
|
||||||
params)
|
params)
|
||||||
self.assertEqual(self.context, network._context)
|
self.assertEqual(self.context, network._context)
|
||||||
|
|
||||||
|
def test_list(self):
|
||||||
|
with mock.patch.object(self.dbapi, 'list_networks',
|
||||||
|
autospec=True) as mock_get_list:
|
||||||
|
mock_get_list.return_value = [self.fake_network]
|
||||||
|
networks = objects.Network.list(self.context)
|
||||||
|
self.assertEqual(1, mock_get_list.call_count)
|
||||||
|
self.assertThat(networks, HasLength(1))
|
||||||
|
self.assertIsInstance(networks[0], objects.Network)
|
||||||
|
self.assertEqual(self.context, networks[0]._context)
|
||||||
|
@ -365,7 +365,7 @@ object_data = {
|
|||||||
'ContainerPCIRequests': '1.0-7b8f7f044661fe4e24e6949c035af2c4',
|
'ContainerPCIRequests': '1.0-7b8f7f044661fe4e24e6949c035af2c4',
|
||||||
'ContainerAction': '1.1-b0c721f9e10c6c0d1e41e512c49eb877',
|
'ContainerAction': '1.1-b0c721f9e10c6c0d1e41e512c49eb877',
|
||||||
'ContainerActionEvent': '1.0-2974d0a6f5d4821fd4e223a88c10181a',
|
'ContainerActionEvent': '1.0-2974d0a6f5d4821fd4e223a88c10181a',
|
||||||
'Network': '1.1-f57547d39a95cf36f2b026aa4a863879',
|
'Network': '1.1-26e8d37a54e5fc905ede657744a221d9',
|
||||||
'ExecInstance': '1.0-59464e7b96db847c0abb1e96d3cec30a',
|
'ExecInstance': '1.0-59464e7b96db847c0abb1e96d3cec30a',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user