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):
|
||||
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):
|
||||
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)
|
||||
|
||||
|
||||
@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")
|
||||
def update_network(context, uuid, values):
|
||||
"""Update properties of a network.
|
||||
|
@ -1250,6 +1250,19 @@ class Connection(object):
|
||||
|
||||
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):
|
||||
# ensure defaults are present for new networks
|
||||
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
|
||||
# (and call docker.create_network later) if there are concurrent
|
||||
# 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, "
|
||||
"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)
|
||||
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
|
||||
def save(self, context=None):
|
||||
"""Save updates to this Network.
|
||||
|
@ -10,8 +10,12 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_utils import uuidutils
|
||||
import six
|
||||
|
||||
from zun.common import exception
|
||||
import zun.conf
|
||||
from zun.db import api as dbapi
|
||||
from zun.tests.unit.db import base
|
||||
from zun.tests.unit.db import utils
|
||||
|
||||
@ -36,3 +40,16 @@ class DbNetworkTestCase(base.DbTestCase):
|
||||
'A network with neutron_net_id 456.*'):
|
||||
utils.create_test_network(context=self.context,
|
||||
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.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):
|
||||
network_name = 'c02afe4e-8350-4263-8078'
|
||||
self.network_api.remove_network(network_name)
|
||||
|
@ -15,6 +15,8 @@
|
||||
|
||||
import mock
|
||||
|
||||
from testtools.matchers import HasLength
|
||||
|
||||
from zun import objects
|
||||
from zun.tests.unit.db import base
|
||||
from zun.tests.unit.db import utils
|
||||
@ -53,3 +55,13 @@ class TestNetworkObject(base.DbTestCase):
|
||||
uuid,
|
||||
params)
|
||||
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',
|
||||
'ContainerAction': '1.1-b0c721f9e10c6c0d1e41e512c49eb877',
|
||||
'ContainerActionEvent': '1.0-2974d0a6f5d4821fd4e223a88c10181a',
|
||||
'Network': '1.1-f57547d39a95cf36f2b026aa4a863879',
|
||||
'Network': '1.1-26e8d37a54e5fc905ede657744a221d9',
|
||||
'ExecInstance': '1.0-59464e7b96db847c0abb1e96d3cec30a',
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user