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 delete_flow(flow_id, flow, correlation_id): try: flow_path = flow['flowpath']['path'] logger.info('Flow path remove: %s', flow_path) 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, 'message_type': "flow"} message_utils.send_message(payload, correlation_id, "INFO") 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): 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 delete_flow(flow_id, flow, correlation_id, parent_tx=None, propagate=True, from_nb=False): """ Simple algorithm - delete the stuff in the DB, send delete commands, send a response. Complexity - each segment in the path may have a separate cookie, so that information needs to be gathered. NB: Each switch in the flow should get a delete command. # TODO: eliminate flowpath as part of delete_flow request; rely on flow_id only # TODO: Add state to flow .. ie "DELETING", as part of refactoring project to add state - eg: flow_utils.update_state(flow, DELETING, parent_tx) :param parent_tx: If there is a larger transaction to use, then use it. :return: True, unless an exception is raised. """ try: # All flows .. single switch or multi .. will start with deleting based on the src and flow cookie; then # we'll have a delete per segment based on the destination. Consequently, the "single switch flow" is # automatically addressed using this algorithm. flow_cookie = int(flow['cookie']) transit_vlan = int(flow['transit_vlan']) current_node = {'switch_id': flow['src_switch'], 'flow_id': flow_id, 'cookie': flow_cookie, 'meter_id': flow['meter_id'], 'in_port': flow['src_port'], 'in_vlan': flow['src_vlan']} nodes = [current_node] segments = flow_utils.fetch_flow_segments(flow_id, flow_cookie) for segment in segments: current_node['out_port'] = segment['src_port'] # every segment should have a cookie field, based on merge_segment; but just in case.. segment_cookie = segment.get('cookie', flow_cookie) current_node = {'switch_id': segment['dst_switch'], 'flow_id': flow_id, 'cookie': segment_cookie, 'meter_id': None, 'in_port': segment['dst_port'], 'in_vlan': transit_vlan, 'out_port': segment['dst_port']} nodes.append(current_node) current_node['out_port'] = flow['dst_port'] if propagate: logger.info('Flow rules remove start: correlation_id=%s, flow_id=%s, path=%s', correlation_id, flow_id, nodes) message_utils.send_delete_commands(nodes, correlation_id) logger.info('Flow rules removed end : correlation_id=%s, flow_id=%s', correlation_id, flow_id) if from_nb: # The request is sent from Northbound .. send response back logger.info('Flow rules from NB: correlation_id=%s, flow_id=%s', correlation_id, flow_id) data = {"payload":{"flowid": flow_id,"status": "DOWN"}, "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 ) flow_utils.remove_flow(flow, parent_tx) logger.info('Flow was removed: correlation_id=%s, flow_id=%s', correlation_id, flow_id) except Exception as e: logger.exception('Can not delete flow: %s', e.message) if not from_nb: # Propagate is the normal scenario, so send response back to FLOW message_utils.send_error_message(correlation_id, "DELETION_FAILURE", e.message, flow_id) else: # This means we tried a UNPUSH, send response back to NORTHBOUND message_utils.send_error_message( correlation_id, "UNPUSH_FAILURE", e.message, flow_id, destination="NORTHBOUND", topic=config.KAFKA_NORTHBOUND_TOPIC) raise return True