srikanth | 116e6e8 | 2014-08-19 07:22:37 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # |
| 3 | # Copyright (c) 2013 Big Switch Networks, Inc. |
| 4 | # |
| 5 | # Licensed under the Eclipse Public License, Version 1.0 (the |
| 6 | # "License"); you may not use this file except in compliance with the |
| 7 | # License. You may obtain a copy of the License at |
| 8 | # |
| 9 | # http://www.eclipse.org/legal/epl-v10.html |
| 10 | # |
| 11 | # Unless required by applicable law or agreed to in writing, software |
| 12 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| 14 | # implied. See the License for the specific language governing |
| 15 | # permissions and limitations under the License. |
| 16 | # |
| 17 | |
| 18 | """Polling interface for the polling services setup by the rest API""" |
| 19 | |
| 20 | import sys, os, time, random, json |
| 21 | |
| 22 | from packetstreamer import PacketStreamer |
| 23 | from packetstreamer.ttypes import * |
| 24 | |
| 25 | from thrift import Thrift |
| 26 | from thrift.transport import TSocket |
| 27 | from thrift.transport import TTransport |
| 28 | from thrift.protocol import TBinaryProtocol |
| 29 | |
| 30 | def sample_func(request, environ): |
| 31 | data = { |
| 32 | 'pid': os.getpid(), |
| 33 | 'random': int(random.random()*100), |
| 34 | } |
| 35 | |
| 36 | return { |
| 37 | 'status': '200 OK', |
| 38 | 'body': json.dumps(data), |
| 39 | 'headers': [('Content-type', 'application/json')], # list of tuples |
| 40 | } |
| 41 | |
| 42 | def getPackets_func(request, environ, sessionid): |
| 43 | retData = {} |
| 44 | |
| 45 | try: |
| 46 | # Make socket |
| 47 | transport = TSocket.TSocket('localhost', 9090) |
| 48 | # Buffering is critical. Raw sockets are very slow |
| 49 | transport = TTransport.TFramedTransport(transport) |
| 50 | # Wrap in a protocol |
| 51 | protocol = TBinaryProtocol.TBinaryProtocol(transport) |
| 52 | # Create a client to use the protocol encoder |
| 53 | client = PacketStreamer.Client(protocol) |
| 54 | # Connect! |
| 55 | transport.open() |
| 56 | |
| 57 | packets = client.getPackets(sessionid) |
| 58 | |
| 59 | # Close! |
| 60 | transport.close() |
| 61 | |
| 62 | retData = { |
| 63 | 'status': '200 OK', |
| 64 | 'body': json.dumps(packets), |
| 65 | 'headers': [('Content-type', 'application/json')], # list of tuples |
| 66 | } |
| 67 | |
| 68 | except Thrift.TException, tx: |
| 69 | retData = { |
| 70 | 'status': '500 Internal Server Error', |
| 71 | 'body': 'error: %s'%tx.message, |
| 72 | 'headers': [('Content-type', 'application/json')], # list of tuples |
| 73 | } |
| 74 | |
| 75 | return retData |
| 76 | |
| 77 | # The polling service |
| 78 | # The service is driven by the urlpatterns tuples that list the specific function |
| 79 | # to use for a matching pattern in URL. The pattern should not include initial '^/poll'. |
| 80 | # For Example: |
| 81 | # (r'^/sample', sample_func) |
| 82 | #from sdncon.rest.poll import sample_func |
| 83 | urlpatterns = [ |
| 84 | (r'^/packets/(?P<sessionid>[A-Za-z0-9_.\-]+)/?$', getPackets_func), |
| 85 | (r'^/sample', sample_func) |
| 86 | ] |
| 87 | |
| 88 | import re, wsgiref.util |
| 89 | |
| 90 | def compile_patterns(urlpatterns): |
| 91 | return map(lambda pat: (re.compile(pat[0]), pat[1]), urlpatterns) |
| 92 | |
| 93 | def main(environ, start_response): |
| 94 | patterns = compile_patterns(urlpatterns) |
| 95 | request = environ['PATH_INFO'] |
| 96 | response = None |
| 97 | status, body = '404 Not Found', 'Sorry, the requested resource "%s" was not found."' % request |
| 98 | headers = [] |
| 99 | for (pat, func) in patterns: |
| 100 | m = pat.match(request) |
| 101 | if m: |
| 102 | args = m.groups() |
| 103 | if args: |
| 104 | response = func(request, environ, *args) |
| 105 | else: |
| 106 | response = func(request, environ) |
| 107 | |
| 108 | status, body = response['status'], response['body'] |
| 109 | if 'headers' in response: |
| 110 | headers.extend(response['headers']) |
| 111 | break |
| 112 | if 'Cache-Control' not in headers: |
| 113 | headers.append(('Cache-Control', 'no-cache')) |
| 114 | if 'Content-type' not in headers: |
| 115 | headers.append(('Content-type', 'text/plain')) |
| 116 | if 'Content-Length' not in headers: |
| 117 | headers.append(('Content-Length', str(len(body)))) |
| 118 | start_response(status, headers) |
| 119 | return [body] |
| 120 | |
| 121 | if __name__ == "__main__": |
| 122 | def start_response(x, y): |
| 123 | print 'Status:', x |
| 124 | print 'Headers:', y |
| 125 | |
| 126 | print 'Sample', sample_func(None, None) |
| 127 | print 'Response:', main({'PATH_INFO':'/sample/100'}, start_response) |
| 128 | print 'Response:', main({'PATH_INFO':'/xsample/100'}, start_response) |