#!/usr/bin/python import time import flow_config_blaster import json class FlowConfigBulkBlaster(flow_config_blaster.FlowConfigBlaster): """ Reusing FlowConfigBlaster class providing flow operations based on bulk processing """ FLW_ADD_RPC_URL = "restconf/operations/sal-bulk-flow:add-flows-rpc" FLW_REMOVE_RPC_URL = "restconf/operations/sal-bulk-flow:remove-flows-rpc" FLW_ADD_DS_URL = "restconf/operations/sal-bulk-flow:add-flows-ds" FLW_REMOVE_DS_URL = "restconf/operations/sal-bulk-flow:remove-flows-ds" def __init__(self, *args, **kwargs): super(FlowConfigBulkBlaster, self).__init__(*args, **kwargs) self.bulk_type = "RPC" def update_post_url_template(self, action): """ Update url templates (defined in parent class) in order to point to bulk API rpcs. :param action: user intention (currently only 'ADD' is supported) """ if self.bulk_type == "RPC": self.post_url_template = "http://%s:" + self.port + "/" if action == "ADD": self.post_url_template += self.FLW_ADD_RPC_URL elif action == "REMOVE": self.post_url_template += self.FLW_REMOVE_RPC_URL elif self.bulk_type == "DS": self.post_url_template = "http://%s:" + self.port + "/" if action == "ADD": self.post_url_template += self.FLW_ADD_DS_URL elif action == "REMOVE": self.post_url_template += self.FLW_REMOVE_DS_URL def assemble_post_url(self, host, node): """ Format url to final form using substitutions. Here the node is ignored. :param host: controller address :param node: node identifier :return: finalized url """ return self.post_url_template % host def create_flow_from_template(self, flow_id, ipaddr, node_id): """ Create one flow beased on template and given values :param flow_id: flow identifier :param ipaddr: part of flow match :param node_id: node identifier :return: flow structure ready to use """ # python 2.7 specific syntax (super) flow = super(FlowConfigBulkBlaster, self).create_flow_from_template( flow_id, ipaddr, node_id ) flow_id = flow["id"] del flow["id"] if self.bulk_type == "DS": flow["flow-id"] = flow_id flow["node"] = ( "/opendaylight-inventory:nodes/opendaylight-inventory" ':node[opendaylight-inventory:id="openflow:{}"]'.format(node_id) ) return flow def convert_to_json(self, flow_list, node_id=None): """ Converts given list of flows into string of json form. :param flow_list: list of flows to convert :param node_id: identifier of corresponding node :return: json string """ json_input = None if self.bulk_type == "RPC": json_input = {"input": {"bulk-flow-item": flow_list}} elif self.bulk_type == "DS": json_input = {"input": {"bulk-flow-ds-item": flow_list}} flow_data = json.dumps(json_input) return flow_data if __name__ == "__main__": ############################################################################ # This program executes the base performance test. The test adds flows into # the controller's config space. This function is basically the CLI frontend # to the FlowConfigBlaster class and drives its main functions: adding and # deleting flows from the controller's config data store ############################################################################ parser = flow_config_blaster.create_arguments_parser() parser.add_argument( "--bulk-type", default="RPC", dest="bulk_type", choices=["RPC", "DS"], help="Bulk type to use: RPC, DS (default is RPC)", ) in_args = parser.parse_args() if in_args.file != "": flow_template = flow_config_blaster.get_json_from_file(in_args.file) else: flow_template = None fcbb = FlowConfigBulkBlaster( in_args.host, in_args.port, in_args.cycles, in_args.threads, in_args.fpr, in_args.nodes, in_args.flows, in_args.startflow, in_args.auth, ) fcbb.bulk_type = in_args.bulk_type fcbb.update_post_url_template("ADD") # Run through , where are started in each cycle and # are added from each thread fcbb.add_blaster() print("\n*** Total flows added: %s" % fcbb.get_ok_flows()) print(" HTTP[OK] results: %d\n" % fcbb.get_ok_rqsts()) if in_args.delay > 0: print( "*** Waiting for %d seconds before the delete cycle ***\n" % in_args.delay ) time.sleep(in_args.delay) # Run through , where are started in each cycle and # previously added in an add cycle are deleted in each thread if in_args.delete: fcbb.delete_blaster() print("\n*** Total flows deleted: %s" % fcbb.get_ok_flows()) print(" HTTP[OK] results: %d\n" % fcbb.get_ok_rqsts())