summaryrefslogtreecommitdiffstats
path: root/cli.py
diff options
context:
space:
mode:
authorMark Beierl <mark.beierl@emc.com>2016-01-19 20:58:35 -0500
committerMark Beierl <mark.beierl@emc.com>2016-01-29 13:43:04 -0500
commit488a47d945d3ef3dfa9ee37ca0aac3b480ffc800 (patch)
tree295ea3f6df99884675ba8f21c207bf892f0170bd /cli.py
parent9960601b321f10a11257832a2ecacb91acf03c53 (diff)
Remote slave agent workload
Add storperf master object to manage stack lifecycle. Add configuration db. Creation of CLI vs. main so that ReST API and CLI API can be kept clear. Fixed License in files. Changed DB objects to be thread safe. Added ssh server to container if desired for CLI. Change-Id: Idfe84bfb7920e6ce19d27462593c21ea86e7b406 JIRA: STORPERF-29 Signed-off-by: Mark Beierl <mark.beierl@emc.com>
Diffstat (limited to 'cli.py')
-rw-r--r--cli.py172
1 files changed, 172 insertions, 0 deletions
diff --git a/cli.py b/cli.py
new file mode 100644
index 0000000..560d77d
--- /dev/null
+++ b/cli.py
@@ -0,0 +1,172 @@
+##############################################################################
+# Copyright (c) 2015 EMC and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+"""
+"""
+
+from storperf.storperf_master import StorPerfMaster
+from storperf.test_executor import UnknownWorkload
+from threading import Thread
+import cPickle
+import getopt
+import json
+import logging
+import logging.config
+import logging.handlers
+import os
+import socket
+import struct
+import sys
+import time
+
+import html2text
+import requests
+
+
+class Usage(Exception):
+ pass
+
+
+def event(event_string):
+ logging.getLogger(__name__).info(event_string)
+
+
+class LogRecordStreamHandler(object):
+
+ def __init__(self):
+ self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ self.socket.bind((
+ 'localhost', logging.handlers.DEFAULT_UDP_LOGGING_PORT))
+ self.level = logging.INFO
+
+ def read_logs(self):
+ try:
+ while True:
+ datagram = self.socket.recv(8192)
+ chunk = datagram[0:4]
+ slen = struct.unpack(">L", chunk)[0]
+ chunk = datagram[4:]
+ obj = cPickle.loads(chunk)
+ record = logging.makeLogRecord(obj)
+ if (record.levelno >= self.level):
+ logger = logging.getLogger(record.name)
+ logger.handle(record)
+
+ except Exception as e:
+ print "ERROR: " + str(e)
+ finally:
+ self.socket.close()
+
+
+def main(argv=None):
+ verbose = False
+ debug = False
+ report = None
+ erase = False
+ options = {}
+
+ storperf = StorPerfMaster()
+
+ if argv is None:
+ argv = sys.argv
+ try:
+ try:
+ opts, args = getopt.getopt(argv[1:], "t:w:r:f:escvdh",
+ ["target=",
+ "workload=",
+ "report=",
+ "configure=",
+ "erase",
+ "nossd",
+ "nowarm",
+ "verbose",
+ "debug",
+ "help",
+ ])
+ except getopt.error, msg:
+ raise Usage(msg)
+
+ configuration = None
+ options['workload'] = None
+
+ for o, a in opts:
+ if o in ("-h", "--help"):
+ print __doc__
+ return 0
+ elif o in ("-t", "--target"):
+ options['filename'] = a
+ elif o in ("-v", "--verbose"):
+ verbose = True
+ elif o in ("-d", "--debug"):
+ debug = True
+ elif o in ("-s", "--nossd"):
+ options['nossd'] = a
+ elif o in ("-c", "--nowarm"):
+ options['nowarm'] = False
+ elif o in ("-w", "--workload"):
+ options['workload'] = a
+ elif o in ("-r", "--report"):
+ report = a
+ elif o in ("-e", "--erase"):
+ erase = True
+ elif o in ("-f", "--configure"):
+ configuration = dict(x.split('=') for x in a.split(','))
+
+ if (debug) or (verbose):
+ udpserver = LogRecordStreamHandler()
+
+ if (debug):
+ udpserver.level = logging.DEBUG
+
+ logging.basicConfig(format="%(asctime)s - %(name)s - " +
+ "%(levelname)s - %(message)s")
+
+ t = Thread(target=udpserver.read_logs, args=())
+ t.setDaemon(True)
+ t.start()
+
+ if (erase):
+ response = requests.delete(
+ 'http://127.0.0.1:5000/api/v1.0/configure')
+ if (response.status_code == 400):
+ content = json.loads(response.content)
+ raise Usage(content['message'])
+ return 0
+
+ if (configuration is not None):
+ response = requests.post(
+ 'http://127.0.0.1:5000/api/v1.0/configure', json=configuration)
+ if (response.status_code == 400):
+ content = json.loads(response.content)
+ raise Usage(content['message'])
+
+ if (report is not None):
+ print storperf.fetch_results(report, workloads)
+ else:
+ print "Calling start..."
+ response = requests.post(
+ 'http://127.0.0.1:5000/api/v1.0/start', json=options)
+ if (response.status_code == 400):
+ content = json.loads(response.content)
+ raise Usage(content['message'])
+
+ content = json.loads(response.content)
+ print "Started job id: " + content['job_id']
+
+ except Usage as e:
+ print >> sys.stderr, str(e)
+ print >> sys.stderr, "For help use --help"
+ return 2
+
+ except Exception as e:
+ print >> sys.stderr, str(e)
+ return 2
+
+
+if __name__ == "__main__":
+ sys.exit(main())