def extid_qos_map(self, port_uuid): for qos in self._ovn_nb.tables[self.TYPE].rows.values(): # TODO(ralonsoh): in "external_ids", add the FIP ID or the port # ID; that will speed up the search without # using regex. qos_row = rowview.RowView(qos) match = self.REGEX_ID.search(qos_row.match) if match: if port_uuid == match.group('id'): yield rowview.RowView(qos)
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 run_idl(self, txn): self.result = [ rowview.RowView(r) if self.row else {c: idlutils.get_column_value(r, c) for c in self.columns} for r in self.table.rows.values() if idlutils.row_match(r, self.conditions) ]
def run_idl(self, txn): # ovn-sbctl does a client-side check for duplicate entry, but since # there is an index on "name", it will fail if we try to insert a # duplicate, so I'm not doing the check unless may_exist is set if self.may_exist: chassis = idlutils.row_by_value(self.api.idl, self.table_name, 'name', self.chassis) if chassis: self.result = rowview.RowView(chassis) return chassis = txn.insert(self.api.tables[self.table_name]) chassis.name = self.chassis encaps = [] for encap_type in self.encap_types: encap = txn.insert(self.api.tables['Encap']) encap.type = encap_type encap.ip = self.encap_ip encap.options = {'csum': 'True'} # ovn-sbctl silently does this... # NOTE(twilson) addvalue seems like it should work, but fails with # Chassis table col encaps references nonexistent row error # chassis.addvalue('encaps', encap) encaps.append(encap) chassis.encaps = encaps for col, val in self.columns.items(): setattr(chassis, col, val) self.result = chassis.uuid
def post_commit(self, txn): # Replace the temporary row with the post-commit UUID to match vsctl u = txn.get_insert_uuid(self.result.uuid) if self.row: self.result = rowview.RowView(self.api.tables[self.table].rows[u]) else: self.result = u
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) self.set_columns(lrp, **self.columns) self.result = lrp.uuid
def run_idl(self, txn): table_schema = self.api._tables[self.table] idx = idlutils.get_index_column(table_schema) columns = self.columns or list(table_schema.columns.keys()) + ['_uuid'] # If there's an index for this table, we'll fetch all columns and # remove the unwanted ones based on self.records. Otherwise, let's try # to get the uuid of the wanted ones which is an O(n^2) operation. if not idx and self.records: rows = [] for record in self.records: try: rows.append(self.api.idl.lookup(self.table, record)) except idlutils.RowNotFound: if self.if_exists: continue raise else: rows = table_schema.rows.values() def _match(row): elem = getattr(row, idx) return elem in self.records def _match_remove(row): elem = getattr(row, idx) found = elem in self.records if found: records_found.remove(elem) return found def _match_true(row): return True records_found = [] if idx and self.records: if self.if_exists: match = _match else: # If we're using the approach of removing the unwanted # elements, we'll use a helper list to remove elements as we # find them in the DB contents. This will help us identify # quickly if there's some record missing to raise a RowNotFound # exception later. records_found = list(self.records) match = _match_remove else: match = _match_true self.result = [ rowview.RowView(row) if self.row else { c: idlutils.get_column_value(row, c) for c in columns } for row in rows if match(row) ] if records_found: raise idlutils.RowNotFound(table=self.table, col=idx, match=records_found[0])
def run_idl(self, txn): # reduce search space if we have any indexed column and '=' match rows = (idlutils.index_condition_match(self.table, *self.conditions) or self.table.rows.values()) self.result = [ rowview.RowView(r) if self.row else {c: idlutils.get_column_value(r, c) for c in self.columns} for r in rows if idlutils.row_match(r, self.conditions) ]
def populate_subtree(self, parent_leaf=None, uuids=None): for uuid in uuids: acl = self._ovn_nb.tables[self.TYPE].rows.get(uuid) acl_row = rowview.RowView(acl) uuid = str(acl_row.uuid) child_leaf = self._treeview.insert(self.own_leaf, 'end', uuid, text=uuid, tags=self.TYPE, values=uuid) self.store_info(acl_row, child_leaf)
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 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
def run_idl(self, txn): # There is requirement for name to be unique # (index in ovn-ic-nb.ovsschema) switch = idlutils.row_by_value(self.api.idl, self.table_name, 'name', self.switch, None) if switch: if self.may_exist: self.result = rowview.RowView(switch) return raise RuntimeError("Transit Switch %s exists" % self.switch) switch = txn.insert(self.api.tables[self.table_name]) switch.name = self.switch self.set_columns(switch, **self.columns) self.result = switch.uuid
def post_commit(self, txn): # If get_insert_uuid fails, self.result was not a result of a # recent insert. Most likely we are post_commit after a lookup() if isinstance(self.result, rowview.RowView): return if isinstance(self.result, ovs.db.idl.Row): row = self.result else: real_uuid = txn.get_insert_uuid(self.result) or self.result # If we have multiple commands in a transation, post_commit can # be called even if *this* command caused no change. Theoretically # the subclass should have set a UUID/RowView result in that case # which is handled above, so raise exception if real_uuid not found row = self.api.tables[self.table_name].rows[real_uuid] self.result = rowview.RowView(row)
def populate_subtree(self, uuids=None): for port_uuid in uuids: port = self._ovn_nb.tables[self.TYPE].rows.get(port_uuid) port_row = rowview.RowView(port) uuid = str(port_row.uuid) child_leaf = self._treeview.insert(self.own_leaf, 'end', uuid, text=uuid, tags=self.TYPE, values=uuid) self.store_info(port_row, child_leaf) qos_tt = QoSes(self._root_tree, self._ovn_nb, self._ovn_sb, parent_leaf=child_leaf, parent_uuid=uuid) qos_tt.populate_subtree()
def run_idl(self, txn): ls = self.api.lookup('Logical_Switch', self.switch) acls = [acl for acl in ls.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 ls.addvalue('acls', acl) for col, value in self.external_ids.items(): acl.setkey('external_ids', col, value) self.result = acl.uuid
def populate_subtree(self, uuids=None): for pg in self._ovn_nb.tables[self.TYPE].rows.values(): pg_row = rowview.RowView(pg) uuid = str(pg_row.uuid) text = uuid sg = pg._data['external_ids'].get('neutron:security_group_id') if sg: text += ' (Neutron SG: %s)' % sg child_leaf = self._treeview.insert(self.own_leaf, 'end', uuid, text=text, tags=self.TYPE, values=uuid) self.store_info(pg_row, child_leaf) acl_tt = ACLs(self._root_tree, self._ovn_nb, self._ovn_sb, parent_leaf=child_leaf, parent_uuid=uuid) acl_tt.populate_subtree(uuids=[acls.uuid for acls in pg_row.acls])
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
def populate_subtree(self, uuids=None): for ls in self._ovn_nb.tables[self.TYPE].rows.values(): ls_row = rowview.RowView(ls) uuid = str(ls_row.uuid) text = uuid network_name = ls._data['external_ids'].get('neutron:network_name') if network_name: text += ' (network: %s)' % network_name child_leaf = self._treeview.insert(self.own_leaf, 'end', uuid, text=text, tags=self.TYPE, values=str(ls_row.uuid)) self.store_info(ls_row, child_leaf) lsp_tt = LogicalSiwtchPorts(self._root_tree, self._ovn_nb, self._ovn_sb, parent_leaf=child_leaf, parent_uuid=uuid) lsp_tt.populate_subtree(uuids=[port.uuid for port in ls_row.ports])
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 run_idl(self, txn): table_schema = self.api._tables[self.table] columns = self.columns or list(table_schema.columns.keys()) + ['_uuid'] if self.records: rows = [] for record in self.records: try: rows.append( idlutils.row_by_record(self.api.idl, self.table, record)) except idlutils.RowNotFound: if self.if_exists: continue raise else: rows = table_schema.rows.values() self.result = [ rowview.RowView(row) if self.row else {c: idlutils.get_column_value(row, c) for c in columns} for row in rows ]
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
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 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
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)
def run_idl(self, txn): self.result = [rowview.RowView(r) for r in self.api.tables['DHCP_Options'].rows.values()]
def run_idl(self, txn): self.result = [rowview.RowView(r) for r in self.api.tables['Chassis'].rows.values()]
def run_idl(self, txn): self.result = [rowview.RowView(r) for r in self.api.tables['Logical_Router'].rows.values()]
def run_idl(self, txn): lr = self.api.lookup('Logical_Router', self.router) self.result = [rowview.RowView(r) for r in lr.nat]
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)
def run_idl(self, txn): table = self.api.tables['Logical_Switch'] self.result = [rowview.RowView(r) for r in table.rows.values()]