def delete_flow(flow_id, flow, correlation_id): try: flow_path = flow['flowpath']['path'] logger.info('Flow path remove: %s', flow_path) # TODO: Remove Flow should be moved down .. opposite order of create. # (I'd do it now, but I'm troubleshooting something else) flow_utils.remove_flow(flow, flow_path) logger.info('Flow was removed: correlation_id=%s, flow_id=%s', correlation_id, flow_id) message_utils.send_delete_commands(flow_path, flow_id, correlation_id, int(flow['cookie'])) logger.info('Flow rules removed: correlation_id=%s, flow_id=%s', correlation_id, flow_id) payload = {'payload': flow, 'clazz': MT_FLOW_RESPONSE} message_utils.send_info_message(payload, correlation_id) except Exception as e: logger.exception('Can not delete flow: %s', e.message) message_utils.send_error_message(correlation_id, "DELETION_FAILURE", e.message, flow_id) raise return True
def update_flow(flow_id, flow, correlation_id, tx): try: old_flow = flow_utils.get_old_flow(flow) # # Start the transaction to govern the create/delete # logger.info('Flow rules were built: correlation_id=%s, flow_id=%s', correlation_id, flow_id) rules = flow_utils.build_rules(flow) # TODO: add tx to store_flow flow_utils.store_flow(flow, tx) logger.info('Flow was stored: correlation_id=%s, flow_id=%s', correlation_id, flow_id) message_utils.send_install_commands(rules, correlation_id) MessageItem.delete_flow(old_flow['flowid'], old_flow, correlation_id, tx) payload = {'payload': flow, 'clazz': MT_FLOW_RESPONSE} message_utils.send_info_message(payload, correlation_id) except Exception as e: logger.exception('Can not update flow: %s', e.message) message_utils.send_error_message( correlation_id, "UPDATE_FAILURE", e.message, flow_id) raise return True
def create_flow(flow_id, flow, correlation_id): try: rules = flow_utils.build_rules(flow) logger.info('Flow rules were built: correlation_id=%s, flow_id=%s', correlation_id, flow_id) flow_utils.store_flow(flow) logger.info('Flow was stored: correlation_id=%s, flow_id=%s', correlation_id, flow_id) message_utils.send_install_commands(rules, correlation_id) logger.info('Flow rules installed: correlation_id=%s, flow_id=%s', correlation_id, flow_id) payload = {'payload': flow, 'clazz': MT_FLOW_RESPONSE} message_utils.send_info_message(payload, correlation_id) except Exception as e: logger.exception('Can not create flow: %s', flow_id) message_utils.send_error_message(correlation_id, "CREATION_FAILURE", e.message, flow_id) raise return True
def flow_operation(self): correlation_id = self.correlation_id timestamp = self.timestamp payload = self.payload operation = payload['operation'] flows = payload['payload'] forward = flows['forward'] reverse = flows['reverse'] flow_id = forward['flowid'] logger.info( 'Flow %s request processing: ' 'timestamp=%s, correlation_id=%s, payload=%s', operation, timestamp, correlation_id, payload) if operation == "CREATE" or operation == "PUSH": propagate = operation == "CREATE" # TODO: leverage transaction for creating both flows self.create_flow(flow_id, forward, correlation_id, propagate) self.create_flow(flow_id, reverse, correlation_id, propagate) elif operation == "DELETE" or operation == "UNPUSH": tx = graph.begin() propagate = operation == "DELETE" MessageItem.delete_flow(flow_id, forward, correlation_id, tx, propagate) MessageItem.delete_flow(flow_id, reverse, correlation_id, tx, propagate) if propagate: message_utils.send_info_message( { 'payload': forward, 'clazz': MT_FLOW_RESPONSE }, correlation_id) message_utils.send_info_message( { 'payload': reverse, 'clazz': MT_FLOW_RESPONSE }, correlation_id) tx.commit() elif operation == "UPDATE": tx = graph.begin() MessageItem.update_flow(flow_id, forward, correlation_id, tx) MessageItem.update_flow(flow_id, reverse, correlation_id, tx) tx.commit() else: logger.warn( 'Flow operation is not supported: ' 'operation=%s, timestamp=%s, correlation_id=%s,', operation, timestamp, correlation_id) logger.info( 'Flow %s request processed: ' 'timestamp=%s, correlation_id=%s, payload=%s', operation, timestamp, correlation_id, payload) return True
def create_flow(flow_id, flow, correlation_id, tx, propagate=True, from_nb=False): """ :param propagate: If true, send to switch :param from_nb: If true, send response to NORTHBOUND API; otherwise to FLOW_TOPOLOGY :return: """ try: rules = flow_utils.build_rules(flow) logger.info('Flow rules were built: correlation_id=%s, flow_id=%s', correlation_id, flow_id) flow_utils.store_flow(flow, tx) logger.info('Flow was stored: correlation_id=%s, flow_id=%s', correlation_id, flow_id) if propagate: message_utils.send_install_commands(rules, correlation_id) logger.info('Flow rules INSTALLED: correlation_id=%s, flow_id=%s', correlation_id, flow_id) if not from_nb: message_utils.send_info_message({'payload': flow, 'clazz': MT_FLOW_RESPONSE}, correlation_id) else: # The request is sent from Northbound .. send response back logger.info('Flow rules NOT PROPAGATED: correlation_id=%s, flow_id=%s', correlation_id, flow_id) data = {"payload":{"flowid": flow_id,"status": "UP"}, "clazz": message_utils.MT_INFO_FLOW_STATUS} message_utils.send_to_topic( payload=data, correlation_id=correlation_id, message_type=message_utils.MT_INFO, destination="NORTHBOUND", topic=config.KAFKA_NORTHBOUND_TOPIC ) except Exception as e: logger.exception('Can not create flow: %s', flow_id) if not from_nb: # Propagate is the normal scenario, so send response back to FLOW message_utils.send_error_message(correlation_id, "CREATION_FAILURE", e.message, flow_id) else: # This means we tried a PUSH, send response back to NORTHBOUND message_utils.send_error_message(correlation_id, "PUSH_FAILURE", e.message, flow_id, destination="NORTHBOUND", topic=config.KAFKA_NORTHBOUND_TOPIC) raise return True
def update_flow(flow_id, flow, correlation_id): try: old_flow = flow_utils.get_old_flow(flow) old_flow_path = json.loads(old_flow['flowpath'])['path'] logger.info('Flow path remove: %s', old_flow_path) flow_utils.remove_flow(old_flow, old_flow_path) logger.info('Flow was removed: correlation_id=%s, flow_id=%s', correlation_id, flow_id) rules = flow_utils.build_rules(flow) logger.info('Flow rules were built: correlation_id=%s, flow_id=%s', correlation_id, flow_id) flow_utils.store_flow(flow) logger.info('Flow was stored: correlation_id=%s, flow_id=%s', correlation_id, flow_id) message_utils.send_install_commands(rules, correlation_id) logger.info('Flow rules installed: correlation_id=%s, flow_id=%s', correlation_id, flow_id) message_utils.send_delete_commands(old_flow_path, old_flow['flowid'], correlation_id, int(old_flow['cookie'])) logger.info('Flow rules removed: correlation_id=%s, flow_id=%s', correlation_id, flow_id) payload = {'payload': flow, 'clazz': MT_FLOW_RESPONSE} message_utils.send_info_message(payload, correlation_id) except Exception as e: logger.exception('Can not update flow: %s', e.message) message_utils.send_error_message(correlation_id, "UPDATE_FAILURE", e.message, flow_id) raise return True
def flow_operation(self): correlation_id = self.correlation_id timestamp = self.timestamp payload = self.payload operation = payload['operation'] flows = payload['payload'] forward = flows['forward'] reverse = flows['reverse'] flow_id = forward['flowid'] if self.not_allow_flow_operation(): logger.info('Flow %s request is not allow: ' 'timestamp=%s, correlation_id=%s, payload=%s', operation, timestamp, correlation_id, payload) # TODO: We really should use the reply-to field, at least in NB, so that we know to send the response. op = payload['operation'].upper() if op == "PUSH" or op == "PUSH_PROPAGATE" or op == "UNPUSH" or op == "UNPUSH_PROPAGATE": message_utils.send_error_message( correlation_id, 'REQUEST_INVALID', op+"-FAILURE - NOT ALLOWED RIGHT NOW - Toggle the feature to allow this behavior", "", destination="NORTHBOUND", topic=config.KAFKA_NORTHBOUND_TOPIC) return True logger.info('Flow %s request processing: ' 'timestamp=%s, correlation_id=%s, payload=%s', operation, timestamp, correlation_id, payload) tx = None # flow_sem.acquire(timeout=10) # wait 10 seconds .. then proceed .. possibly causing some issue. neo4j_update_lock.acquire() try: OP = operation.upper() if OP == "CREATE" or OP == "PUSH" or OP == "PUSH_PROPAGATE": propagate = (OP == "CREATE" or OP == "PUSH_PROPAGATE") from_nb = (OP == "PUSH" or OP == "PUSH_PROPAGATE") tx = graph.begin() self.create_flow(flow_id, forward, correlation_id, tx, propagate, from_nb) self.create_flow(flow_id, reverse, correlation_id, tx, propagate, from_nb) tx.commit() tx = None elif OP == "DELETE" or OP == "UNPUSH" or OP == "UNPUSH_PROPAGATE": tx = graph.begin() propagate = (OP == "DELETE" or OP == "UNPUSH_PROPAGATE") from_nb = (OP == "UNPUSH" or OP == "UNPUSH_PROPAGATE") MessageItem.delete_flow(flow_id, forward, correlation_id, tx, propagate, from_nb) MessageItem.delete_flow(flow_id, reverse, correlation_id, tx, propagate, from_nb) if not from_nb: message_utils.send_info_message({'payload': forward, 'clazz': MT_FLOW_RESPONSE}, correlation_id) message_utils.send_info_message({'payload': reverse, 'clazz': MT_FLOW_RESPONSE}, correlation_id) tx.commit() tx = None elif OP == "UPDATE": tx = graph.begin() MessageItem.update_flow(flow_id, forward, correlation_id, tx) MessageItem.update_flow(flow_id, reverse, correlation_id, tx) tx.commit() tx = None else: logger.warn('Flow operation is not supported: ' 'operation=%s, timestamp=%s, correlation_id=%s,', operation, timestamp, correlation_id) except Exception: if tx is not None: tx.rollback() # flow_sem.release() raise finally: #flow_sem.release() neo4j_update_lock.release() logger.info('Flow %s request processed: ' 'timestamp=%s, correlation_id=%s, payload=%s', operation, timestamp, correlation_id, payload) return True
def flow_operation(self): correlation_id = self.correlation_id timestamp = self.timestamp payload = self.payload operation = payload['operation'] flows = payload['payload'] forward = flows['forward'] reverse = flows['reverse'] flow_id = forward['flowid'] logger.info( 'Flow %s request processing: ' 'timestamp=%s, correlation_id=%s, payload=%s', operation, timestamp, correlation_id, payload) tx = None # flow_sem.acquire(timeout=10) # wait 10 seconds .. then proceed .. possibly causing some issue. neo4j_update_lock.acquire() try: OP = operation.upper() if OP == "CREATE" or OP == "PUSH" or OP == "PUSH_PROPAGATE": propagate = (OP == "CREATE" or OP == "PUSH_PROPAGATE") from_nb = (OP == "PUSH" or OP == "PUSH_PROPAGATE") tx = graph.begin() self.create_flow(flow_id, forward, correlation_id, tx, propagate, from_nb) self.create_flow(flow_id, reverse, correlation_id, tx, propagate, from_nb) tx.commit() tx = None elif OP == "DELETE" or OP == "UNPUSH" or OP == "UNPUSH_PROPAGATE": tx = graph.begin() propagate = (OP == "DELETE" or OP == "UNPUSH_PROPAGATE") from_nb = (OP == "UNPUSH" or OP == "UNPUSH_PROPAGATE") MessageItem.delete_flow(flow_id, forward, correlation_id, tx, propagate, from_nb) MessageItem.delete_flow(flow_id, reverse, correlation_id, tx, propagate, from_nb) if not from_nb: message_utils.send_info_message( { 'payload': forward, 'clazz': MT_FLOW_RESPONSE }, correlation_id) message_utils.send_info_message( { 'payload': reverse, 'clazz': MT_FLOW_RESPONSE }, correlation_id) tx.commit() tx = None elif OP == "UPDATE": tx = graph.begin() MessageItem.update_flow(flow_id, forward, correlation_id, tx) MessageItem.update_flow(flow_id, reverse, correlation_id, tx) tx.commit() tx = None else: logger.warn( 'Flow operation is not supported: ' 'operation=%s, timestamp=%s, correlation_id=%s,', operation, timestamp, correlation_id) except Exception: if tx is not None: tx.rollback() # flow_sem.release() raise finally: #flow_sem.release() neo4j_update_lock.release() logger.info( 'Flow %s request processed: ' 'timestamp=%s, correlation_id=%s, payload=%s', operation, timestamp, correlation_id, payload) return True