Merge "Add Port_Group commands"

This commit is contained in:
Zuul 2018-05-30 09:12:57 +00:00 committed by Gerrit Code Review
commit 68177608cd
6 changed files with 296 additions and 0 deletions

View File

@ -24,6 +24,7 @@ netaddr==0.7.18
openstackdocstheme==1.18.1
os-client-config==1.28.0
os-testr==1.0.0
oslo.utils==3.33.0
oslotest==3.2.0
ovs==2.8.0
pbr==2.0.0

View File

@ -821,3 +821,89 @@ class API(api.API):
:type external_ids: key: string, value: string
:returns: :class:`Command` with no result
"""
@abc.abstractmethod
def pg_add(self, name, may_exist=False, **columns):
"""Create a port group
:param name: The name of the port group
:type name: string
:param may_exist: If True, don't fail if the port group already
exists
:type may_exist: bool
:param columns: Additional columns to directly set on the port
group (e.g external_ids, ports, acls)
:type columns: dictionary
:returns: :class:`Command` with RowView result
"""
@abc.abstractmethod
def pg_del(self, name, if_exists=False):
"""Delete a port group
:param name: The name of the port group
:type name: string
:param if_exists: If True, don't fail if the router doesn't exist
:type if_exists: boolean
:returns: :class:`Command` with no result
"""
@abc.abstractmethod
def pg_add_ports(self, pg_id, lsp):
"""Add a list of logical port to a port group
:param pg_id: The name or uuid of the port group
:type pg_id: string or uuid.UUID
:param lsp: A list of :class:`Command` with a Logical_Switch_Port
instance result or UUID
:type lsp: A list of :class:`Command` with a Logical_Switch_Port
or string or uuid.UUID
A Logical_Switch_Port instance or string
or uuid.UUID
:returns: :class:`Command` with no result
"""
@abc.abstractmethod
def pg_del_ports(self, pg_id, lsp, if_exists=False):
"""Delete a list of logical port from a port group
:param pg_id: The name or uuid of the port group
:type pg_id: string or uuid.UUID
:param lsp: A list of :class:`Command` with a Logical_Switch_Port
instance result or UUID
:type lsp: A list of :class:`Command` with a Logical_Switch_Port
or string or uuid.UUID
:type if_exists: If True, don't fail if the logical port(s) doesn't
exist
:type if_exists: boolean
:returns: :class:`Command` with no result
"""
@abc.abstractmethod
def pg_add_acls(self, pg_id, acl):
"""Add a list of ACL to a port group
:param pg_id: The name or uuid of the port group
:type pg_id: string or uuid.UUID
:param acl: The ACL instance or UUID
:type acl: A list of ACL instance or string or uuid.UUID
:param acl: A list of :class:`Command` with an ACL instance
result or UUID
:type acl: A :class:`Command` with an ACL or string
r uuid.UUID
:returns: :class:`Command` with no result
"""
@abc.abstractmethod
def pg_del_acls(self, pg_id, acl, if_exists=False):
"""Delete a list of ACL from a port group
:param pg_id: The name or uuid of the port group
:type pg_id: string or uuid.UUID
:type acl: A list of ACL instance or string or uuid.UUID
:param acl: A list of :class:`Command` with an ACL instance
result or UUID
:type if_exists: If True, don't fail if the ACL(s) doesn't exist
:type if_exists: boolean
:returns: :class:`Command` with no result
"""

View File

@ -12,6 +12,7 @@
import re
import netaddr
from oslo_utils import uuidutils
from ovsdbapp.backend.ovs_idl import command as cmd
from ovsdbapp.backend.ovs_idl import idlutils
@ -1152,3 +1153,101 @@ class DnsSetExternalIdsCommand(cmd.BaseCommand):
except idlutils.RowNotFound:
msg = "DNS %s does not exist" % self.row_uuid
raise RuntimeError(msg)
class PgAddCommand(cmd.AddCommand):
table_name = 'Port_Group'
def __init__(self, api, name, may_exist=False, **columns):
super(PgAddCommand, self).__init__(api)
self.name = name
self.may_exist = may_exist
self.columns = columns
def run_idl(self, txn):
if self.may_exist:
try:
pg = self.api.lookup(self.table_name, self.name)
self.result = rowview.RowView(pg)
except idlutils.RowNotFound:
pass
pg = txn.insert(self.api._tables[self.table_name])
pg.name = self.name
self.set_columns(pg, **self.columns)
self.result = pg.uuid
class PgDelCommand(cmd.BaseCommand):
table_name = 'Port_Group'
def __init__(self, api, name, if_exists=False):
super(PgDelCommand, self).__init__(api)
self.name = name
self.if_exists = if_exists
def run_idl(self, txn):
try:
pg = self.api.lookup(self.table_name, self.name)
pg.delete()
except idlutils.RowNotFound:
if self.if_exists:
return
raise RuntimeError('Port group %s does not exist' % self.name)
class _PgUpdateHelper(cmd.BaseCommand):
method = None
def __init__(self, api, port_group, lsp=None, acl=None, if_exists=False):
super(_PgUpdateHelper, self).__init__(api)
self.port_group = port_group
self.lsp = [] if lsp is None else self._listify(lsp)
self.acl = [] if acl is None else self._listify(acl)
self.if_exists = if_exists
def _listify(self, res):
return res if isinstance(res, (list, tuple)) else [res]
def _fetch_resource(self, type_, uuid_):
table = 'Logical_Switch_Port' if type_ == 'ports' else 'ACL'
return self.api.lookup(table, uuid_)
def _run_method(self, pg, column, resource):
if not resource:
return
if isinstance(resource, cmd.BaseCommand):
resource = resource.result
elif uuidutils.is_uuid_like(resource):
try:
resource = self._fetch_resource(column, resource)
except idlutils.RowNotFound:
if self.if_exists:
return
raise RuntimeError(
'Resource %(res)s of type "%(type)s" does not exist' %
{'res': resource, 'type': column})
getattr(pg, self.method)(column, resource)
def run_idl(self, txn):
try:
pg = self.api.lookup('Port_Group', self.port_group)
except idlutils.RowNotFound:
raise RuntimeError('Port group %s does not exist' %
self.port_group)
for lsp in self.lsp:
self._run_method(pg, 'ports', lsp)
for acl in self.acl:
self._run_method(pg, 'acls', acl)
class PgAddDataCommand(_PgUpdateHelper):
method = 'addvalue'
class PgDelDataCommand(_PgUpdateHelper):
method = 'delvalue'

View File

@ -260,3 +260,21 @@ class OvnNbApiIdlImpl(ovs_idl.Backend, api.API):
def dns_set_external_ids(self, uuid, **external_ids):
return cmd.DnsSetExternalIdsCommand(self, uuid, **external_ids)
def pg_add(self, name, may_exist=False, **columns):
return cmd.PgAddCommand(self, name, may_exist=may_exist, **columns)
def pg_del(self, name, if_exists=False):
return cmd.PgDelCommand(self, name, if_exists=if_exists)
def pg_add_ports(self, pg_id, lsp):
return cmd.PgAddDataCommand(self, pg_id, lsp=lsp)
def pg_del_ports(self, pg_id, lsp, if_exists=False):
return cmd.PgDelDataCommand(self, pg_id, lsp=lsp, if_exists=if_exists)
def pg_add_acls(self, pg_id, acl):
return cmd.PgAddDataCommand(self, pg_id, acl=acl)
def pg_del_acls(self, pg_id, acl, if_exists=False):
return cmd.PgDelDataCommand(self, pg_id, acl=acl, if_exists=if_exists)

View File

@ -11,6 +11,7 @@
# under the License.
import netaddr
from oslo_utils import uuidutils
import testscenarios
from ovsdbapp.backend.ovs_idl import idlutils
@ -1297,3 +1298,93 @@ class TestLsDnsOps(OvnNorthboundTest):
[dns.uuid for dns in ls1.dns_records])
self.api.ls_remove_dns_record(ls1.uuid, dns1.uuid).execute()
self.assertEqual([], ls1.dns_records)
class TestPortGroup(OvnNorthboundTest):
def setUp(self):
super(TestPortGroup, self).setUp()
self.switch = self.useFixture(fixtures.LogicalSwitchFixture()).obj
self.pg_name = 'testpg-%s' % uuidutils.generate_uuid()
def test_port_group(self):
# Assert the Port Group was added
self.api.pg_add(self.pg_name).execute(check_error=True)
row = self.api.db_find(
'Port_Group',
('name', '=', self.pg_name)).execute(check_error=True)
self.assertIsNotNone(row)
self.assertEqual(self.pg_name, row[0]['name'])
self.assertEqual([], row[0]['ports'])
self.assertEqual([], row[0]['acls'])
# Assert the Port Group was deleted
self.api.pg_del(self.pg_name).execute(check_error=True)
row = self.api.db_find(
'Port_Group',
('name', '=', self.pg_name)).execute(check_error=True)
self.assertEqual([], row)
def test_port_group_ports_and_acls(self):
lsp_add_cmd = self.api.lsp_add(self.switch.uuid, 'testport')
acl_add_cmd_1 = self.api.acl_add(
self.switch.uuid, 'from-lport', 0, 'output == "fake_port"',
'drop')
acl_add_cmd_2 = self.api.acl_add(
self.switch.uuid, 'from-lport', 0, 'output == "fake_port" && ip',
'drop')
with self.api.transaction(check_error=True) as txn:
txn.add(lsp_add_cmd)
txn.add(acl_add_cmd_1)
txn.add(acl_add_cmd_2)
txn.add(self.api.pg_add(self.pg_name))
txn.add(self.api.pg_add_acls(
self.pg_name, [acl_add_cmd_1, acl_add_cmd_2]))
port_uuid = lsp_add_cmd.result.uuid
acl_uuid_1 = acl_add_cmd_1.result.uuid
acl_uuid_2 = acl_add_cmd_2.result.uuid
# Lets add the port using the UUID instead of a `Command` to
# exercise the API
self.api.pg_add_ports(self.pg_name, port_uuid).execute(
check_error=True)
row = self.api.db_find(
'Port_Group',
('name', '=', self.pg_name)).execute(check_error=True)
self.assertIsNotNone(row)
self.assertEqual(self.pg_name, row[0]['name'])
# Assert the port and ACLs were added from the Port Group
self.assertEqual([port_uuid], row[0]['ports'])
self.assertEqual(sorted([acl_uuid_1, acl_uuid_2]),
sorted(row[0]['acls']))
# Delete an ACL and the Port from the Port Group
with self.api.transaction(check_error=True) as txn:
txn.add(self.api.pg_del_ports(self.pg_name, port_uuid))
txn.add(self.api.pg_del_acls(self.pg_name, acl_uuid_1))
row = self.api.db_find(
'Port_Group',
('name', '=', self.pg_name)).execute(check_error=True)
self.assertIsNotNone(row)
self.assertEqual(self.pg_name, row[0]['name'])
# Assert the port and ACL were removed from the Port Group
self.assertEqual([], row[0]['ports'])
self.assertEqual([acl_uuid_2], row[0]['acls'])
def test_pg_del_ports_and_acls_if_exists(self):
self.api.pg_add(self.pg_name).execute(check_error=True)
non_existent_res = uuidutils.generate_uuid()
# Assert that if if_exists is False (default) it will raise an error
self.assertRaises(RuntimeError, self.api.pg_del_ports(self.pg_name,
non_existent_res).execute, True)
self.assertRaises(RuntimeError, self.api.pg_del_acls(self.pg_name,
non_existent_res).execute, True)
# Assert that if if_exists is True it won't raise an error
self.api.pg_del_ports(self.pg_name, non_existent_res,
if_exists=True).execute(check_error=True)
self.api.pg_del_acls(self.pg_name, non_existent_res,
if_exists=True).execute(check_error=True)

View File

@ -4,6 +4,7 @@
fixtures>=3.0.0 # Apache-2.0/BSD
netaddr>=0.7.18 # BSD
oslo.utils>=3.33.0 # Apache-2.0
ovs>=2.8.0 # Apache-2.0
pbr!=2.1.0,>=2.0.0 # Apache-2.0
six>=1.10.0 # MIT