def register(extschema, ovsschema, ovsremote): """Register interest in all configuration and index columns for all tables in ovsschema. Args: extschema (opslib.RestSchema): This is the parsed extended-schema (vswitch.extschema) object. ovsschema: OVSDB schema file ovsremote: OVSDB remote socket Returns: ovs.db.idl.Idl instance """ schema_helper = SchemaHelper(ovsschema) for tablename, tableschema in extschema.ovs_tables.iteritems(): register_columns = [] # configuration columns config_columns = [str(key) for key in tableschema.config.keys()] # reference columns reference_columns = [str(key) for key in tableschema.references.keys()] # index columns for item in tableschema.index_columns: if not item in config_columns: register_columns.append(str(item)) register_columns += config_columns register_columns += reference_columns # dynamic columns if tableschema.dynamic: for key in tableschema.dynamic.keys(): if key not in register_columns: register_columns.append(key) # NOTE: remove this when we have a proper # solution for TG-1116 if str(tablename) == 'VLAN': register_columns.append('internal_usage') schema_helper.register_columns(str(tablename), register_columns) idl = ops.opsidl.OpsIdl(ovsremote, schema_helper) return idl
def start(self): # reset all connections try: app_log.info("Starting Connection Manager!") if self.idl is not None: self.idl.close() # set up the schema and register all tables self.schema_helper = SchemaHelper(self.schema) self.schema_helper.register_all() self.idl = Idl(self.remote, self.schema_helper) self.curr_seqno = self.idl.change_seqno # we do not reset transactions when the DB connection goes down if self.transactions is None: self.transactions = OvsdbTransactionList() self.idl_run() self.monitor_connection() except Exception as e: # TODO: log this exception # attempt again in the next IOLoop iteration app_log.info("Connection Manager failed! Reason: %s" % e) IOLoop.current().add_timeout(time.time() + self.timeout, self.start)
def find(self, columns, table, cond=None): """ which only works in main thread, depends on signal """ schema_file = "%s/vswitch.ovsschema" % ovs.dirs.PKGDATADIR try: from ovs.db.idl import SchemaHelper schema_helper = SchemaHelper(schema_file) schema_helper.register_all() schema = schema_helper.get_idl_schema() self._check_column(schema, columns, table, cond) idl = ovs.db.idl.Idl(self.sock, schema_helper) except ImportError: schema = ovs.db.schema.DbSchema.from_json( ovs.json.from_file(schema_file)) # check schema self._check_column(schema, columns, table, cond) idl = ovs.db.idl.Idl(self.sock, schema) seqno = idl.change_seqno while True: idl.run() if seqno == idl.change_seqno: poller = ovs.poller.Poller() idl.wait(poller) poller.block() continue break results = list() def __append_row(results, row): result = dict() for column_name in columns: result[column_name] = self._get_row_val(row, column_name) results.append(result) return for row in idl.tables[table].rows.itervalues(): match = True if cond: for k, v in cond.iteritems(): if self._get_row_val(row, k) != v: match = False break if match: __append_row(results, row) idl.close() return results
def connect(): ovsschema = settings.get('cfg_db_schema') ovsremote = settings.get('ovs_remote') schema_helper = SchemaHelper(ovsschema) schema_helper.register_all() idl = Idl(ovsremote, schema_helper) change_seqno = idl.change_seqno while True: idl.run() if change_seqno != idl.change_seqno: break poller = ovs.poller.Poller() idl.wait(poller) poller.block() return idl
def start(self, register_tables=None, track_all=False): try: app_log.info("Starting Connection Manager!") # Ensure stopping of any existing connection self.stop() self.schema_helper = SchemaHelper(self.schema) # Store registration and tracking info in case initial # connection is unsuccessful. If initial connection is unsuccesful, # the timeout callback will cause register_tables and track_all # to be None. if register_tables is not None: self.register_tables = register_tables if track_all is not False: self.track_all = track_all if not self.register_tables: self.register_schema_helper_columns(self.schema_helper, self.rest_schema) else: for table in self.register_tables: self.schema_helper.register_table(str(table)) self.idl = OpsIdl(self.remote, self.schema_helper) self.curr_seqno = self.idl.change_seqno if self.track_all: app_log.debug("Tracking all changes") self.idl.track_add_all() # We do not reset transactions when the DB connection goes down if self.transactions is None: self.transactions = OvsdbTransactionList() self.idl_init() except Exception as e: app_log.info("Connection Manager failed! Reason: %s" % e) self.timeout_handle = \ IOLoop.current().add_timeout(time.time() + self.timeout, self.start)
def ovs_run_module(): module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=supports_check_mode, ) module._ovs_vars = {} state = module.params['state'] op = ops_with_defaults[state] if not HAS_OVS: module.fail_json( msg='Python Open vSwitch library is not installed') try: schema_path = '{}/{}'.format(ovs.dirs.PKGDATADIR, schema_file) remote = 'unix:{}/{}'.format(ovs.dirs.RUNDIR, ctl) schema = SchemaHelper(location=schema_path) op['register_interest'](schema) idl = Idl(remote, schema) try: wait_for_db_change(idl) except Exception as e: module.fail_json(msg=str(e), exception=traceback.format_exc()) op['prepare'](module, idl) if not module.check_mode: for i in range(3): txn = Transaction(idl) op['build_txn'](module, idl, txn) status = txn.commit_block() if status == Transaction.SUCCESS: break elif status != Transaction.TRY_AGAIN: break if status == Transaction.SUCCESS: changed = True elif status == Transaction.UNCHANGED: changed = False else: msg = op['txn_failure_msg'](module) module.fail_json(msg='{}: {}'.format(msg, status)) else: changed = True module.exit_json(changed=changed) except Exception as e: module.fail_json(msg=str(e), exception=traceback.format_exc()) finally: if 'idl' in locals(): idl.close()
def register(extschema, ovsschema, ovsremote): """Register interest in all configuration and index columns for all tables in ovsschema. Args: extschema (opslib.RestSchema): This is the parsed extended-schema (vswitch.extschema) object. ovsschema: OVSDB schema file ovsremote: OVSDB remote socket Returns: ovs.db.idl.Idl instance """ schema_helper = SchemaHelper(ovsschema) for tablename, tableschema in extschema.ovs_tables.iteritems(): register_columns = [] # configuration columns config_columns = [str(key) for key in tableschema.config.keys()] # reference columns reference_columns = [str(key) for key in tableschema.references.keys()] # index columns for item in tableschema.index_columns: if not item in config_columns: register_columns.append(str(item)) register_columns += config_columns register_columns += reference_columns schema_helper.register_columns(str(tablename), register_columns) idl = ops.opsidl.OpsIdl(ovsremote, schema_helper) return idl
def start(self): try: app_log.info("Starting Connection Manager!") if self.idl is not None: self.idl.close() self.schema_helper = SchemaHelper(self.schema) self.schema_helper.register_all() self.idl = OpsIdl(self.remote, self.schema_helper) self.curr_seqno = self.idl.change_seqno # We do not reset transactions when the DB connection goes down if self.transactions is None: self.transactions = OvsdbTransactionList() self.idl_init() except Exception as e: app_log.info("Connection Manager failed! Reason: %s" % e) IOLoop.current().add_timeout(time.time() + self.timeout, self.start)
class OvsdbConnectionManager: def __init__(self, remote, schema, *args, **kwargs): self.timeout = OVSDB_DEFAULT_CONNECTION_TIMEOUT self.remote = remote self.schema = schema self.schema_helper = None self.idl = None self.transactions = None self.curr_seqno = 0 self.connected = False def start(self): try: app_log.info("Starting Connection Manager!") if self.idl is not None: self.idl.close() self.schema_helper = SchemaHelper(self.schema) self.schema_helper.register_all() self.idl = OpsIdl(self.remote, self.schema_helper) self.curr_seqno = self.idl.change_seqno # We do not reset transactions when the DB connection goes down if self.transactions is None: self.transactions = OvsdbTransactionList() self.idl_init() except Exception as e: app_log.info("Connection Manager failed! Reason: %s" % e) IOLoop.current().add_timeout(time.time() + self.timeout, self.start) def idl_init(self): try: self.idl.run() if not self.idl.has_ever_connected(): app_log.debug("ovsdb unavailable retrying") IOLoop.current().add_timeout(time.time() + self.timeout, self.idl_init) else: self.idl_establish_connection() except error.Error as e: # idl will raise an error exception if cannot connect app_log.debug("Failed to connect, retrying. Reason: %s" % e) IOLoop.current().add_timeout(time.time() + self.timeout, self.idl_init) def idl_reconnect(self): try: app_log.debug("Trying to reconnect to ovsdb") # Idl run will do the reconnection self.idl.run() # If the seqno change the ovsdb connection is restablished. if self.curr_seqno == self.idl.change_seqno: app_log.debug("ovsdb unavailable retrying") self.connected = False IOLoop.current().add_timeout(time.time() + self.timeout, self.idl_reconnect) else: self.idl_establish_connection() except error.Error as e: # idl will raise an error exception if cannot reconnect app_log.debug("Failed to connect, retrying. Reason: %s" % e) IOLoop.current().add_timeout(time.time() + self.timeout, self.idl_reconnect) def idl_establish_connection(self): app_log.info("ovsdb connection ready") self.connected = True self.curr_seqno = self.idl.change_seqno self.ovs_socket = self.idl._session.rpc.stream.socket IOLoop.current().add_handler(self.ovs_socket.fileno(), self.idl_run, IOLoop.READ | IOLoop.ERROR) def idl_run(self, fd=None, events=None): if events & IOLoop.ERROR: app_log.debug("Socket fd %s error" % fd) if fd is not None: IOLoop.current().remove_handler(fd) self.idl_reconnect() elif events & IOLoop.READ: app_log.debug("Updating idl replica") self.idl.run() if self.curr_seqno != self.idl.change_seqno and \ len(self.transactions.txn_list): self.check_transactions() self.curr_seqno = self.idl.change_seqno def check_transactions(self): for index, tx in enumerate(self.transactions.txn_list): tx.commit() # TODO: Handle all states if tx.status is not INCOMPLETE: self.transactions.txn_list.pop(index) tx.event.set() def get_new_transaction(self): return OvsdbTransaction(self.idl) def monitor_transaction(self, txn): self.transactions.add_txn(txn)
class OvsdbConnectionManager: def __init__(self, remote, schema, *args, **kwargs): self.timeout = OVSDB_DEFAULT_CONNECTION_TIMEOUT self.remote = remote self.schema = schema self.schema_helper = None self.idl = None self.transactions = None self.curr_seqno = 0 def start(self): # reset all connections try: app_log.info("Starting Connection Manager!") if self.idl is not None: self.idl.close() # set up the schema and register all tables self.schema_helper = SchemaHelper(self.schema) self.schema_helper.register_all() self.idl = Idl(self.remote, self.schema_helper) self.curr_seqno = self.idl.change_seqno # we do not reset transactions when the DB connection goes down if self.transactions is None: self.transactions = OvsdbTransactionList() self.idl_run() self.monitor_connection() except Exception as e: # TODO: log this exception # attempt again in the next IOLoop iteration app_log.info("Connection Manager failed! Reason: %s" % e) IOLoop.current().add_timeout(time.time() + self.timeout, self.start) def monitor_connection(self): try: self.poller = Poller() self.idl.wait(self.poller) self.timeout = self.poller.timeout / 1000.0 self.add_fd_callbacks() except: self.idl_run() IOLoop.current().add_timeout(time.time() + self.timeout, self.monitor_connection) def add_fd_callbacks(self): # add handlers to file descriptors from poll if len(self.poller.poll.rlist) is 0: self.rlist = [] self.wlist = [] self.xlist = [] raise Exception('ovsdb read unavailable') for fd in self.poller.poll.rlist: if fd not in self.rlist: IOLoop.current().add_handler(fd, self.read_handler, IOLoop.READ | IOLoop.ERROR) self.rlist.append(fd) IOLoop.current().add_timeout(time.time() + self.timeout, self.read_handler) def read_handler(self, fd=None, events=None): if fd is not None: IOLoop.current().remove_handler(fd) self.rlist.remove(fd) self.idl_run() IOLoop.current().add_callback(self.monitor_connection) def idl_run(self): self.idl.run() self.curr_seqno = self.idl.change_seqno if len(self.transactions.txn_list): self.check_transactions() def check_transactions(self): for item in self.transactions.txn_list: item.commit() count = 0 for item in self.transactions.txn_list: # TODO: Handle all states if item.status is not INCOMPLETE: self.transactions.txn_list.pop(count) item.event.set() else: count += 1 def get_new_transaction(self): return OvsdbTransaction(self.idl) def monitor_transaction(self, txn): self.transactions.add_txn(txn)
class OvsdbConnectionManager: def __init__(self, remote, schema, rest_schema, *args, **kwargs): self.timeout = OVSDB_DEFAULT_CONNECTION_TIMEOUT self.remote = remote self.schema = schema self.rest_schema = rest_schema self.schema_helper = None self.idl = None self.transactions = None self.curr_seqno = 0 self.connected = False self._callbacks = {} self._callbacks[CHANGES_CB_TYPE] = set() self._callbacks[ESTABLISHED_CB_TYPE] = set() self.timeout_handle = None self.ovs_socket = None self.register_tables = None self.track_all = False self.txn_timeout_handle = None def start(self, register_tables=None, track_all=False): try: app_log.info("Starting Connection Manager!") # Ensure stopping of any existing connection self.stop() self.schema_helper = SchemaHelper(self.schema) # Store registration and tracking info in case initial # connection is unsuccessful. If initial connection is unsuccesful, # the timeout callback will cause register_tables and track_all # to be None. if register_tables is not None: self.register_tables = register_tables if track_all is not False: self.track_all = track_all if not self.register_tables: self.register_schema_helper_columns(self.schema_helper, self.rest_schema) else: for table in self.register_tables: self.schema_helper.register_table(str(table)) self.idl = OpsIdl(self.remote, self.schema_helper) self.curr_seqno = self.idl.change_seqno if self.track_all: app_log.debug("Tracking all changes") self.idl.track_add_all() # We do not reset transactions when the DB connection goes down if self.transactions is None: self.transactions = OvsdbTransactionList() self.idl_init() except Exception as e: app_log.info("Connection Manager failed! Reason: %s" % e) self.timeout_handle = \ IOLoop.current().add_timeout(time.time() + self.timeout, self.start) def stop(self): if self.ovs_socket: IOLoop.current().remove_handler(self.ovs_socket) self.ovs_socket = None if self.timeout_handle: IOLoop.current().remove_timeout(self.timeout_handle) self.timeout_handle = None self.stop_transaction_timer() if self.idl: self.idl.close() self.idl = None def idl_init(self): try: self.idl.run() if not self.idl.has_ever_connected(): app_log.debug("ovsdb unavailable retrying") self.timeout_handle = \ IOLoop.current().add_timeout(time.time() + self.timeout, self.idl_init) else: self.idl_establish_connection() except error.Error as e: # idl will raise an error exception if cannot connect app_log.debug("Failed to connect, retrying. Reason: %s" % e) self.timeout_handle = \ IOLoop.current().add_timeout(time.time() + self.timeout, self.idl_init) def idl_reconnect(self): try: app_log.debug("Trying to reconnect to ovsdb") # Idl run will do the reconnection self.idl.run() # If the seqno change the ovsdb connection is restablished. if self.curr_seqno == self.idl.change_seqno: app_log.debug("ovsdb unavailable retrying") self.connected = False self.timeout_handle = \ IOLoop.current().add_timeout(time.time() + self.timeout, self.idl_reconnect) else: self.idl_establish_connection() except error.Error as e: # idl will raise an error exception if cannot reconnect app_log.debug("Failed to connect, retrying. Reason: %s" % e) self.timeout_handle = \ IOLoop.current().add_timeout(time.time() + self.timeout, self.idl_reconnect) def idl_establish_connection(self): app_log.info("ovsdb connection ready") self.connected = True self.curr_seqno = self.idl.change_seqno self.ovs_socket = self.idl._session.rpc.stream.socket IOLoop.current().add_handler(self.ovs_socket.fileno(), self.idl_run, IOLoop.READ | IOLoop.ERROR) self.run_callbacks(ESTABLISHED_CB_TYPE) def idl_check_and_update(self): self.idl.run() if self.curr_seqno != self.idl.change_seqno: self.run_callbacks(CHANGES_CB_TYPE) if len(self.transactions.txn_list): self.check_transactions() self.curr_seqno = self.idl.change_seqno def idl_run(self, fd=None, events=None): if events & IOLoop.ERROR: app_log.debug("Socket fd %s error" % fd) if fd is not None: IOLoop.current().remove_handler(fd) self.idl_reconnect() elif events & IOLoop.READ: self.idl_check_and_update() def check_transactions(self): self.stop_transaction_timer() txn_incomplete = False for index, tx in enumerate(self.transactions.txn_list): tx.commit() # TODO: Handle all states if tx.status is not INCOMPLETE: self.transactions.txn_list.pop(index) tx.event.set() else: txn_incomplete = True if txn_incomplete: self.start_transaction_timer() def get_new_transaction(self): return OvsdbTransaction(self.idl) def monitor_transaction(self, txn): self.transactions.add_txn(txn) self.start_transaction_timer() def stop_transaction_timer(self): if self.txn_timeout_handle: IOLoop.current().remove_timeout(self.txn_timeout_handle) self.txn_timeout_handle = None def start_transaction_timer(self): if not self.txn_timeout_handle: self.txn_timeout_handle = \ IOLoop.current().add_timeout(time.time() + self.timeout, self.check_transactions) def add_callback(self, cb_type, callback): if cb_type in self._callbacks: self._callbacks[cb_type].add(callback) def remove_callback(self, cb_type, callback): if cb_type in self._callbacks: self._callbacks[cb_type].discard(callback) def run_callbacks(self, cb_type): if cb_type in self._callbacks: for callback in self._callbacks[cb_type]: callback(self, self.idl) # Clear any change tracking info received for next notifications if cb_type == CHANGES_CB_TYPE: self.idl.track_clear_all() def register_schema_helper_columns(self, schema_helper, ext_schema): app_log.debug("Registering schema helper columns..") for table_name, table_schema in ext_schema.ovs_tables.iteritems(): if table_name in ON_DEMAND_FETCHED_TABLES: schema_helper.register_columns(str(table_name), table_schema.columns, table_schema.readonly_columns) else: schema_helper.register_table(str(table_name))