Hi All

When I am trying to run two REST applications - gui_topology.py and
tap_rest.py using ryu-manager, all REST API calls are failing.

ubuntu@sdnhubvm:~/ryu[20:46] (master)$ ./bin/ryu-manager
ryu/app/gui_topology/gui_topology.py ryu/app/sdnhub_apps/tap_rest.py
loading app ryu/app/gui_topology/gui_topology.py
loading app ryu/app/sdnhub_apps/tap_rest.py
loading app ryu.app.rest_topology
loading app ryu.app.ws_topology
loading app ryu.app.ofctl_rest
loading app ryu.controller.ofp_handler
instantiating app None of Switches
creating context switches
instantiating app None of DPSet
creating context dpset
creating context wsgi
instantiating app None of StarterTap
creating context tap
instantiating app ryu.controller.ofp_handler of OFPHandler
instantiating app ryu/app/gui_topology/gui_topology.py of GUIServerApp
instantiating app ryu.app.rest_topology of TopologyAPI
instantiating app ryu/app/sdnhub_apps/tap_rest.py of TapRestApi
instantiating app ryu.app.ofctl_rest of RestStatsApi
instantiating app ryu.app.ws_topology of WebSocketTopology
(3824) wsgi starting up on http://0.0.0.0:8080/
/home/ubuntu/ryu/ryu/topology/switches.py:478: UserWarning: Datapath#ports
is kept for compatibility with the previous openflow versions (< 1.3). This
not be updated by EventOFPPortStatus message. If you want to be updated,
you can use 'ryu.controller.dpset' or 'ryu.topology.switches'.
  for port in dp.ports.values():
(3824) accepted ('127.0.0.1', 55477)
127.0.0.1 - - [06/Apr/2017 20:47:23] "GET /v1.0/topology/switches HTTP/1.1"
404 352 0.014968
(3824) accepted ('127.0.0.1', 55478)
127.0.0.1 - - [06/Apr/2017 20:47:32] "GET /stats/switches HTTP/1.1" 404 344
0.002400
(3824) accepted ('127.0.0.1', 55479)
127.0.0.1 - - [06/Apr/2017 20:47:37] "POST /v1.0/tap/create HTTP/1.1" 404
345 0.001055

I have attached tap_rest.py file.

Can anyone help me on how to resolve this problem.

Best Regards
Phani
# Copyright (C) 2014 SDN Hub
#
# Licensed under the GNU GENERAL PUBLIC LICENSE, Version 3.
# You may not use this file except in compliance with this License.
# You may obtain a copy of the License at
#
#    http://www.gnu.org/licenses/gpl-3.0.txt
#
# 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.

import logging

import json
from webob import Response
import os
import mimetypes

from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller import dpset
from ryu.controller.handler import MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.ofproto import ofproto_v1_0
from ryu.ofproto import ofproto_v1_3
from ryu.lib import ofctl_v1_0
from ryu.lib import ofctl_v1_3
from ryu.app.wsgi import ControllerBase, WSGIApplication
from ryu.app.sdnhub_apps import tap
from ryu.ofproto import inet

LOG = logging.getLogger('ryu.app.sdnhub_apps.tap_rest')

# REST API
#
############# Configure tap
#
# get all taps
# GET /tap
#
# create tap filter
# POST /v1.0/tap/create
#
# delete tap filter
# DELETE /v1.0/tap/delete
#

import re, socket
def is_mac_valid(x):
    if re.match("[0-9a-f]{2}([-:])[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$", x.lower()):
        return True
    else:
        return False

def is_ip_valid(x):
    y = x.split('/')
    if len(y) > 2:
        return False
    try:
        socket.inet_aton(y[0])
        return True
    except socket.error:
       return False

class TapController(ControllerBase):
    def __init__(self, req, link, data, **config):
        super(TapController, self).__init__(req, link, data, **config)
        self.tap = data['tap']
        self.tap.dpset = data['dpset']

    def is_filter_data_valid(self, filter_data):
        if 'sources' not in filter_data:
            LOG.error('missing sources %s', filter_data)
            return False
        else:
            for source in filter_data['sources']:
                if 'dpid' not in source or 'port_no' not in source:
                    LOG.error('Invalid source description %s', source)
                    return False

        if 'sinks' not in filter_data:
            LOG.error('missing sinks %s', filter_data)
            return False
        else:
            for sink in filter_data['sinks']:
                if 'dpid' not in sink or 'port_no' not in sink:
                    LOG.error('Invalid source description %s', sink)
                    return False

        if 'fields' in filter_data:
            for key, val in filter_data['fields'].items():
                if key == 'dl_src' or key == 'dl_dst' or key == 'dl_host':
                    if not is_mac_valid(val):
                        LOG.error('Invalid MAC address in filter field %s=%s', 
key, val)
                        return False
                if key == 'nw_src' or key == 'nw_dst' or key == 'nw_host':
                    if 'dl_type' not in filter_data['fields']:
                        LOG.error('Ethertype is not set, but IP fields 
specified')
                        return False
                    if not is_ip_valid(val):
                        LOG.error('Invalid IP address in filter field %s=%s', 
key, val)
                        return False
                if key == 'tp_src' or key == 'tp_dst' or key == 'tp_port':
                    nw_proto = filter_data['fields']['nw_proto']
                    if nw_proto != inet.IPPROTO_TCP and nw_proto != 
inet.IPPROTO_UDP:
                        LOG.error('Non TCP/UDP packet specifies TP fields')
                        return False
                        
        return True

    def create_tap(self, req, **_kwargs):
        try:
            filter_data = eval(req.body)
            print filter_data
            if not self.is_filter_data_valid(filter_data):
                return Response(status=400)
        except SyntaxError:
            LOG.error('Invalid syntax %s', req.body)
            return Response(status=400)

        if self.tap.create_tap(filter_data):
            return Response(status=200,content_type='application/json',
                    body=json.dumps({'status':'success'}))
        else:
            LOG.error('Create tap failed')
            return Response(status=501)

    def delete_tap(self, req, **_kwargs):
        try:
            filter_data = eval(req.body)
            if not self.is_filter_data_valid(filter_data):
                return Response(status=400)
        except SyntaxError:
            LOG.error('Invalid syntax %s', req.body)

        self.tap.delete_tap(filter_data)
        return Response(status=200,content_type='application/json',
                    body=json.dumps({'status':'success'}))

class TapRestApi(app_manager.RyuApp):
    OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION,
                    ofproto_v1_3.OFP_VERSION]
    _CONTEXTS = {
        'dpset': dpset.DPSet,
        'wsgi': WSGIApplication,
        'tap': tap.StarterTap
    }

    def __init__(self, *args, **kwargs):
        super(TapRestApi, self).__init__(*args, **kwargs)
        self.dpset = kwargs['dpset']
        tap = kwargs['tap']
        wsgi = kwargs['wsgi']
        self.waiters = {}
        self.data = {}
        self.data['dpset'] = self.dpset
        self.data['waiters'] = self.waiters
        self.data['tap'] = tap

        wsgi.registory['TapController'] = self.data
        mapper = wsgi.mapper

        mapper.connect('tap', '/v1.0/tap/create',
                       controller=TapController, action='create_tap',
                       conditions=dict(method=['POST']))

        mapper.connect('tap', '/v1.0/tap/delete',
                       controller=TapController, action='delete_tap',
                       conditions=dict(method=['POST']))


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Ryu-devel mailing list
Ryu-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to