1482 lines
51 KiB
Python
1482 lines
51 KiB
Python
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
import re
|
|
|
|
import netaddr
|
|
|
|
from ovsdbapp.backend.ovs_idl import command as cmd
|
|
from ovsdbapp.backend.ovs_idl import idlutils
|
|
from ovsdbapp.backend.ovs_idl import rowview
|
|
from ovsdbapp import constants as const
|
|
from ovsdbapp import utils
|
|
|
|
|
|
class LsAddCommand(cmd.AddCommand):
|
|
table_name = 'Logical_Switch'
|
|
|
|
def __init__(self, api, switch=None, may_exist=False, **columns):
|
|
super(LsAddCommand, self).__init__(api)
|
|
self.switch = switch
|
|
self.columns = columns
|
|
self.may_exist = may_exist
|
|
|
|
def run_idl(self, txn):
|
|
# There is no requirement for name to be unique, so if a name is
|
|
# specified, we always have to do a lookup since adding it won't
|
|
# fail. If may_exist is set, we just don't do anything when dup'd
|
|
if self.switch:
|
|
sw = idlutils.row_by_value(self.api.idl, self.table_name, 'name',
|
|
self.switch, None)
|
|
if sw:
|
|
if self.may_exist:
|
|
self.result = rowview.RowView(sw)
|
|
return
|
|
raise RuntimeError("Switch %s exists" % self.switch)
|
|
elif self.may_exist:
|
|
raise RuntimeError("may_exist requires name")
|
|
sw = txn.insert(self.api.tables[self.table_name])
|
|
if self.switch:
|
|
sw.name = self.switch
|
|
else:
|
|
# because ovs.db.idl brokenly requires a changed column
|
|
sw.name = ""
|
|
self.set_columns(sw, **self.columns)
|
|
self.result = sw.uuid
|
|
|
|
|
|
class LsDelCommand(cmd.BaseCommand):
|
|
def __init__(self, api, switch, if_exists=False):
|
|
super(LsDelCommand, self).__init__(api)
|
|
self.switch = switch
|
|
self.if_exists = if_exists
|
|
|
|
def run_idl(self, txn):
|
|
try:
|
|
lswitch = self.api.lookup('Logical_Switch', self.switch)
|
|
lswitch.delete()
|
|
except idlutils.RowNotFound:
|
|
if self.if_exists:
|
|
return
|
|
msg = "Logical Switch %s does not exist" % self.switch
|
|
raise RuntimeError(msg)
|
|
|
|
|
|
class LsListCommand(cmd.ReadOnlyCommand):
|
|
def run_idl(self, txn):
|
|
table = self.api.tables['Logical_Switch']
|
|
self.result = [rowview.RowView(r) for r in table.rows.values()]
|
|
|
|
|
|
class LsGetCommand(cmd.BaseGetRowCommand):
|
|
table = 'Logical_Switch'
|
|
|
|
|
|
class _AclAddHelper(cmd.AddCommand):
|
|
table_name = 'ACL'
|
|
|
|
def __init__(self, api, entity, direction, priority, match, action,
|
|
log=False, may_exist=False, severity=None, name=None,
|
|
**external_ids):
|
|
if direction not in ('from-lport', 'to-lport'):
|
|
raise TypeError("direction must be either from-lport or to-lport")
|
|
if not 0 <= priority <= const.ACL_PRIORITY_MAX:
|
|
raise ValueError("priority must be between 0 and %s, inclusive" % (
|
|
const.ACL_PRIORITY_MAX))
|
|
if action not in ('allow', 'allow-related', 'drop', 'reject'):
|
|
raise TypeError("action must be allow/allow-related/drop/reject")
|
|
super(_AclAddHelper, self).__init__(api)
|
|
self.entity = entity
|
|
self.direction = direction
|
|
self.priority = priority
|
|
self.match = match
|
|
self.action = action
|
|
self.log = log
|
|
self.may_exist = may_exist
|
|
self.severity = severity
|
|
self.name = name
|
|
self.external_ids = external_ids
|
|
|
|
def acl_match(self, row):
|
|
return (self.direction == row.direction and
|
|
self.priority == row.priority and
|
|
self.match == row.match)
|
|
|
|
def run_idl(self, txn):
|
|
entity = self.api.lookup(self.lookup_table, self.entity)
|
|
acls = [acl for acl in entity.acls if self.acl_match(acl)]
|
|
if acls:
|
|
if self.may_exist:
|
|
self.result = rowview.RowView(acls[0])
|
|
return
|
|
raise RuntimeError("ACL (%s, %s, %s) already exists" % (
|
|
self.direction, self.priority, self.match))
|
|
acl = txn.insert(self.api.tables[self.table_name])
|
|
acl.direction = self.direction
|
|
acl.priority = self.priority
|
|
acl.match = self.match
|
|
acl.action = self.action
|
|
acl.log = self.log
|
|
acl.severity = self.severity
|
|
acl.name = self.name
|
|
entity.addvalue('acls', acl)
|
|
for col, value in self.external_ids.items():
|
|
acl.setkey('external_ids', col, value)
|
|
self.result = acl.uuid
|
|
|
|
|
|
class AclAddCommand(_AclAddHelper):
|
|
lookup_table = 'Logical_Switch'
|
|
|
|
def __init__(self, api, switch, direction, priority, match, action,
|
|
log=False, may_exist=False, severity=None, name=None,
|
|
**external_ids):
|
|
# NOTE: we're overriding the constructor here to not break any
|
|
# existing callers before we introduced Port Groups.
|
|
super(AclAddCommand, self).__init__(api, switch, direction, priority,
|
|
match, action, log, may_exist,
|
|
severity, name, **external_ids)
|
|
|
|
|
|
class PgAclAddCommand(_AclAddHelper):
|
|
lookup_table = 'Port_Group'
|
|
|
|
|
|
class _AclDelHelper(cmd.BaseCommand):
|
|
def __init__(self, api, entity, direction=None,
|
|
priority=None, match=None):
|
|
if (priority is None) != (match is None):
|
|
raise TypeError("Must specify priority and match together")
|
|
if priority is not None and not direction:
|
|
raise TypeError("Cannot specify priority/match without direction")
|
|
super(_AclDelHelper, self).__init__(api)
|
|
self.entity = entity
|
|
self.conditions = []
|
|
if direction:
|
|
self.conditions.append(('direction', '=', direction))
|
|
# priority can be 0
|
|
if match: # and therefore priority due to the above check
|
|
self.conditions += [('priority', '=', priority),
|
|
('match', '=', match)]
|
|
|
|
def run_idl(self, txn):
|
|
entity = self.api.lookup(self.lookup_table, self.entity)
|
|
for acl in [a for a in entity.acls
|
|
if idlutils.row_match(a, self.conditions)]:
|
|
entity.delvalue('acls', acl)
|
|
acl.delete()
|
|
|
|
|
|
class AclDelCommand(_AclDelHelper):
|
|
lookup_table = 'Logical_Switch'
|
|
|
|
def __init__(self, api, switch, direction=None,
|
|
priority=None, match=None):
|
|
# NOTE: we're overriding the constructor here to not break any
|
|
# existing callers before we introduced Port Groups.
|
|
super(AclDelCommand, self).__init__(api, switch, direction, priority,
|
|
match)
|
|
|
|
|
|
class PgAclDelCommand(_AclDelHelper):
|
|
lookup_table = 'Port_Group'
|
|
|
|
|
|
class _AclListHelper(cmd.ReadOnlyCommand):
|
|
def __init__(self, api, entity):
|
|
super(_AclListHelper, self).__init__(api)
|
|
self.entity = entity
|
|
|
|
def run_idl(self, txn):
|
|
entity = self.api.lookup(self.lookup_table, self.entity)
|
|
self.result = [rowview.RowView(acl) for acl in entity.acls]
|
|
|
|
|
|
class AclListCommand(_AclListHelper):
|
|
lookup_table = 'Logical_Switch'
|
|
|
|
|
|
class PgAclListCommand(_AclListHelper):
|
|
lookup_table = 'Port_Group'
|
|
|
|
|
|
class QoSAddCommand(cmd.AddCommand):
|
|
table_name = 'QoS'
|
|
|
|
def __init__(self, api, switch, direction, priority, match, rate=None,
|
|
burst=None, dscp=None, may_exist=False, **columns):
|
|
if direction not in ('from-lport', 'to-lport'):
|
|
raise TypeError("direction must be either from-lport or to-lport")
|
|
if not 0 <= priority <= const.ACL_PRIORITY_MAX:
|
|
raise ValueError("priority must be between 0 and %s, inclusive" %
|
|
const.ACL_PRIORITY_MAX)
|
|
if rate is not None and not 1 <= rate <= const.QOS_BANDWIDTH_MAX:
|
|
raise ValueError("rate(%s) must be between 1 and %s, inclusive" %
|
|
rate, const.QOS_BANDWIDTH_MAX)
|
|
if burst is not None and not 1 <= burst <= const.QOS_BANDWIDTH_MAX:
|
|
raise ValueError("burst(%s) must be between 1 and %s, "
|
|
"inclusive" % burst, const.QOS_BANDWIDTH_MAX)
|
|
if dscp is not None and not 0 <= dscp <= const.QOS_DSCP_MAX:
|
|
raise ValueError("dscp(%s) must be between 0 and %s, inclusive" %
|
|
dscp, const.QOS_DSCP_MAX)
|
|
if rate is None and dscp is None:
|
|
raise ValueError("One of the rate or dscp must be configured")
|
|
super(QoSAddCommand, self).__init__(api)
|
|
self.switch = switch
|
|
self.direction = direction
|
|
self.priority = priority
|
|
self.match = match
|
|
self.rate = rate
|
|
self.burst = burst
|
|
self.dscp = dscp
|
|
self.may_exist = may_exist
|
|
self.columns = columns
|
|
|
|
def qos_match(self, row):
|
|
return (self.direction == row.direction and
|
|
self.priority == row.priority and
|
|
self.match == row.match)
|
|
|
|
def run_idl(self, txn):
|
|
ls = self.api.lookup('Logical_Switch', self.switch)
|
|
for qos_rule in iter(r for r in ls.qos_rules if self.qos_match(r)):
|
|
if self.may_exist:
|
|
self.result = rowview.RowView(qos_rule)
|
|
return
|
|
raise RuntimeError("QoS (%s, %s, %s) already exists" % (
|
|
self.direction, self.priority, self.match))
|
|
row = txn.insert(self.api.tables[self.table_name])
|
|
row.direction = self.direction
|
|
row.priority = self.priority
|
|
row.match = self.match
|
|
if self.rate:
|
|
row.setkey('bandwidth', 'rate', self.rate)
|
|
if self.burst:
|
|
row.setkey('bandwidth', 'burst', self.burst)
|
|
if self.dscp is not None:
|
|
row.setkey('action', 'dscp', self.dscp)
|
|
self.set_columns(row, **self.columns)
|
|
ls.addvalue('qos_rules', row)
|
|
self.result = row.uuid
|
|
|
|
|
|
class QoSDelCommand(cmd.BaseCommand):
|
|
def __init__(self, api, switch, direction=None,
|
|
priority=None, match=None):
|
|
if (priority is None) != (match is None):
|
|
raise TypeError("Must specify priority and match together")
|
|
if priority is not None and not direction:
|
|
raise TypeError("Cannot specify priority/match without direction")
|
|
super(QoSDelCommand, self).__init__(api)
|
|
self.switch = switch
|
|
self.conditions = []
|
|
if direction:
|
|
self.conditions.append(('direction', '=', direction))
|
|
# priority can be 0
|
|
if match: # and therefor priority due to the above check
|
|
self.conditions += [('priority', '=', priority),
|
|
('match', '=', match)]
|
|
|
|
def run_idl(self, txn):
|
|
ls = self.api.lookup('Logical_Switch', self.switch)
|
|
for row in ls.qos_rules:
|
|
if idlutils.row_match(row, self.conditions):
|
|
ls.delvalue('qos_rules', row)
|
|
row.delete()
|
|
|
|
|
|
class QoSListCommand(cmd.ReadOnlyCommand):
|
|
def __init__(self, api, switch):
|
|
super(QoSListCommand, self).__init__(api)
|
|
self.switch = switch
|
|
|
|
def run_idl(self, txn):
|
|
ls = self.api.lookup('Logical_Switch', self.switch)
|
|
self.result = [rowview.RowView(row) for row in ls.qos_rules]
|
|
|
|
|
|
class QoSDelExtIdCommand(cmd.BaseCommand):
|
|
def __init__(self, api, lswitch, external_ids, if_exists=False):
|
|
if not external_ids:
|
|
raise TypeError('external_ids dictionary cannot be empty')
|
|
super(QoSDelExtIdCommand, self).__init__(api)
|
|
self.lswitch = lswitch
|
|
self.external_ids = external_ids
|
|
self.if_exists = if_exists
|
|
|
|
def run_idl(self, txn):
|
|
try:
|
|
lswitch = idlutils.row_by_value(self.api.idl, 'Logical_Switch',
|
|
'name', self.lswitch)
|
|
except idlutils.RowNotFound:
|
|
if self.if_exists:
|
|
return
|
|
msg = 'Logical Switch %s does not exist' % self.lswitch
|
|
raise RuntimeError(msg)
|
|
|
|
for qos in lswitch.qos_rules:
|
|
if self.external_ids.items() <= qos.external_ids.items():
|
|
lswitch.delvalue('qos_rules', qos)
|
|
qos.delete()
|
|
|
|
|
|
class LspAddCommand(cmd.AddCommand):
|
|
table_name = 'Logical_Switch_Port'
|
|
|
|
def __init__(self, api, switch, port, parent_name=None, tag=None,
|
|
may_exist=False, **columns):
|
|
if tag and not 0 <= tag <= 4095:
|
|
raise TypeError("tag must be 0 to 4095, inclusive")
|
|
if (parent_name is None) != (tag is None):
|
|
raise TypeError("parent_name and tag must be passed together")
|
|
super(LspAddCommand, self).__init__(api)
|
|
self.switch = switch
|
|
self.port = port
|
|
self.parent = parent_name
|
|
self.tag = tag
|
|
self.may_exist = may_exist
|
|
self.columns = columns
|
|
|
|
def run_idl(self, txn):
|
|
ls = self.api.lookup('Logical_Switch', self.switch)
|
|
try:
|
|
lsp = self.api.lookup(self.table_name, self.port)
|
|
if self.may_exist:
|
|
msg = None
|
|
if lsp not in ls.ports:
|
|
msg = "%s exists, but is not in %s" % (
|
|
self.port, self.switch)
|
|
if self.parent:
|
|
if not lsp.parent_name:
|
|
msg = "%s exists, but has no parent" % self.port
|
|
# parent_name, being optional, is stored as list
|
|
if self.parent not in lsp.parent_name:
|
|
msg = "%s exists with different parent" % self.port
|
|
if self.tag not in lsp.tag_request:
|
|
msg = "%s exists with different tag request" % (
|
|
self.port,)
|
|
elif lsp.parent_name:
|
|
msg = "%s exists, but with a parent" % self.port
|
|
|
|
if msg:
|
|
raise RuntimeError(msg)
|
|
self.result = rowview.RowView(lsp)
|
|
return
|
|
except idlutils.RowNotFound:
|
|
# This is what we want
|
|
pass
|
|
lsp = txn.insert(self.api.tables[self.table_name])
|
|
lsp.name = self.port
|
|
if self.tag is not None:
|
|
lsp.parent_name = self.parent
|
|
lsp.tag_request = self.tag
|
|
ls.addvalue('ports', lsp)
|
|
self.set_columns(lsp, **self.columns)
|
|
self.result = lsp.uuid
|
|
|
|
|
|
class PortDelCommand(cmd.BaseCommand):
|
|
def __init__(self, api, table, port, parent_table, parent=None,
|
|
if_exists=False):
|
|
super(PortDelCommand, self).__init__(api)
|
|
self.table = table
|
|
self.port = port
|
|
self.parent_table = parent_table
|
|
self.parent = parent
|
|
self.if_exists = if_exists
|
|
|
|
def run_idl(self, txn):
|
|
try:
|
|
row = self.api.lookup(self.table, self.port)
|
|
except idlutils.RowNotFound:
|
|
if self.if_exists:
|
|
return
|
|
raise RuntimeError("%s does not exist" % self.port)
|
|
|
|
# We need to delete the port from its parent
|
|
if self.parent:
|
|
parent = self.api.lookup(self.parent_table, self.parent)
|
|
else:
|
|
parent = next(iter(
|
|
p for p in self.api.tables[self.parent_table].rows.values()
|
|
if row in p.ports), None)
|
|
if not (parent and row in parent.ports):
|
|
raise RuntimeError("%s does not exist in %s" % (
|
|
self.port, self.parent))
|
|
parent.delvalue('ports', row)
|
|
row.delete()
|
|
|
|
|
|
class LspDelCommand(PortDelCommand):
|
|
def __init__(self, api, port, switch=None, if_exists=False):
|
|
super(LspDelCommand, self).__init__(
|
|
api, 'Logical_Switch_Port', port, 'Logical_Switch', switch,
|
|
if_exists)
|
|
|
|
|
|
class LspListCommand(cmd.ReadOnlyCommand):
|
|
def __init__(self, api, switch=None):
|
|
super(LspListCommand, self).__init__(api)
|
|
self.switch = switch
|
|
|
|
def run_idl(self, txn):
|
|
if self.switch:
|
|
ports = self.api.lookup('Logical_Switch', self.switch).ports
|
|
else:
|
|
ports = self.api.tables['Logical_Switch_Port'].rows.values()
|
|
self.result = [rowview.RowView(r) for r in ports]
|
|
|
|
|
|
class LspGetCommand(cmd.BaseGetRowCommand):
|
|
table = 'Logical_Switch_Port'
|
|
|
|
|
|
class LspGetParentCommand(cmd.ReadOnlyCommand):
|
|
def __init__(self, api, port):
|
|
super(LspGetParentCommand, self).__init__(api)
|
|
self.port = port
|
|
|
|
def run_idl(self, txn):
|
|
lsp = self.api.lookup('Logical_Switch_Port', self.port)
|
|
self.result = next(iter(lsp.parent_name), "")
|
|
|
|
|
|
class LspGetTagCommand(cmd.ReadOnlyCommand):
|
|
def __init__(self, api, port):
|
|
super(LspGetTagCommand, self).__init__(api)
|
|
self.port = port
|
|
|
|
def run_idl(self, txn):
|
|
lsp = self.api.lookup('Logical_Switch_Port', self.port)
|
|
self.result = next(iter(lsp.tag), -1)
|
|
|
|
|
|
class LspSetAddressesCommand(cmd.BaseCommand):
|
|
addr_re = re.compile(
|
|
r'^(router|unknown|dynamic|([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}( .+)*)$')
|
|
|
|
def __init__(self, api, port, addresses):
|
|
for addr in addresses:
|
|
if not self.addr_re.match(addr):
|
|
raise TypeError(
|
|
"address (%s) must be router/unknown/dynamic/"
|
|
"ethaddr[ ipaddr...]" % (addr,))
|
|
super(LspSetAddressesCommand, self).__init__(api)
|
|
self.port = port
|
|
self.addresses = addresses
|
|
|
|
def run_idl(self, txn):
|
|
lsp = self.api.lookup('Logical_Switch_Port', self.port)
|
|
lsp.addresses = self.addresses
|
|
|
|
|
|
class LspGetAddressesCommand(cmd.ReadOnlyCommand):
|
|
def __init__(self, api, port):
|
|
super(LspGetAddressesCommand, self).__init__(api)
|
|
self.port = port
|
|
|
|
def run_idl(self, txn):
|
|
lsp = self.api.lookup('Logical_Switch_Port', self.port)
|
|
self.result = lsp.addresses
|
|
|
|
|
|
class LspSetPortSecurityCommand(cmd.BaseCommand):
|
|
def __init__(self, api, port, addresses):
|
|
# NOTE(twilson) ovn-nbctl.c does not do any checking of addresses
|
|
# so neither do we
|
|
super(LspSetPortSecurityCommand, self).__init__(api)
|
|
self.port = port
|
|
self.addresses = addresses
|
|
|
|
def run_idl(self, txn):
|
|
lsp = self.api.lookup('Logical_Switch_Port', self.port)
|
|
lsp.port_security = self.addresses
|
|
|
|
|
|
class LspGetPortSecurityCommand(cmd.ReadOnlyCommand):
|
|
def __init__(self, api, port):
|
|
super(LspGetPortSecurityCommand, self).__init__(api)
|
|
self.port = port
|
|
|
|
def run_idl(self, txn):
|
|
lsp = self.api.lookup('Logical_Switch_Port', self.port)
|
|
self.result = lsp.port_security
|
|
|
|
|
|
class LspGetUpCommand(cmd.ReadOnlyCommand):
|
|
def __init__(self, api, port):
|
|
super(LspGetUpCommand, self).__init__(api)
|
|
self.port = port
|
|
|
|
def run_idl(self, txn):
|
|
lsp = self.api.lookup('Logical_Switch_Port', self.port)
|
|
# 'up' is optional, but if not up, it's not up :p
|
|
self.result = next(iter(lsp.up), False)
|
|
|
|
|
|
class LspSetEnabledCommand(cmd.BaseCommand):
|
|
def __init__(self, api, port, is_enabled):
|
|
super(LspSetEnabledCommand, self).__init__(api)
|
|
self.port = port
|
|
self.is_enabled = is_enabled
|
|
|
|
def run_idl(self, txn):
|
|
lsp = self.api.lookup('Logical_Switch_Port', self.port)
|
|
lsp.enabled = self.is_enabled
|
|
|
|
|
|
class LspGetEnabledCommand(cmd.ReadOnlyCommand):
|
|
def __init__(self, api, port):
|
|
super(LspGetEnabledCommand, self).__init__(api)
|
|
self.port = port
|
|
|
|
def run_idl(self, txn):
|
|
lsp = self.api.lookup('Logical_Switch_Port', self.port)
|
|
# enabled is optional, but if not disabled then enabled
|
|
self.result = next(iter(lsp.enabled), True)
|
|
|
|
|
|
class LspSetTypeCommand(cmd.BaseCommand):
|
|
def __init__(self, api, port, port_type):
|
|
super(LspSetTypeCommand, self).__init__(api)
|
|
self.port = port
|
|
self.port_type = port_type
|
|
|
|
def run_idl(self, txn):
|
|
lsp = self.api.lookup('Logical_Switch_Port', self.port)
|
|
lsp.type = self.port_type
|
|
|
|
|
|
class LspGetTypeCommand(cmd.ReadOnlyCommand):
|
|
def __init__(self, api, port):
|
|
super(LspGetTypeCommand, self).__init__(api)
|
|
self.port = port
|
|
|
|
def run_idl(self, txn):
|
|
lsp = self.api.lookup('Logical_Switch_Port', self.port)
|
|
self.result = lsp.type
|
|
|
|
|
|
class LspSetOptionsCommand(cmd.BaseCommand):
|
|
table = 'Logical_Switch_Port'
|
|
|
|
def __init__(self, api, port, **options):
|
|
super(LspSetOptionsCommand, self).__init__(api)
|
|
self.port = port
|
|
self.options = options
|
|
|
|
def run_idl(self, txn):
|
|
lsp = self.api.lookup(self.table, self.port)
|
|
lsp.options = self.options
|
|
|
|
|
|
class LspGetOptionsCommand(cmd.ReadOnlyCommand):
|
|
table = 'Logical_Switch_Port'
|
|
|
|
def __init__(self, api, port):
|
|
super(LspGetOptionsCommand, self).__init__(api)
|
|
self.port = port
|
|
|
|
def run_idl(self, txn):
|
|
lsp = self.api.lookup(self.table, self.port)
|
|
self.result = lsp.options
|
|
|
|
|
|
class LspSetDhcpV4OptionsCommand(cmd.BaseCommand):
|
|
def __init__(self, api, port, dhcpopt_uuid):
|
|
super(LspSetDhcpV4OptionsCommand, self).__init__(api)
|
|
self.port = port
|
|
self.dhcpopt_uuid = dhcpopt_uuid
|
|
|
|
def run_idl(self, txn):
|
|
lsp = self.api.lookup('Logical_Switch_Port', self.port)
|
|
lsp.dhcpv4_options = self.dhcpopt_uuid
|
|
|
|
|
|
class LspGetDhcpV4OptionsCommand(cmd.ReadOnlyCommand):
|
|
def __init__(self, api, port):
|
|
super(LspGetDhcpV4OptionsCommand, self).__init__(api)
|
|
self.port = port
|
|
|
|
def run_idl(self, txn):
|
|
lsp = self.api.lookup('Logical_Switch_Port', self.port)
|
|
self.result = next((rowview.RowView(d)
|
|
for d in lsp.dhcpv4_options), [])
|
|
|
|
|
|
class DhcpOptionsAddCommand(cmd.AddCommand):
|
|
table_name = 'DHCP_Options'
|
|
|
|
def __init__(self, api, cidr, **external_ids):
|
|
cidr = netaddr.IPNetwork(cidr)
|
|
super(DhcpOptionsAddCommand, self).__init__(api)
|
|
self.cidr = str(cidr)
|
|
self.external_ids = external_ids
|
|
|
|
def run_idl(self, txn):
|
|
dhcpopt = txn.insert(self.api.tables[self.table_name])
|
|
dhcpopt.cidr = self.cidr
|
|
dhcpopt.external_ids = self.external_ids
|
|
self.result = dhcpopt.uuid
|
|
|
|
|
|
class DhcpOptionsDelCommand(cmd.BaseCommand):
|
|
def __init__(self, api, dhcpopt_uuid):
|
|
super(DhcpOptionsDelCommand, self).__init__(api)
|
|
self.dhcpopt_uuid = dhcpopt_uuid
|
|
|
|
def run_idl(self, txn):
|
|
dhcpopt = self.api.lookup('DHCP_Options', self.dhcpopt_uuid)
|
|
dhcpopt.delete()
|
|
|
|
|
|
class DhcpOptionsListCommand(cmd.ReadOnlyCommand):
|
|
def run_idl(self, txn):
|
|
self.result = [rowview.RowView(r) for
|
|
r in self.api.tables['DHCP_Options'].rows.values()]
|
|
|
|
|
|
class DhcpOptionsGetCommand(cmd.BaseGetRowCommand):
|
|
table = 'DHCP_Options'
|
|
|
|
|
|
class DhcpOptionsSetOptionsCommand(cmd.BaseCommand):
|
|
def __init__(self, api, dhcpopt_uuid, **options):
|
|
super(DhcpOptionsSetOptionsCommand, self).__init__(api)
|
|
self.dhcpopt_uuid = dhcpopt_uuid
|
|
self.options = options
|
|
|
|
def run_idl(self, txn):
|
|
dhcpopt = self.api.lookup('DHCP_Options', self.dhcpopt_uuid)
|
|
dhcpopt.options = self.options
|
|
|
|
|
|
class DhcpOptionsGetOptionsCommand(cmd.ReadOnlyCommand):
|
|
def __init__(self, api, dhcpopt_uuid):
|
|
super(DhcpOptionsGetOptionsCommand, self).__init__(api)
|
|
self.dhcpopt_uuid = dhcpopt_uuid
|
|
|
|
def run_idl(self, txn):
|
|
dhcpopt = self.api.lookup('DHCP_Options', self.dhcpopt_uuid)
|
|
self.result = dhcpopt.options
|
|
|
|
|
|
class LrAddCommand(cmd.BaseCommand):
|
|
def __init__(self, api, router=None, may_exist=False, **columns):
|
|
super(LrAddCommand, self).__init__(api)
|
|
self.router = router
|
|
self.may_exist = may_exist
|
|
self.columns = columns
|
|
|
|
def run_idl(self, txn):
|
|
if self.router:
|
|
try:
|
|
lr = self.api.lookup('Logical_Router', self.router)
|
|
if self.may_exist:
|
|
self.result = rowview.RowView(lr)
|
|
return
|
|
except idlutils.RowNotFound:
|
|
pass
|
|
lr = txn.insert(self.api.tables['Logical_Router'])
|
|
lr.name = self.router if self.router else ""
|
|
self.set_columns(lr, **self.columns)
|
|
self.result = lr.uuid
|
|
|
|
def post_commit(self, txn):
|
|
real_uuid = txn.get_insert_uuid(self.result)
|
|
if real_uuid:
|
|
row = self.api.tables['Logical_Router'].rows[real_uuid]
|
|
self.result = rowview.RowView(row)
|
|
|
|
|
|
class LrDelCommand(cmd.BaseCommand):
|
|
def __init__(self, api, router, if_exists=False):
|
|
super(LrDelCommand, self).__init__(api)
|
|
self.router = router
|
|
self.if_exists = if_exists
|
|
|
|
def run_idl(self, txn):
|
|
try:
|
|
lr = self.api.lookup('Logical_Router', self.router)
|
|
lr.delete()
|
|
except idlutils.RowNotFound:
|
|
if self.if_exists:
|
|
return
|
|
msg = "Logical Router %s does not exist" % self.router
|
|
raise RuntimeError(msg)
|
|
|
|
|
|
class LrListCommand(cmd.ReadOnlyCommand):
|
|
def run_idl(self, txn):
|
|
self.result = [rowview.RowView(r) for
|
|
r in self.api.tables['Logical_Router'].rows.values()]
|
|
|
|
|
|
class LrGetCommand(cmd.BaseGetRowCommand):
|
|
table = 'Logical_Router'
|
|
|
|
|
|
class LrpAddCommand(cmd.BaseCommand):
|
|
def __init__(self, api, router, port, mac, networks,
|
|
peer=None, may_exist=False, **columns):
|
|
self.mac = str(netaddr.EUI(mac, dialect=netaddr.mac_unix_expanded))
|
|
self.networks = [str(netaddr.IPNetwork(net)) for net in networks]
|
|
self.router = router
|
|
self.port = port
|
|
self.peer = peer
|
|
self.may_exist = may_exist
|
|
self.columns = columns
|
|
super(LrpAddCommand, self).__init__(api)
|
|
|
|
def run_idl(self, txn):
|
|
lr = self.api.lookup('Logical_Router', self.router)
|
|
try:
|
|
lrp = self.api.lookup('Logical_Router_Port', self.port)
|
|
if self.may_exist:
|
|
msg = None
|
|
if lrp not in lr.ports:
|
|
msg = "Port %s exists, but is not in router %s" % (
|
|
self.port, self.router)
|
|
elif netaddr.EUI(lrp.mac) != netaddr.EUI(self.mac):
|
|
msg = "Port %s exists with different mac" % (self.port)
|
|
elif set(self.networks) != set(lrp.networks):
|
|
msg = "Port %s exists with different networks" % (
|
|
self.port)
|
|
elif (not self.peer) != (not lrp.peer) or (
|
|
self.peer != lrp.peer):
|
|
msg = "Port %s exists with different peer" % (self.port)
|
|
if msg:
|
|
raise RuntimeError(msg)
|
|
self.result = rowview.RowView(lrp)
|
|
return
|
|
except idlutils.RowNotFound:
|
|
pass
|
|
lrp = txn.insert(self.api.tables['Logical_Router_Port'])
|
|
# This is what ovn-nbctl does, though the lookup is by uuid or name
|
|
lrp.name = self.port
|
|
lrp.mac = self.mac
|
|
lrp.networks = self.networks
|
|
if self.peer:
|
|
lrp.peer = self.peer
|
|
lr.addvalue('ports', lrp)
|
|
gwcs = self.columns.pop('gateway_chassis', [])
|
|
for n, chassis in enumerate(gwcs):
|
|
gwc_name = '%s_%s' % (lrp.name, chassis)
|
|
cmd = GatewayChassisAddCommand(self.api, gwc_name, chassis,
|
|
len(gwcs) - n, may_exist=True)
|
|
cmd.run_idl(txn)
|
|
lrp.addvalue('gateway_chassis', cmd.result)
|
|
self.set_columns(lrp, **self.columns)
|
|
self.result = lrp.uuid
|
|
|
|
def post_commit(self, txn):
|
|
real_uuid = txn.get_insert_uuid(self.result)
|
|
if real_uuid:
|
|
row = self.api.tables['Logical_Router_Port'].rows[real_uuid]
|
|
self.result = rowview.RowView(row)
|
|
|
|
|
|
class LrpDelCommand(PortDelCommand):
|
|
def __init__(self, api, port, router=None, if_exists=False):
|
|
super(LrpDelCommand, self).__init__(
|
|
api, 'Logical_Router_Port', port, 'Logical_Router', router,
|
|
if_exists)
|
|
|
|
|
|
class LrpListCommand(cmd.ReadOnlyCommand):
|
|
def __init__(self, api, router):
|
|
super(LrpListCommand, self).__init__(api)
|
|
self.router = router
|
|
|
|
def run_idl(self, txn):
|
|
router = self.api.lookup('Logical_Router', self.router)
|
|
self.result = [rowview.RowView(r) for r in router.ports]
|
|
|
|
|
|
class LrpSetEnabledCommand(cmd.BaseCommand):
|
|
def __init__(self, api, port, is_enabled):
|
|
super(LrpSetEnabledCommand, self).__init__(api)
|
|
self.port = port
|
|
self.is_enabled = is_enabled
|
|
|
|
def run_idl(self, txn):
|
|
lrp = self.api.lookup('Logical_Router_Port', self.port)
|
|
lrp.enabled = self.is_enabled
|
|
|
|
|
|
class LrpGetEnabledCommand(cmd.ReadOnlyCommand):
|
|
def __init__(self, api, port):
|
|
super(LrpGetEnabledCommand, self).__init__(api)
|
|
self.port = port
|
|
|
|
def run_idl(self, txn):
|
|
lrp = self.api.lookup('Logical_Router_Port', self.port)
|
|
# enabled is optional, but if not disabled then enabled
|
|
self.result = next(iter(lrp.enabled), True)
|
|
|
|
|
|
class LrpSetOptionsCommand(LspSetOptionsCommand):
|
|
table = 'Logical_Router_Port'
|
|
|
|
|
|
class LrpGetOptionsCommand(LspGetOptionsCommand):
|
|
table = 'Logical_Router_Port'
|
|
|
|
|
|
class LrRouteAddCommand(cmd.BaseCommand):
|
|
def __init__(self, api, router, prefix, nexthop, port=None,
|
|
policy='dst-ip', may_exist=False):
|
|
prefix = str(netaddr.IPNetwork(prefix))
|
|
nexthop = str(netaddr.IPAddress(nexthop))
|
|
super(LrRouteAddCommand, self).__init__(api)
|
|
self.router = router
|
|
self.prefix = prefix
|
|
self.nexthop = nexthop
|
|
self.port = port
|
|
self.policy = policy
|
|
self.may_exist = may_exist
|
|
|
|
def run_idl(self, txn):
|
|
lr = self.api.lookup('Logical_Router', self.router)
|
|
for route in lr.static_routes:
|
|
if self.prefix == route.ip_prefix:
|
|
if not self.may_exist:
|
|
msg = "Route %s already exists on router %s" % (
|
|
self.prefix, self.router)
|
|
raise RuntimeError(msg)
|
|
route.nexthop = self.nexthop
|
|
route.policy = self.policy
|
|
if self.port:
|
|
route.port = self.port
|
|
self.result = rowview.RowView(route)
|
|
return
|
|
route = txn.insert(self.api.tables['Logical_Router_Static_Route'])
|
|
route.ip_prefix = self.prefix
|
|
route.nexthop = self.nexthop
|
|
route.policy = self.policy
|
|
if self.port:
|
|
route.port = self.port
|
|
lr.addvalue('static_routes', route)
|
|
self.result = route.uuid
|
|
|
|
def post_commit(self, txn):
|
|
real_uuid = txn.get_insert_uuid(self.result)
|
|
if real_uuid:
|
|
table = self.api.tables['Logical_Router_Static_Route']
|
|
row = table.rows[real_uuid]
|
|
self.result = rowview.RowView(row)
|
|
|
|
|
|
class LrRouteDelCommand(cmd.BaseCommand):
|
|
def __init__(self, api, router, prefix=None, if_exists=False):
|
|
if prefix is not None:
|
|
prefix = str(netaddr.IPNetwork(prefix))
|
|
super(LrRouteDelCommand, self).__init__(api)
|
|
self.router = router
|
|
self.prefix = prefix
|
|
self.if_exists = if_exists
|
|
|
|
def run_idl(self, txn):
|
|
lr = self.api.lookup('Logical_Router', self.router)
|
|
if not self.prefix:
|
|
lr.static_routes = []
|
|
return
|
|
for route in lr.static_routes:
|
|
if self.prefix == route.ip_prefix:
|
|
lr.delvalue('static_routes', route)
|
|
# There should only be one possible match
|
|
return
|
|
|
|
if not self.if_exists:
|
|
msg = "Route for %s in router %s does not exist" % (
|
|
self.prefix, self.router)
|
|
raise RuntimeError(msg)
|
|
|
|
|
|
class LrRouteListCommand(cmd.ReadOnlyCommand):
|
|
def __init__(self, api, router):
|
|
super(LrRouteListCommand, self).__init__(api)
|
|
self.router = router
|
|
|
|
def run_idl(self, txn):
|
|
lr = self.api.lookup('Logical_Router', self.router)
|
|
self.result = [rowview.RowView(r) for r in lr.static_routes]
|
|
|
|
|
|
class LrNatAddCommand(cmd.BaseCommand):
|
|
def __init__(self, api, router, nat_type, external_ip, logical_ip,
|
|
logical_port=None, external_mac=None, may_exist=False):
|
|
if nat_type not in const.NAT_TYPES:
|
|
raise TypeError("nat_type not in %s" % str(const.NAT_TYPES))
|
|
external_ip = str(netaddr.IPAddress(external_ip))
|
|
if nat_type == const.NAT_DNAT:
|
|
logical_ip = str(netaddr.IPAddress(logical_ip))
|
|
else:
|
|
net = netaddr.IPNetwork(logical_ip)
|
|
logical_ip = str(net.ip if net.prefixlen == 32 else net)
|
|
if (logical_port is None) != (external_mac is None):
|
|
msg = "logical_port and external_mac must be passed together"
|
|
raise TypeError(msg)
|
|
if logical_port and nat_type != const.NAT_BOTH:
|
|
msg = "logical_port/external_mac only valid for %s" % (
|
|
const.NAT_BOTH,)
|
|
raise TypeError(msg)
|
|
if external_mac:
|
|
external_mac = str(
|
|
netaddr.EUI(external_mac, dialect=netaddr.mac_unix_expanded))
|
|
super(LrNatAddCommand, self).__init__(api)
|
|
self.router = router
|
|
self.nat_type = nat_type
|
|
self.external_ip = external_ip
|
|
self.logical_ip = logical_ip
|
|
self.logical_port = logical_port or []
|
|
self.external_mac = external_mac or []
|
|
self.may_exist = may_exist
|
|
|
|
def run_idl(self, txn):
|
|
lr = self.api.lookup('Logical_Router', self.router)
|
|
if self.logical_port:
|
|
lp = self.api.lookup('Logical_Switch_Port', self.logical_port)
|
|
for nat in lr.nat:
|
|
if ((self.nat_type, self.external_ip, self.logical_ip) ==
|
|
(nat.type, nat.external_ip, nat.logical_ip)):
|
|
if self.may_exist:
|
|
nat.logical_port = self.logical_port
|
|
nat.external_mac = self.external_mac
|
|
self.result = rowview.RowView(nat)
|
|
return
|
|
raise RuntimeError("NAT already exists")
|
|
nat = txn.insert(self.api.tables['NAT'])
|
|
nat.type = self.nat_type
|
|
nat.external_ip = self.external_ip
|
|
nat.logical_ip = self.logical_ip
|
|
if self.logical_port:
|
|
# It seems kind of weird that ovn uses a name string instead of
|
|
# a ref to a LSP, especially when ovn-nbctl looks the value up by
|
|
# either name or uuid (and discards the result and store the name).
|
|
nat.logical_port = lp.name
|
|
nat.external_mac = self.external_mac
|
|
lr.addvalue('nat', nat)
|
|
self.result = nat.uuid
|
|
|
|
def post_commit(self, txn):
|
|
real_uuid = txn.get_insert_uuid(self.result)
|
|
if real_uuid:
|
|
row = self.api.tables['NAT'].rows[real_uuid]
|
|
self.result = rowview.RowView(row)
|
|
|
|
|
|
class LrNatDelCommand(cmd.BaseCommand):
|
|
def __init__(self, api, router, nat_type=None, match_ip=None,
|
|
if_exists=False):
|
|
super(LrNatDelCommand, self).__init__(api)
|
|
self.conditions = []
|
|
if nat_type:
|
|
if nat_type not in const.NAT_TYPES:
|
|
raise TypeError("nat_type not in %s" % str(const.NAT_TYPES))
|
|
self.conditions += [('type', '=', nat_type)]
|
|
if match_ip:
|
|
try:
|
|
match_ip = str(netaddr.IPAddress(match_ip))
|
|
except ValueError:
|
|
# logical_ip can be IPNetwork
|
|
if nat_type == const.NAT_SNAT:
|
|
match_ip = str(netaddr.IPNetwork(match_ip))
|
|
else:
|
|
raise
|
|
self.col = ('logical_ip' if nat_type == const.NAT_SNAT
|
|
else 'external_ip')
|
|
self.conditions += [(self.col, '=', match_ip)]
|
|
elif match_ip:
|
|
raise TypeError("must specify nat_type with match_ip")
|
|
self.router = router
|
|
self.nat_type = nat_type
|
|
self.match_ip = match_ip
|
|
self.if_exists = if_exists
|
|
|
|
def run_idl(self, txn):
|
|
lr = self.api.lookup('Logical_Router', self.router)
|
|
found = False
|
|
for nat in [r for r in lr.nat
|
|
if idlutils.row_match(r, self.conditions)]:
|
|
found = True
|
|
lr.delvalue('nat', nat)
|
|
nat.delete()
|
|
if self.match_ip:
|
|
break
|
|
if self.match_ip and not (found or self.if_exists):
|
|
raise idlutils.RowNotFound(table='NAT', col=self.col,
|
|
match=self.match_ip)
|
|
|
|
|
|
class LrNatListCommand(cmd.ReadOnlyCommand):
|
|
def __init__(self, api, router):
|
|
super(LrNatListCommand, self).__init__(api)
|
|
self.router = router
|
|
|
|
def run_idl(self, txn):
|
|
lr = self.api.lookup('Logical_Router', self.router)
|
|
self.result = [rowview.RowView(r) for r in lr.nat]
|
|
|
|
|
|
class LbAddCommand(cmd.BaseCommand):
|
|
def __init__(self, api, lb, vip, ips, protocol=const.PROTO_TCP,
|
|
may_exist=False, **columns):
|
|
super(LbAddCommand, self).__init__(api)
|
|
self.lb = lb
|
|
self.vip = utils.normalize_ip_port(vip)
|
|
self.ips = ",".join(utils.normalize_ip_port(ip) for ip in ips)
|
|
self.protocol = protocol
|
|
self.may_exist = may_exist
|
|
self.columns = columns
|
|
|
|
def run_idl(self, txn):
|
|
try:
|
|
lb = self.api.lookup('Load_Balancer', self.lb)
|
|
if lb.vips.get(self.vip):
|
|
if not self.may_exist:
|
|
raise RuntimeError("Load Balancer %s exists" % lb.name)
|
|
# Update load balancer vip
|
|
lb.setkey('vips', self.vip, self.ips)
|
|
lb.protocol = self.protocol
|
|
except idlutils.RowNotFound:
|
|
# New load balancer
|
|
lb = txn.insert(self.api.tables['Load_Balancer'])
|
|
lb.name = self.lb
|
|
lb.protocol = self.protocol
|
|
lb.vips = {self.vip: self.ips}
|
|
self.set_columns(lb, **self.columns)
|
|
self.result = lb.uuid
|
|
|
|
def post_commit(self, txn):
|
|
real_uuid = txn.get_insert_uuid(self.result) or self.result
|
|
row = self.api.tables['Load_Balancer'].rows[real_uuid]
|
|
self.result = rowview.RowView(row)
|
|
|
|
|
|
class LbDelCommand(cmd.BaseCommand):
|
|
def __init__(self, api, lb, vip=None, if_exists=False):
|
|
super(LbDelCommand, self).__init__(api)
|
|
self.lb = lb
|
|
self.vip = utils.normalize_ip_port(vip) if vip else vip
|
|
self.if_exists = if_exists
|
|
|
|
def run_idl(self, txn):
|
|
try:
|
|
lb = self.api.lookup('Load_Balancer', self.lb)
|
|
except idlutils.RowNotFound:
|
|
if not self.if_exists:
|
|
raise
|
|
return
|
|
if self.vip:
|
|
if self.vip in lb.vips:
|
|
lb.delkey('vips', self.vip)
|
|
elif not self.if_exists:
|
|
raise idlutils.RowNotFound(table='Load_Balancer', col=self.vip,
|
|
match=self.lb)
|
|
# Remove load balancer if vips were not provided or no vips are left.
|
|
if not self.vip or not lb.vips:
|
|
lb.delete()
|
|
|
|
|
|
class LbListCommand(cmd.ReadOnlyCommand):
|
|
def run_idl(self, txn):
|
|
self.result = [rowview.RowView(r)
|
|
for r in self.api.tables['Load_Balancer'].rows.values()]
|
|
|
|
|
|
class LrLbAddCommand(cmd.BaseCommand):
|
|
def __init__(self, api, router, lb, may_exist=False):
|
|
super(LrLbAddCommand, self).__init__(api)
|
|
self.router = router
|
|
self.lb = lb
|
|
self.may_exist = may_exist
|
|
|
|
def run_idl(self, txn):
|
|
lr = self.api.lookup('Logical_Router', self.router)
|
|
lb = self.api.lookup('Load_Balancer', self.lb)
|
|
if lb in lr.load_balancer:
|
|
if self.may_exist:
|
|
return
|
|
raise RuntimeError("LB %s already exist in router %s" % (
|
|
lb.uuid, lr.uuid))
|
|
lr.addvalue('load_balancer', lb)
|
|
|
|
|
|
class LrLbDelCommand(cmd.BaseCommand):
|
|
def __init__(self, api, router, lb=None, if_exists=False):
|
|
super(LrLbDelCommand, self).__init__(api)
|
|
self.router = router
|
|
self.lb = lb
|
|
self.if_exists = if_exists
|
|
|
|
def run_idl(self, txn):
|
|
lr = self.api.lookup('Logical_Router', self.router)
|
|
if not self.lb:
|
|
lr.load_balancer = []
|
|
return
|
|
try:
|
|
lb = self.api.lookup('Load_Balancer', self.lb)
|
|
lr.delvalue('load_balancer', lb)
|
|
except idlutils.RowNotFound:
|
|
if self.if_exists:
|
|
return
|
|
raise
|
|
|
|
|
|
class LrLbListCommand(cmd.ReadOnlyCommand):
|
|
def __init__(self, api, router):
|
|
super(LrLbListCommand, self).__init__(api)
|
|
self.router = router
|
|
|
|
def run_idl(self, txn):
|
|
lr = self.api.lookup('Logical_Router', self.router)
|
|
self.result = [rowview.RowView(r) for r in lr.load_balancer]
|
|
|
|
|
|
class LsLbAddCommand(cmd.BaseCommand):
|
|
def __init__(self, api, switch, lb, may_exist=False):
|
|
super(LsLbAddCommand, self).__init__(api)
|
|
self.switch = switch
|
|
self.lb = lb
|
|
self.may_exist = may_exist
|
|
|
|
def run_idl(self, txn):
|
|
ls = self.api.lookup('Logical_Switch', self.switch)
|
|
lb = self.api.lookup('Load_Balancer', self.lb)
|
|
if lb in ls.load_balancer:
|
|
if self.may_exist:
|
|
return
|
|
raise RuntimeError("LB %s alseady exist in switch %s" % (
|
|
lb.uuid, ls.uuid))
|
|
ls.addvalue('load_balancer', lb)
|
|
|
|
|
|
class LsLbDelCommand(cmd.BaseCommand):
|
|
def __init__(self, api, switch, lb=None, if_exists=False):
|
|
super(LsLbDelCommand, self).__init__(api)
|
|
self.switch = switch
|
|
self.lb = lb
|
|
self.if_exists = if_exists
|
|
|
|
def run_idl(self, txn):
|
|
ls = self.api.lookup('Logical_Switch', self.switch)
|
|
if not self.lb:
|
|
ls.load_balancer = []
|
|
return
|
|
try:
|
|
lb = self.api.lookup('Load_Balancer', self.lb)
|
|
ls.delvalue('load_balancer', lb)
|
|
except idlutils.RowNotFound:
|
|
if self.if_exists:
|
|
return
|
|
raise
|
|
|
|
|
|
class LsLbListCommand(cmd.ReadOnlyCommand):
|
|
def __init__(self, api, switch):
|
|
super(LsLbListCommand, self).__init__(api)
|
|
self.switch = switch
|
|
|
|
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.ReadOnlyCommand):
|
|
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)
|
|
|
|
|
|
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)
|
|
return
|
|
except idlutils.RowNotFound:
|
|
pass
|
|
|
|
pg = txn.insert(self.api._tables[self.table_name])
|
|
pg.name = self.name or ""
|
|
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 _PgUpdatePortsHelper(cmd.BaseCommand):
|
|
method = None
|
|
|
|
def __init__(self, api, port_group, lsp=None, if_exists=False):
|
|
super(_PgUpdatePortsHelper, self).__init__(api)
|
|
self.port_group = port_group
|
|
self.lsp = [] if lsp is None else self._listify(lsp)
|
|
self.if_exists = if_exists
|
|
|
|
def _listify(self, res):
|
|
return res if isinstance(res, (list, tuple)) else [res]
|
|
|
|
def _run_method(self, pg, port):
|
|
if not port:
|
|
return
|
|
|
|
if isinstance(port, cmd.BaseCommand):
|
|
port = port.result
|
|
elif utils.is_uuid_like(port):
|
|
try:
|
|
port = self.api.lookup('Logical_Switch_Port', port)
|
|
except idlutils.RowNotFound:
|
|
if self.if_exists:
|
|
return
|
|
raise RuntimeError(
|
|
'Port %s does not exist' % port)
|
|
|
|
getattr(pg, self.method)('ports', port)
|
|
|
|
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, lsp)
|
|
|
|
|
|
class PgAddPortCommand(_PgUpdatePortsHelper):
|
|
method = 'addvalue'
|
|
|
|
|
|
class PgDelPortCommand(_PgUpdatePortsHelper):
|
|
method = 'delvalue'
|
|
|
|
|
|
class PgGetCommand(cmd.BaseGetRowCommand):
|
|
table = 'Port_Group'
|
|
|
|
|
|
class GatewayChassisAddCommand(cmd.AddCommand):
|
|
table_name = 'Gateway_Chassis'
|
|
|
|
def __init__(self, api, name, chassis_name, priority=0, may_exist=False,
|
|
**columns):
|
|
super(GatewayChassisAddCommand, self).__init__(api)
|
|
self.name = name
|
|
self.chassis_name = chassis_name
|
|
self.priority = priority
|
|
self.may_exist = may_exist
|
|
self.columns = columns
|
|
|
|
def run_idl(self, txn):
|
|
if self.may_exist:
|
|
gwc = self.api.lookup(self.table_name, self.name, None)
|
|
else:
|
|
gwc = None
|
|
if not gwc:
|
|
# If gwc exists with name, this will properly fail if not may_exist
|
|
# since 'name' is indexed
|
|
gwc = txn.insert(self.api.tables[self.table_name])
|
|
gwc.name = self.name
|
|
gwc.priority = self.priority
|
|
self.set_columns(gwc, **self.columns)
|
|
self.result = gwc
|
|
|
|
|
|
class HAChassisGroupAddCommand(cmd.AddCommand):
|
|
table_name = 'HA_Chassis_Group'
|
|
|
|
def __init__(self, api, name, may_exist=False, **columns):
|
|
super(HAChassisGroupAddCommand, self).__init__(api)
|
|
self.name = name
|
|
self.may_exist = may_exist
|
|
self.columns = columns
|
|
|
|
def run_idl(self, txn):
|
|
if self.may_exist:
|
|
try:
|
|
hcg = self.api.lookup(self.table_name, self.name)
|
|
self.result = rowview.RowView(hcg)
|
|
return
|
|
except idlutils.RowNotFound:
|
|
pass
|
|
|
|
hcg = txn.insert(self.api._tables[self.table_name])
|
|
hcg.name = self.name
|
|
self.set_columns(hcg, **self.columns)
|
|
self.result = hcg.uuid
|
|
|
|
|
|
class HAChassisGroupDelCommand(cmd.BaseCommand):
|
|
table_name = 'HA_Chassis_Group'
|
|
|
|
def __init__(self, api, name, if_exists=False):
|
|
super(HAChassisGroupDelCommand, self).__init__(api)
|
|
self.name = name
|
|
self.if_exists = if_exists
|
|
|
|
def run_idl(self, txn):
|
|
try:
|
|
hcg = self.api.lookup(self.table_name, self.name)
|
|
hcg.delete()
|
|
except idlutils.RowNotFound:
|
|
if self.if_exists:
|
|
return
|
|
raise RuntimeError(
|
|
'HA Chassis Group %s does not exist' % self.name)
|
|
|
|
|
|
class HAChassisGroupGetCommand(cmd.BaseGetRowCommand):
|
|
table = 'HA_Chassis_Group'
|
|
|
|
|
|
class HAChassisGroupAddChassisCommand(cmd.AddCommand):
|
|
table_name = 'HA_Chassis'
|
|
|
|
def __init__(self, api, hcg_id, chassis, priority, **columns):
|
|
super(HAChassisGroupAddChassisCommand, self).__init__(api)
|
|
self.hcg_id = hcg_id
|
|
self.chassis = chassis
|
|
self.priority = priority
|
|
self.columns = columns
|
|
|
|
def run_idl(self, txn):
|
|
hc_group = self.api.lookup('HA_Chassis_Group', self.hcg_id)
|
|
found = False
|
|
hc = None
|
|
for hc in hc_group.ha_chassis:
|
|
if hc.chassis_name != self.chassis:
|
|
continue
|
|
found = True
|
|
break
|
|
else:
|
|
hc = txn.insert(self.api.tables[self.table_name])
|
|
hc.chassis_name = self.chassis
|
|
|
|
hc.priority = self.priority
|
|
self.set_columns(hc, **self.columns)
|
|
if not found:
|
|
hc_group.addvalue('ha_chassis', hc)
|
|
|
|
self.result = hc.uuid
|
|
|
|
|
|
class HAChassisGroupDelChassisCommand(cmd.BaseCommand):
|
|
table_name = 'HA_Chassis'
|
|
|
|
def __init__(self, api, hcg_id, chassis, if_exists=False):
|
|
super(HAChassisGroupDelChassisCommand, self).__init__(api)
|
|
self.hcg_id = hcg_id
|
|
self.chassis = chassis
|
|
self.if_exists = if_exists
|
|
|
|
def run_idl(self, txn):
|
|
try:
|
|
hc_group = self.api.lookup('HA_Chassis_Group', self.hcg_id)
|
|
except idlutils.RowNotFound:
|
|
if self.if_exists:
|
|
return
|
|
|
|
hc = None
|
|
for hc in hc_group.ha_chassis:
|
|
if hc.chassis_name == self.chassis:
|
|
break
|
|
else:
|
|
if self.if_exists:
|
|
return
|
|
raise RuntimeError(
|
|
'HA Chassis %s does not exist' % self.hcg_id)
|
|
|
|
hc_group.delvalue('ha_chassis', hc)
|
|
hc.delete()
|