51baabb9ee
Signed-off-by: YAMADA Hideki <yamada.hideki@po.ntts.co.jp> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
282 lines
9.1 KiB
Python
282 lines
9.1 KiB
Python
# Copyright (C) 2011 Nippon Telegraph and Telephone Corporation.
|
|
# Copyright (C) 2011, 2012 Isaku Yamahata <yamahata at valinux co jp>
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
# implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import httplib
|
|
import json
|
|
import urlparse
|
|
|
|
|
|
def ignore_http_not_found(func):
|
|
"""
|
|
Ignore http not found(404) with Ryu client library.
|
|
Ryu client raises httplib.HTTPException with an error in args[0]
|
|
"""
|
|
try:
|
|
func()
|
|
except httplib.HTTPException as e:
|
|
res = e.args[0]
|
|
if res.status != httplib.NOT_FOUND:
|
|
raise
|
|
|
|
|
|
class RyuClientBase(object):
|
|
def __init__(self, version, address):
|
|
super(RyuClientBase, self).__init__()
|
|
self.version = version
|
|
res = urlparse.SplitResult('', address, '', '', '')
|
|
self.host = res.hostname
|
|
self.port = res.port
|
|
self.url_prefix = '/' + self.version + '/'
|
|
|
|
def _do_request(self, method, action, body=None):
|
|
conn = httplib.HTTPConnection(self.host, self.port)
|
|
url = self.url_prefix + action
|
|
headers = {}
|
|
if body is not None:
|
|
body = json.dumps(body)
|
|
headers['Content-Type'] = 'application/json'
|
|
conn.request(method, url, body, headers)
|
|
res = conn.getresponse()
|
|
if res.status in (httplib.OK,
|
|
httplib.CREATED,
|
|
httplib.ACCEPTED,
|
|
httplib.NO_CONTENT):
|
|
return res
|
|
|
|
raise httplib.HTTPException(
|
|
res, 'code %d reason %s' % (res.status, res.reason),
|
|
res.getheaders(), res.read())
|
|
|
|
def _do_request_read(self, method, action):
|
|
res = self._do_request(method, action)
|
|
return res.read()
|
|
|
|
|
|
class OFPClientV1_0(RyuClientBase):
|
|
version = 'v1.0'
|
|
|
|
# /networks/{network_id}/{dpid}_{port}/macs/{mac_address}
|
|
path_networks = 'networks'
|
|
path_network = path_networks + '/%s'
|
|
path_port = path_network + '/%s_%s'
|
|
path_macs = path_port + '/macs'
|
|
path_mac = path_macs + '/%s'
|
|
|
|
def __init__(self, address):
|
|
super(OFPClientV1_0, self).__init__(OFPClientV1_0.version, address)
|
|
|
|
def get_networks(self):
|
|
return self._do_request_read('GET', self.path_networks)
|
|
|
|
def create_network(self, network_id):
|
|
self._do_request('POST', self.path_network % network_id)
|
|
|
|
def update_network(self, network_id):
|
|
self._do_request('PUT', self.path_network % network_id)
|
|
|
|
def delete_network(self, network_id):
|
|
self._do_request('DELETE', self.path_network % network_id)
|
|
|
|
def get_ports(self, network_id):
|
|
return self._do_request_read('GET', self.path_network % network_id)
|
|
|
|
def create_port(self, network_id, dpid, port):
|
|
self._do_request('POST', self.path_port % (network_id, dpid, port))
|
|
|
|
def update_port(self, network_id, dpid, port):
|
|
self._do_request('PUT', self.path_port % (network_id, dpid, port))
|
|
|
|
def delete_port(self, network_id, dpid, port):
|
|
self._do_request('DELETE', self.path_port % (network_id, dpid, port))
|
|
|
|
def list_macs(self, network_id, dpid, port):
|
|
return self._do_request_read('GET',
|
|
self.path_macs % (network_id, dpid, port))
|
|
|
|
def create_mac(self, network_id, dpid, port, mac_address):
|
|
self._do_request('POST', self.path_mac % (network_id, dpid, port,
|
|
mac_address))
|
|
|
|
def update_mac(self, network_id, dpid, port, mac_address):
|
|
self._do_request('PUT', self.path_mac % (network_id, dpid, port,
|
|
mac_address))
|
|
|
|
|
|
OFPClient = OFPClientV1_0
|
|
|
|
|
|
class TunnelClientV1_0(RyuClientBase):
|
|
version = 'v1.0'
|
|
|
|
# /tunnels/networks/{network-id}/key/{tunnel_key}
|
|
# /tunnels/switches/{dpid}/ports/{port-id}/{remote_dpip}
|
|
path_tunnels = 'tunnels'
|
|
path_key = path_tunnels + '/networks/%(network_id)s/key'
|
|
path_tunnel_key = path_key + '/%(tunnel_key)s'
|
|
path_ports = path_tunnels + '/switches/%(dpid)s/ports'
|
|
path_port = path_ports + '/%(port_no)s'
|
|
path_remote_dpid = path_port + '/%(remote_dpid)s'
|
|
|
|
def __init__(self, address):
|
|
super(TunnelClientV1_0, self).__init__(self.version, address)
|
|
|
|
def get_tunnel_key(self, network_id):
|
|
return self._do_request_read('GET', self.path_key % locals())
|
|
|
|
def delete_tunnel_key(self, network_id):
|
|
return self._do_request_read('DELETE', self.path_key % locals())
|
|
|
|
def create_tunnel_key(self, network_id, tunnel_key):
|
|
self._do_request('POST', self.path_tunnel_key % locals())
|
|
|
|
def update_tunnel_key(self, network_id, tunnel_key):
|
|
self._do_request('PUT', self.path_tunnel_key % locals())
|
|
|
|
def list_ports(self, dpid):
|
|
return self._do_request_read('GET', self.path_ports % locals())
|
|
|
|
def delete_port(self, dpid, port_no):
|
|
return self._do_request_read('DELETE', self.path_port % locals())
|
|
|
|
def get_remote_dpid(self, dpid, port_no):
|
|
return self._do_request_read('GET', self.path_port % locals())
|
|
|
|
def create_remote_dpid(self, dpid, port_no, remote_dpid):
|
|
self._do_request('POST', self.path_remote_dpid % locals())
|
|
|
|
def update_remote_dpid(self, dpid, port_no, remote_dpid):
|
|
self._do_request('PUT', self.path_remote_dpid % locals())
|
|
|
|
|
|
TunnelClient = TunnelClientV1_0
|
|
|
|
|
|
class SwitchConfClientV1_0(RyuClientBase):
|
|
version = 'v1.0'
|
|
|
|
# /conf/switches
|
|
# /conf/switches/<dpid>
|
|
# /conf/switches/<dpid>/<key>
|
|
path_conf_switches = 'conf/switches'
|
|
path_switch = path_conf_switches + '/%(dpid)s'
|
|
path_key = path_switch + '/%(key)s'
|
|
|
|
def __init__(self, address):
|
|
super(SwitchConfClientV1_0, self).__init__(self.version, address)
|
|
|
|
def list_switches(self):
|
|
return self._do_request_read('GET', self.path_conf_switches)
|
|
|
|
def delete_switch(self, dpid):
|
|
self._do_request('DELETE', self.path_switch % locals())
|
|
|
|
def list_keys(self, dpid):
|
|
return self._do_request_read('GET', self.path_switch % locals())
|
|
|
|
def set_key(self, dpid, key, value):
|
|
self._do_request('PUT', self.path_key % locals(), value)
|
|
|
|
def get_key(self, dpid, key):
|
|
return self._do_request_read('GET', self.path_key % locals())
|
|
|
|
def delete_key(self, dpid, key):
|
|
self._do_request('DELETE', self.path_key % locals())
|
|
|
|
|
|
SwitchConfClient = SwitchConfClientV1_0
|
|
|
|
|
|
class QuantumIfaceClientV1_0(RyuClientBase):
|
|
version = 'v1.0'
|
|
|
|
# /quantum/ports
|
|
# /quantum/ports/{iface_id}
|
|
# /quantum/ports/{iface_id}/keys/
|
|
# /quantum/ports/{iface_id}/keys/{key}/{value}
|
|
path_quantum_ports = 'quantum/ports'
|
|
path_iface_id = path_quantum_ports + '/%(iface_id)s'
|
|
path_keys = path_iface_id + '/keys'
|
|
path_key = path_keys + '/%(key)s'
|
|
path_value = path_key + '/%(value)s'
|
|
|
|
def __init__(self, address):
|
|
super(QuantumIfaceClientV1_0, self).__init__(self.version, address)
|
|
|
|
def list_ifaces(self):
|
|
return self._do_request_read('GET', self.path_quantum_ports)
|
|
|
|
def delete_iface(self, iface_id):
|
|
self._do_request('DELETE', self.path_iface_id % locals())
|
|
|
|
def list_keys(self, iface_id):
|
|
return self._do_request_read('GET', self.path_keys % locals())
|
|
|
|
def get_key(self, iface_id, key):
|
|
return self._do_request_read('GET', self.path_key % locals())
|
|
|
|
def create_key(self, iface_id, key, value):
|
|
self._do_request('POST', self.path_value % locals())
|
|
|
|
def update_key(self, iface_id, key, value):
|
|
self._do_request('PUT', self.path_value % locals())
|
|
|
|
# for convenience
|
|
def get_network_id(self, iface_id):
|
|
return self.get_key(iface_id, 'network_id')
|
|
|
|
def create_network_id(self, iface_id, network_id):
|
|
self.create_key(iface_id, 'network_id', network_id)
|
|
|
|
def update_network_id(self, iface_id, network_id):
|
|
self.update_key(iface_id, 'network_id', network_id)
|
|
|
|
|
|
QuantumIfaceClient = QuantumIfaceClientV1_0
|
|
|
|
|
|
class TopologyClientV1_0(RyuClientBase):
|
|
version = 'v1.0'
|
|
|
|
# /topology/switches
|
|
# /topology/switches/{dpid}
|
|
# /topology/links
|
|
# /topology/links/{dpid}
|
|
_path_switches = 'topology/switches'
|
|
_path_links = 'topology/links'
|
|
|
|
def __init__(self, address):
|
|
super(TopologyClientV1_0, self).__init__(self.version, address)
|
|
|
|
# dpid: string representation (see ryu.lib.dpid)
|
|
# if None, get all
|
|
def list_switches(self, dpid=None):
|
|
uri = self._path_switches
|
|
if dpid:
|
|
uri += '/%s' % (dpid)
|
|
|
|
return self._do_request('GET', uri)
|
|
|
|
# dpid: string representation (see ryu.lib.dpid)
|
|
# if None, get all
|
|
def list_links(self, dpid=None):
|
|
uri = self._path_links
|
|
if dpid:
|
|
uri += '/%s' % (dpid)
|
|
return self._do_request('GET', uri)
|
|
|
|
|
|
TopologyClient = TopologyClientV1_0
|