def _lookup(self, table, record): if record == "": raise TypeError("Cannot look up record by empty string") # Handle commands by simply returning its result if isinstance(record, cmd.BaseCommand): return record.result t = self.tables[table] if isinstance(record, uuid.UUID): try: return t.rows[record] except KeyError: raise idlutils.RowNotFound(table=table, col='uuid', match=record) from None try: uuid_ = uuid.UUID(record) return t.rows[uuid_] except ValueError: # Not a UUID string, continue lookup by other means pass except KeyError: # If record isn't found by UUID , go ahead and look up by the table pass if not self.lookup_table: raise idlutils.RowNotFound(table=table, col='record', match=record) # NOTE (twilson) This is an approximation of the db-ctl implementation # that allows a partial table, assuming that if a table has a single # index, that we should be able to do a lookup by it. rl = self.lookup_table.get( table, idlutils.RowLookup(table, idlutils.get_index_column(t), None)) # no table means uuid only, no column means lookup table has one row if rl.table is None: raise idlutils.RowNotFound(table=table, col='uuid', match=record) if rl.column is None: if t.max_rows == 1: return next(iter(t.rows.values())) raise idlutils.RowNotFound(table=table, col='uuid', match=record) row = idlutils.row_by_value(self, rl.table, rl.column, record) if rl.uuid_column: rows = getattr(row, rl.uuid_column) if len(rows) != 1: raise idlutils.RowNotFound(table=table, col='record', match=record) row = rows[0] return row
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 _get_subnet(self): for dhcp in self.api._tables['DHCP_Options'].rows.values(): ext_ids = getattr(dhcp, 'external_ids', {}) # Ignore ports DHCP Options if ext_ids.get('port_id'): continue if ext_ids.get('subnet_id') == self.name: return dhcp raise idlutils.RowNotFound( table='DHCP_Options', col='external_ids', match=self.name)
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)
def _get_floatingip(self): # TODO(lucasagomes): We can't use self.api.lookup() because that # method does not introspect map type columns. We could either: # 1. Enhance it to look into maps or, 2. Add a new ``name`` column # to the NAT table so that we can use lookup() just like we do # for other resources for nat in self.api._tables['NAT'].rows.values(): if nat.type != 'dnat_and_snat': continue ext_ids = getattr(nat, 'external_ids', {}) if ext_ids.get(ovn_const.OVN_FIP_EXT_ID_KEY) == self.name: return nat raise idlutils.RowNotFound( table='NAT', col='external_ids', match=self.name)
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()
def _get_floatingip_or_pf(self): # TYPE_FLOATINGIPS: Determine table to use based on name. # Floating ip port forwarding resources are kept in load # balancer table and have a well known name. if self.name.startswith(PORT_FORWARDING_PREFIX): return self.api.lookup('Load_Balancer', self.name) # TODO(lucasagomes): We can't use self.api.lookup() because that # method does not introspect map type columns. We could either: # 1. Enhance it to look into maps or, 2. Add a new ``name`` column # to the NAT table so that we can use lookup() just like we do # for other resources for nat in self.api._tables['NAT'].rows.values(): if nat.type != 'dnat_and_snat': continue ext_ids = getattr(nat, 'external_ids', {}) if ext_ids.get(ovn_const.OVN_FIP_EXT_ID_KEY) == self.name: return nat raise idlutils.RowNotFound(table='NAT', col='external_ids', match=self.name)