def _transaction(self): req = self._txn_q.popleft() txn = idl.Transaction(self._idl) uuids = req.func(self._idl.tables, txn.insert) status = txn.commit_block() insert_uuids = {} err_msg = None if status in (idl.Transaction.SUCCESS, idl.Transaction.UNCHANGED): if uuids: if isinstance(uuids, uuid.UUID): insert_uuids[uuids] = txn.get_insert_uuid(uuids) else: insert_uuids = dict((uuid, txn.get_insert_uuid(uuid)) for uuid in uuids) else: err_msg = txn.get_error() rep = event.EventModifyReply(self.system_id, status, insert_uuids, err_msg) self.reply_to_request(req, rep)
def commit_f(): operation = None while True: txn = idl.Transaction(self.idl) if bgp_path['is_withdraw']: operation = 'del' rows = self.idl.tables['BGP_Route'].rows.values() for row in rows: if utils.get_column_value( row, 'prefix') == bgp_path['prefix']: operation = 'del' prefix_uuid = utils.get_column_value(row, '_uuid') self.idl.tables['BGP_Route'].rows[ prefix_uuid].delete() else: operation = 'add' row_nh = utils.row_by_value(self.idl, 'BGP_Nexthop', 'ip_address', bgp_path['nexthop']) if not row_nh: row_nh = txn.insert(self.idl.tables['BGP_Nexthop']) row_nh.ip_address = bgp_path['nexthop'] row_nh.type = 'unicast' row_path = txn.insert(self.idl.tables['BGP_Route']) row_path.address_family = 'ipv4' row_path.bgp_nexthops = row_nh row_path.distance = [] row_path.metric = 0 row_path.path_attributes = bgp_path['bgp_pathattr'] row_path.peer = 'Remote announcement' row_path.prefix = bgp_path['prefix'] row_path.sub_address_family = 'unicast' row_path.vrf = self.idl.tables['VRF'].rows.values()[0] status = txn.commit_block() seqno = self.idl.change_seqno if status == txn.TRY_AGAIN: log.error("OVSDB transaction returned TRY_AGAIN, retrying") utils.wait_for_change(self.idl, self.timeout, seqno) continue elif status == txn.ERROR: log.error("OVSDB transaction returned ERROR: {0}".format( txn.get_error())) elif status == txn.ABORTED: log.error("Transaction aborted") return elif status == txn.UNCHANGED: log.error("Transaction caused no change") break if operation is None: log.warn('route is not exist in ops: prefix={0}'.format( bgp_path['prefix'])) else: log.debug('Send bgp route to ops: type={0}, prefix={1}'.format( operation, bgp_path['prefix']))
def do_commit(self): self.start_time = time.time() attempts = 0 if not self.commands: LOG.debug("There are no commands to commit") return [] while True: if attempts > 0 and self.timeout_exceeded(): raise RuntimeError("OVS transaction timed out") attempts += 1 # TODO(twilson) Make sure we don't loop longer than vsctl_timeout txn = idl.Transaction(self.api.idl) self.pre_commit(txn) for i, command in enumerate(self.commands): LOG.debug("Running txn n=%(n)d command(idx=%(idx)s): %(cmd)s", {'idx': i, 'cmd': command, 'n': attempts}) try: command.run_idl(txn) except Exception: txn.abort() if self.check_error: raise status = txn.commit_block() if status == txn.TRY_AGAIN: LOG.debug("OVSDB transaction returned TRY_AGAIN, retrying") # In the case that there is a reconnection after # Connection.run() calls self.idl.run() but before do_commit() # is called, commit_block() can loop w/o calling idl.run() # which does the reconnect logic. It will then always return # TRY_AGAIN until we time out and Connection.run() calls # idl.run() again. So, call idl.run() here just in case. self.api.idl.run() continue elif status in (txn.ERROR, txn.NOT_LOCKED): msg = 'OVSDB Error: ' if status == txn.NOT_LOCKED: msg += ("The transaction failed because the IDL has " "been configured to require a database lock " "but didn't get it yet or has already lost it") else: msg += txn.get_error() if self.log_errors: LOG.error(msg) if self.check_error: # For now, raise similar error to vsctl/utils.execute() raise RuntimeError(msg) return elif status == txn.ABORTED: LOG.debug("Transaction aborted") return elif status == txn.UNCHANGED: LOG.debug("Transaction caused no change") elif status == txn.SUCCESS: self.post_commit(txn) else: LOG.debug("Transaction returned an unknown status: %s", status) return [cmd.result for cmd in self.commands]
def add_chassis(self, name, ip, tunnel_type): txn = idl.Transaction(self.idl) encap_row = txn.insert(self.idl.tables['Encap']) encap_row.ip = ip encap_row.type = tunnel_type chassis_row = txn.insert(self.idl.tables['Chassis']) chassis_row.encaps = encap_row chassis_row.name = name status = txn.commit_block() return status
def run(self): # For demo, txn is single command, this would go on Tranaction obj # and the loop would iterate through commands on the txn if not self.txn: self.has_run = False self.txn = idl.Transaction(i) if self.has_run: return row = self.txn.insert(self.idl.tables['Bridge']) row.name = "testbr%d" % self.val next(iter(self.idl.tables['Open_vSwitch'].rows.values())).addvalue( 'bridges', row) self.has_run = True
def do_commit(self): start_time = time.time() attempts = 0 while True: elapsed_time = time.time() - start_time if attempts > 0 and elapsed_time > self.context.vsctl_timeout: raise RuntimeError("OVS transaction timed out") attempts += 1 # TODO(twilson) Make sure we don't loop longer than vsctl_timeout txn = idl.Transaction(self.api.idl) for i, command in enumerate(self.commands): LOG.debug("Running txn command(idx=%(idx)s): %(cmd)s", { 'idx': i, 'cmd': command }) try: command.run_idl(txn) except Exception: with excutils.save_and_reraise_exception() as ctx: txn.abort() if not self.check_error: ctx.reraise = False seqno = self.api.idl.change_seqno status = txn.commit_block() if status == txn.TRY_AGAIN: LOG.debug("OVSDB transaction returned TRY_AGAIN, retrying") if self.api.idl._session.rpc.status != 0: LOG.debug("Lost connection to OVSDB, reconnecting!") self.api.idl.force_reconnect() idlutils.wait_for_change( self.api.idl, self.context.vsctl_timeout - elapsed_time, seqno) continue elif status == txn.ERROR: msg = _LE("OVSDB Error: %s") % txn.get_error() if self.log_errors: LOG.error(msg) if self.check_error: # For now, raise similar error to vsctl/utils.execute() raise RuntimeError(msg) return elif status == txn.ABORTED: LOG.debug("Transaction aborted") return elif status == txn.UNCHANGED: LOG.debug("Transaction caused no change") return [cmd.result for cmd in self.commands]
def register_local_ports(self, chassis_name, local_ports_ids): txn = idl.Transaction(self.idl) chassis = idlutils.row_by_value(self.idl, 'Chassis', 'name', chassis_name) for binding in self.idl.tables['Binding'].rows.values(): if binding.logical_port in local_ports_ids: if binding.chassis == chassis_name: continue # Bind this port to this chassis binding.chassis = chassis elif binding.chassis == chassis_name: binding.chassis = [] status = txn.commit_block() return status
def do_commit(self): self.start_time = time.time() attempts = 0 while True: if attempts > 0 and self.timeout_exceeded(): raise RuntimeError(_("OVS transaction timed out")) attempts += 1 # TODO(twilson) Make sure we don't loop longer than vsctl_timeout txn = idl.Transaction(self.api.idl) self.pre_commit(txn) for i, command in enumerate(self.commands): LOG.debug("Running txn command(idx=%(idx)s): %(cmd)s", {'idx': i, 'cmd': command}) try: command.run_idl(txn) except Exception: with excutils.save_and_reraise_exception() as ctx: txn.abort() if not self.check_error: ctx.reraise = False status = txn.commit_block() if status == txn.TRY_AGAIN: LOG.debug("OVSDB transaction returned TRY_AGAIN, retrying") continue elif status == txn.ERROR: msg = _("OVSDB Error: %s") % txn.get_error() if self.log_errors: LOG.error(msg) if self.check_error: # For now, raise similar error to vsctl/utils.execute() raise RuntimeError(msg) return elif status == txn.ABORTED: LOG.debug("Transaction aborted") return elif status == txn.UNCHANGED: LOG.debug("Transaction caused no change") elif status == txn.SUCCESS: self.post_commit(txn) return [cmd.result for cmd in self.commands]