Max has submitted this change and it was merged. ( 
https://gerrit.osmocom.org/11952 )

Change subject: Move Trap class back to separate files
......................................................................

Move Trap class back to separate files

After further testing it turns out that Trap() have too many
implementation details which makes it cumbersome to be shared. Instead,
it's easier to make it into wrapper over shared functions.

Change-Id: I8a3c62bcdf4286f8127c5b6d8dee6d740aca23b9
---
M scripts/ctrl2cgi.py
M scripts/soap.py
2 files changed, 114 insertions(+), 15 deletions(-)

Approvals:
  Jenkins Builder: Verified
  Pau Espin Pedrol: Looks good to me, approved



diff --git a/scripts/ctrl2cgi.py b/scripts/ctrl2cgi.py
index 18cfdbe..843aeb9 100755
--- a/scripts/ctrl2cgi.py
+++ b/scripts/ctrl2cgi.py
@@ -22,14 +22,14 @@
  */
 """

-__version__ = "0.0.1" # bump this on every non-trivial change
+__version__ = "0.0.2" # bump this on every non-trivial change

 from twisted.internet import defer, reactor
 from osmopy.twisted_ipa import CTRL, IPAFactory, __version__ as 
twisted_ipa_version
 from osmopy.osmo_ipa import Ctrl
 from treq import post, collect
 from functools import partial
-from osmopy.trap_helper import Trap, reloader, debug_init
+from osmopy.trap_helper import reloader, debug_init, get_type, get_r, p_h, 
make_params
 from distutils.version import StrictVersion as V # FIXME: use 
NormalizedVersion from PEP-386 when available
 import argparse, datetime, signal, sys, os, logging, logging.handlers
 import hashlib
@@ -75,6 +75,61 @@
     #print('HASH: \nparams="%r"\ninput="%s" \nres="%s"' %(params, input, res))
     return res

+class Trap(CTRL):
+    """
+    TRAP handler (agnostic to factory's client object)
+    """
+    def ctrl_TRAP(self, data, op_id, v):
+        """
+        Parse CTRL TRAP and dispatch to appropriate handler after normalization
+        """
+        self.factory.log.debug('TRAP %s' % v)
+        t_type = get_type(v)
+        p = p_h(v)
+        method = getattr(self, 'handle_' + t_type.replace('-', ''), lambda *_: 
"Unhandled %s trap" % t_type)
+        method(p(1), p(3), p(5), p(7), get_r(v))
+
+    def ctrl_SET_REPLY(self, data, _, v):
+        """
+        Debug log for replies to our commands
+        """
+        self.factory.log.debug('SET REPLY %s' % v)
+
+    def ctrl_ERROR(self, data, op_id, v):
+        """
+        We want to know if smth went wrong
+        """
+        self.factory.log.debug('CTRL ERROR [%s] %s' % (op_id, v))
+
+    def connectionMade(self):
+        """
+        Logging wrapper, calling super() is necessary not to break 
reconnection logic
+        """
+        self.factory.log.info("Connected to CTRL@%s:%d" % (self.factory.host, 
self.factory.port))
+        super(CTRL, self).connectionMade()
+
+    @defer.inlineCallbacks
+    def handle_locationstate(self, net, bsc, bts, trx, data):
+        """
+        Handle location-state TRAP: parse trap content, build CGI Request and 
use treq's routines to post it while setting up async handlers
+        """
+        params = make_params(bsc, data)
+        self.factory.log.debug('location-state@%s.%s.%s.%s (%s) => %s' % (net, 
bsc, bts, trx, params['time_stamp'], data))
+        params['h'] = gen_hash(params, self.factory.secret_key)
+        d = post(self.factory.location, None, params=params)
+        d.addCallback(partial(handle_reply, self.transport.write, 
self.factory.log)) # treq's collect helper is handy to get all reply content at 
once using closure on ctx
+        d.addErrback(lambda e, bsc: self.factory.log.critical("HTTP POST error 
%s while trying to register BSC %s on %s" % (e, bsc, self.factory.location)), 
bsc) # handle HTTP errors
+        # Ensure that we run only limited number of requests in parallel:
+        yield self.factory.semaphore.acquire()
+        yield d # we end up here only if semaphore is available which means 
it's ok to fire the request without exceeding the limit
+        self.factory.semaphore.release()
+
+    def handle_notificationrejectionv1(self, net, bsc, bts, trx, data):
+        """
+        Handle notification-rejection-v1 TRAP: just an example to show how 
more message types can be handled
+        """
+        self.factory.log.debug('notification-rejection-v1@bsc-id %s => %s' % 
(bsc, data))
+

 class TrapFactory(IPAFactory):
     """
@@ -100,12 +155,6 @@
         self.log.setLevel(level)
         self.log.debug("Using IPA %s, CGI server: %s" % (Ctrl.version, 
self.location))

-    def prepare_params(bsc, lon, lat, fix, tstamp, oper, admin, policy):
-        params = {'bsc_id': bsc, 'lon': lon, 'lat': lat, 'position_validity': 
fix, 'time_stamp': tstamp, 'oper_status': oper, 'admin_status': admin, 
'policy_status': policy }
-        params['h'] = gen_hash(params, self.factory.secret_key)
-        d = post(self.factory.location, None, params=params)
-        d.addCallback(partial(handle_reply, self.transport.write, 
self.factory.log))
-        return d

 if __name__ == '__main__':
     p = argparse.ArgumentParser(description='Proxy between given GCI service 
and Osmocom CTRL protocol.')
diff --git a/scripts/soap.py b/scripts/soap.py
index 156157c..75acd89 100755
--- a/scripts/soap.py
+++ b/scripts/soap.py
@@ -30,7 +30,7 @@
 from treq import post, collect
 from suds.client import Client
 from functools import partial
-from osmopy.trap_helper import Trap, reloader, debug_init
+from osmopy.trap_helper import reloader, debug_init, get_type, get_r, p_h, 
make_params
 from distutils.version import StrictVersion as V # FIXME: use 
NormalizedVersion from PEP-386 when available
 import argparse, datetime, signal, sys, os, logging, logging.handlers

@@ -51,6 +51,62 @@
         f(m)


+class Trap(CTRL):
+    """
+    TRAP handler (agnostic to factory's client object)
+    """
+    def ctrl_TRAP(self, data, op_id, v):
+        """
+        Parse CTRL TRAP and dispatch to appropriate handler after normalization
+        """
+        self.factory.log.debug('TRAP %s' % v)
+        t_type = get_type(v)
+        p = p_h(v)
+        method = getattr(self, 'handle_' + t_type.replace('-', ''), lambda *_: 
"Unhandled %s trap" % t_type)
+        method(p(1), p(3), p(5), p(7), get_r(v))
+
+    def ctrl_SET_REPLY(self, data, _, v):
+        """
+        Debug log for replies to our commands
+        """
+        self.factory.log.debug('SET REPLY %s' % v)
+
+    def ctrl_ERROR(self, data, op_id, v):
+        """
+        We want to know if smth went wrong
+        """
+        self.factory.log.debug('CTRL ERROR [%s] %s' % (op_id, v))
+
+    def connectionMade(self):
+        """
+        Logging wrapper, calling super() is necessary not to break 
reconnection logic
+        """
+        self.factory.log.info("Connected to CTRL@%s:%d" % (self.factory.host, 
self.factory.port))
+        super(CTRL, self).connectionMade()
+
+    @defer.inlineCallbacks
+    def handle_locationstate(self, net, bsc, bts, trx, data):
+        """
+        Handle location-state TRAP: parse trap content, build SOAP context and 
use treq's routines to post it while setting up async handlers
+        """
+        params = make_params(bsc, data)
+        self.factory.log.debug('location-state@%s.%s.%s.%s (%s) => %s' % (net, 
bsc, bts, trx, params['time_stamp'], data))
+        ctx = self.factory.client.registerSiteLocation(bsc, 
float(params['lon']), float(params['lat']), params['position_validity'], 
params['time_stamp'], params['oper_status'], params['admin_status'], 
params['policy_status'])
+        d = post(self.factory.location, ctx.envelope)
+        d.addCallback(collect, partial(handle_reply, ctx.process_reply, 
self.transport.write, self.factory.log)) # treq's collect helper is handy to 
get all reply content at once using closure on ctx
+        d.addErrback(lambda e, bsc: self.factory.log.critical("HTTP POST error 
%s while trying to register BSC %s on %s" % (e, bsc, self.factory.location)), 
bsc) # handle HTTP errors
+        # Ensure that we run only limited number of requests in parallel:
+        yield self.factory.semaphore.acquire()
+        yield d # we end up here only if semaphore is available which means 
it's ok to fire the request without exceeding the limit
+        self.factory.semaphore.release()
+
+    def handle_notificationrejectionv1(self, net, bsc, bts, trx, data):
+        """
+        Handle notification-rejection-v1 TRAP: just an example to show how 
more message types can be handled
+        """
+        self.factory.log.debug('notification-rejection-v1@bsc-id %s => %s' % 
(bsc, data))
+
+
 class TrapFactory(IPAFactory):
     """
     Store SOAP client object so TRAP handler can use it for requests
@@ -75,12 +131,6 @@
         self.log.setLevel(level)
         self.log.debug("Using IPA %s, SUDS client: %s" % (Ctrl.version, soap))

-    def prepare_params(bsc, lon, lat, fix, tstamp, oper, admin, policy):
-        ctx = self.factory.client.registerSiteLocation(bsc, float(lon), 
float(lat), fix, tstamp, oper, admin, policy)
-        d = post(self.factory.location, ctx.envelope)
-         # treq's collect helper is handy to get all reply content at once 
using closure on ctx:
-        d.addCallback(collect, partial(handle_reply, ctx.process_reply, 
self.transport.write, self.factory.log))
-        return d

 if __name__ == '__main__':
     p = argparse.ArgumentParser(description='Proxy between given SOAP service 
and Osmocom CTRL protocol.')

--
To view, visit https://gerrit.osmocom.org/11952
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: python/osmo-python-tests
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: I8a3c62bcdf4286f8127c5b6d8dee6d740aca23b9
Gerrit-Change-Number: 11952
Gerrit-PatchSet: 2
Gerrit-Owner: Max <msur...@sysmocom.de>
Gerrit-Reviewer: Harald Welte <lafo...@gnumonks.org>
Gerrit-Reviewer: Jenkins Builder (1000002)
Gerrit-Reviewer: Max <msur...@sysmocom.de>
Gerrit-Reviewer: Pau Espin Pedrol <pes...@sysmocom.de>
Gerrit-Reviewer: daniel <dwillm...@sysmocom.de>

Reply via email to