1 # Copyright (C) 2012 Nippon Telegraph and Telephone Corporation.
2 # Copyright (C) 2012 Isaku Yamahata <yamahata at private email ne jp>
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
18 This module provides a set of REST API for switch configuration.
19 - Per-switch Key-Value store
21 Used by OpenStack Ryu agent.
26 from six.moves import http_client
28 from ryu.app.wsgi import ControllerBase
29 from ryu.app.wsgi import Response
30 from ryu.base import app_manager
31 from ryu.controller import conf_switch
32 from ryu.lib import dpid as dpid_lib
35 # REST API for switch configuration
37 # get all the switches
38 # GET /v1.0/conf/switches
40 # get all the configuration keys of a switch
41 # GET /v1.0/conf/switches/<dpid>
43 # delete all the configuration of a switch
44 # DELETE /v1.0/conf/switches/<dpid>
46 # set the <key> configuration of a switch
47 # PUT /v1.0/conf/switches/<dpid>/<key>
49 # get the <key> configuration of a switch
50 # GET /v1.0/conf/switches/<dpid>/<key>
52 # delete the <key> configuration of a switch
53 # DELETE /v1.0/conf/switches/<dpid>/<key>
56 # <dpid>: datapath id in 16 hex
59 class ConfSwitchController(ControllerBase):
60 def __init__(self, req, link, data, **config):
61 super(ConfSwitchController, self).__init__(req, link, data, **config)
62 self.conf_switch = data
64 def list_switches(self, _req, **_kwargs):
65 dpids = self.conf_switch.dpids()
66 body = json.dumps([dpid_lib.dpid_to_str(dpid) for dpid in dpids])
67 return Response(content_type='application/json', body=body)
70 def _do_switch(dpid, func, ret_func):
71 dpid = dpid_lib.str_to_dpid(dpid)
75 return Response(status=http_client.NOT_FOUND,
76 body='no dpid is found %s' %
77 dpid_lib.dpid_to_str(dpid))
81 def delete_switch(self, _req, dpid, **_kwargs):
82 def _delete_switch(dpid):
83 self.conf_switch.del_dpid(dpid)
87 return Response(status=http_client.ACCEPTED)
89 return self._do_switch(dpid, _delete_switch, _ret)
91 def list_keys(self, _req, dpid, **_kwargs):
93 return self.conf_switch.keys(dpid)
96 body = json.dumps(keys)
97 return Response(content_type='application/json', body=body)
99 return self._do_switch(dpid, _list_keys, _ret)
102 def _do_key(dpid, key, func, ret_func):
103 dpid = dpid_lib.str_to_dpid(dpid)
105 ret = func(dpid, key)
107 return Response(status=http_client.NOT_FOUND,
108 body='no dpid/key is found %s %s' %
109 (dpid_lib.dpid_to_str(dpid), key))
112 def set_key(self, req, dpid, key, **_kwargs):
113 def _set_val(dpid, key):
115 val = req.json if req.body else {}
117 return Response(status=http_client.BAD_REQUEST,
118 body='invalid syntax %s' % req.body)
119 self.conf_switch.set_key(dpid, key, val)
123 return Response(status=http_client.CREATED)
125 return self._do_key(dpid, key, _set_val, _ret)
127 def get_key(self, _req, dpid, key, **_kwargs):
128 def _get_key(dpid, key):
129 return self.conf_switch.get_key(dpid, key)
132 return Response(content_type='application/json',
133 body=json.dumps(val))
135 return self._do_key(dpid, key, _get_key, _ret)
137 def delete_key(self, _req, dpid, key, **_kwargs):
138 def _delete_key(dpid, key):
139 self.conf_switch.del_key(dpid, key)
145 return self._do_key(dpid, key, _delete_key, _ret)
148 class ConfSwitchAPI(app_manager.RyuApp):
150 'conf_switch': conf_switch.ConfSwitchSet,
153 def __init__(self, *args, **kwargs):
154 super(ConfSwitchAPI, self).__init__(*args, **kwargs)
155 self.conf_switch = kwargs['conf_switch']
156 wsgi = kwargs['wsgi']
159 controller = ConfSwitchController
160 wsgi.registory[controller.__name__] = self.conf_switch
161 route_name = 'conf_switch'
162 uri = '/v1.0/conf/switches'
163 mapper.connect(route_name, uri, controller=controller,
164 action='list_switches',
165 conditions=dict(method=['GET']))
168 requirements = {'dpid': dpid_lib.DPID_PATTERN}
169 s = mapper.submapper(controller=controller, requirements=requirements)
170 s.connect(route_name, uri, action='delete_switch',
171 conditions=dict(method=['DELETE']))
172 s.connect(route_name, uri, action='list_keys',
173 conditions=dict(method=['GET']))
176 s.connect(route_name, uri, action='set_key',
177 conditions=dict(method=['PUT']))
178 s.connect(route_name, uri, action='get_key',
179 conditions=dict(method=['GET']))
180 s.connect(route_name, uri, action='delete_key',
181 conditions=dict(method=['DELETE']))