15fc642a0d331355ddb10294d6302841114afdf1
[integration/test.git] / tools / odl-lispflowmapping-performance-tests / mapping_blaster.py
1 #!/usr/bin/python
2 """
3 Script to add LISP mappings to ODL.  Currently it only supports the
4 RPC interface.  Support for RESTCONF is planned in a future release.
5
6 Use `./mapping_blaster.py --help` to see options
7
8 Code inspired from `flow_config_blaster.py` by Jan Medved
9 """
10
11 import argparse
12 import copy
13 import json
14
15 import netaddr
16 import requests
17
18 __author__ = "Lori Jakab"
19 __copyright__ = "Copyright (c) 2014, Cisco Systems, Inc."
20 __credits__ = ["Jan Medved"]
21 __license__ = "New-style BSD"
22 __email__ = "lojakab@cisco.com"
23 __version__ = "0.0.3"
24
25
26 class MappingRPCBlaster(object):
27     putheaders = {'Content-type': 'application/json'}
28     getheaders = {'Accept': 'application/json'}
29
30     RPC_URL_LI = 'restconf/operations/lfm-mapping-database:'
31     RPC_URL_BE = 'restconf/operations/mappingservice:'
32     TIMEOUT = 10
33
34     # Template for adding mappings
35     add_mapping_template = {
36         u'input': {
37             u'recordTtl': 60,
38             u'maskLength': 32,
39             u'authoritative': True,
40             u'action': u'NoAction',
41             u'LispAddressContainer': {
42                 u'Ipv4Address': {
43                     u'afi': 1,
44                     u'Ipv4Address': u'10.0.0.0'
45                 }
46             },
47             u'LocatorRecord': [
48                 {
49                     u'name': u'ipv4:172.16.0.0',
50                     u'priority': 1,
51                     u'weight': 1,
52                     u'multicastPriority': 255,
53                     u'multicastWeight': 0,
54                     u'localLocator': True,
55                     u'rlocProbed': False,
56                     u'routed': True,
57                     u'LispAddressContainer': {
58                         u'Ipv4Address': {
59                             u'afi': 1,
60                             u'Ipv4Address': u'172.16.0.0'
61                         }
62                     }
63                 }
64             ]
65         }
66     }
67
68     # Template for getting mappings
69     get_mapping_template = {
70         u'input': {
71             u'LispAddressContainer': {
72                 u'Ipv4Address': {
73                     u'afi': 1,
74                     u'Ipv4Address': u'10.0.0.0'
75                 }
76             },
77             u'mask-length': 32
78         }
79     }
80
81     def __init__(self, host, port, start_eid, mask, start_rloc, nmappings, v):
82         """
83         Args:
84             :param host: The host running ODL where we want to send the RPCs
85             :param port: The RESTCONF port on the ODL host
86             :param start_eid: The starting EID for adding mappings as an IPv4
87                 literal
88             :param mask: The network mask for the EID prefixes to be added
89             :param start_rloc: The starting RLOC for the locators in the
90                 mappings as an IPv4 literal
91             :param nmappings: The number of mappings to be generated
92             :param v: Version of the ODL instance (since the RPC URL changed
93                 from Lithium to Beryllium
94         """
95         self.session = requests.Session()
96         self.host = host
97         self.port = port
98         self.start_eid = netaddr.IPAddress(start_eid)
99         self.mask = mask
100         self.start_rloc = netaddr.IPAddress(start_rloc)
101         self.nmappings = nmappings
102         if v == "Li" or v == "li":
103             print "Using the Lithium RPC URL"
104             rpc_url = self.RPC_URL_LI
105         else:
106             print "Using the Beryllium and later RPC URL"
107             rpc_url = self.RPC_URL_BE
108
109         self.post_url_template = 'http://' + self.host + ':' \
110             + self.port + '/' + rpc_url
111
112     def mapping_from_tpl(self, eid, mask, rloc):
113         """Create an add-mapping RPC input dictionary from the mapping template
114         Args:
115             :param eid: Replace the default EID in the template with this one
116             :param mask: Replace the default mask in the template with this one
117             :param rloc: Replace the default RLOC in the template with this one
118         Returns:
119             :return dict: mapping - template modified with the arguments
120         """
121         mapping = copy.deepcopy(self.add_mapping_template['input'])
122         mapping['maskLength'] = mask
123         mapping['LispAddressContainer']['Ipv4Address']['Ipv4Address'] \
124             = str(netaddr.IPAddress(eid))
125         mapping['LocatorRecord'][0]['name'] = 'ipv4:' \
126             + str(netaddr.IPAddress(rloc))
127         address_container = mapping['LocatorRecord'][0]['LispAddressContainer']
128         address_container['Ipv4Address']['Ipv4Address'] \
129             = str(netaddr.IPAddress(rloc))
130         return mapping
131
132     def send_rpc(self, session, method, body):
133         """Send an HTTP POST to the RPC URL and return the status code
134         Args:
135             :param session: The HTTP session handle
136             :param method: "add" or "del"ete mapping
137             :param body: the JSON body to be sent
138         Returns:
139             :return int: status_code - HTTP status code
140         """
141         rpc_url = self.post_url_template + method
142         r = session.post(rpc_url, data=body, headers=self.putheaders,
143                          stream=False, auth=('admin', 'admin'),
144                          timeout=self.TIMEOUT)
145         return r.status_code
146
147     def add_n_mappings(self):
148         """Add self.nmappings mappings to ODL"""
149         rpc = dict(self.add_mapping_template)
150         increment = pow(2, 32 - int(self.mask))
151         for i in range(self.nmappings):
152             rpc['input'] = self.mapping_from_tpl(self.start_eid + i *
153                                                  increment, self.mask,
154                                                  self.start_rloc + i)
155             rpc_json = json.dumps(rpc)
156             self.send_rpc(self.session, 'add-mapping', rpc_json)
157         self.session.close()
158
159     def get_n_mappings(self):
160         """Retrieve self.nmappings mappings from ODL
161         """
162         rpc = dict(self.get_mapping_template)
163         increment = pow(2, 32 - int(self.mask))
164         for i in range(self.nmappings):
165             eid = self.start_eid + i * increment
166             rpc['input']['LispAddressContainer']['Ipv4Address']['Ipv4Address']\
167                 = str(netaddr.IPAddress(eid))
168             rpc['input']['mask-length'] = self.mask
169             rpc_json = json.dumps(rpc)
170             self.send_rpc(self.session, 'get-mapping', rpc_json)
171         self.session.close()
172
173 if __name__ == "__main__":
174     parser = argparse.ArgumentParser(description='Add simple IPv4 \
175         prefix-to-IPv4 locator LISP mappings to OpenDaylight')
176
177     parser.add_argument('--mode', default='add',
178                         help='Operating mode, can be "add" or "get" \
179                             (default is "add")')
180     parser.add_argument('--host', default='127.0.0.1',
181                         help='Host where ODL controller is running (default \
182                             is 127.0.0.1)')
183     parser.add_argument('--port', default='8181',
184                         help='Port on which ODL\'s RESTCONF is listening \
185                             (default is 8181)')
186     parser.add_argument('--start-eid', default='10.0.0.0',
187                         help='Start incrementing EID from this address \
188                             (default is 10.0.0.0)')
189     parser.add_argument('--mask', default='32',
190                         help='Network mask for the IPv4 EID prefixes \
191                             (default is 32)')
192     parser.add_argument('--start-rloc', default='172.16.0.0',
193                         help='Start incrementing RLOC from this address \
194                             (default is 172.16.0.0, ignored for "get")')
195     parser.add_argument('--mappings', type=int, default=1,
196                         help='Number of mappings to add/get (default 1)')
197     parser.add_argument('--odl-version', default='Be',
198                         help='OpenDaylight version, can be "Li" or "Be" \
199                             (default is "Be")')
200
201     in_args = parser.parse_args()
202
203     mapping_rpc_blaster = MappingRPCBlaster(in_args.host, in_args.port,
204                                             in_args.start_eid, in_args.mask,
205                                             in_args.start_rloc,
206                                             in_args.mappings,
207                                             in_args.odl_version)
208
209     if in_args.mode == "add":
210         mapping_rpc_blaster.add_n_mappings()
211     elif in_args.mode == "get":
212         mapping_rpc_blaster.get_n_mappings()
213     else:
214         print "Unsupported mode:", in_args.mode