Add Port_Group commands
This patch is adding commands to manipulate the new Port_Group table introduced in the OVN Northbound Database. Four new commands are being added: * pg_add() -> To add a new Port Group * pg_del() -> To delete a Port Group * pg_add_ports() -> To add a list of LSP to a Port Group * pg_add_acls() -> To add a list of ACL to a Port Group * pg_del_ports() -> To delete a list of LSP from a Port Group * pg_del_acls() -> To delete a list of ACL from a Port Group Change-Id: I9bae9a5681501d8e8a85c25ccb6d496d5b3f8681
This commit is contained in:
parent
476b174f7d
commit
90dfca5dfc
@ -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
|
||||
|
@ -766,3 +766,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
|
||||
"""
|
||||
|
@ -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
|
||||
@ -1056,3 +1057,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'
|
||||
|
@ -249,3 +249,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)
|
||||
|
@ -11,6 +11,7 @@
|
||||
# under the License.
|
||||
|
||||
import netaddr
|
||||
from oslo_utils import uuidutils
|
||||
import testscenarios
|
||||
|
||||
from ovsdbapp.backend.ovs_idl import idlutils
|
||||
@ -1197,3 +1198,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)
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user