fix container image and use latest code
[samplevnf.git] / VNFs / DPPD-PROX / helper-scripts / rapid / prox_ctrl.py
index 586731e..40375c5 100644 (file)
@@ -25,7 +25,7 @@ import os
 import time
 import subprocess
 import socket
-from rapid_log import RapidLog 
+from rapid_log import RapidLog
 
 class prox_ctrl(object):
     def __init__(self, ip, key=None, user=None):
@@ -53,12 +53,12 @@ class prox_ctrl(object):
                 self.test_connect()
                 break
             except RuntimeWarning as ex:
+                RapidLog.debug("RuntimeWarning %d:\n%s"
+                    % (ex.returncode, ex.output.strip()))
                 attempts += 1
                 if attempts > 20:
                     RapidLog.exception("Failed to connect to instance after %d\
                             attempts:\n%s" % (attempts, ex))
-                    raise Exception("Failed to connect to instance after %d \
-                            attempts:\n%s" % (attempts, ex))
                 time.sleep(2)
                 RapidLog.debug("Trying to connect to machine \
                        on %s, attempt: %d" % (self._ip, attempts))
@@ -77,8 +77,6 @@ class prox_ctrl(object):
             if attempts > 20:
                 RapidLog.exception("Failed to connect to PROX on %s after %d \
                         attempts" % (self._ip, attempts))
-                raise Exception("Failed to connect to PROX on %s after %d \
-                        attempts" % (self._ip, attempts))
             time.sleep(2)
             RapidLog.debug("Trying to connect to PROX (just launched) on %s, \
                     attempt: %d" % (self._ip, attempts))
@@ -99,10 +97,7 @@ class prox_ctrl(object):
         try:
             return subprocess.check_output(cmd, stderr=subprocess.STDOUT)
         except subprocess.CalledProcessError as ex:
-            #if _connect and ex.returncode == 255:
-            if _connect:
-                raise RuntimeWarning(ex.output.strip())
-            raise RuntimeError('ssh returned exit status %d:\n%s'
+            RapidLog.exception('ssh returned exit status %d:\n%s'
                     % (ex.returncode, ex.output.strip()))
 
     def prox_sock(self, port=8474):
@@ -137,7 +132,7 @@ class prox_ctrl(object):
             # Actually ignore output on success, but capture stderr on failure
             subprocess.check_output(cmd, stderr=subprocess.STDOUT)
         except subprocess.CalledProcessError as ex:
-            raise RuntimeError('scp returned exit status %d:\n%s'
+            RapidLog.exception('scp returned exit status %d:\n%s'
                     % (ex.returncode, ex.output.strip()))
 
     def scp_get(self, src, dst):
@@ -159,7 +154,7 @@ class prox_ctrl(object):
             # Actually ignore output on success, but capture stderr on failure
             subprocess.check_output(cmd, stderr=subprocess.STDOUT)
         except subprocess.CalledProcessError as ex:
-            raise RuntimeError('scp returned exit status %d:\n%s'
+            RapidLog.exception('scp returned exit status %d:\n%s'
                     % (ex.returncode, ex.output.strip()))
 
     def _build_ssh(self, command):
@@ -183,9 +178,8 @@ class prox_sock(object):
         self._sock = sock
         self._rcvd = b''
 
-    def quit(self):
+    def __del__(self):
         if self._sock is not None:
-            self._send('quit')
             self._sock.close()
             self._sock = None
 
@@ -204,10 +198,14 @@ class prox_sock(object):
         self._send('reset stats')
 
     def lat_stats(self, cores, tasks=[0]):
-        min_lat = 999999999
-        max_lat = avg_lat = 0
+        result = {}
+        result['lat_min'] = 999999999
+        result['lat_max'] = result['lat_avg'] = 0
+        result['buckets'] = [0] * 128
+        result['mis_ordered'] = 0
+        result['extent'] = 0
+        result['duplicate'] = 0
         number_tasks_returning_stats = 0
-        buckets = [0] * 128
         self._send('lat all stats %s %s' % (','.join(map(str, cores)),
             ','.join(map(str, tasks))))
         for core in cores:
@@ -220,37 +218,42 @@ class prox_sock(object):
                         (potential incompatibility between scripts and PROX)")
                 raise Exception("lat stats error")
             number_tasks_returning_stats += 1
-            min_lat = min(int(stats[0]),min_lat)
-            max_lat = max(int(stats[1]),max_lat)
-            avg_lat += int(stats[2])
+            result['lat_min'] = min(int(stats[0]),result['lat_min'])
+            result['lat_max'] = max(int(stats[1]),result['lat_max'])
+            result['lat_avg'] += int(stats[2])
             #min_since begin = int(stats[3])
             #max_since_begin = int(stats[4])
-            tsc = int(stats[5]) # Taking the last tsc as the timestamp since
-                                # PROX will return the same tsc for each 
-                                # core/task combination 
-            hz = int(stats[6])
+            result['lat_tsc'] = int(stats[5])
+            # Taking the last tsc as the timestamp since
+            # PROX will return the same tsc for each
+            # core/task combination
+            result['lat_hz'] = int(stats[6])
             #coreid = int(stats[7])
             #taskid = int(stats[8])
+            result['mis_ordered'] += int(stats[9])
+            result['extent'] += int(stats[10])
+            result['duplicate'] += int(stats[11])
             stats = self._recv().split(':')
             if stats[0].startswith('error'):
                 RapidLog.critical("lat stats error: unexpected lat bucket \
                         reply (potential incompatibility between scripts \
                         and PROX)")
                 raise Exception("lat bucket reply error")
-            buckets[0] = int(stats[1])
+            result['buckets'][0] = int(stats[1])
             for i in range(1, 128):
                 stats = self._recv().split(':')
-                buckets[i] = int(stats[1])
-        avg_lat = old_div(avg_lat,number_tasks_returning_stats)
+                result['buckets'][i] += int(stats[1])
+        result['lat_avg'] = old_div(result['lat_avg'],
+                number_tasks_returning_stats)
         self._send('stats latency(0).used')
         used = float(self._recv())
         self._send('stats latency(0).total')
         total = float(self._recv())
-        return (min_lat, max_lat, avg_lat, (old_div(used,total)), tsc, hz,
-                buckets)
+        result['lat_used'] = old_div(used,total)
+        return (result)
 
     def irq_stats(self, core, bucket, task=0):
-        self._send('stats task.core(%s).task(%s).irq(%s)' % 
+        self._send('stats task.core(%s).task(%s).irq(%s)' %
                 (core, task, bucket))
         stats = self._recv().split(',')
         return int(stats[0])
@@ -264,12 +267,12 @@ class prox_sock(object):
 
     def core_stats(self, cores, tasks=[0]):
         rx = tx = drop = tsc = hz = rx_non_dp = tx_non_dp = tx_fail = 0
-        self._send('dp core stats %s %s' % (','.join(map(str, cores)), 
+        self._send('dp core stats %s %s' % (','.join(map(str, cores)),
             ','.join(map(str, tasks))))
         for core in cores:
             for task in tasks:
                 stats = self._recv().split(',')
-                if stats[0].startswith('error'):  
+                if stats[0].startswith('error'):
                     if stats[0].startswith('error: invalid syntax'):
                         RapidLog.critical("dp core stats error: unexpected \
                                 invalid syntax (potential incompatibility \
@@ -290,7 +293,7 @@ class prox_sock(object):
         rx = tx = port_id = tsc = no_mbufs = errors = 0
         self._send('multi port stats %s' % (','.join(map(str, ports))))
         result = self._recv().split(';')
-        if result[0].startswith('error'):  
+        if result[0].startswith('error'):
             RapidLog.critical("multi port stats error: unexpected invalid \
                     syntax (potential incompatibility between scripts and \
                     PROX)")
@@ -306,35 +309,46 @@ class prox_sock(object):
         return rx, tx, no_mbufs, errors, tsc
 
     def set_random(self, cores, task, offset, mask, length):
-        self._send('set random %s %s %s %s %s' % (','.join(map(str, cores)), 
+        self._send('set random %s %s %s %s %s' % (','.join(map(str, cores)),
             task, offset, mask, length))
 
     def set_size(self, cores, task, pkt_size):
-        self._send('pkt_size %s %s %s' % (','.join(map(str, cores)), task, 
+        self._send('pkt_size %s %s %s' % (','.join(map(str, cores)), task,
             pkt_size))
 
     def set_imix(self, cores, task, imix):
-        self._send('imix %s %s %s' % (','.join(map(str, cores)), task, 
+        self._send('imix %s %s %s' % (','.join(map(str, cores)), task,
             ','.join(map(str,imix))))
 
     def set_value(self, cores, task, offset, value, length):
-        self._send('set value %s %s %s %s %s' % (','.join(map(str, cores)), 
+        self._send('set value %s %s %s %s %s' % (','.join(map(str, cores)),
             task, offset, value, length))
 
+    def quit_prox(self):
+        self._send('quit')
+
     def _send(self, cmd):
         """Append LF and send command to the PROX instance."""
         if self._sock is None:
             raise RuntimeError("PROX socket closed, cannot send '%s'" % cmd)
-        self._sock.sendall(cmd.encode() + b'\n')
+        try:
+            self._sock.sendall(cmd.encode() + b'\n')
+        except ConnectionResetError as e:
+            RapidLog.error('Pipe reset by Prox instance: traffic too high?')
+            raise
 
     def _recv(self):
         """Receive response from PROX instance, return it with LF removed."""
         if self._sock is None:
             raise RuntimeError("PROX socket closed, cannot receive anymore")
-        pos = self._rcvd.find(b'\n')
-        while pos == -1:
-            self._rcvd += self._sock.recv(256)
+        try:
             pos = self._rcvd.find(b'\n')
-        rsp = self._rcvd[:pos]
-        self._rcvd = self._rcvd[pos+1:]
+            while pos == -1:
+                self._rcvd += self._sock.recv(256)
+                pos = self._rcvd.find(b'\n')
+            rsp = self._rcvd[:pos]
+            self._rcvd = self._rcvd[pos+1:]
+        except ConnectionResetError as e:
+            RapidLog.error('Pipe reset by Prox instance: traffic too high?')
+            raise
         return rsp.decode()