Add DNS APIs
OVN Northbound DB has DNS table. Support CRUD operations for this table. These APIs will be used by networking-ovn to use OVN's native DNS feature. Note: ovn-nbctl do not support these APIs as of now. But it is good to have these in ovsdbapp and it will be useful. Partial-bug: #1688172 Change-Id: I5528829eef0a7534d9266bb3abc2aec269e4ba35
This commit is contained in:
parent
558783eba2
commit
d7e3313b2c
|
@ -64,6 +64,34 @@ class API(api.API):
|
|||
:returns: :class:`Command` with RowView result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def ls_set_dns_records(self, switch_uuid, dns_uuids):
|
||||
"""Sets 'dns_records' column on the switch with uuid 'switch_uuid'
|
||||
|
||||
:returns: :class:`Command` with RowView result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def ls_clear_dns_records(self, switch):
|
||||
"""Clears 'dns_records' from the switch with uuid 'switch_uuid'
|
||||
|
||||
:returns: :class:`Command` with RowView result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def ls_add_dns_record(self, switch_uuid, dns_uuid):
|
||||
"""Add the 'dns_record' to the switch's 'dns_records' list
|
||||
|
||||
:returns: :class:`Command` with RowView result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def ls_remove_dns_record(self, switch_uuid, dns_uuid):
|
||||
"""Remove the 'dns_record' from the switch's 'dns_records' list
|
||||
|
||||
:returns: :class:`Command` with RowView result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def acl_add(self, switch, direction, priority, match, action, log=False):
|
||||
"""Add an ACL to 'switch'
|
||||
|
@ -657,3 +685,78 @@ class API(api.API):
|
|||
:type uuid: string or uuid.UUID
|
||||
:returns: :class:`Command` with dict result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def dns_add(self, **external_ids):
|
||||
"""Create a DNS row with external_ids
|
||||
|
||||
:param external_ids: external_id field key/value mapping
|
||||
:type external_ids: key: string, value: string
|
||||
:returns: :class:`Command` with RowView result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def dns_del(self, uuid):
|
||||
"""Delete DNS row with 'uuid'
|
||||
|
||||
:param uuid: The uuid of the DNS row to delete
|
||||
:type uuid: string or uuid.UUID
|
||||
:returns: :class:`Command` with no result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def dns_get(self, uuid):
|
||||
"""Get DNS row with 'uuid'
|
||||
|
||||
:returns: :class:`Command` with RowView result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def dns_list(self):
|
||||
"""Get all DNS rows
|
||||
|
||||
:returns: :class:`Command with RowView list result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def dns_set_records(self, uuid, **records):
|
||||
"""Sets the 'records' field of the DNS row
|
||||
|
||||
:param uuid: The uuid of the DNS row to set the records with
|
||||
:type uuid: string or uuid.UUID
|
||||
:param records: keys and values for the DNS 'records' dict
|
||||
:type records: key: string, value: string
|
||||
:returns: :class:`Command` with no result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def dns_add_record(self, uuid, hostname, ips):
|
||||
"""Add the record 'hostname: ips' into the records column of the DNS
|
||||
|
||||
:param uuid: The uuid of the DNS row to add the record
|
||||
:type uuid: string or uuid.UUID
|
||||
:param hostname: hostname as the key to the record dict
|
||||
:type ips: IPs as the value to the hostname key in the 'records'
|
||||
:returns: :class:`Command` with no result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def dns_remove_record(self, uuid, hostname):
|
||||
"""Remove the 'hostname' from the 'records' field of the DNS row
|
||||
|
||||
:param uuid: The uuid of the DNS row to set the records with
|
||||
:type uuid: string or uuid.UUID
|
||||
:param hostname: hostname as the key to the record dict
|
||||
:returns: :class:`Command` with no result
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def dns_set_external_ids(self, uuid, **external_ids):
|
||||
"""Sets the 'external_ids' field of the DNS row
|
||||
|
||||
:param uuid: The uuid of the DNS row to set the external_ids with
|
||||
:type uuid: string or uuid.UUID
|
||||
:param external_ids: keys and values for the DNS 'external_ids' dict
|
||||
:type external_ids: key: string, value: string
|
||||
:returns: :class:`Command` with no result
|
||||
"""
|
||||
|
|
|
@ -990,3 +990,64 @@ class LsLbListCommand(cmd.BaseCommand):
|
|||
def run_idl(self, txn):
|
||||
ls = self.api.lookup('Logical_Switch', self.switch)
|
||||
self.result = [rowview.RowView(r) for r in ls.load_balancer]
|
||||
|
||||
|
||||
class DnsAddCommand(cmd.AddCommand):
|
||||
table_name = 'DNS'
|
||||
|
||||
def __init__(self, api, **columns):
|
||||
super(DnsAddCommand, self).__init__(api)
|
||||
self.columns = columns
|
||||
|
||||
def run_idl(self, txn):
|
||||
dns = txn.insert(self.api.tables[self.table_name])
|
||||
# Transaction will not be commited if the row is not initialized with
|
||||
# any columns.
|
||||
dns.external_ids = {}
|
||||
self.set_columns(dns, **self.columns)
|
||||
self.result = dns.uuid
|
||||
|
||||
|
||||
class DnsDelCommand(cmd.DbDestroyCommand):
|
||||
def __init__(self, api, uuid):
|
||||
super(DnsDelCommand, self).__init__(api, 'DNS', uuid)
|
||||
|
||||
|
||||
class DnsGetCommand(cmd.BaseGetRowCommand):
|
||||
table = 'DNS'
|
||||
|
||||
|
||||
class DnsListCommand(cmd.BaseCommand):
|
||||
def run_idl(self, txn):
|
||||
table = self.api.tables['DNS']
|
||||
self.result = [rowview.RowView(r) for r in table.rows.values()]
|
||||
|
||||
|
||||
class DnsSetRecordsCommand(cmd.BaseCommand):
|
||||
def __init__(self, api, row_uuid, **records):
|
||||
super(DnsSetRecordsCommand, self).__init__(api)
|
||||
self.row_uuid = row_uuid
|
||||
self.records = records
|
||||
|
||||
def run_idl(self, txn):
|
||||
try:
|
||||
dns = self.api.lookup('DNS', self.row_uuid)
|
||||
dns.records = self.records
|
||||
except idlutils.RowNotFound:
|
||||
msg = "DNS %s does not exist" % self.row_uuid
|
||||
raise RuntimeError(msg)
|
||||
|
||||
|
||||
class DnsSetExternalIdsCommand(cmd.BaseCommand):
|
||||
def __init__(self, api, row_uuid, **external_ids):
|
||||
super(DnsSetExternalIdsCommand, self).__init__(api)
|
||||
self.row_uuid = row_uuid
|
||||
self.external_ids = external_ids
|
||||
|
||||
def run_idl(self, txn):
|
||||
try:
|
||||
dns = self.api.lookup('DNS', self.row_uuid)
|
||||
dns.external_ids = self.external_ids
|
||||
except idlutils.RowNotFound:
|
||||
msg = "DNS %s does not exist" % self.row_uuid
|
||||
raise RuntimeError(msg)
|
||||
|
|
|
@ -15,6 +15,7 @@ from ovsdbapp.backend.ovs_idl import idlutils
|
|||
from ovsdbapp import constants as const
|
||||
from ovsdbapp.schema.ovn_northbound import api
|
||||
from ovsdbapp.schema.ovn_northbound import commands as cmd
|
||||
from ovsdbapp import utils
|
||||
|
||||
|
||||
class OvnNbApiIdlImpl(ovs_idl.Backend, api.API):
|
||||
|
@ -37,6 +38,21 @@ class OvnNbApiIdlImpl(ovs_idl.Backend, api.API):
|
|||
def ls_get(self, switch):
|
||||
return cmd.LsGetCommand(self, switch)
|
||||
|
||||
def ls_set_dns_records(self, switch_uuid, dns_uuids):
|
||||
return self.db_set('Logical_Switch', switch_uuid,
|
||||
('dns_records', dns_uuids))
|
||||
|
||||
def ls_clear_dns_records(self, switch_uuid):
|
||||
return self.db_clear('Logical_Switch', switch_uuid, 'dns_records')
|
||||
|
||||
def ls_add_dns_record(self, switch_uuid, dns_uuid):
|
||||
return self.db_add('Logical_Switch', switch_uuid, 'dns_records',
|
||||
dns_uuid)
|
||||
|
||||
def ls_remove_dns_record(self, switch_uuid, dns_uuid):
|
||||
return self.db_remove('Logical_Switch', switch_uuid, 'dns_records',
|
||||
dns_uuid)
|
||||
|
||||
def acl_add(self, switch, direction, priority, match, action, log=False,
|
||||
may_exist=False, **external_ids):
|
||||
return cmd.AclAddCommand(self, switch, direction, priority,
|
||||
|
@ -204,3 +220,29 @@ class OvnNbApiIdlImpl(ovs_idl.Backend, api.API):
|
|||
|
||||
def dhcp_options_get_options(self, dhcpopt_uuid):
|
||||
return cmd.DhcpOptionsGetOptionsCommand(self, dhcpopt_uuid)
|
||||
|
||||
def dns_add(self, **columns):
|
||||
return cmd.DnsAddCommand(self, **columns)
|
||||
|
||||
def dns_del(self, uuid):
|
||||
return cmd.DnsDelCommand(self, uuid)
|
||||
|
||||
def dns_get(self, uuid):
|
||||
return cmd.DnsGetCommand(self, uuid)
|
||||
|
||||
def dns_list(self):
|
||||
return cmd.DnsListCommand(self)
|
||||
|
||||
def dns_set_records(self, uuid, **records):
|
||||
return cmd.DnsSetRecordsCommand(self, uuid, **records)
|
||||
|
||||
def dns_add_record(self, uuid, hostname, ips):
|
||||
if isinstance(ips, list):
|
||||
ips = " ".join(utils.normalize_ip_port(ip) for ip in ips)
|
||||
return self.db_add('DNS', uuid, 'records', {hostname: ips})
|
||||
|
||||
def dns_remove_record(self, uuid, hostname):
|
||||
return self.db_remove('DNS', uuid, 'records', hostname)
|
||||
|
||||
def dns_set_external_ids(self, uuid, **external_ids):
|
||||
return cmd.DnsSetExternalIdsCommand(self, uuid, **external_ids)
|
||||
|
|
|
@ -37,3 +37,10 @@ class LoadBalancerFixture(fixtures.ImplIdlFixture):
|
|||
api = impl_idl.OvnNbApiIdlImpl
|
||||
create = 'lb_add'
|
||||
delete = 'lb_del'
|
||||
|
||||
|
||||
class DnsFixture(fixtures.ImplIdlFixture):
|
||||
api = impl_idl.OvnNbApiIdlImpl
|
||||
create = 'dns_add'
|
||||
delete = 'dns_del'
|
||||
delete_args = {}
|
||||
|
|
|
@ -1087,3 +1087,113 @@ class TestCommonDbOps(OvnNorthboundTest):
|
|||
# should be a NoOp, not fail
|
||||
self.api.db_remove('Logical_Switch', self.switch.uuid, 'ports',
|
||||
"badvalue").execute(check_error=True)
|
||||
|
||||
|
||||
class TestDnsOps(OvnNorthboundTest):
|
||||
def _dns_add(self, *args, **kwargs):
|
||||
dns = self.useFixture(fixtures.DnsFixture(*args, **kwargs)).obj
|
||||
return dns
|
||||
|
||||
def test_dns_get(self):
|
||||
dns = self._dns_add()
|
||||
found = self.api.dns_get(dns.uuid).execute(
|
||||
check_error=True)
|
||||
self.assertEqual(dns, found)
|
||||
|
||||
def test_dns_get_no_exist(self):
|
||||
cmd = self.api.dns_get("noexist")
|
||||
self.assertRaises(idlutils.RowNotFound, cmd.execute, check_error=True)
|
||||
|
||||
def test_dns_add(self):
|
||||
self._dns_add()
|
||||
|
||||
def test_dns_add_ext_ids(self):
|
||||
ext_ids = {'net-id': '1', 'other-id': '2'}
|
||||
dns = self._dns_add(external_ids=ext_ids)
|
||||
self.assertEqual(ext_ids, dns.external_ids)
|
||||
|
||||
def test_dns_list(self):
|
||||
dnses = {self._dns_add() for d in range(3)}
|
||||
dnses_set = set(
|
||||
self.api.dns_list().execute(check_error=True))
|
||||
self.assertTrue(dnses.issubset(dnses_set))
|
||||
|
||||
def test_dns_set_records(self):
|
||||
dns = self._dns_add()
|
||||
records = {'a': 'one', 'b': 'two'}
|
||||
self.api.dns_set_records(
|
||||
dns.uuid, **records).execute(check_error=True)
|
||||
dns = self.api.dns_get(dns.uuid).execute(
|
||||
check_error=True)
|
||||
self.assertEqual(records, dns.records)
|
||||
self.api.dns_set_records(
|
||||
dns.uuid, **{}).execute(check_error=True)
|
||||
self.assertEqual({}, dns.records)
|
||||
|
||||
def test_dns_set_external_ids(self):
|
||||
dns = self._dns_add()
|
||||
external_ids = {'a': 'one', 'b': 'two'}
|
||||
self.api.dns_set_external_ids(
|
||||
dns.uuid, **external_ids).execute(check_error=True)
|
||||
dns = self.api.dns_get(dns.uuid).execute(
|
||||
check_error=True)
|
||||
self.assertEqual(external_ids, dns.external_ids)
|
||||
self.api.dns_set_external_ids(
|
||||
dns.uuid, **{}).execute(check_error=True)
|
||||
self.assertEqual({}, dns.external_ids)
|
||||
|
||||
def test_dns_add_remove_records(self):
|
||||
dns = self._dns_add()
|
||||
self.api.dns_add_record(dns.uuid, 'a', 'one').execute()
|
||||
self.api.dns_add_record(dns.uuid, 'b', 'two').execute()
|
||||
dns = self.api.dns_get(dns.uuid).execute(
|
||||
check_error=True)
|
||||
records = {'a': 'one', 'b': 'two'}
|
||||
self.assertEqual(records, dns.records)
|
||||
self.api.dns_remove_record(dns.uuid, 'a').execute()
|
||||
records.pop('a')
|
||||
self.assertEqual(records, dns.records)
|
||||
self.api.dns_remove_record(dns.uuid, 'b').execute()
|
||||
self.assertEqual({}, dns.records)
|
||||
|
||||
|
||||
class TestLsDnsOps(OvnNorthboundTest):
|
||||
def _dns_add(self, *args, **kwargs):
|
||||
dns = self.useFixture(fixtures.DnsFixture(*args, **kwargs)).obj
|
||||
return dns
|
||||
|
||||
def _ls_add(self, *args, **kwargs):
|
||||
fix = self.useFixture(fixtures.LogicalSwitchFixture(*args, **kwargs))
|
||||
return fix.obj
|
||||
|
||||
def test_ls_dns_set_clear_records(self):
|
||||
dns1 = self._dns_add()
|
||||
dns2 = self._dns_add()
|
||||
|
||||
ls1 = self._ls_add('ls1')
|
||||
self.api.ls_set_dns_records(ls1.uuid, [dns1.uuid, dns2.uuid]).execute()
|
||||
self.assertItemsEqual([dns1.uuid, dns2.uuid],
|
||||
[dns.uuid for dns in ls1.dns_records])
|
||||
|
||||
self.api.ls_clear_dns_records(ls1.uuid).execute()
|
||||
self.assertEqual([], ls1.dns_records)
|
||||
|
||||
def test_ls_dns_add_remove_records(self):
|
||||
dns1 = self._dns_add()
|
||||
dns2 = self._dns_add()
|
||||
|
||||
ls1 = self._ls_add('ls1')
|
||||
|
||||
self.api.ls_add_dns_record(ls1.uuid, dns1.uuid).execute()
|
||||
self.assertItemsEqual([dns1.uuid],
|
||||
[dns.uuid for dns in ls1.dns_records])
|
||||
|
||||
self.api.ls_add_dns_record(ls1.uuid, dns2.uuid).execute()
|
||||
self.assertItemsEqual([dns1.uuid, dns2.uuid],
|
||||
[dns.uuid for dns in ls1.dns_records])
|
||||
|
||||
self.api.ls_remove_dns_record(ls1.uuid, dns2.uuid).execute()
|
||||
self.assertItemsEqual([dns1.uuid],
|
||||
[dns.uuid for dns in ls1.dns_records])
|
||||
self.api.ls_remove_dns_record(ls1.uuid, dns1.uuid).execute()
|
||||
self.assertEqual([], ls1.dns_records)
|
||||
|
|
Loading…
Reference in New Issue