f24d5ab06239df2ae0839208a49ca905e48609c0
[integration/test.git] / tools / odl-mdsal-clustering-tests / clustering-performance-test / flow_config_blaster_bulk.py
1 #!/usr/bin/python
2 import time
3
4 import flow_config_blaster
5 import json
6
7
8 class FlowConfigBulkBlaster(flow_config_blaster.FlowConfigBlaster):
9     """
10     Reusing FlowConfigBlaster class providing flow operations based on bulk processing
11     """
12
13     FLW_ADD_RPC_URL = "restconf/operations/sal-bulk-flow:add-flows-rpc"
14     FLW_REMOVE_RPC_URL = "restconf/operations/sal-bulk-flow:remove-flows-rpc"
15     FLW_ADD_DS_URL = "restconf/operations/sal-bulk-flow:add-flows-ds"
16     FLW_REMOVE_DS_URL = "restconf/operations/sal-bulk-flow:remove-flows-ds"
17
18     def __init__(self, *args, **kwargs):
19         super(FlowConfigBulkBlaster, self).__init__(*args, **kwargs)
20         self.bulk_type = 'RPC'
21
22     def update_post_url_template(self, action):
23         """
24         Update url templates (defined in parent class) in order to point to bulk API rpcs.
25         :param action: user intention (currently only 'ADD' is supported)
26         """
27         if self.bulk_type == 'RPC':
28             self.post_url_template = 'http://%s:' + self.port + '/'
29             if action == 'ADD':
30                 self.post_url_template += self.FLW_ADD_RPC_URL
31             elif action == 'REMOVE':
32                 self.post_url_template += self.FLW_REMOVE_RPC_URL
33         elif self.bulk_type == 'DS':
34             self.post_url_template = 'http://%s:' + self.port + '/'
35             if action == 'ADD':
36                 self.post_url_template += self.FLW_ADD_DS_URL
37             elif action == 'REMOVE':
38                 self.post_url_template += self.FLW_REMOVE_DS_URL
39
40     def assemble_post_url(self, host, node):
41         """
42         Format url to final form using substitutions. Here the node is ignored.
43         :param host: controller address
44         :param node: node identifier
45         :return: finalized url
46         """
47         return self.post_url_template % host
48
49     def create_flow_from_template(self, flow_id, ipaddr, node_id):
50         """
51         Create one flow beased on template and given values
52         :param flow_id: flow identifier
53         :param ipaddr: part of flow match
54         :param node_id: node identifier
55         :return: flow structure ready to use
56         """
57         # python 2.7 specific syntax (super)
58         flow = super(FlowConfigBulkBlaster, self).create_flow_from_template(flow_id, ipaddr, node_id)
59         flow_id = flow['id']
60         del(flow['id'])
61         if self.bulk_type == 'DS':
62             flow['flow-id'] = flow_id
63         flow['node'] = '/opendaylight-inventory:nodes/opendaylight-inventory' \
64                        ':node[opendaylight-inventory:id="openflow:{}"]'.format(node_id)
65         return flow
66
67     def convert_to_json(self, flow_list, node_id=None):
68         """
69         Converts given list of flows into string of json form.
70         :param flow_list: list of flows to convert
71         :param node_id: identifier of corresponding node
72         :return: json string
73         """
74         json_input = None
75         if self.bulk_type == 'RPC':
76             json_input = {'input': {'bulk-flow-item': flow_list}}
77         elif self.bulk_type == 'DS':
78             json_input = {'input': {'bulk-flow-ds-item': flow_list}}
79
80         flow_data = json.dumps(json_input)
81         return flow_data
82
83
84 if __name__ == "__main__":
85     ############################################################################
86     # This program executes the base performance test. The test adds flows into
87     # the controller's config space. This function is basically the CLI frontend
88     # to the FlowConfigBlaster class and drives its main functions: adding and
89     # deleting flows from the controller's config data store
90     ############################################################################
91     parser = flow_config_blaster.create_arguments_parser()
92     parser.add_argument('--bulk-type', default='RPC', dest='bulk_type',
93                         choices=['RPC', 'DS'],
94                         help='Bulk type to use: RPC, DS (default is RPC)')
95
96     in_args = parser.parse_args()
97
98     if in_args.file != '':
99         flow_template = flow_config_blaster.get_json_from_file(in_args.file)
100     else:
101         flow_template = None
102
103     fcbb = FlowConfigBulkBlaster(in_args.host, in_args.port, in_args.cycles,
104                                  in_args.threads, in_args.fpr, in_args.nodes,
105                                  in_args.flows, in_args.startflow, in_args.auth)
106     fcbb.bulk_type = in_args.bulk_type
107     fcbb.update_post_url_template('ADD')
108
109     # Run through <cycles>, where <threads> are started in each cycle and
110     # <flows> are added from each thread
111     fcbb.add_blaster()
112
113     print('\n*** Total flows added: %s' % fcbb.get_ok_flows())
114     print('    HTTP[OK] results:  %d\n' % fcbb.get_ok_rqsts())
115
116     if in_args.delay > 0:
117         print('*** Waiting for %d seconds before the delete cycle ***\n' % in_args.delay)
118         time.sleep(in_args.delay)
119
120     # Run through <cycles>, where <threads> are started in each cycle and
121     # <flows> previously added in an add cycle are deleted in each thread
122     if in_args.delete:
123         fcbb.delete_blaster()
124         print('\n*** Total flows deleted: %s' % fcbb.get_ok_flows())
125         print('    HTTP[OK] results:    %d\n' % fcbb.get_ok_rqsts())