refactored codes, added standalone CLI client, option of interactive vs. standalone CLI 03/14803/1
authorUlas Kozat <ulas.kozat@gmail.com>
Sat, 28 May 2016 06:26:54 +0000 (23:26 -0700)
committerUlas Kozat <ulas.kozat@gmail.com>
Sat, 28 May 2016 06:26:54 +0000 (23:26 -0700)
Change-Id: I262aaf4f5908c0d9b7eae87699c49ba385437589
Signed-off-by: Ulas Kozat <ulas.kozat@gmail.com>
15 files changed:
DominoClient.py
DominoServer.py
README.md
domino-cli.py [new file with mode: 0755]
domino-cli.thrift [new file with mode: 0644]
domino_conf.py
lib/dominoCLI/DominoClientCLI-remote [new file with mode: 0755]
lib/dominoCLI/DominoClientCLI.py [new file with mode: 0644]
lib/dominoCLI/DominoClientCLI.pyc [new file with mode: 0644]
lib/dominoCLI/__init__.py [new file with mode: 0644]
lib/dominoCLI/__init__.pyc [new file with mode: 0644]
lib/dominoCLI/constants.py [new file with mode: 0644]
lib/dominoCLI/constants.pyc [new file with mode: 0644]
lib/dominoCLI/ttypes.py [new file with mode: 0644]
lib/dominoCLI/ttypes.pyc [new file with mode: 0644]

index 51a765b..c0a3cf1 100755 (executable)
@@ -24,6 +24,10 @@ from dominoRPC import Communication
 from dominoRPC.ttypes import *
 from dominoRPC.constants import *
 
+from dominoCLI import DominoClientCLI
+from dominoCLI.ttypes import *
+from dominoCLI.constants import *
+
 from thrift import Thrift
 from thrift.transport import TSocket
 from thrift.transport import TTransport
@@ -40,7 +44,6 @@ class CommunicationHandler:
     self.log = {}
 
   def __init__(self, dominoclient):
-    global DOMINO_SERVER_IP, DOMINO_SERVER_PORT
     self.log = {}
     self.dominoClient = dominoclient
     try:
@@ -96,6 +99,24 @@ class CommunicationHandler:
 
   def closeconnection():
     self.transport.close()
+
+class CLIHandler:
+  def __init__(self):
+    self.log = {}
+
+  def __init__(self, dominoclient, CLIservice):
+    self.log = {}
+    self.dominoClient = dominoclient
+    self.CLIservice = CLIservice
+
+  def d_CLI(self, msg):
+    logging.info('Received CLI %s', msg.CLI_input)
+
+    self.CLIservice.process_input(msg.CLI_input)
+    
+    CLIrespmsg = CLIResponse()
+    CLIrespmsg.CLI_response = "Testing..."
+    return CLIrespmsg
  
 def read_templatefile(temp_filename): 
   f = open(temp_filename, 'r')
@@ -104,108 +125,79 @@ def read_templatefile(temp_filename):
   return lines
 
 class DominoClientCLIService(threading.Thread):
-  def __init__(self, dominoclient, communicationhandler):
+  def __init__(self, dominoclient, communicationhandler, interactive):
     threading.Thread.__init__(self)
     self.dominoclient = dominoclient
     self.communicationhandler = communicationhandler
+    self.interactive = interactive
+
+  def process_input(self, args):
+        
+    try:
+      if args[0] == 'heartbeat':
+        self.dominoclient.heartbeat()
+
+      elif args[0] == 'publish':
+        opts, args = getopt.getopt(args[1:],"t:",["tosca-file="])
+        if len(opts) == 0:
+         print '\nUsage: publish -t <toscafile>'
+         return
+
+        for opt, arg in opts:
+         if opt in ('-t', '--tosca-file'):
+           toscafile = arg
+       
+        self.dominoclient.publish(toscafile)
+
+      elif args[0] == 'subscribe':
+        labels = []    
+        templateTypes = []
+        opts, args = getopt.getopt(args[1:],"l:t:",["labels=","ttype="])
+        for opt, arg in opts:
+         if opt in ('-l', '--labels'):
+           labels = labels + arg.split(',')
+         elif opt in ('-t', '--ttype'):
+           templateTypes = templateTypes + arg.split(',')    
+
+        #check if labels or supported templates are nonempty
+        if labels != [] or templateTypes != []:
+          self.dominoclient.subscribe(labels, templateTypes)
+
+      elif args[0] == 'register':
+        self.dominoclient.start()
+
+    except getopt.GetoptError:
+      print 'Command is misentered or not supported!'
+
 
   def run(self):
     global DEFAULT_TOSCA_PUBFILE
-    while True:
-       sys.stdout.write('>>')
-       input_string = raw_input()
-       args = input_string.split()
-       if len(args) == 0:
-         continue
-
-       labels = []       
-       templateTypes = []
-
-       #process input arguments
-       try:
+    if self.interactive == "TRUE":
+      flag = True
+    else:
+      flag = False
+
+    if flag: #interactive CLI, loop in while until killed
+      while True:
+        sys.stdout.write('>>')
+        input_string = raw_input()
+        args = input_string.split()
+        if len(args) == 0:
+          continue
+
          sys.stdout.write('>>')
-         if args[0] == 'heartbeat':
-           logging.info('%d Sending heatbeat', self.dominoclient.UDID)
-           hbm = HeartBeatMessage()
-           hbm.domino_udid = self.dominoclient.UDID
-           hbm.seq_no = self.dominoclient.seqno
-           try:
-             hbm_r = self.communicationhandler.sender.d_heartbeat(hbm)
-             logging.info('heart beat received from: %d ,sequence number: %d' , hbm_r.domino_udid, hbm_r.seq_no)
-           except (Thrift.TException, TSocket.TTransportException) as tx:
-             logging.error('%s' , tx.message)
-           except (socket.timeout) as tx:
-             self.dominoclient.handle_RPC_timeout(hbm)
-           except:
-             logging.error('Unexpected error: %s', sys.exc_info()[0])
-           self.dominoclient.seqno = self.dominoclient.seqno + 1
-         
-         elif args[0] == 'publish':
-           opts, args = getopt.getopt(args[1:],"t:",["tosca-file="])
-           if len(opts) == 0:
-             print '\nUsage: publish -t <toscafile>'
-             continue
-
-           #toscafile = DEFAULT_TOSCA_PUBFILE
-           for opt, arg in opts:
-             if opt in ('-t', '--tosca-file'):
-               toscafile = arg
-           
-           pub_msg = PublishMessage()
-           pub_msg.domino_udid = self.dominoclient.UDID
-           pub_msg.seq_no = self.dominoclient.seqno
-           pub_msg.template_type = 'tosca-nfv-v1.0'
-           try:
-             pub_msg.template = read_templatefile(toscafile)
-           except IOError as e:
-             logging.error('I/O error(%d): %s' , e.errno, e.strerror)
-             continue
-           logging.info('Publishing the template file: ' + toscafile)
-           try:
-             pub_msg_r = self.communicationhandler.sender.d_publish(pub_msg)
-             logging.info('Publish Response is received from: %d ,sequence number: %d', pub_msg_r.domino_udid, pub_msg_r.seq_no)
-           except (Thrift.TException, TSocket.TTransportException) as tx:
-             print '%s' % (tx.message)
-           except (socket.timeout) as tx:
-             self.dominoclient.handle_RPC_timeout(pub_msg)
-
-           self.dominoclient.seqno = self.dominoclient.seqno + 1
-       
-         elif args[0] == 'subscribe':         
-           opts, args = getopt.getopt(args[1:],"l:t:",["labels=","ttype="])
-           for opt, arg in opts:
-              if opt in ('-l', '--labels'):
-                 labels = labels + arg.split(',')
-              elif opt in ('-t', '--ttype'):
-                 templateTypes = templateTypes + arg.split(',')
-         
-         elif args[0] == 'register':
-           self.dominoclient.start()
-  
-       except getopt.GetoptError:
-         print 'Command is misentered or not supported!'
-
-
-       #check if labels or supported templates are nonempty
-       if labels != [] or templateTypes != []:
-         #send subscription message
-         sub_msg = SubscribeMessage()
-         sub_msg.domino_udid = self.dominoclient.UDID
-         sub_msg.seq_no = self.dominoclient.seqno
-         sub_msg.template_op = APPEND
-         sub_msg.supported_template_types = templateTypes
-         sub_msg.label_op = APPEND
-         sub_msg.labels = labels
-         logging.info('subscribing labels %s and templates %s', labels, templateTypes)
-         try:
-           sub_msg_r = self.communicationhandler.sender.d_subscribe(sub_msg) 
-           logging.info('Subscribe Response is received from: %d ,sequence number: %d', sub_msg_r.domino_udid,sub_msg_r.seq_no)
-         except (Thrift.TException, TSocket.TTransportException) as tx:
-           logging.error('%s' , tx.message)
-         except (socket.timeout) as tx:
-           self.dominoclient.handle_RPC_timeout(sub_msg)
-
-         self.dominoclient.seqno = self.dominoclient.seqno + 1
+        #process input arguments
+         self.process_input(args)
+    else: #domino cli-client is used, listen for the CLI rpc calls
+      cliHandler = CLIHandler(self.dominoclient, self)
+      processor = DominoClientCLI.Processor(cliHandler)
+      transport = TSocket.TServerSocket(port=self.dominoclient.CLIport)
+      tfactory = TTransport.TBufferedTransportFactory()
+      pfactory = TBinaryProtocol.TBinaryProtocolFactory()
+      #Use TThreadedServer or TThreadPoolServer for a multithreaded server
+      CLIServer = TServer.TSimpleServer(processor, transport, tfactory, pfactory)
+      logging.debug('RPC service for CLI is starting...')
+      CLIServer.serve()       
 
 class DominoClient:
   def __init__(self):
@@ -216,11 +208,13 @@ class DominoClient:
     self.pfactory = None
     self.communicationServer = None
 
-    self.CLIservice = DominoClientCLIService(self, self.communicationHandler)
+    self.CLIservice = None
 
     self.serviceport = 9091
     self.dominoserver_IP = 'localhost'
 
+    self.CLIport = DOMINO_CLI_PORT 
+
     #Start from UNREGISTERED STATE
     #TO BE DONE: initialize from a saved state
     self.state = 'UNREGISTERED'
@@ -247,6 +241,7 @@ class DominoClient:
    
   def register(self):  
     if self.state == 'UNREGISTERED':
+      logging.info('%d Sending Registration', self.UDID)
       #prepare registration message
       reg_msg = RegisterMessage()
       reg_msg.domino_udid_desired = UDID_DESIRED
@@ -275,6 +270,75 @@ class DominoClient:
         logging.error('%s' , tx.message)
       self.seqno = self.seqno + 1
 
+  def heartbeat(self):
+    if self.state == 'UNREGISTERED':
+      self.start()
+          
+    logging.info('%d Sending heartbeat', self.UDID)
+    hbm = HeartBeatMessage()         
+    hbm.domino_udid = self.UDID        
+    hbm.seq_no = self.seqno         
+
+    try:
+      hbm_r = self.sender().d_heartbeat(hbm)
+      logging.info('heart beat received from: %d ,sequence number: %d' , hbm_r.domino_udid, hbm_r.seq_no)
+    except (Thrift.TException, TSocket.TTransportException) as tx:
+      logging.error('%s' , tx.message)
+    except (socket.timeout) as tx:
+      self.handle_RPC_timeout(hbm)
+    except:
+      logging.error('Unexpected error: %s', sys.exc_info()[0])
+    
+    self.seqno = self.seqno + 1    
+
+  def publish(self, toscafile):
+    if self.state == 'UNREGISTERED':
+      self.start()
+
+    logging.info('Publishing the template file: ' + toscafile)
+    pub_msg = PublishMessage()
+    pub_msg.domino_udid = self.UDID
+    pub_msg.seq_no = self.seqno
+    pub_msg.template_type = 'tosca-nfv-v1.0'
+
+    try:
+      pub_msg.template = read_templatefile(toscafile)
+    except IOError as e:
+      logging.error('I/O error(%d): %s' , e.errno, e.strerror)
+      return
+    try:
+      pub_msg_r = self.sender().d_publish(pub_msg)
+      logging.info('Publish Response is received from: %d ,sequence number: %d', pub_msg_r.domino_udid, pub_msg_r.seq_no)
+    except (Thrift.TException, TSocket.TTransportException) as tx:
+      print '%s' % (tx.message)
+    except (socket.timeout) as tx:
+      self.handle_RPC_timeout(pub_msg)
+
+    self.seqno = self.seqno + 1
+
+  def subscribe(self, labels, templateTypes):
+     if self.state == 'UNREGISTERED':
+       self.start()
+
+     logging.info('subscribing labels %s and templates %s', labels, templateTypes)
+     #send subscription message
+     sub_msg = SubscribeMessage()
+     sub_msg.domino_udid = self.UDID
+     sub_msg.seq_no = self.seqno
+     sub_msg.template_op = APPEND
+     sub_msg.supported_template_types = templateTypes
+     sub_msg.label_op = APPEND
+     sub_msg.labels = labels
+     try:
+       sub_msg_r = self.sender().d_subscribe(sub_msg)
+       logging.info('Subscribe Response is received from: %d ,sequence number: %d', sub_msg_r.domino_udid,sub_msg_r.seq_no)
+     except (Thrift.TException, TSocket.TTransportException) as tx: 
+       logging.error('%s' , tx.message)
+     except (socket.timeout) as tx: 
+       self.handle_RPC_timeout(sub_msg)
+
+     self.seqno = self.seqno + 1 
+
   def stop(self):
     try:
       self.communicationHandler.closeconnection()
@@ -284,7 +348,8 @@ class DominoClient:
   def sender(self):
     return self.communicationHandler.sender
 
-  def startCLI(self):
+  def startCLI(self, interactive):
+    self.CLIservice = DominoClientCLIService(self, self.communicationHandler, interactive)
     logging.info('CLI Service is starting')
     self.CLIservice.start()
     #to wait until CLI service is finished
@@ -293,6 +358,9 @@ class DominoClient:
   def set_serviceport(self, port):
     self.serviceport = port
 
+  def set_CLIport(self, cliport):
+    self.CLIport = cliport
+
   def set_dominoserver_ipaddr(self, ipaddr):
     self.dominoserver_IP = ipaddr
 
@@ -312,15 +380,16 @@ class DominoClient:
 def main(argv):
   client = DominoClient()
   loglevel = 'WARNING'
+  interactive = "FALSE"
   #process input arguments
   try:
-      opts, args = getopt.getopt(argv,"hc:p:i:l:",["conf=","port=","ipaddr=","log="])
+      opts, args = getopt.getopt(argv,"hc:p:i:l:",["conf=","port=","ipaddr=","log=","iac=","cliport="])
   except getopt.GetoptError:
-      print 'DominoClient.py -c/--conf <configfile> -p/--port <socketport> -i/--ipaddr <IPaddr> -l/--log <loglevel>'
+      print 'DominoClient.py -c/--conf <configfile> -p/--port <socketport> -i/--ipaddr <IPaddr> -l/--log <loglevel> --iac=true/false'
       sys.exit(2)
   for opt, arg in opts:
       if opt == '-h':
-         print 'DominoClient.py -c/--conf <configfile> -p/--port <socketport> -i/--ipaddr <IPaddr> -l/--log <loglevel>'
+         print 'DominoClient.py -c/--conf <configfile> -p/--port <socketport> -i/--ipaddr <IPaddr> -l/--log <loglevel> --iac=true/false'
          sys.exit()
       elif opt in ("-c", "--conf"):
          configfile = arg
@@ -328,8 +397,12 @@ def main(argv):
          client.set_serviceport(int(arg))
       elif opt in ("-i", "--ipaddr"):
          client.set_dominoserver_ipaddr(arg)
-      elif opt in ("--log"):
+      elif opt in ("-l", "--log"):
          loglevel = arg
+      elif opt in ("--iac"):
+         interactive = arg.upper()
+      elif opt in ("--cliport"):
+         client.set_CLIport(int(arg))
 
   #Set logging level
   numeric_level = getattr(logging, loglevel.upper(), None)
@@ -344,7 +417,7 @@ def main(argv):
   #The client is starting
   logging.debug('Domino Client Starting...')
   client.start()
-  client.startCLI()
+  client.startCLI(interactive)
   client.start_communicationService()
 
 if __name__ == "__main__":
index d056542..417144e 100755 (executable)
@@ -314,7 +314,7 @@ def main(argv):
          sys.exit()
       elif opt in ("-c", "--conf"):
          configfile = arg
-      elif opt in ("--log"):
+      elif opt in ("-l", "--log"):
          loglevel= arg
   #Set logging level
   numeric_level = getattr(logging, loglevel.upper(), None)
index 5120d0e..0ebf5e0 100644 (file)
--- a/README.md
+++ b/README.md
@@ -13,8 +13,10 @@ Tested on Ubuntu 14.04 and OS X El Capitan
 ###Start the first Domino Client:
     ./DominoClient.py -p 9091 --log=DEBUG
 
+Note: if --log option is ommitted, the default logging level is Warning messages
+
 ###Start the second Domino Client:
-    ./DominoClient.py -p 9092
+    ./DominoClient.py -p 9092 --log=DEBUG
 
 ##CLI at the Domino Client:
 
diff --git a/domino-cli.py b/domino-cli.py
new file mode 100755 (executable)
index 0000000..8768ea6
--- /dev/null
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+
+#Copyright 2015 Open Platform for NFV Project, Inc. and its contributors
+#   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 sys, glob, getopt
+
+sys.path.insert(0, glob.glob('./lib')[0])
+
+from dominoCLI import DominoClientCLI
+from dominoCLI.ttypes import *
+from dominoCLI.constants import *
+
+from thrift import Thrift
+from thrift.transport import TSocket
+from thrift.transport import TTransport
+from thrift.protocol import TBinaryProtocol
+
+#Load configuration parameters
+from domino_conf import *
+
+def main(argv):
+#  try:
+#    if argv[0] == 'heartbeat':
+#      print 'Heartbeat input'
+#  except IndexError as ex:
+#    print 'Insufficient number of arguments entered'
+#  except:
+#    print('Error: %s', sys.exc_info()[0])
+
+  try:
+    # Make socket
+    transport = TSocket.TSocket('localhost', DOMINO_CLI_PORT)
+    # Buffering is critical. Raw sockets are very slow
+    transport = TTransport.TBufferedTransport(transport)
+    # Wrap in a protocol
+    protocol = TBinaryProtocol.TBinaryProtocol(transport)
+
+    # Create a client to use the protocol encoder
+    client = DominoClientCLI.Client(protocol)
+
+    # Connect!
+    transport.open()
+
+    CLImsg = CLIMessage()
+    CLImsg.CLI_input = argv
+    CLIrespmsg = client.d_CLI(CLImsg)
+    print CLIrespmsg.CLI_response
+
+  except Thrift.TException, tx:
+    print '%s' % (tx.message)
+
+if __name__ == "__main__":
+   main(sys.argv[1:])
diff --git a/domino-cli.thrift b/domino-cli.thrift
new file mode 100644 (file)
index 0000000..e21c0ec
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * Thrift types:
+ *
+ *  bool        Boolean, one byte
+ *  byte        Signed byte
+ *  i16         Signed 16-bit integer
+ *  i32         Signed 32-bit integer
+ *  i64         Signed 64-bit integer
+ *  double      64-bit floating point value
+ *  string      String
+ *  binary      Blob (byte array)
+ *  map<t1,t2>  Map from one type to another
+ *  list<t1>    Ordered list of one type
+ *  set<t1>     Set of unique elements of one type
+ *
+ */
+
+
+namespace cpp dominoCLI
+namespace py dominoCLI
+namespace java dominoCLI
+
+
+/**
+* Domino sends periodic heartbeats from 
+* Domino Clients and Domino Server echos
+*/
+struct CLIMessage {
+ 1: list<string> CLI_input
+}
+
+struct CLIResponse {
+ 1: string CLI_response
+}
+
+service DominoClientCLI {
+
+   CLIResponse d_CLI(1:CLIMessage msg),
+}
index 3ce442b..f311d43 100644 (file)
@@ -6,6 +6,7 @@ CLIENT_SEQNO = 0
 
 DOMINO_SERVER_IP = 'localhost'
 DOMINO_SERVER_PORT = 9090
+DOMINO_CLI_PORT = 9100
 
 UDID_DESIRED = 12467
 LIST_SUPPORTED_TEMPLATES = ['tosca-nfv-v1.0']
diff --git a/lib/dominoCLI/DominoClientCLI-remote b/lib/dominoCLI/DominoClientCLI-remote
new file mode 100755 (executable)
index 0000000..da93c65
--- /dev/null
@@ -0,0 +1,94 @@
+#!/usr/bin/env python
+#
+# Autogenerated by Thrift Compiler (0.9.3)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+import sys
+import pprint
+from urlparse import urlparse
+from thrift.transport import TTransport
+from thrift.transport import TSocket
+from thrift.transport import TSSLSocket
+from thrift.transport import THttpClient
+from thrift.protocol import TBinaryProtocol
+
+from dominoCLI import DominoClientCLI
+from dominoCLI.ttypes import *
+
+if len(sys.argv) <= 1 or sys.argv[1] == '--help':
+  print('')
+  print('Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] [-s[sl]] function [arg1 [arg2...]]')
+  print('')
+  print('Functions:')
+  print('  CLIResponse d_CLI(CLIMessage msg)')
+  print('')
+  sys.exit(0)
+
+pp = pprint.PrettyPrinter(indent = 2)
+host = 'localhost'
+port = 9090
+uri = ''
+framed = False
+ssl = False
+http = False
+argi = 1
+
+if sys.argv[argi] == '-h':
+  parts = sys.argv[argi+1].split(':')
+  host = parts[0]
+  if len(parts) > 1:
+    port = int(parts[1])
+  argi += 2
+
+if sys.argv[argi] == '-u':
+  url = urlparse(sys.argv[argi+1])
+  parts = url[1].split(':')
+  host = parts[0]
+  if len(parts) > 1:
+    port = int(parts[1])
+  else:
+    port = 80
+  uri = url[2]
+  if url[4]:
+    uri += '?%s' % url[4]
+  http = True
+  argi += 2
+
+if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed':
+  framed = True
+  argi += 1
+
+if sys.argv[argi] == '-s' or sys.argv[argi] == '-ssl':
+  ssl = True
+  argi += 1
+
+cmd = sys.argv[argi]
+args = sys.argv[argi+1:]
+
+if http:
+  transport = THttpClient.THttpClient(host, port, uri)
+else:
+  socket = TSSLSocket.TSSLSocket(host, port, validate=False) if ssl else TSocket.TSocket(host, port)
+  if framed:
+    transport = TTransport.TFramedTransport(socket)
+  else:
+    transport = TTransport.TBufferedTransport(socket)
+protocol = TBinaryProtocol.TBinaryProtocol(transport)
+client = DominoClientCLI.Client(protocol)
+transport.open()
+
+if cmd == 'd_CLI':
+  if len(args) != 1:
+    print('d_CLI requires 1 args')
+    sys.exit(1)
+  pp.pprint(client.d_CLI(eval(args[0]),))
+
+else:
+  print('Unrecognized method %s' % cmd)
+  sys.exit(1)
+
+transport.close()
diff --git a/lib/dominoCLI/DominoClientCLI.py b/lib/dominoCLI/DominoClientCLI.py
new file mode 100644 (file)
index 0000000..c0d28c7
--- /dev/null
@@ -0,0 +1,241 @@
+#
+# Autogenerated by Thrift Compiler (0.9.3)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+from thrift.Thrift import TType, TMessageType, TException, TApplicationException
+import logging
+from ttypes import *
+from thrift.Thrift import TProcessor
+from thrift.transport import TTransport
+from thrift.protocol import TBinaryProtocol, TProtocol
+try:
+  from thrift.protocol import fastbinary
+except:
+  fastbinary = None
+
+
+class Iface:
+  def d_CLI(self, msg):
+    """
+    Parameters:
+     - msg
+    """
+    pass
+
+
+class Client(Iface):
+  def __init__(self, iprot, oprot=None):
+    self._iprot = self._oprot = iprot
+    if oprot is not None:
+      self._oprot = oprot
+    self._seqid = 0
+
+  def d_CLI(self, msg):
+    """
+    Parameters:
+     - msg
+    """
+    self.send_d_CLI(msg)
+    return self.recv_d_CLI()
+
+  def send_d_CLI(self, msg):
+    self._oprot.writeMessageBegin('d_CLI', TMessageType.CALL, self._seqid)
+    args = d_CLI_args()
+    args.msg = msg
+    args.write(self._oprot)
+    self._oprot.writeMessageEnd()
+    self._oprot.trans.flush()
+
+  def recv_d_CLI(self):
+    iprot = self._iprot
+    (fname, mtype, rseqid) = iprot.readMessageBegin()
+    if mtype == TMessageType.EXCEPTION:
+      x = TApplicationException()
+      x.read(iprot)
+      iprot.readMessageEnd()
+      raise x
+    result = d_CLI_result()
+    result.read(iprot)
+    iprot.readMessageEnd()
+    if result.success is not None:
+      return result.success
+    raise TApplicationException(TApplicationException.MISSING_RESULT, "d_CLI failed: unknown result")
+
+
+class Processor(Iface, TProcessor):
+  def __init__(self, handler):
+    self._handler = handler
+    self._processMap = {}
+    self._processMap["d_CLI"] = Processor.process_d_CLI
+
+  def process(self, iprot, oprot):
+    (name, type, seqid) = iprot.readMessageBegin()
+    if name not in self._processMap:
+      iprot.skip(TType.STRUCT)
+      iprot.readMessageEnd()
+      x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name))
+      oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid)
+      x.write(oprot)
+      oprot.writeMessageEnd()
+      oprot.trans.flush()
+      return
+    else:
+      self._processMap[name](self, seqid, iprot, oprot)
+    return True
+
+  def process_d_CLI(self, seqid, iprot, oprot):
+    args = d_CLI_args()
+    args.read(iprot)
+    iprot.readMessageEnd()
+    result = d_CLI_result()
+    try:
+      result.success = self._handler.d_CLI(args.msg)
+      msg_type = TMessageType.REPLY
+    except (TTransport.TTransportException, KeyboardInterrupt, SystemExit):
+      raise
+    except Exception as ex:
+      msg_type = TMessageType.EXCEPTION
+      logging.exception(ex)
+      result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error')
+    oprot.writeMessageBegin("d_CLI", msg_type, seqid)
+    result.write(oprot)
+    oprot.writeMessageEnd()
+    oprot.trans.flush()
+
+
+# HELPER FUNCTIONS AND STRUCTURES
+
+class d_CLI_args:
+  """
+  Attributes:
+   - msg
+  """
+
+  thrift_spec = (
+    None, # 0
+    (1, TType.STRUCT, 'msg', (CLIMessage, CLIMessage.thrift_spec), None, ), # 1
+  )
+
+  def __init__(self, msg=None,):
+    self.msg = msg
+
+  def read(self, iprot):
+    if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
+      fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
+      return
+    iprot.readStructBegin()
+    while True:
+      (fname, ftype, fid) = iprot.readFieldBegin()
+      if ftype == TType.STOP:
+        break
+      if fid == 1:
+        if ftype == TType.STRUCT:
+          self.msg = CLIMessage()
+          self.msg.read(iprot)
+        else:
+          iprot.skip(ftype)
+      else:
+        iprot.skip(ftype)
+      iprot.readFieldEnd()
+    iprot.readStructEnd()
+
+  def write(self, oprot):
+    if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
+      oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
+      return
+    oprot.writeStructBegin('d_CLI_args')
+    if self.msg is not None:
+      oprot.writeFieldBegin('msg', TType.STRUCT, 1)
+      self.msg.write(oprot)
+      oprot.writeFieldEnd()
+    oprot.writeFieldStop()
+    oprot.writeStructEnd()
+
+  def validate(self):
+    return
+
+
+  def __hash__(self):
+    value = 17
+    value = (value * 31) ^ hash(self.msg)
+    return value
+
+  def __repr__(self):
+    L = ['%s=%r' % (key, value)
+      for key, value in self.__dict__.iteritems()]
+    return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+  def __eq__(self, other):
+    return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+  def __ne__(self, other):
+    return not (self == other)
+
+class d_CLI_result:
+  """
+  Attributes:
+   - success
+  """
+
+  thrift_spec = (
+    (0, TType.STRUCT, 'success', (CLIResponse, CLIResponse.thrift_spec), None, ), # 0
+  )
+
+  def __init__(self, success=None,):
+    self.success = success
+
+  def read(self, iprot):
+    if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
+      fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
+      return
+    iprot.readStructBegin()
+    while True:
+      (fname, ftype, fid) = iprot.readFieldBegin()
+      if ftype == TType.STOP:
+        break
+      if fid == 0:
+        if ftype == TType.STRUCT:
+          self.success = CLIResponse()
+          self.success.read(iprot)
+        else:
+          iprot.skip(ftype)
+      else:
+        iprot.skip(ftype)
+      iprot.readFieldEnd()
+    iprot.readStructEnd()
+
+  def write(self, oprot):
+    if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
+      oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
+      return
+    oprot.writeStructBegin('d_CLI_result')
+    if self.success is not None:
+      oprot.writeFieldBegin('success', TType.STRUCT, 0)
+      self.success.write(oprot)
+      oprot.writeFieldEnd()
+    oprot.writeFieldStop()
+    oprot.writeStructEnd()
+
+  def validate(self):
+    return
+
+
+  def __hash__(self):
+    value = 17
+    value = (value * 31) ^ hash(self.success)
+    return value
+
+  def __repr__(self):
+    L = ['%s=%r' % (key, value)
+      for key, value in self.__dict__.iteritems()]
+    return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+  def __eq__(self, other):
+    return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+  def __ne__(self, other):
+    return not (self == other)
diff --git a/lib/dominoCLI/DominoClientCLI.pyc b/lib/dominoCLI/DominoClientCLI.pyc
new file mode 100644 (file)
index 0000000..0c01101
Binary files /dev/null and b/lib/dominoCLI/DominoClientCLI.pyc differ
diff --git a/lib/dominoCLI/__init__.py b/lib/dominoCLI/__init__.py
new file mode 100644 (file)
index 0000000..e52a87f
--- /dev/null
@@ -0,0 +1 @@
+__all__ = ['ttypes', 'constants', 'DominoClientCLI']
diff --git a/lib/dominoCLI/__init__.pyc b/lib/dominoCLI/__init__.pyc
new file mode 100644 (file)
index 0000000..dfa3544
Binary files /dev/null and b/lib/dominoCLI/__init__.pyc differ
diff --git a/lib/dominoCLI/constants.py b/lib/dominoCLI/constants.py
new file mode 100644 (file)
index 0000000..4a6492b
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Autogenerated by Thrift Compiler (0.9.3)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+from thrift.Thrift import TType, TMessageType, TException, TApplicationException
+from ttypes import *
+
diff --git a/lib/dominoCLI/constants.pyc b/lib/dominoCLI/constants.pyc
new file mode 100644 (file)
index 0000000..466e728
Binary files /dev/null and b/lib/dominoCLI/constants.pyc differ
diff --git a/lib/dominoCLI/ttypes.py b/lib/dominoCLI/ttypes.py
new file mode 100644 (file)
index 0000000..9794dba
--- /dev/null
@@ -0,0 +1,159 @@
+#
+# Autogenerated by Thrift Compiler (0.9.3)
+#
+# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+#
+#  options string: py
+#
+
+from thrift.Thrift import TType, TMessageType, TException, TApplicationException
+
+from thrift.transport import TTransport
+from thrift.protocol import TBinaryProtocol, TProtocol
+try:
+  from thrift.protocol import fastbinary
+except:
+  fastbinary = None
+
+
+
+class CLIMessage:
+  """
+  Domino sends periodic heartbeats from
+  Domino Clients and Domino Server echos
+
+  Attributes:
+   - CLI_input
+  """
+
+  thrift_spec = (
+    None, # 0
+    (1, TType.LIST, 'CLI_input', (TType.STRING,None), None, ), # 1
+  )
+
+  def __init__(self, CLI_input=None,):
+    self.CLI_input = CLI_input
+
+  def read(self, iprot):
+    if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
+      fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
+      return
+    iprot.readStructBegin()
+    while True:
+      (fname, ftype, fid) = iprot.readFieldBegin()
+      if ftype == TType.STOP:
+        break
+      if fid == 1:
+        if ftype == TType.LIST:
+          self.CLI_input = []
+          (_etype3, _size0) = iprot.readListBegin()
+          for _i4 in xrange(_size0):
+            _elem5 = iprot.readString()
+            self.CLI_input.append(_elem5)
+          iprot.readListEnd()
+        else:
+          iprot.skip(ftype)
+      else:
+        iprot.skip(ftype)
+      iprot.readFieldEnd()
+    iprot.readStructEnd()
+
+  def write(self, oprot):
+    if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
+      oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
+      return
+    oprot.writeStructBegin('CLIMessage')
+    if self.CLI_input is not None:
+      oprot.writeFieldBegin('CLI_input', TType.LIST, 1)
+      oprot.writeListBegin(TType.STRING, len(self.CLI_input))
+      for iter6 in self.CLI_input:
+        oprot.writeString(iter6)
+      oprot.writeListEnd()
+      oprot.writeFieldEnd()
+    oprot.writeFieldStop()
+    oprot.writeStructEnd()
+
+  def validate(self):
+    return
+
+
+  def __hash__(self):
+    value = 17
+    value = (value * 31) ^ hash(self.CLI_input)
+    return value
+
+  def __repr__(self):
+    L = ['%s=%r' % (key, value)
+      for key, value in self.__dict__.iteritems()]
+    return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+  def __eq__(self, other):
+    return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+  def __ne__(self, other):
+    return not (self == other)
+
+class CLIResponse:
+  """
+  Attributes:
+   - CLI_response
+  """
+
+  thrift_spec = (
+    None, # 0
+    (1, TType.STRING, 'CLI_response', None, None, ), # 1
+  )
+
+  def __init__(self, CLI_response=None,):
+    self.CLI_response = CLI_response
+
+  def read(self, iprot):
+    if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
+      fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
+      return
+    iprot.readStructBegin()
+    while True:
+      (fname, ftype, fid) = iprot.readFieldBegin()
+      if ftype == TType.STOP:
+        break
+      if fid == 1:
+        if ftype == TType.STRING:
+          self.CLI_response = iprot.readString()
+        else:
+          iprot.skip(ftype)
+      else:
+        iprot.skip(ftype)
+      iprot.readFieldEnd()
+    iprot.readStructEnd()
+
+  def write(self, oprot):
+    if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
+      oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
+      return
+    oprot.writeStructBegin('CLIResponse')
+    if self.CLI_response is not None:
+      oprot.writeFieldBegin('CLI_response', TType.STRING, 1)
+      oprot.writeString(self.CLI_response)
+      oprot.writeFieldEnd()
+    oprot.writeFieldStop()
+    oprot.writeStructEnd()
+
+  def validate(self):
+    return
+
+
+  def __hash__(self):
+    value = 17
+    value = (value * 31) ^ hash(self.CLI_response)
+    return value
+
+  def __repr__(self):
+    L = ['%s=%r' % (key, value)
+      for key, value in self.__dict__.iteritems()]
+    return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
+
+  def __eq__(self, other):
+    return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
+
+  def __ne__(self, other):
+    return not (self == other)
diff --git a/lib/dominoCLI/ttypes.pyc b/lib/dominoCLI/ttypes.pyc
new file mode 100644 (file)
index 0000000..03a5979
Binary files /dev/null and b/lib/dominoCLI/ttypes.pyc differ