diff options
Diffstat (limited to 'yardstick')
76 files changed, 1112 insertions, 682 deletions
diff --git a/yardstick/__init__.py b/yardstick/__init__.py index c31948d43..5c279c800 100644 --- a/yardstick/__init__.py +++ b/yardstick/__init__.py @@ -8,18 +8,40 @@ ############################################################################## import logging -import logging.config -import sys import os +import sys + import yardstick.vTC.apexlake as apexlake # Hack to be able to run apexlake unit tests # without having to install apexlake. sys.path.append(os.path.dirname(apexlake.__file__)) -logging.basicConfig( - level=logging.WARNING, - format='[%(asctime)s] %(name)-20s %(filename)s:%(lineno)d ' - '%(levelname)s %(message)s', # noqa - datefmt='%m/%d/%y %H:%M:%S') -logging.getLogger(__name__).setLevel(logging.INFO) +LOG_FILE = '/tmp/yardstick.log' +LOG_FORMATTER = ('%(asctime)s ' + '%(name)s %(filename)s:%(lineno)d ' + '%(levelname)s %(message)s') + +_LOG_FORMATTER = logging.Formatter(LOG_FORMATTER) +_LOG_STREAM_HDLR = logging.StreamHandler() +_LOG_FILE_HDLR = logging.FileHandler(LOG_FILE) + +LOG = logging.getLogger(__name__) + + +def _init_logging(): + + _LOG_STREAM_HDLR.setFormatter(_LOG_FORMATTER) + + # don't append to log file, clobber + _LOG_FILE_HDLR.setFormatter(_LOG_FORMATTER) + + del logging.root.handlers[:] + logging.root.addHandler(_LOG_STREAM_HDLR) + logging.root.addHandler(_LOG_FILE_HDLR) + logging.debug("logging.root.handlers = %s", logging.root.handlers) + + if os.environ.get('CI_DEBUG', '').lower() in {'1', 1, 'y', "yes", "true"}: + LOG.setLevel(logging.DEBUG) + else: + LOG.setLevel(logging.INFO) diff --git a/yardstick/benchmark/contexts/heat.py b/yardstick/benchmark/contexts/heat.py index 8c514d250..fcbe825d6 100644 --- a/yardstick/benchmark/contexts/heat.py +++ b/yardstick/benchmark/contexts/heat.py @@ -7,8 +7,10 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## +import os import sys import pkg_resources +import paramiko from yardstick.benchmark.contexts.base import Context from yardstick.benchmark.contexts.model import Server @@ -16,6 +18,7 @@ from yardstick.benchmark.contexts.model import PlacementGroup from yardstick.benchmark.contexts.model import Network from yardstick.benchmark.contexts.model import update_scheduler_hints from yardstick.orchestrator.heat import HeatTemplate +from yardstick.definitions import YARDSTICK_ROOT_PATH class HeatContext(Context): @@ -37,6 +40,8 @@ class HeatContext(Context): self._user = None self.template_file = None self.heat_parameters = None + self.key_filename = YARDSTICK_ROOT_PATH + \ + 'yardstick/resources/files/yardstick_key' super(self.__class__, self).__init__() def init(self, attrs): @@ -74,6 +79,17 @@ class HeatContext(Context): self.servers.append(server) self._server_map[server.dn] = server + print "Generating RSA host key ..." + rsa_key = paramiko.RSAKey.generate(bits=2048, progress_func=None) + print "Writing yardstick_key ..." + rsa_key.write_private_key_file(self.key_filename) + print "Writing yardstick_key.pub ..." + open(self.key_filename + ".pub", "w").write("%s %s\n" % + (rsa_key.get_name(), + rsa_key.get_base64())) + del rsa_key + print "... done!" + @property def image(self): '''returns application's default image name''' @@ -214,6 +230,13 @@ class HeatContext(Context): self.stack = None print "Context '%s' undeployed" % self.name + if os.path.exists(self.key_filename): + try: + os.remove(self.key_filename) + os.remove(self.key_filename + ".pub") + except OSError, e: + print ("Error: %s - %s." % (e.key_filename, e.strerror)) + def _get_server(self, attr_name): '''lookup server info by name from context attr_name: either a name for a server created by yardstick or a dict diff --git a/yardstick/benchmark/contexts/node.py b/yardstick/benchmark/contexts/node.py index c3d652119..78bce8259 100644 --- a/yardstick/benchmark/contexts/node.py +++ b/yardstick/benchmark/contexts/node.py @@ -8,10 +8,12 @@ ############################################################################## import sys +import os import yaml import logging from yardstick.benchmark.contexts.base import Context +from yardstick.definitions import YARDSTICK_ROOT_PATH LOG = logging.getLogger(__name__) @@ -33,7 +35,9 @@ class NodeContext(Context): def init(self, attrs): '''initializes itself from the supplied arguments''' self.name = attrs["name"] - self.file_path = attrs.get("file", "/etc/yardstick/nodes/pod.yaml") + self.file_path = attrs.get("file", "pod.yaml") + if not os.path.exists(self.file_path): + self.file_path = os.path.join(YARDSTICK_ROOT_PATH, self.file_path) LOG.info("Parsing pod file: %s", self.file_path) @@ -79,7 +83,7 @@ class NodeContext(Context): return None elif len(nodes) > 1: LOG.error("Duplicate nodes!!!") - LOG.error("Nodes: %r" % nodes) + LOG.error("Nodes: %r", nodes) sys.exit(-1) # A clone is created in order to avoid affecting the diff --git a/yardstick/benchmark/runners/arithmetic.py b/yardstick/benchmark/runners/arithmetic.py index 74a236f44..69ea915a1 100755 --- a/yardstick/benchmark/runners/arithmetic.py +++ b/yardstick/benchmark/runners/arithmetic.py @@ -93,7 +93,7 @@ def _worker_process(queue, cls, method_name, scenario_cfg, if aborted.is_set(): break - LOG.debug("runner=%(runner)s seq=%(sequence)s START" % + LOG.debug("runner=%(runner)s seq=%(sequence)s START", {"runner": runner_cfg["runner_id"], "sequence": sequence}) for i, value in enumerate(comb_values): @@ -109,7 +109,7 @@ def _worker_process(queue, cls, method_name, scenario_cfg, if sla_action == "assert": raise elif sla_action == "monitor": - LOG.warning("SLA validation failed: %s" % assertion.args) + LOG.warning("SLA validation failed: %s", assertion.args) errors = assertion.args except Exception as e: errors = traceback.format_exc() @@ -129,7 +129,7 @@ def _worker_process(queue, cls, method_name, scenario_cfg, queue.put(record) - LOG.debug("runner=%(runner)s seq=%(sequence)s END" % + LOG.debug("runner=%(runner)s seq=%(sequence)s END", {"runner": runner_cfg["runner_id"], "sequence": sequence}) sequence += 1 diff --git a/yardstick/benchmark/runners/base.py b/yardstick/benchmark/runners/base.py index 23749924f..8f3f75fa1 100755 --- a/yardstick/benchmark/runners/base.py +++ b/yardstick/benchmark/runners/base.py @@ -63,7 +63,7 @@ def _execute_shell_command(command): except Exception: exitcode = -1 output = traceback.format_exc() - log.error("exec command '%s' error:\n " % command) + log.error("exec command '%s' error:\n ", command) log.error(traceback.format_exc()) return exitcode, output @@ -76,10 +76,10 @@ def _single_action(seconds, command, queue): log.debug("single action: executing command: '%s'", command) ret_code, data = _execute_shell_command(command) if ret_code < 0: - log.error("single action error! command:%s" % command) + log.error("single action error! command:%s", command) queue.put({'single-action-data': data}) return - log.debug("single action data: \n%s" % data) + log.debug("single action data: \n%s", data) queue.put({'single-action-data': data}) @@ -96,7 +96,7 @@ def _periodic_action(interval, command, queue): log.error("periodic action error! command:%s", command) queue.put({'periodic-action-data': data}) break - log.debug("periodic action data: \n%s" % data) + log.debug("periodic action data: \n%s", data) queue.put({'periodic-action-data': data}) @@ -127,7 +127,7 @@ class Runner(object): """ # if there is no runner, start the output serializer subprocess if len(Runner.runners) == 0: - log.debug("Starting dump process file '%s'" % + log.debug("Starting dump process file '%s'", config["output_filename"]) Runner.queue = multiprocessing.Queue() Runner.dump_process = multiprocessing.Process( @@ -196,13 +196,13 @@ class Runner(object): '''run a potentially configured post-stop action''' if "post-stop-action" in self.config: command = self.config["post-stop-action"]["command"] - log.debug("post stop action: command: '%s'" % command) + log.debug("post stop action: command: '%s'", command) ret_code, data = _execute_shell_command(command) if ret_code < 0: log.error("post action error! command:%s", command) self.result_queue.put({'post-stop-action-data': data}) return - log.debug("post-stop data: \n%s" % data) + log.debug("post-stop data: \n%s", data) self.result_queue.put({'post-stop-action-data': data}) def run(self, scenario_cfg, context_cfg): @@ -219,13 +219,13 @@ class Runner(object): # run a potentially configured pre-start action if "pre-start-action" in self.config: command = self.config["pre-start-action"]["command"] - log.debug("pre start action: command: '%s'" % command) + log.debug("pre start action: command: '%s'", command) ret_code, data = _execute_shell_command(command) if ret_code < 0: log.error("pre-start action error! command:%s", command) self.result_queue.put({'pre-start-action-data': data}) return - log.debug("pre-start data: \n%s" % data) + log.debug("pre-start data: \n%s", data) self.result_queue.put({'pre-start-action-data': data}) if "single-shot-action" in self.config: diff --git a/yardstick/benchmark/runners/duration.py b/yardstick/benchmark/runners/duration.py index 1f51f513f..1412c0caa 100644 --- a/yardstick/benchmark/runners/duration.py +++ b/yardstick/benchmark/runners/duration.py @@ -58,7 +58,7 @@ def _worker_process(queue, cls, method_name, scenario_cfg, start = time.time() while True: - LOG.debug("runner=%(runner)s seq=%(sequence)s START" % + LOG.debug("runner=%(runner)s seq=%(sequence)s START", {"runner": runner_cfg["runner_id"], "sequence": sequence}) data = {} @@ -71,7 +71,7 @@ def _worker_process(queue, cls, method_name, scenario_cfg, if sla_action == "assert": raise elif sla_action == "monitor": - LOG.warning("SLA validation failed: %s" % assertion.args) + LOG.warning("SLA validation failed: %s", assertion.args) errors = assertion.args except Exception as e: errors = traceback.format_exc() @@ -91,7 +91,7 @@ def _worker_process(queue, cls, method_name, scenario_cfg, queue.put(record) - LOG.debug("runner=%(runner)s seq=%(sequence)s END" % + LOG.debug("runner=%(runner)s seq=%(sequence)s END", {"runner": runner_cfg["runner_id"], "sequence": sequence}) sequence += 1 diff --git a/yardstick/benchmark/runners/iteration.py b/yardstick/benchmark/runners/iteration.py index b23b32b08..3a839b65f 100644 --- a/yardstick/benchmark/runners/iteration.py +++ b/yardstick/benchmark/runners/iteration.py @@ -60,7 +60,7 @@ def _worker_process(queue, cls, method_name, scenario_cfg, if "run" in run_step: while True: - LOG.debug("runner=%(runner)s seq=%(sequence)s START" % + LOG.debug("runner=%(runner)s seq=%(sequence)s START", {"runner": runner_cfg["runner_id"], "sequence": sequence}) @@ -74,7 +74,7 @@ def _worker_process(queue, cls, method_name, scenario_cfg, if sla_action == "assert": raise elif sla_action == "monitor": - LOG.warning("SLA validation failed: %s" % assertion.args) + LOG.warning("SLA validation failed: %s", assertion.args) errors = assertion.args except Exception as e: errors = traceback.format_exc() @@ -94,7 +94,7 @@ def _worker_process(queue, cls, method_name, scenario_cfg, queue.put(record) - LOG.debug("runner=%(runner)s seq=%(sequence)s END" % + LOG.debug("runner=%(runner)s seq=%(sequence)s END", {"runner": runner_cfg["runner_id"], "sequence": sequence}) diff --git a/yardstick/benchmark/runners/sequence.py b/yardstick/benchmark/runners/sequence.py index fe53412ca..3b06e2a36 100644 --- a/yardstick/benchmark/runners/sequence.py +++ b/yardstick/benchmark/runners/sequence.py @@ -67,7 +67,7 @@ def _worker_process(queue, cls, method_name, scenario_cfg, for value in sequence_values: options[arg_name] = value - LOG.debug("runner=%(runner)s seq=%(sequence)s START" % + LOG.debug("runner=%(runner)s seq=%(sequence)s START", {"runner": runner_cfg["runner_id"], "sequence": sequence}) data = {} @@ -80,7 +80,7 @@ def _worker_process(queue, cls, method_name, scenario_cfg, if sla_action == "assert": raise elif sla_action == "monitor": - LOG.warning("SLA validation failed: %s" % assertion.args) + LOG.warning("SLA validation failed: %s", assertion.args) errors = assertion.args except Exception as e: errors = traceback.format_exc() @@ -100,7 +100,7 @@ def _worker_process(queue, cls, method_name, scenario_cfg, queue.put(record) - LOG.debug("runner=%(runner)s seq=%(sequence)s END" % + LOG.debug("runner=%(runner)s seq=%(sequence)s END", {"runner": runner_cfg["runner_id"], "sequence": sequence}) sequence += 1 diff --git a/yardstick/benchmark/scenarios/availability/actionrollbackers.py b/yardstick/benchmark/scenarios/availability/actionrollbackers.py index 4b732a10c..38f57d476 100644 --- a/yardstick/benchmark/scenarios/availability/actionrollbackers.py +++ b/yardstick/benchmark/scenarios/availability/actionrollbackers.py @@ -28,8 +28,8 @@ class AttackerRollbacker(ActionRollbacker): def rollback(self): LOG.debug( - "\033[93m recovering attacker %s \033[0m" - % (self.underlyingAttacker.key)) + "\033[93m recovering attacker %s \033[0m", + self.underlyingAttacker.key) self.underlyingAttacker.recover() @@ -40,6 +40,6 @@ class OperationRollbacker(ActionRollbacker): def rollback(self): LOG.debug( - "\033[93m rollback operation %s \033[0m" - % (self.underlyingOperation.key)) + "\033[93m rollback operation %s \033[0m", + self.underlyingOperation.key) self.underlyingOperation.rollback() diff --git a/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py b/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py index b35869d07..e88fed636 100644 --- a/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py +++ b/yardstick/benchmark/scenarios/availability/attacker/attacker_baremetal.py @@ -24,24 +24,25 @@ def _execute_shell_command(command, stdin=None): except Exception: exitcode = -1 output = traceback.format_exc() - LOG.error("exec command '%s' error:\n " % command) + LOG.error("exec command '%s' error:\n ", command) LOG.error(traceback.format_exc()) return exitcode, output class BaremetalAttacker(BaseAttacker): - __attacker_type__ = 'bare-metal-down' def setup(self): - LOG.debug("config:%s context:%s" % (self._config, self._context)) + LOG.debug("config:%s context:%s", self._config, self._context) host = self._context.get(self._config['host'], None) ip = host.get("ip", None) user = host.get("user", "root") + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) key_filename = host.get("key_filename", "~/.ssh/id_rsa") - self.connection = ssh.SSH(user, ip, key_filename=key_filename) + self.connection = ssh.SSH(user, ip, key_filename=key_filename, + port=ssh_port) self.connection.wait(timeout=600) LOG.debug("ssh host success!") self.host_ip = ip @@ -60,14 +61,15 @@ class BaremetalAttacker(BaseAttacker): self.setup_done = True def check(self): - exit_status, stdout, stderr = self.connection.execute( - "/bin/sh -s {0} -W 10".format(self.host_ip), - stdin=open(self.check_script, "r")) + with open(self.check_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + "/bin/sh -s {0} -W 10".format(self.host_ip), + stdin=stdin_file) - LOG.debug("check ret: %s out:%s err:%s" % - (exit_status, stdout, stderr)) + LOG.debug("check ret: %s out:%s err:%s", + exit_status, stdout, stderr) if not stdout or "running" not in stdout: - LOG.info("the host (ipmi_ip:%s) is not running!" % self.ipmi_ip) + LOG.info("the host (ipmi_ip:%s) is not running!", self.ipmi_ip) return False return True @@ -75,8 +77,8 @@ class BaremetalAttacker(BaseAttacker): def inject_fault(self): exit_status, stdout, stderr = self.connection.execute( "shutdown -h now") - LOG.debug("inject fault ret: %s out:%s err:%s" % - (exit_status, stdout, stderr)) + LOG.debug("inject fault ret: %s out:%s err:%s", + exit_status, stdout, stderr) if not exit_status: LOG.info("inject fault success") @@ -87,18 +89,21 @@ class BaremetalAttacker(BaseAttacker): host = self._context.get(jump_host_name, None) ip = host.get("ip", None) user = host.get("user", "root") + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) pwd = host.get("pwd", None) - LOG.debug("jump_host ip:%s user:%s" % (ip, user)) - self.jump_connection = ssh.SSH(user, ip, password=pwd) + LOG.debug("jump_host ip:%s user:%s", ip, user) + self.jump_connection = ssh.SSH(user, ip, password=pwd, + port=ssh_port) self.jump_connection.wait(timeout=600) LOG.debug("ssh jump host success!") if self.jump_connection is not None: - exit_status, stdout, stderr = self.jump_connection.execute( - "/bin/bash -s {0} {1} {2} {3}".format( - self.ipmi_ip, self.ipmi_user, self.ipmi_pwd, "on"), - stdin=open(self.recovery_script, "r")) + with open(self.recovery_script, "r") as stdin_file: + exit_status, stdout, stderr = self.jump_connection.execute( + "/bin/bash -s {0} {1} {2} {3}".format( + self.ipmi_ip, self.ipmi_user, self.ipmi_pwd, "on"), + stdin=stdin_file) else: exit_status, stdout = _execute_shell_command( "/bin/bash -s {0} {1} {2} {3}".format( diff --git a/yardstick/benchmark/scenarios/availability/attacker/attacker_general.py b/yardstick/benchmark/scenarios/availability/attacker/attacker_general.py index 816e7e37d..595067a95 100644 --- a/yardstick/benchmark/scenarios/availability/attacker/attacker_general.py +++ b/yardstick/benchmark/scenarios/availability/attacker/attacker_general.py @@ -20,13 +20,15 @@ class GeneralAttacker(BaseAttacker): __attacker_type__ = 'general-attacker' def setup(self): - LOG.debug("config:%s context:%s" % (self._config, self._context)) + LOG.debug("config:%s context:%s", self._config, self._context) host = self._context.get(self._config['host'], None) ip = host.get("ip", None) user = host.get("user", "root") + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) key_filename = host.get("key_filename", "~/.ssh/id_rsa") - self.connection = ssh.SSH(user, ip, key_filename=key_filename) + self.connection = ssh.SSH(user, ip, key_filename=key_filename, + port=ssh_port) self.connection.wait(timeout=600) LOG.debug("ssh host success!") @@ -63,13 +65,15 @@ class GeneralAttacker(BaseAttacker): if "action_parameter" in self._config: LOG.debug("the shell command is: {0}".format(self.action_param)) - exit_status, stdout, stderr = self.connection.execute( - self.action_param, - stdin=open(self.inject_script, "r")) + with open(self.inject_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + self.action_param, + stdin=stdin_file) else: - exit_status, stdout, stderr = self.connection.execute( - "/bin/bash -s ", - stdin=open(self.inject_script, "r")) + with open(self.inject_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + "/bin/bash -s ", + stdin=stdin_file) LOG.debug("the inject_fault's exit status is: {0}".format(exit_status)) if exit_status == 0: @@ -77,16 +81,18 @@ class GeneralAttacker(BaseAttacker): .format(stdout)) else: LOG.error( - "the inject_fault's error, stdout:%s, stderr:%s" % - (stdout, stderr)) + "the inject_fault's error, stdout:%s, stderr:%s", + stdout, stderr) def recover(self): if "rollback_parameter" in self._config: LOG.debug("the shell command is: {0}".format(self.rollback_param)) - exit_status, stdout, stderr = self.connection.execute( - self.rollback_param, - stdin=open(self.recovery_script, "r")) + with open(self.recovery_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + self.rollback_param, + stdin=stdin_file) else: - exit_status, stdout, stderr = self.connection.execute( - "/bin/bash -s ", - stdin=open(self.recovery_script, "r")) + with open(self.recovery_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + "/bin/bash -s ", + stdin=stdin_file) diff --git a/yardstick/benchmark/scenarios/availability/attacker/attacker_process.py b/yardstick/benchmark/scenarios/availability/attacker/attacker_process.py index 5118ad628..1d190a160 100644 --- a/yardstick/benchmark/scenarios/availability/attacker/attacker_process.py +++ b/yardstick/benchmark/scenarios/availability/attacker/attacker_process.py @@ -19,13 +19,15 @@ class ProcessAttacker(BaseAttacker): __attacker_type__ = 'kill-process' def setup(self): - LOG.debug("config:%s context:%s" % (self._config, self._context)) + LOG.debug("config:%s context:%s", self._config, self._context) host = self._context.get(self._config['host'], None) ip = host.get("ip", None) user = host.get("user", "root") + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) key_filename = host.get("key_filename", "~/.ssh/id_rsa") - self.connection = ssh.SSH(user, ip, key_filename=key_filename) + self.connection = ssh.SSH(user, ip, key_filename=key_filename, + port=ssh_port) self.connection.wait(timeout=600) LOG.debug("ssh host success!") @@ -43,25 +45,28 @@ class ProcessAttacker(BaseAttacker): self.setup_done = True def check(self): - exit_status, stdout, stderr = self.connection.execute( - "/bin/sh -s {0}".format(self.service_name), - stdin=open(self.check_script, "r")) + with open(self.check_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + "/bin/sh -s {0}".format(self.service_name), + stdin=stdin_file) if stdout and "running" in stdout: LOG.info("check the envrioment success!") return True else: LOG.error( - "the host envrioment is error, stdout:%s, stderr:%s" % - (stdout, stderr)) + "the host envrioment is error, stdout:%s, stderr:%s", + stdout, stderr) return False def inject_fault(self): - exit_status, stdout, stderr = self.connection.execute( - "/bin/sh -s {0}".format(self.service_name), - stdin=open(self.inject_script, "r")) + with open(self.inject_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + "/bin/sh -s {0}".format(self.service_name), + stdin=stdin_file) def recover(self): - exit_status, stdout, stderr = self.connection.execute( - "/bin/sh -s {0} ".format(self.service_name), - stdin=open(self.recovery_script, "r")) + with open(self.recovery_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + "/bin/sh -s {0} ".format(self.service_name), + stdin=stdin_file) diff --git a/yardstick/benchmark/scenarios/availability/attacker/baseattacker.py b/yardstick/benchmark/scenarios/availability/attacker/baseattacker.py index 78276efa2..f96e57728 100644 --- a/yardstick/benchmark/scenarios/availability/attacker/baseattacker.py +++ b/yardstick/benchmark/scenarios/availability/attacker/baseattacker.py @@ -26,7 +26,7 @@ class AttackerMgr(object): self._attacker_list = [] def init_attackers(self, attacker_cfgs, context): - LOG.debug("attackerMgr confg: %s" % attacker_cfgs) + LOG.debug("attackerMgr confg: %s", attacker_cfgs) for cfg in attacker_cfgs: attacker_cls = BaseAttacker.get_attacker_cls(cfg) diff --git a/yardstick/benchmark/scenarios/availability/director.py b/yardstick/benchmark/scenarios/availability/director.py index 267933dd0..104c68380 100644 --- a/yardstick/benchmark/scenarios/availability/director.py +++ b/yardstick/benchmark/scenarios/availability/director.py @@ -63,7 +63,7 @@ class Director(object): def createActionPlayer(self, type, key): LOG.debug( - "the type of current action is %s, the key is %s" % (type, key)) + "the type of current action is %s, the key is %s", type, key) if type == ActionType.ATTACKER: return actionplayers.AttackerPlayer(self.attackerMgr[key]) if type == ActionType.MONITOR: @@ -77,13 +77,13 @@ class Director(object): def createActionRollbacker(self, type, key): LOG.debug( - "the type of current action is %s, the key is %s" % (type, key)) + "the type of current action is %s, the key is %s", type, key) if type == ActionType.ATTACKER: return actionrollbackers.AttackerRollbacker(self.attackerMgr[key]) if type == ActionType.OPERATION: return actionrollbackers.OperationRollbacker( self.operationMgr[key]) - LOG.debug("no rollbacker created for %s" % (key)) + LOG.debug("no rollbacker created for %s", key) def verify(self): result = True diff --git a/yardstick/benchmark/scenarios/availability/monitor/basemonitor.py b/yardstick/benchmark/scenarios/availability/monitor/basemonitor.py index d26c99c75..38d1c4e5c 100644 --- a/yardstick/benchmark/scenarios/availability/monitor/basemonitor.py +++ b/yardstick/benchmark/scenarios/availability/monitor/basemonitor.py @@ -27,7 +27,7 @@ class MonitorMgr(object): self._monitor_list = [] def init_monitors(self, monitor_cfgs, context): - LOG.debug("monitorMgr config: %s" % monitor_cfgs) + LOG.debug("monitorMgr config: %s", monitor_cfgs) for monitor_cfg in monitor_cfgs: monitor_type = monitor_cfg["monitor_type"] @@ -87,7 +87,7 @@ class BaseMonitor(multiprocessing.Process): return os.path.join(base_path, path) def run(self): - LOG.debug("config:%s context:%s" % (self._config, self._context)) + LOG.debug("config:%s context:%s", self._config, self._context) self.setup() monitor_time = self._config.get("monitor_time", 0) @@ -140,7 +140,7 @@ class BaseMonitor(multiprocessing.Process): def wait_monitor(self): self.join() self._result = self._queue.get() - LOG.debug("the monitor result:%s" % self._result) + LOG.debug("the monitor result:%s", self._result) def setup(self): # pragma: no cover pass diff --git a/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py b/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py index c285024e1..cd33e6188 100644 --- a/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py +++ b/yardstick/benchmark/scenarios/availability/monitor/monitor_command.py @@ -24,7 +24,7 @@ def _execute_shell_command(command): except Exception: exitcode = -1 output = traceback.format_exc() - LOG.error("exec command '%s' error:\n " % command) + LOG.error("exec command '%s' error:\n ", command) LOG.error(traceback.format_exc()) return exitcode, output @@ -42,9 +42,11 @@ class MonitorOpenstackCmd(basemonitor.BaseMonitor): host = self._context[node_name] ip = host.get("ip", None) user = host.get("user", "root") + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) key_filename = host.get("key_filename", "~/.ssh/id_rsa") - self.connection = ssh.SSH(user, ip, key_filename=key_filename) + self.connection = ssh.SSH(user, ip, key_filename=key_filename, + port=ssh_port) self.connection.wait(timeout=600) LOG.debug("ssh host success!") @@ -56,12 +58,13 @@ class MonitorOpenstackCmd(basemonitor.BaseMonitor): def monitor_func(self): exit_status = 0 if self.connection: - exit_status, stdout, stderr = self.connection.execute( - "/bin/bash -s '{0}'".format(self.cmd), - stdin=open(self.check_script, "r")) + with open(self.check_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + "/bin/bash -s '{0}'".format(self.cmd), + stdin=stdin_file) - LOG.debug("the ret stats: %s stdout: %s stderr: %s" % - (exit_status, stdout, stderr)) + LOG.debug("the ret stats: %s stdout: %s stderr: %s", + exit_status, stdout, stderr) else: exit_status, stdout = _execute_shell_command(self.cmd) if exit_status: @@ -70,10 +73,10 @@ class MonitorOpenstackCmd(basemonitor.BaseMonitor): def verify_SLA(self): outage_time = self._result.get('outage_time', None) - LOG.debug("the _result:%s" % self._result) + LOG.debug("the _result:%s", self._result) max_outage_time = self._config["sla"]["max_outage_time"] if outage_time > max_outage_time: - LOG.info("SLA failure: %f > %f" % (outage_time, max_outage_time)) + LOG.info("SLA failure: %f > %f", outage_time, max_outage_time) return False else: LOG.info("the sla is passed") diff --git a/yardstick/benchmark/scenarios/availability/monitor/monitor_general.py b/yardstick/benchmark/scenarios/availability/monitor/monitor_general.py index 61efc0520..461a2ded5 100644 --- a/yardstick/benchmark/scenarios/availability/monitor/monitor_general.py +++ b/yardstick/benchmark/scenarios/availability/monitor/monitor_general.py @@ -25,6 +25,7 @@ class GeneralMonitor(basemonitor.BaseMonitor): host = self._context[self._config["host"]] ip = host.get("ip", None) user = host.get("user", "root") + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) key_filename = host.get("key_filename", "~/.ssh/id_rsa") self.key = self._config["key"] self.monitor_key = self._config["monitor_key"] @@ -40,33 +41,36 @@ class GeneralMonitor(basemonitor.BaseMonitor): self.monitor_key) self.monitor_script = self.get_script_fullpath( self.monitor_cfg['monitor_script']) - self.connection = ssh.SSH(user, ip, key_filename=key_filename) + self.connection = ssh.SSH(user, ip, key_filename=key_filename, + port=ssh_port) self.connection.wait(timeout=600) LOG.debug("ssh host success!") def monitor_func(self): if "parameter" in self._config: - exit_status, stdout, stderr = self.connection.execute( - self.cmd_param, - stdin=open(self.monitor_script, "r")) + with open(self.monitor_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + self.cmd_param, + stdin=stdin_file) else: - exit_status, stdout, stderr = self.connection.execute( - "/bin/bash -s ", - stdin=open(self.monitor_script, "r")) + with open(self.monitor_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + "/bin/bash -s ", + stdin=stdin_file) if exit_status: return False return True def verify_SLA(self): - LOG.debug("the _result:%s" % self._result) + LOG.debug("the _result:%s", self._result) outage_time = self._result.get('outage_time', None) max_outage_time = self._config["sla"]["max_outage_time"] if outage_time is None: LOG.error("There is no outage_time in monitor result.") return False if outage_time > max_outage_time: - LOG.error("SLA failure: %f > %f" % (outage_time, max_outage_time)) + LOG.error("SLA failure: %f > %f", outage_time, max_outage_time) return False else: return True diff --git a/yardstick/benchmark/scenarios/availability/monitor/monitor_process.py b/yardstick/benchmark/scenarios/availability/monitor/monitor_process.py index 53a6d8e4d..5f492ad69 100644 --- a/yardstick/benchmark/scenarios/availability/monitor/monitor_process.py +++ b/yardstick/benchmark/scenarios/availability/monitor/monitor_process.py @@ -23,9 +23,11 @@ class MonitorProcess(basemonitor.BaseMonitor): host = self._context[self._config["host"]] ip = host.get("ip", None) user = host.get("user", "root") + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) key_filename = host.get("key_filename", "~/.ssh/id_rsa") - self.connection = ssh.SSH(user, ip, key_filename=key_filename) + self.connection = ssh.SSH(user, ip, key_filename=key_filename, + port=ssh_port) self.connection.wait(timeout=600) LOG.debug("ssh host success!") self.check_script = self.get_script_fullpath( @@ -33,21 +35,22 @@ class MonitorProcess(basemonitor.BaseMonitor): self.process_name = self._config["process_name"] def monitor_func(self): - exit_status, stdout, stderr = self.connection.execute( - "/bin/sh -s {0}".format(self.process_name), - stdin=open(self.check_script, "r")) + with open(self.check_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + "/bin/sh -s {0}".format(self.process_name), + stdin=stdin_file) if not stdout or int(stdout) <= 0: - LOG.info("the process (%s) is not running!" % self.process_name) + LOG.info("the process (%s) is not running!", self.process_name) return False return True def verify_SLA(self): - LOG.debug("the _result:%s" % self._result) + LOG.debug("the _result:%s", self._result) outage_time = self._result.get('outage_time', None) max_outage_time = self._config["sla"]["max_recover_time"] if outage_time > max_outage_time: - LOG.error("SLA failure: %f > %f" % (outage_time, max_outage_time)) + LOG.error("SLA failure: %f > %f", outage_time, max_outage_time) return False else: return True diff --git a/yardstick/benchmark/scenarios/availability/operation/baseoperation.py b/yardstick/benchmark/scenarios/availability/operation/baseoperation.py index e776e87ae..80efd1b02 100644 --- a/yardstick/benchmark/scenarios/availability/operation/baseoperation.py +++ b/yardstick/benchmark/scenarios/availability/operation/baseoperation.py @@ -26,7 +26,7 @@ class OperationMgr(object): self._operation_list = [] def init_operations(self, operation_cfgs, context): - LOG.debug("operationMgr confg: %s" % operation_cfgs) + LOG.debug("operationMgr confg: %s", operation_cfgs) for cfg in operation_cfgs: operation_type = cfg['operation_type'] operation_cls = BaseOperation.get_operation_cls(operation_type) diff --git a/yardstick/benchmark/scenarios/availability/operation/operation_general.py b/yardstick/benchmark/scenarios/availability/operation/operation_general.py index e43f6e1d5..c82df836d 100644 --- a/yardstick/benchmark/scenarios/availability/operation/operation_general.py +++ b/yardstick/benchmark/scenarios/availability/operation/operation_general.py @@ -19,13 +19,15 @@ class GeneralOperaion(BaseOperation): __operation__type__ = "general-operation" def setup(self): - LOG.debug("config:%s context:%s" % (self._config, self._context)) + LOG.debug("config:%s context:%s", self._config, self._context) host = self._context.get(self._config['host'], None) ip = host.get("ip", None) user = host.get("user", "root") + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) key_filename = host.get("key_filename", "~/.ssh/id_rsa") - self.connection = ssh.SSH(user, ip, key_filename=key_filename) + self.connection = ssh.SSH(user, ip, key_filename=key_filename, + port=ssh_port) self.connection.wait(timeout=600) LOG.debug("ssh host success!") @@ -53,27 +55,31 @@ class GeneralOperaion(BaseOperation): def run(self): if "action_parameter" in self._config: - exit_status, stdout, stderr = self.connection.execute( - self.action_param, - stdin=open(self.action_script, "r")) + with open(self.action_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + self.action_param, + stdin=stdin_file) else: - exit_status, stdout, stderr = self.connection.execute( - "/bin/sh -s ", - stdin=open(self.action_script, "r")) + with open(self.action_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + "/bin/sh -s ", + stdin=stdin_file) if exit_status == 0: LOG.debug("success,the operation's output is: {0}".format(stdout)) else: LOG.error( - "the operation's error, stdout:%s, stderr:%s" % - (stdout, stderr)) + "the operation's error, stdout:%s, stderr:%s", + stdout, stderr) def rollback(self): if "rollback_parameter" in self._config: - exit_status, stdout, stderr = self.connection.execute( - self.rollback_param, - stdin=open(self.rollback_script, "r")) + with open(self.rollback_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + self.rollback_param, + stdin=stdin_file) else: - exit_status, stdout, stderr = self.connection.execute( - "/bin/sh -s ", - stdin=open(self.rollback_script, "r")) + with open(self.rollback_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + "/bin/sh -s ", + stdin=stdin_file) diff --git a/yardstick/benchmark/scenarios/availability/result_checker/baseresultchecker.py b/yardstick/benchmark/scenarios/availability/result_checker/baseresultchecker.py index 1bdb9f2c2..a24f26e81 100644 --- a/yardstick/benchmark/scenarios/availability/result_checker/baseresultchecker.py +++ b/yardstick/benchmark/scenarios/availability/result_checker/baseresultchecker.py @@ -26,7 +26,7 @@ class ResultCheckerMgr(object): self._result_checker_list = [] def init_ResultChecker(self, resultchecker_cfgs, context): - LOG.debug("resultcheckerMgr confg: %s" % resultchecker_cfgs) + LOG.debug("resultcheckerMgr confg: %s", resultchecker_cfgs) for cfg in resultchecker_cfgs: resultchecker_type = cfg['checker_type'] diff --git a/yardstick/benchmark/scenarios/availability/result_checker/result_checker_general.py b/yardstick/benchmark/scenarios/availability/result_checker/result_checker_general.py index 681fbf63f..275aff076 100644 --- a/yardstick/benchmark/scenarios/availability/result_checker/result_checker_general.py +++ b/yardstick/benchmark/scenarios/availability/result_checker/result_checker_general.py @@ -17,17 +17,18 @@ LOG = logging.getLogger(__name__) class GeneralResultChecker(BaseResultChecker): - __result_checker__type__ = "general-result-checker" def setup(self): - LOG.debug("config:%s context:%s" % (self._config, self._context)) + LOG.debug("config:%s context:%s", self._config, self._context) host = self._context.get(self._config['host'], None) ip = host.get("ip", None) user = host.get("user", "root") + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) key_filename = host.get("key_filename", "~/.ssh/id_rsa") - self.connection = ssh.SSH(user, ip, key_filename=key_filename) + self.connection = ssh.SSH(user, ip, key_filename=key_filename, + port=ssh_port) self.connection.wait(timeout=600) LOG.debug("ssh host success!") @@ -52,21 +53,23 @@ class GeneralResultChecker(BaseResultChecker): def verify(self): if "parameter" in self._config: - exit_status, stdout, stderr = self.connection.execute( - self.shell_cmd, - stdin=open(self.verify_script, "r")) + with open(self.verify_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + self.shell_cmd, + stdin=stdin_file) LOG.debug("action script of the operation is: {0}" .format(self.verify_script)) LOG.debug("action parameter the of operation is: {0}" .format(self.shell_cmd)) else: - exit_status, stdout, stderr = self.connection.execute( - "/bin/bash -s ", - stdin=open(self.verify_script, "r")) + with open(self.verify_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + "/bin/bash -s ", + stdin=stdin_file) LOG.debug("action script of the operation is: {0}" .format(self.verify_script)) - LOG.debug("exit_status ,stdout : {0} ,{1}".format(exit_status, stdout)) + LOG.debug("exit_status ,stdout : %s ,%s", exit_status, stdout) if exit_status == 0 and stdout: self.actualResult = stdout LOG.debug("verifying resultchecker: {0}".format(self.key)) @@ -103,6 +106,6 @@ class GeneralResultChecker(BaseResultChecker): LOG.error(stderr) LOG.debug( - "verifying resultchecker: {0},the result is : {1}" - .format(self.key, self.success)) + "verifying resultchecker: %s,the result is : %s", self.key, + self.success) return self.success diff --git a/yardstick/benchmark/scenarios/availability/scenario_general.py b/yardstick/benchmark/scenarios/availability/scenario_general.py index 0a128aa09..b064c6724 100644 --- a/yardstick/benchmark/scenarios/availability/scenario_general.py +++ b/yardstick/benchmark/scenarios/availability/scenario_general.py @@ -22,7 +22,7 @@ class ScenarioGeneral(base.Scenario): def __init__(self, scenario_cfg, context_cfg): LOG.debug( - "scenario_cfg:%s context_cfg:%s" % (scenario_cfg, context_cfg)) + "scenario_cfg:%s context_cfg:%s", scenario_cfg, context_cfg) self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg diff --git a/yardstick/benchmark/scenarios/availability/serviceha.py b/yardstick/benchmark/scenarios/availability/serviceha.py index 10f2c4f45..46a197c3b 100755 --- a/yardstick/benchmark/scenarios/availability/serviceha.py +++ b/yardstick/benchmark/scenarios/availability/serviceha.py @@ -21,8 +21,8 @@ class ServiceHA(base.Scenario): def __init__(self, scenario_cfg, context_cfg): LOG.debug( - "scenario_cfg:%s context_cfg:%s" % - (scenario_cfg, context_cfg)) + "scenario_cfg:%s context_cfg:%s", + scenario_cfg, context_cfg) self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg self.setup_done = False diff --git a/yardstick/benchmark/scenarios/compute/cachestat.py b/yardstick/benchmark/scenarios/compute/cachestat.py index da4aa754f..20786ff61 100644 --- a/yardstick/benchmark/scenarios/compute/cachestat.py +++ b/yardstick/benchmark/scenarios/compute/cachestat.py @@ -75,22 +75,23 @@ class CACHEstat(base.Scenario): host = self.context_cfg['host'] user = host.get('user', 'ubuntu') + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) ip = host.get('ip', None) key_filename = host.get('key_filename', '~/.ssh/id_rsa') LOG.info("user:%s, host:%s", user, ip) - self.client = ssh.SSH(user, ip, key_filename=key_filename) + self.client = ssh.SSH(user, ip, key_filename=key_filename, + port=ssh_port) self.client.wait(timeout=600) # copy scripts to host - self.client.run("cat > ~/cache_stat.sh", - stdin=open(self.target_script, 'rb')) + self.client._put_file_shell(self.target_script, '~/cache_stat.sh') self.setup_done = True def _execute_command(self, cmd): """Execute a command on server.""" - LOG.info("Executing: %s" % cmd) + LOG.info("Executing: %s", cmd) status, stdout, stderr = self.client.execute(cmd) if status: raise RuntimeError("Failed executing command: ", diff --git a/yardstick/benchmark/scenarios/compute/computecapacity.bash b/yardstick/benchmark/scenarios/compute/computecapacity.bash index 98d4b8fb5..68741a94f 100644 --- a/yardstick/benchmark/scenarios/compute/computecapacity.bash +++ b/yardstick/benchmark/scenarios/compute/computecapacity.bash @@ -9,13 +9,15 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -# Measure compute capacity and scale of a host +# compute capacity and scale of a host set -e # run capacity test run_capacity() { + #parameter used for HT(Hyper-Thread) check + HT_Para=2 # Number of CPUs CPU=$(grep 'physical id' /proc/cpuinfo | sort -u | wc -l) # Number of physical cores in a single CPU @@ -31,6 +33,12 @@ run_capacity() CACHE=$(grep 'cache size' /proc/cpuinfo | sort -u) CA=$(echo $CACHE | awk '/ /{printf "%s", $4}') CACHES=$[$CA * $CPU] + HT_Value=$[$HT_Para * $CORES] + if [ $HT_Value -eq $THREAD ]; then + HT_OPEN=1 + else + HT_OPEN=0 + fi } # write the result to stdout in json format @@ -41,7 +49,8 @@ output_json() \"Core_number\":\"$CORES\", \ \"Thread_number\":\"$THREAD\", \ \"Memory_size\": \"$ME\", \ - \"Cache_size\": \"$CACHES KB\" \ + \"Cache_size\": \"$CACHES KB\", \ + \"HT_Open\": \"$HT_OPEN\" \ }" } diff --git a/yardstick/benchmark/scenarios/compute/computecapacity.py b/yardstick/benchmark/scenarios/compute/computecapacity.py index 0d7d76143..7f0c58de1 100644 --- a/yardstick/benchmark/scenarios/compute/computecapacity.py +++ b/yardstick/benchmark/scenarios/compute/computecapacity.py @@ -40,15 +40,16 @@ class ComputeCapacity(base.Scenario): nodes = self.context_cfg['nodes'] node = nodes.get('host', None) host_user = node.get('user', 'ubuntu') + ssh_port = node.get('ssh_port', ssh.DEFAULT_PORT) host_ip = node.get('ip', None) host_pwd = node.get('password', 'root') LOG.debug("user:%s, host:%s", host_user, host_ip) - self.client = ssh.SSH(host_user, host_ip, password=host_pwd) + self.client = ssh.SSH(host_user, host_ip, password=host_pwd, + port=ssh_port) self.client.wait(timeout=600) # copy script to host - self.client.run("cat > ~/computecapacity.sh", - stdin=open(self.target_script, 'rb')) + self.client._put_file_shell(self.target_script, '~/computecapacity.sh') self.setup_done = True diff --git a/yardstick/benchmark/scenarios/compute/cpuload.py b/yardstick/benchmark/scenarios/compute/cpuload.py index f45313e91..9d71038ef 100644 --- a/yardstick/benchmark/scenarios/compute/cpuload.py +++ b/yardstick/benchmark/scenarios/compute/cpuload.py @@ -67,10 +67,12 @@ class CPULoad(base.Scenario): host = self.context_cfg['host'] user = host.get('user', 'ubuntu') ip = host.get('ip', None) + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) key_filename = host.get('key_filename', '~/.ssh/id_rsa') LOG.info("user:%s, host:%s", user, ip) - self.client = ssh.SSH(user, ip, key_filename=key_filename) + self.client = ssh.SSH(user, ip, key_filename=key_filename, + port=ssh_port) self.client.wait(timeout=600) # Check if mpstat prog is installed @@ -94,7 +96,7 @@ class CPULoad(base.Scenario): def _execute_command(self, cmd): """Execute a command on server.""" - LOG.info("Executing: %s" % cmd) + LOG.info("Executing: %s", cmd) status, stdout, stderr = self.client.execute(cmd) if status != 0: raise RuntimeError("Failed executing command: ", diff --git a/yardstick/benchmark/scenarios/compute/cyclictest.py b/yardstick/benchmark/scenarios/compute/cyclictest.py index 478b0a1a2..568e6e7df 100644 --- a/yardstick/benchmark/scenarios/compute/cyclictest.py +++ b/yardstick/benchmark/scenarios/compute/cyclictest.py @@ -69,14 +69,14 @@ class Cyclictest(base.Scenario): rpm_dir = setup_options["rpm_dir"] script_dir = setup_options["script_dir"] image_dir = setup_options["image_dir"] - LOG.debug("Send RPMs from %s to workspace %s" % - (rpm_dir, self.WORKSPACE)) + LOG.debug("Send RPMs from %s to workspace %s", + rpm_dir, self.WORKSPACE) client.put(rpm_dir, self.WORKSPACE, recursive=True) - LOG.debug("Send scripts from %s to workspace %s" % - (script_dir, self.WORKSPACE)) + LOG.debug("Send scripts from %s to workspace %s", + script_dir, self.WORKSPACE) client.put(script_dir, self.WORKSPACE, recursive=True) - LOG.debug("Send guest image from %s to workspace %s" % - (image_dir, self.WORKSPACE)) + LOG.debug("Send guest image from %s to workspace %s", + image_dir, self.WORKSPACE) client.put(image_dir, self.WORKSPACE, recursive=True) def _connect_host(self): @@ -93,14 +93,16 @@ class Cyclictest(base.Scenario): host = self.context_cfg["host"] user = host.get("user", "root") ip = host.get("ip", None) + ssh_port = host.get("ssh_port", 5555) key_filename = host.get("key_filename", "~/.ssh/id_rsa") LOG.debug("user:%s, host:%s", user, ip) - self.guest = ssh.SSH(user, ip, port=5555, key_filename=key_filename) + self.guest = ssh.SSH(user, ip, port=ssh_port, + key_filename=key_filename) self.guest.wait(timeout=600) def _run_setup_cmd(self, client, cmd): - LOG.debug("Run cmd: %s" % cmd) + LOG.debug("Run cmd: %s", cmd) status, stdout, stderr = client.execute(cmd) if status: if re.search(self.REBOOT_CMD_PATTERN, cmd): @@ -152,8 +154,8 @@ class Cyclictest(base.Scenario): self.target_script = pkg_resources.resource_filename( "yardstick.benchmark.scenarios.compute", Cyclictest.TARGET_SCRIPT) - self.guest.run("cat > ~/cyclictest_benchmark.sh", - stdin=open(self.target_script, "rb")) + self.guest._put_file_shell( + self.target_script, '~/cyclictest_benchmark.sh') self.setup_done = True diff --git a/yardstick/benchmark/scenarios/compute/lmbench.py b/yardstick/benchmark/scenarios/compute/lmbench.py index d3e802f3b..518840c09 100644 --- a/yardstick/benchmark/scenarios/compute/lmbench.py +++ b/yardstick/benchmark/scenarios/compute/lmbench.py @@ -77,20 +77,22 @@ class Lmbench(base.Scenario): Lmbench.LATENCY_CACHE_SCRIPT) host = self.context_cfg["host"] user = host.get("user", "ubuntu") + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) ip = host.get("ip", None) key_filename = host.get('key_filename', "~/.ssh/id_rsa") LOG.info("user:%s, host:%s", user, ip) - self.client = ssh.SSH(user, ip, key_filename=key_filename) + self.client = ssh.SSH(user, ip, key_filename=key_filename, + port=ssh_port) self.client.wait(timeout=600) # copy scripts to host - self.client.run("cat > ~/lmbench_latency.sh", - stdin=open(self.latency_target_script, 'rb')) - self.client.run("cat > ~/lmbench_bandwidth.sh", - stdin=open(self.bandwidth_target_script, 'rb')) - self.client.run("cat > ~/lmbench_latency_for_cache.sh", - stdin=open(self.latency_for_cache_script, 'rb')) + self.client._put_file_shell( + self.latency_target_script, '~/lmbench_latency.sh') + self.client._put_file_shell( + self.bandwidth_target_script, '~/lmbench_bandwidth.sh') + self.client._put_file_shell( + self.latency_for_cache_script, '~/lmbench_latency_for_cache.sh') self.setup_done = True def run(self, result): diff --git a/yardstick/benchmark/scenarios/compute/memload.py b/yardstick/benchmark/scenarios/compute/memload.py index bafd89617..e1ba93d02 100644 --- a/yardstick/benchmark/scenarios/compute/memload.py +++ b/yardstick/benchmark/scenarios/compute/memload.py @@ -48,18 +48,20 @@ class MEMLoad(base.Scenario): """Scenario setup.""" host = self.context_cfg['host'] user = host.get('user', 'ubuntu') + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) ip = host.get('ip', None) key_filename = host.get('key_filename', '~/.ssh/id_rsa') LOG.info("user:%s, host:%s", user, ip) - self.client = ssh.SSH(user, ip, key_filename=key_filename) + self.client = ssh.SSH(user, ip, key_filename=key_filename, + port=ssh_port) self.client.wait(timeout=600) self.setup_done = True def _execute_command(self, cmd): """Execute a command on server.""" - LOG.info("Executing: %s" % cmd) + LOG.info("Executing: %s", cmd) status, stdout, stderr = self.client.execute(cmd) if status: raise RuntimeError("Failed executing command: ", diff --git a/yardstick/benchmark/scenarios/compute/perf.py b/yardstick/benchmark/scenarios/compute/perf.py index f408e9cb4..8f1a4d630 100644 --- a/yardstick/benchmark/scenarios/compute/perf.py +++ b/yardstick/benchmark/scenarios/compute/perf.py @@ -47,16 +47,17 @@ class Perf(base.Scenario): 'yardstick.benchmark.scenarios.compute', Perf.TARGET_SCRIPT) host = self.context_cfg['host'] user = host.get('user', 'ubuntu') + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) ip = host.get('ip', None) key_filename = host.get('key_filename', '~/.ssh/id_rsa') LOG.info("user:%s, host:%s", user, ip) - self.client = ssh.SSH(user, ip, key_filename=key_filename) + self.client = ssh.SSH(user, ip, key_filename=key_filename, + port=ssh_port) self.client.wait(timeout=600) # copy script to host - self.client.run("cat > ~/perf_benchmark.sh", - stdin=open(self.target_script, "rb")) + self.client._put_file_shell(self.target_script, '~/perf_benchmark.sh') self.setup_done = True diff --git a/yardstick/benchmark/scenarios/compute/plugintest.py b/yardstick/benchmark/scenarios/compute/plugintest.py index e41fb8399..e7ec91c5c 100644 --- a/yardstick/benchmark/scenarios/compute/plugintest.py +++ b/yardstick/benchmark/scenarios/compute/plugintest.py @@ -30,10 +30,12 @@ class PluginTest(base.Scenario): nodes = self.context_cfg['nodes'] node = nodes.get('host1', None) host_user = node.get('user', 'ubuntu') + host_ssh_port = node.get('ssh_port', ssh.DEFAULT_PORT) host_ip = node.get('ip', None) host_pwd = node.get('password', 'root') LOG.debug("user:%s, host:%s", host_user, host_ip) - self.client = ssh.SSH(host_user, host_ip, password=host_pwd) + self.client = ssh.SSH(host_user, host_ip, password=host_pwd, + port=host_ssh_port) self.client.wait(timeout=600) self.setup_done = True diff --git a/yardstick/benchmark/scenarios/compute/ramspeed.py b/yardstick/benchmark/scenarios/compute/ramspeed.py index 819ef769b..db70af90b 100644 --- a/yardstick/benchmark/scenarios/compute/ramspeed.py +++ b/yardstick/benchmark/scenarios/compute/ramspeed.py @@ -87,18 +87,20 @@ class Ramspeed(base.Scenario): host = self.context_cfg["host"] user = host.get("user", "ubuntu") + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) ip = host.get("ip", None) key_filename = host.get('key_filename', "~/.ssh/id_rsa") LOG.info("user:%s, host:%s", user, ip) - self.client = ssh.SSH(user, ip, key_filename=key_filename) + self.client = ssh.SSH(user, ip, key_filename=key_filename, + port=ssh_port) self.client.wait(timeout=600) # copy scripts to host - self.client.run("cat > ~/ramspeed_mark_benchmark.sh", - stdin=open(self.mark_target_script, 'rb')) - self.client.run("cat > ~/ramspeed_mem_benchmark.sh", - stdin=open(self.mem_target_script, 'rb')) + self.client._put_file_shell( + self.mark_target_script, '~/ramspeed_mark_benchmark.sh') + self.client._put_file_shell( + self.mem_target_script, '~/ramspeed_mem_benchmark.sh') self.setup_done = True def run(self, result): diff --git a/yardstick/benchmark/scenarios/compute/unixbench.py b/yardstick/benchmark/scenarios/compute/unixbench.py index e6318b92e..b22be29c9 100644 --- a/yardstick/benchmark/scenarios/compute/unixbench.py +++ b/yardstick/benchmark/scenarios/compute/unixbench.py @@ -67,16 +67,18 @@ class Unixbench(base.Scenario): host = self.context_cfg["host"] user = host.get("user", "ubuntu") + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) ip = host.get("ip", None) key_filename = host.get('key_filename', "~/.ssh/id_rsa") LOG.info("user:%s, host:%s", user, ip) - self.client = ssh.SSH(user, ip, key_filename=key_filename) + self.client = ssh.SSH(user, ip, key_filename=key_filename, + port=ssh_port) self.client.wait(timeout=600) # copy scripts to host - self.client.run("cat > ~/unixbench_benchmark.sh", - stdin=open(self.target_script, 'rb')) + self.client._put_file_shell( + self.target_script, '~/unixbench_benchmark.sh') self.setup_done = True @@ -152,5 +154,6 @@ def _test(): # pragma: no cover p.run(result) print result + if __name__ == '__main__': _test() diff --git a/yardstick/benchmark/scenarios/networking/iperf3.py b/yardstick/benchmark/scenarios/networking/iperf3.py index bb41c3df1..13fa0155b 100644 --- a/yardstick/benchmark/scenarios/networking/iperf3.py +++ b/yardstick/benchmark/scenarios/networking/iperf3.py @@ -56,21 +56,24 @@ For more info see http://software.es.net/iperf def setup(self): host = self.context_cfg['host'] host_user = host.get('user', 'ubuntu') + host_ssh_port = host.get('ssh_port', ssh.DEFAULT_PORT) host_ip = host.get('ip', None) host_key_filename = host.get('key_filename', '~/.ssh/id_rsa') target = self.context_cfg['target'] target_user = target.get('user', 'ubuntu') + target_ssh_port = target.get('ssh_port', ssh.DEFAULT_PORT) target_ip = target.get('ip', None) target_key_filename = target.get('key_filename', '~/.ssh/id_rsa') LOG.info("user:%s, target:%s", target_user, target_ip) self.target = ssh.SSH(target_user, target_ip, - key_filename=target_key_filename) + key_filename=target_key_filename, + port=target_ssh_port) self.target.wait(timeout=600) LOG.info("user:%s, host:%s", host_user, host_ip) self.host = ssh.SSH(host_user, host_ip, - key_filename=host_key_filename) + key_filename=host_key_filename, port=host_ssh_port) self.host.wait(timeout=600) cmd = "iperf3 -s -D" diff --git a/yardstick/benchmark/scenarios/networking/netperf.py b/yardstick/benchmark/scenarios/networking/netperf.py index dcd4ef7b6..28f5bea56 100755 --- a/yardstick/benchmark/scenarios/networking/netperf.py +++ b/yardstick/benchmark/scenarios/networking/netperf.py @@ -62,27 +62,30 @@ class Netperf(base.Scenario): Netperf.TARGET_SCRIPT) host = self.context_cfg['host'] host_user = host.get('user', 'ubuntu') + host_ssh_port = host.get('ssh_port', ssh.DEFAULT_PORT) host_ip = host.get('ip', None) host_key_filename = host.get('key_filename', '~/.ssh/id_rsa') target = self.context_cfg['target'] target_user = target.get('user', 'ubuntu') + target_ssh_port = target.get('ssh_port', ssh.DEFAULT_PORT) target_ip = target.get('ip', None) target_key_filename = target.get('key_filename', '~/.ssh/id_rsa') # netserver start automatically during the vm boot LOG.info("user:%s, target:%s", target_user, target_ip) self.server = ssh.SSH(target_user, target_ip, - key_filename=target_key_filename) + key_filename=target_key_filename, + port=target_ssh_port) self.server.wait(timeout=600) LOG.info("user:%s, host:%s", host_user, host_ip) self.client = ssh.SSH(host_user, host_ip, - key_filename=host_key_filename) + key_filename=host_key_filename, + port=host_ssh_port) self.client.wait(timeout=600) # copy script to host - self.client.run("cat > ~/netperf.sh", - stdin=open(self.target_script, "rb")) + self.client._put_file_shell(self.target_script, '~/netperf.sh') self.setup_done = True @@ -174,5 +177,6 @@ def _test(): netperf.run(result) print result + if __name__ == '__main__': _test() diff --git a/yardstick/benchmark/scenarios/networking/netperf_benchmark.bash b/yardstick/benchmark/scenarios/networking/netperf_benchmark.bash index a425c5df0..f6245c9cd 100755 --- a/yardstick/benchmark/scenarios/networking/netperf_benchmark.bash +++ b/yardstick/benchmark/scenarios/networking/netperf_benchmark.bash @@ -12,6 +12,7 @@ set -e # Commandline arguments +OPTIONS_SIZE="$#" OPTIONS="$@" OUTPUT_FILE=/tmp/netperf-out.log @@ -24,14 +25,40 @@ run_netperf() # write the result to stdout in json format output_json() { - mean=$(awk '/\/s/{print $3}' $OUTPUT_FILE) - troughput=$(awk '/\/s/{print $1}' $OUTPUT_FILE) - unit=$(awk '/\/s/{print $2}' $OUTPUT_FILE) - echo -e "{ \ - \"mean_latency\":\"$mean\", \ - \"troughput\":\"$troughput\", \ - \"troughput_unit\":\"$unit\" \ - }" + #ARR=($OPTIONS) + #declare -p ARR + read -r -a ARR <<< "$OPTIONS" + opt_size=0 + while [ $opt_size -lt "$OPTIONS_SIZE" ] + do + if [ "${ARR[$opt_size]}" = "-O" ] + then + break + fi + opt_size=$((opt_size+1)) + done + opt_size=$((opt_size+1)) + out_opt="${ARR[$opt_size]}" + IFS=, read -r -a PARTS <<< "$out_opt" + #declare -p PARTS + part_num=${#PARTS[*]} + tran_num=0 + for f in "${PARTS[@]}" + do + array_name[$tran_num]=$(echo "$f" | tr '[A-Z]' '[a-z]') + tran_num=$((tran_num+1)) + done + read -r -a DATA_PARTS <<< "$(sed -n '$p' $OUTPUT_FILE)" + out_str="{" + for((i=0;i<part_num-1;i++)) + do + modify_str=\"${array_name[i]}\":\"${DATA_PARTS[i]}\", + out_str=$out_str$modify_str + done + modify_str=\"${array_name[part_num-1]}\":\"${DATA_PARTS[part_num-1]}\" + out_str=$out_str$modify_str"}" + + echo -e "$out_str" } # main entry @@ -44,4 +71,4 @@ main() output_json } -main
\ No newline at end of file +main diff --git a/yardstick/benchmark/scenarios/networking/netperf_install.bash b/yardstick/benchmark/scenarios/networking/netperf_install.bash index eaa9f530a..0e3808f9c 100755 --- a/yardstick/benchmark/scenarios/networking/netperf_install.bash +++ b/yardstick/benchmark/scenarios/networking/netperf_install.bash @@ -11,6 +11,13 @@ set -e +svc="netserver" +if pgrep $svc >/dev/null +then + echo "$svc have existed, exit!" + exit 0 +fi + echo "===Install netperf before test begin!!!===" cp /etc/apt/sources.list /etc/apt/sources.list_bkp cp /etc/resolv.conf /etc/resolv.conf_bkp @@ -30,3 +37,4 @@ sudo apt-get install -y netperf service netperf start echo "===Install netperf before test end!!!===" + diff --git a/yardstick/benchmark/scenarios/networking/netperf_node.py b/yardstick/benchmark/scenarios/networking/netperf_node.py index 87aa8d78d..a76982b6f 100755 --- a/yardstick/benchmark/scenarios/networking/netperf_node.py +++ b/yardstick/benchmark/scenarios/networking/netperf_node.py @@ -63,9 +63,11 @@ class NetperfNode(base.Scenario): NetperfNode.TARGET_SCRIPT) host = self.context_cfg['host'] host_user = host.get('user', 'ubuntu') + host_ssh_port = host.get('ssh_port', ssh.DEFAULT_PORT) host_ip = host.get('ip', None) target = self.context_cfg['target'] target_user = target.get('user', 'ubuntu') + target_ssh_port = target.get('ssh_port', ssh.DEFAULT_PORT) target_ip = target.get('ip', None) self.target_ip = target.get('ip', None) host_password = host.get('password', None) @@ -75,18 +77,17 @@ class NetperfNode(base.Scenario): # netserver start automatically during the vm boot LOG.info("user:%s, target:%s", target_user, target_ip) self.server = ssh.SSH(target_user, target_ip, - password=target_password) + password=target_password, port=target_ssh_port) self.server.wait(timeout=600) LOG.info("user:%s, host:%s", host_user, host_ip) self.client = ssh.SSH(host_user, host_ip, - password=host_password) + password=host_password, port=host_ssh_port) self.client.wait(timeout=600) # copy script to host - self.client.run("cat > ~/netperf.sh", - stdin=open(self.target_script, "rb")) - + with open(self.target_script, "rb") as file_run: + self.client.run("cat > ~/netperf.sh", stdin=file_run) # copy script to host and client self.install_script = pkg_resources.resource_filename( 'yardstick.benchmark.scenarios.networking', @@ -95,14 +96,14 @@ class NetperfNode(base.Scenario): 'yardstick.benchmark.scenarios.networking', NetperfNode.REMOVE_SCRIPT) - self.server.run("cat > ~/netperf_install.sh", - stdin=open(self.install_script, "rb")) - self.client.run("cat > ~/netperf_install.sh", - stdin=open(self.install_script, "rb")) - self.server.run("cat > ~/netperf_remove.sh", - stdin=open(self.remove_script, "rb")) - self.client.run("cat > ~/netperf_remove.sh", - stdin=open(self.remove_script, "rb")) + with open(self.install_script, "rb") as file_install: + self.server.run("cat > ~/netperf_install.sh", stdin=file_install) + with open(self.install_script, "rb") as file_install: + self.client.run("cat > ~/netperf_install.sh", stdin=file_install) + with open(self.remove_script, "rb") as file_remove: + self.server.run("cat > ~/netperf_remove.sh", stdin=file_remove) + with open(self.remove_script, "rb") as file_remove: + self.client.run("cat > ~/netperf_remove.sh", stdin=file_remove) self.server.execute("sudo bash netperf_install.sh") self.client.execute("sudo bash netperf_install.sh") @@ -129,10 +130,12 @@ class NetperfNode(base.Scenario): else: testlen = 20 - cmd_args = "-H %s -l %s -t %s" % (ipaddr, testlen, testname) + cmd_args = "-H %s -l %s -t %s -c -C" % (ipaddr, testlen, testname) # get test specific options - default_args = "-O 'THROUGHPUT,THROUGHPUT_UNITS,MEAN_LATENCY'" + output_opt = options.get( + "output_opt", "THROUGHPUT,THROUGHPUT_UNITS,MEAN_LATENCY") + default_args = "-O %s" % output_opt cmd_args += " -- %s" % default_args option_pair_list = [("send_msg_size", "-m"), ("recv_msg_size", "-M"), diff --git a/yardstick/benchmark/scenarios/networking/netutilization.py b/yardstick/benchmark/scenarios/networking/netutilization.py index ea43e6077..1ea92cca3 100644 --- a/yardstick/benchmark/scenarios/networking/netutilization.py +++ b/yardstick/benchmark/scenarios/networking/netutilization.py @@ -70,18 +70,20 @@ class NetUtilization(base.Scenario): """Scenario setup.""" host = self.context_cfg['host'] user = host.get('user', 'ubuntu') + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) ip = host.get('ip', None) key_filename = host.get('key_filename', '~/.ssh/id_rsa') LOG.info("user:%s, host:%s", user, ip) - self.client = ssh.SSH(user, ip, key_filename=key_filename) + self.client = ssh.SSH(user, ip, key_filename=key_filename, + port=ssh_port) self.client.wait(timeout=600) self.setup_done = True def _execute_command(self, cmd): """Execute a command on target.""" - LOG.info("Executing: %s" % cmd) + LOG.info("Executing: %s", cmd) status, stdout, stderr = self.client.execute(cmd) if status: raise RuntimeError("Failed executing command: ", diff --git a/yardstick/benchmark/scenarios/networking/networkcapacity.bash b/yardstick/benchmark/scenarios/networking/networkcapacity.bash index a18f97e0b..e2d3eb745 100644 --- a/yardstick/benchmark/scenarios/networking/networkcapacity.bash +++ b/yardstick/benchmark/scenarios/networking/networkcapacity.bash @@ -9,7 +9,7 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -# Measure compute capacity and scale of a host +# Measure network capacity and scale of a host set -e OUTPUT_FILE=/tmp/netperf-out.log diff --git a/yardstick/benchmark/scenarios/networking/networkcapacity.py b/yardstick/benchmark/scenarios/networking/networkcapacity.py index 57d3b5072..250f7eaf0 100644 --- a/yardstick/benchmark/scenarios/networking/networkcapacity.py +++ b/yardstick/benchmark/scenarios/networking/networkcapacity.py @@ -1,69 +1,70 @@ -##############################################################################
-# Copyright (c) 2016 Huawei Technologies Co.,Ltd 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
-##############################################################################
-import pkg_resources
-import logging
-import json
-
-import yardstick.ssh as ssh
-from yardstick.benchmark.scenarios import base
-
-LOG = logging.getLogger(__name__)
-
-
-class NetworkCapacity(base.Scenario):
- """Measure Network capacity and scale.
-
- This scenario reads network status including number of connections,
- number of frames sent/received.
- """
- __scenario_type__ = "NetworkCapacity"
- TARGET_SCRIPT = "networkcapacity.bash"
-
- def __init__(self, scenario_cfg, context_cfg):
- self.scenario_cfg = scenario_cfg
- self.context_cfg = context_cfg
- self.setup_done = False
-
- def setup(self):
- """scenario setup"""
- self.target_script = pkg_resources.resource_filename(
- "yardstick.benchmark.scenarios.networking",
- NetworkCapacity.TARGET_SCRIPT)
-
- host = self.context_cfg['host']
- if host is None:
- raise RuntimeError('No right node.please check the configuration')
- host_user = host.get('user', 'ubuntu')
- host_ip = host.get('ip', None)
- host_pwd = host.get('password', None)
-
- LOG.debug("user:%s, host:%s", host_user, host_ip)
- self.client = ssh.SSH(host_user, host_ip, password=host_pwd)
- self.client.wait(timeout=600)
-
- # copy script to host
- self.client.run("cat > ~/networkcapacity.sh",
- stdin=open(self.target_script, 'rb'))
-
- self.setup_done = True
-
- def run(self, result):
- """execute the benchmark"""
-
- if not self.setup_done:
- self.setup()
-
- cmd = "sudo bash networkcapacity.sh"
-
- LOG.debug("Executing command: %s", cmd)
- status, stdout, stderr = self.client.execute(cmd)
- if status:
- raise RuntimeError(stderr)
-
- result.update(json.loads(stdout))
+############################################################################## +# Copyright (c) 2016 Huawei Technologies Co.,Ltd 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 +############################################################################## +import pkg_resources +import logging +import json + +import yardstick.ssh as ssh +from yardstick.benchmark.scenarios import base + +LOG = logging.getLogger(__name__) + + +class NetworkCapacity(base.Scenario): + """Measure Network capacity and scale. + + This scenario reads network status including number of connections, + number of frames sent/received. + """ + __scenario_type__ = "NetworkCapacity" + TARGET_SCRIPT = "networkcapacity.bash" + + def __init__(self, scenario_cfg, context_cfg): + self.scenario_cfg = scenario_cfg + self.context_cfg = context_cfg + self.setup_done = False + + def setup(self): + """scenario setup""" + self.target_script = pkg_resources.resource_filename( + "yardstick.benchmark.scenarios.networking", + NetworkCapacity.TARGET_SCRIPT) + + host = self.context_cfg['host'] + if host is None: + raise RuntimeError('No right node.please check the configuration') + host_user = host.get('user', 'ubuntu') + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) + host_ip = host.get('ip', None) + host_pwd = host.get('password', None) + + LOG.debug("user:%s, host:%s", host_user, host_ip) + self.client = ssh.SSH(host_user, host_ip, password=host_pwd, + port=ssh_port) + self.client.wait(timeout=600) + + # copy script to host + self.client._put_file_shell(self.target_script, '~/networkcapacity.sh') + + self.setup_done = True + + def run(self, result): + """execute the benchmark""" + + if not self.setup_done: + self.setup() + + cmd = "sudo bash networkcapacity.sh" + + LOG.debug("Executing command: %s", cmd) + status, stdout, stderr = self.client.execute(cmd) + if status: + raise RuntimeError(stderr) + + result.update(json.loads(stdout)) diff --git a/yardstick/benchmark/scenarios/networking/ping.py b/yardstick/benchmark/scenarios/networking/ping.py index e09ea4a20..6e49a1437 100644 --- a/yardstick/benchmark/scenarios/networking/ping.py +++ b/yardstick/benchmark/scenarios/networking/ping.py @@ -39,6 +39,7 @@ class Ping(base.Scenario): 'yardstick.benchmark.scenarios.networking', Ping.TARGET_SCRIPT) host = self.context_cfg['host'] user = host.get('user', 'ubuntu') + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) ip = host.get('ip', None) key_filename = host.get('key_filename', '/root/.ssh/id_rsa') password = host.get('password', None) @@ -46,11 +47,13 @@ class Ping(base.Scenario): if password is not None: LOG.info("Log in via pw, user:%s, host:%s, pw:%s", user, ip, password) - self.connection = ssh.SSH(user, ip, password=password) + self.connection = ssh.SSH(user, ip, password=password, + port=ssh_port) else: LOG.info("Log in via key, user:%s, host:%s, key_filename:%s", user, ip, key_filename) - self.connection = ssh.SSH(user, ip, key_filename=key_filename) + self.connection = ssh.SSH(user, ip, key_filename=key_filename, + port=ssh_port) self.connection.wait(timeout=600) @@ -76,9 +79,10 @@ class Ping(base.Scenario): target_vm = self.scenario_cfg['target'] LOG.debug("ping '%s' '%s'", options, dest) - exit_status, stdout, stderr = self.connection.execute( - "/bin/sh -s {0} {1}".format(dest, options), - stdin=open(self.target_script, "r")) + with open(self.target_script, "r") as stdin_file: + exit_status, stdout, stderr = self.connection.execute( + "/bin/sh -s {0} {1}".format(dest, options), + stdin=stdin_file) if exit_status != 0: raise RuntimeError(stderr) diff --git a/yardstick/benchmark/scenarios/networking/ping6.py b/yardstick/benchmark/scenarios/networking/ping6.py index e68756462..f4d23ce7b 100644 --- a/yardstick/benchmark/scenarios/networking/ping6.py +++ b/yardstick/benchmark/scenarios/networking/ping6.py @@ -37,28 +37,50 @@ class Ping6(base.Scenario): # pragma: no cover def __init__(self, scenario_cfg, context_cfg): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg + self.nodes = context_cfg['nodes'] + self.options = scenario_cfg['options'] self.setup_done = False self.run_done = False + self.external_network = self.options.get("external_network", "ext-net") + self.ping_options = "-s %s -c %s" % \ + (self.options.get("packetsize", '56'), + self.options.get("ping_count", '5')) + self.openrc = self.options.get("openrc", "/opt/admin-openrc.sh") + + def _ssh_host(self, node_name): + # ssh host + node = self.nodes.get(node_name, None) + user = node.get('user', 'ubuntu') + ssh_port = node.get("ssh_port", ssh.DEFAULT_PORT) + ip = node.get('ip', None) + pwd = node.get('password', None) + key_fname = node.get('key_filename', '/root/.ssh/id_rsa') + if pwd is not None: + LOG.debug("Log in via pw, user:%s, host:%s, password:%s", + user, ip, pwd) + self.client = ssh.SSH(user, ip, password=pwd, port=ssh_port) + else: + LOG.debug("Log in via key, user:%s, host:%s, key_filename:%s", + user, ip, key_fname) + self.client = ssh.SSH(user, ip, key_filename=key_fname, + port=ssh_port) + self.client.wait(timeout=60) def _pre_setup(self): for node_name in self.host_list: self._ssh_host(node_name) - self.client.run("cat > ~/pre_setup.sh", - stdin=open(self.pre_setup_script, "rb")) + self.client._put_file_shell( + self.pre_setup_script, '~/pre_setup.sh') status, stdout, stderr = self.client.execute( "sudo bash pre_setup.sh") - def _ssh_host(self, node_name): - # ssh host - print node_name - nodes = self.context_cfg['nodes'] - node = nodes.get(node_name, None) - host_user = node.get('user', 'ubuntu') - host_ip = node.get('ip', None) - host_pwd = node.get('password', 'root') - LOG.debug("user:%s, host:%s", host_user, host_ip) - self.client = ssh.SSH(host_user, host_ip, password=host_pwd) - self.client.wait(timeout=600) + def _get_controller_node(self, host_list): + for host_name in host_list: + node = self.nodes.get(host_name, None) + node_role = node.get('role', None) + if node_role == 'Controller': + return host_name + return None def setup(self): '''scenario setup''' @@ -82,33 +104,36 @@ class Ping6(base.Scenario): # pragma: no cover 'yardstick.benchmark.scenarios.networking', Ping6.RADVD_SCRIPT) - options = self.scenario_cfg['options'] - host_str = options.get("host", 'host1') + host_str = self.options.get("host", 'host1') self.host_list = host_str.split(',') self.host_list.sort() - pre_setup = options.get("pre_setup", True) + pre_setup = self.options.get("pre_setup", True) if pre_setup: self._pre_setup() - # ssh host1 - self._ssh_host(self.host_list[0]) - - self.client.run("cat > ~/metadata.txt", - stdin=open(self.ping6_metadata_script, "rb")) + # log in a contronller node to setup + controller_node_name = self._get_controller_node(self.host_list) + LOG.debug("The Controller Node is: %s", controller_node_name) + if controller_node_name is None: + LOG.exception("Can't find controller node in the context!!!") + self._ssh_host(controller_node_name) + self.client._put_file_shell( + self.ping6_metadata_script, '~/metadata.txt') # run script to setup ipv6 with nosdn or odl - sdn = options.get("sdn", 'nosdn') + sdn = self.options.get("sdn", 'nosdn') if 'odl' in sdn: - self.client.run("cat > ~/br-ex.radvd.conf", - stdin=open(self.ping6_radvd_script, "rb")) - self.client.run("cat > ~/setup_odl.sh", - stdin=open(self.setup_odl_script, "rb")) - cmd = "sudo bash setup_odl.sh" + self.client._put_file_shell( + self.ping6_radvd_script, '~/br-ex.radvd.conf') + self.client._put_file_shell( + self.setup_odl_script, '~/setup_odl.sh') + setup_bash_file = "setup_odl.sh" else: - self.client.run("cat > ~/setup.sh", - stdin=open(self.setup_script, "rb")) - cmd = "sudo bash setup.sh" - + self.client._put_file_shell(self.setup_script, '~/setup.sh') + setup_bash_file = "setup.sh" + cmd = "sudo bash %s %s %s" % \ + (setup_bash_file, self.openrc, self.external_network) + LOG.debug("Executing setup command: %s", cmd) status, stdout, stderr = self.client.execute(cmd) self.setup_done = True @@ -123,19 +148,17 @@ class Ping6(base.Scenario): # pragma: no cover self.ping6_find_host_script = pkg_resources.resource_filename( 'yardstick.benchmark.scenarios.networking', Ping6.FIND_HOST_SCRIPT) - if not self.setup_done: - options = self.scenario_cfg['options'] - host_str = options.get("host", 'host1') + host_str = self.options.get("host", 'host1') self.host_list = host_str.split(',') self.host_list.sort() self._ssh_host(self.host_list[0]) # find ipv4-int-network1 to ssh VM - self.client.run("cat > ~/find_host.sh", - stdin=open(self.ping6_find_host_script, "rb")) - cmd = "sudo bash find_host.sh" - LOG.debug("Executing command: %s", cmd) + self.client._put_file_shell( + self.ping6_find_host_script, '~/find_host.sh') + cmd = "sudo bash find_host.sh %s" % self.openrc + LOG.debug("Executing find_host command: %s", cmd) status, stdout, stderr = self.client.execute(cmd) host_name = stdout.strip() @@ -147,10 +170,9 @@ class Ping6(base.Scenario): # pragma: no cover stdin=open("/tmp/vRouterKey", "rb")) # run ping6 benchmark - self.client.run("cat > ~/ping6.sh", - stdin=open(self.ping6_script, "rb")) - cmd = "sudo bash ping6.sh" - LOG.debug("Executing command: %s", cmd) + self.client._put_file_shell(self.ping6_script, '~/ping6.sh') + cmd = "sudo bash ping6.sh %s %s" % (self.openrc, self.ping_options) + LOG.debug("Executing ping6 command: %s", cmd) status, stdout, stderr = self.client.execute(cmd) if status: @@ -164,7 +186,7 @@ class Ping6(base.Scenario): # pragma: no cover assert result["rtt"] <= sla_max_rtt, \ "rtt %f > sla:max_rtt(%f); " % (result["rtt"], sla_max_rtt) else: - LOG.error("ping6 timeout") + LOG.error("ping6 timeout!!!") self.run_done = True def teardown(self): @@ -174,8 +196,7 @@ class Ping6(base.Scenario): # pragma: no cover 'yardstick.benchmark.scenarios.networking', Ping6.POST_TEARDOWN_SCRIPT) - options = self.scenario_cfg['options'] - host_str = options.get("host", 'node1') + host_str = self.options.get("host", 'node1') self.host_list = host_str.split(',') self.host_list.sort() @@ -185,12 +206,12 @@ class Ping6(base.Scenario): # pragma: no cover self.teardown_script = pkg_resources.resource_filename( 'yardstick.benchmark.scenarios.networking', Ping6.TEARDOWN_SCRIPT) - self.client.run("cat > ~/teardown.sh", - stdin=open(self.teardown_script, "rb")) - cmd = "sudo bash teardown.sh" + self.client._put_file_shell(self.teardown_script, '~/teardown.sh') + cmd = "sudo bash teardown.sh %s %s" % \ + (self.openrc, self.external_network) status, stdout, stderr = self.client.execute(cmd) - post_teardown = options.get("post_teardown", True) + post_teardown = self.options.get("post_teardown", True) if post_teardown: self._post_teardown() @@ -205,7 +226,7 @@ class Ping6(base.Scenario): # pragma: no cover def _post_teardown(self): for node_name in self.host_list: self._ssh_host(node_name) - self.client.run("cat > ~/post_teardown.sh", - stdin=open(self.post_teardown_script, "rb")) + self.client._put_file_shell( + self.post_teardown_script, '~/post_teardown.sh') status, stdout, stderr = self.client.execute( "sudo bash post_teardown.sh") diff --git a/yardstick/benchmark/scenarios/networking/ping6_benchmark.bash b/yardstick/benchmark/scenarios/networking/ping6_benchmark.bash index 16cb0f07e..a50e01f65 100644 --- a/yardstick/benchmark/scenarios/networking/ping6_benchmark.bash +++ b/yardstick/benchmark/scenarios/networking/ping6_benchmark.bash @@ -11,12 +11,18 @@ # Run a single ping6 command towards a ipv6 router set -e -source /opt/admin-openrc.sh +openrc=$1 +source $openrc +shift +ping6_options=$* chmod 600 vRouterKey + # TODO find host +vm1_ip=$(nova list|grep VM1 | awk -F [=] '{print $2}' | awk '{print $1}') +# echo "vm1_ip=$vm1_ip" wait_vm_ok() { retry=0 - until timeout 100s sudo ip netns exec qdhcp-$(neutron net-list | grep -w ipv4-int-network1 | awk '{print $2}') ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i vRouterKey fedora@20.0.0.4 "exit" >/dev/null 2>&1 + until timeout 100s sudo ip netns exec qdhcp-$(neutron net-list | grep -w ipv4-int-network1 | awk '{print $2}') ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i vRouterKey fedora@$vm1_ip "exit" >/dev/null 2>&1 do sleep 10 let retry+=1 @@ -29,4 +35,4 @@ wait_vm_ok() { } wait_vm_ok sleep 360 -sudo ip netns exec qdhcp-$(neutron net-list | grep -w ipv4-int-network1 | awk '{print $2}') ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i vRouterKey fedora@20.0.0.4 "ping6 -c 1 2001:db8:0:1::1 | grep ttl | awk -F [=\ ] '{printf \$10}'"
\ No newline at end of file +sudo ip netns exec qdhcp-$(neutron net-list | grep -w ipv4-int-network1 | awk '{print $2}') ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i vRouterKey fedora@$vm1_ip "ping6 $ping6_options 2001:db8:0:1::1 | grep rtt | awk -F [\/\ ] '{printf \$8}'" diff --git a/yardstick/benchmark/scenarios/networking/ping6_find_host.bash b/yardstick/benchmark/scenarios/networking/ping6_find_host.bash index 85c4b3898..db8dbe881 100644 --- a/yardstick/benchmark/scenarios/networking/ping6_find_host.bash +++ b/yardstick/benchmark/scenarios/networking/ping6_find_host.bash @@ -8,7 +8,7 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## - -source /opt/admin-openrc.sh -host_num=$(neutron dhcp-agent-list-hosting-net ipv4-int-network1 | grep True | awk -F [=\ ] '{printf $4}') > /tmp/ipv6.log -echo $host_num
\ No newline at end of file +openrc=$* +source $openrc +host_num=$(neutron dhcp-agent-list-hosting-net ipv4-int-network1 | grep True | head -1 | awk -F [=\ ] '{printf $4}' | grep -o '[0-9]\+') > /tmp/ipv6.log +echo "host$host_num" diff --git a/yardstick/benchmark/scenarios/networking/ping6_metadata.txt b/yardstick/benchmark/scenarios/networking/ping6_metadata.txt index 5dc08d30f..ad97b24c1 100644 --- a/yardstick/benchmark/scenarios/networking/ping6_metadata.txt +++ b/yardstick/benchmark/scenarios/networking/ping6_metadata.txt @@ -45,7 +45,11 @@ write_files: owner: root:root - content: | TYPE="Ethernet" - BOOTPROTO=static + BOOTPROTO="dhcp" + DEFROUTE="no" + PEERDNS="no" + PEERROUTES="no" + IPV4_FAILURE_FATAL="no" IPV6INIT=yes IPV6ADDR="2001:db8:0:2::1/64" NAME=eth1 @@ -79,4 +83,4 @@ write_files: IPV6FORWARDING=yes path: /etc/sysconfig/network permissions: '0644' - owner: root:root
\ No newline at end of file + owner: root:root diff --git a/yardstick/benchmark/scenarios/networking/ping6_post_teardown.bash b/yardstick/benchmark/scenarios/networking/ping6_post_teardown.bash index f40d47d64..a0976e3d5 100644 --- a/yardstick/benchmark/scenarios/networking/ping6_post_teardown.bash +++ b/yardstick/benchmark/scenarios/networking/ping6_post_teardown.bash @@ -8,10 +8,7 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -sed -i 's/enable_security_group= False/enable_security_group = True/g' /etc/neutron/plugins/ml2/ml2_conf.ini -sed -i 3d /etc/neutron/plugins/ml2/ml2_conf.ini -sed -i 's/firewall_driver= neutron.agent.firewall.NoopFirewallDriver/firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver/g' /etc/neutron/plugins/ml2/ml2_conf.ini -sed -i 's/security_group_api= nova/security_group_api = neutron/g' /etc/nova/nova.conf +cp /etc/neutron/plugins/ml2/ml2_conf.ini_bkp /etc/neutron/plugins/ml2/ml2_conf.ini service neutron-l3-agent restart service neutron-dhcp-agent restart @@ -23,4 +20,4 @@ service nova-conductor restart service nova-consoleauth restart service nova-novncproxy restart service nova-scheduler restart -service nova-compute restart
\ No newline at end of file +service nova-compute restart diff --git a/yardstick/benchmark/scenarios/networking/ping6_pre_setup.bash b/yardstick/benchmark/scenarios/networking/ping6_pre_setup.bash index 4a781d21e..7fa60592d 100644 --- a/yardstick/benchmark/scenarios/networking/ping6_pre_setup.bash +++ b/yardstick/benchmark/scenarios/networking/ping6_pre_setup.bash @@ -9,12 +9,34 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -sed -i 's/enable_security_group = True/enable_security_group= False/g' /etc/neutron/plugins/ml2/ml2_conf.ini -sed -i '2a extension_drivers = port_security' /etc/neutron/plugins/ml2/ml2_conf.ini -sed -i 's/firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver/firewall_driver= neutron.agent.firewall.NoopFirewallDriver/g' /etc/neutron/plugins/ml2/ml2_conf.ini -sed -i 's/security_group_api = neutron/security_group_api= nova/g' /etc/nova/nova.conf +ML2_CONF_FILE="/etc/neutron/plugins/ml2/ml2_conf.ini" +NOVA_CONF_FILE="/etc/nova/nova.conf" +cp $ML2_CONF_FILE ${ML2_CONF_FILE}_bkp + +agent_line_num=$(grep -n '\[agent\]' $ML2_CONF_FILE | awk -F [:] '{print $1}') +if [ -z "$agent_line_num" ] +then + echo "[agent]" >> $ML2_CONF_FILE + agent_line_num=$(wc -l $ML2_CONF_FILE | awk '{print $1}') +fi +sed -i "${agent_line_num}a prevent_arp_spoofing = False" $ML2_CONF_FILE + +sed -i 's/firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver/firewall_driver= neutron.agent.firewall.NoopFirewallDriver/g' $ML2_CONF_FILE + +#check parameters +echo "check if parameters ok" +echo $ML2_CONF_FILE +grep -n 'enable_security_group = True' $ML2_CONF_FILE +grep -n 'extension_drivers = port_security' $ML2_CONF_FILE +grep -n 'prevent_arp_spoofing = False' $ML2_CONF_FILE +echo $NOVA_CONF_FILE +grep -n 'security_group_api = neutron' $NOVA_CONF_FILE +grep -n 'firewall_driver = nova.virt.firewall.NoopFirewallDriver' $NOVA_CONF_FILE +echo "check parameters end" + +# restart nova and neutron service service neutron-l3-agent restart service neutron-dhcp-agent restart service neutron-metadata-agent restart diff --git a/yardstick/benchmark/scenarios/networking/ping6_setup.bash b/yardstick/benchmark/scenarios/networking/ping6_setup.bash index 658e1d3cf..592ced3df 100644 --- a/yardstick/benchmark/scenarios/networking/ping6_setup.bash +++ b/yardstick/benchmark/scenarios/networking/ping6_setup.bash @@ -11,8 +11,17 @@ # download and create image -source /opt/admin-openrc.sh -wget https://download.fedoraproject.org/pub/fedora/linux/releases/22/Cloud/x86_64/Images/Fedora-Cloud-Base-22-20150521.x86_64.qcow2 >/dev/null 2>&1 +openrc=$1 +external_network=$2 +echo "openrc=$openrc" +echo "external_network=$external_network" +echo "nameserver 8.8.4.4" >> /etc/resolv.conf +source $openrc + +fedora_img="Fedora-Cloud-Base-22-20150521.x86_64.qcow2" +if [ ! -f "$fedora_img" ]; then + wget https://download.fedoraproject.org/pub/fedora/linux/releases/22/Cloud/x86_64/Images/${fedora_img} >/dev/null 2>&1 +fi glance image-create --name 'Fedora22' --disk-format qcow2 \ --container-format bare --file ./Fedora-Cloud-Base-22-20150521.x86_64.qcow2 @@ -24,8 +33,8 @@ neutron router-create ipv6-router # create (ipv4,ipv6)router and net and subnet -neutron net-create --port_security_enabled=False ipv4-int-network1 -neutron net-create --port_security_enabled=False ipv6-int-network2 +neutron net-create ipv4-int-network1 +neutron net-create ipv6-int-network2 # Create IPv4 subnet and associate it to ipv4-router neutron subnet-create --name ipv4-int-subnet1 \ @@ -33,8 +42,8 @@ neutron subnet-create --name ipv4-int-subnet1 \ neutron router-interface-add ipv4-router ipv4-int-subnet1 # Associate the net04_ext to the Neutron routers -neutron router-gateway-set ipv6-router ext-net -neutron router-gateway-set ipv4-router ext-net +neutron router-gateway-set ipv6-router $external_network +neutron router-gateway-set ipv4-router $external_network # Create two subnets, one IPv4 subnet ipv4-int-subnet2 and # one IPv6 subnet ipv6-int-subnet2 in ipv6-int-network2, and associate both subnets to ipv6-router @@ -78,4 +87,13 @@ nova boot --image Fedora22 --flavor m1.small \ --nic port-id=$(neutron port-list | grep -w eth0-VM2 | awk '{print $2}') \ --key-name vRouterKey VM2 +sleep 60 + nova list +# disable eth0-VM1, eth0-VM2, eth0-vRouter, eth1-vRouter port-security +for port in eth0-VM1 eth0-VM2 eth0-vRouter eth1-vRouter +do + neutron port-update --no-security-groups $port + neutron port-update $port --port-security-enabled=False + neutron port-show $port | grep port_security_enabled +done diff --git a/yardstick/benchmark/scenarios/networking/ping6_setup_with_odl.bash b/yardstick/benchmark/scenarios/networking/ping6_setup_with_odl.bash index f9a2c4094..21566d2aa 100644 --- a/yardstick/benchmark/scenarios/networking/ping6_setup_with_odl.bash +++ b/yardstick/benchmark/scenarios/networking/ping6_setup_with_odl.bash @@ -11,7 +11,11 @@ # need to debug # download and create image -source /opt/admin-openrc.sh +openrc=$1 +external_network=$2 +echo "openrc=$openrc" +echo "external_network=$external_network" +source $openrc wget https://download.fedoraproject.org/pub/fedora/linux/releases/22/Cloud/x86_64/Images/Fedora-Cloud-Base-22-20150521.x86_64.qcow2 glance image-create --name 'Fedora22' --disk-format qcow2 \ --container-format bare --file ./Fedora-Cloud-Base-22-20150521.x86_64.qcow2 @@ -21,8 +25,8 @@ neutron router-create ipv4-router neutron router-create ipv6-router # Associate the net04_ext to the Neutron routers -neutron router-gateway-set ipv6-router ext-net -neutron router-gateway-set ipv4-router ext-net +neutron router-gateway-set ipv6-router $external_network +neutron router-gateway-set ipv4-router $external_network # create two ipv4 networks with associated subnets neutron net-create ipv4-int-network1 diff --git a/yardstick/benchmark/scenarios/networking/ping6_teardown.bash b/yardstick/benchmark/scenarios/networking/ping6_teardown.bash index 33eff5ca7..2fe3ef2fb 100644 --- a/yardstick/benchmark/scenarios/networking/ping6_teardown.bash +++ b/yardstick/benchmark/scenarios/networking/ping6_teardown.bash @@ -8,7 +8,11 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -source /opt/admin-openrc.sh +openrc=$1 +echo "openrc=$openrc" +source $openrc +external_network=$2 +echo "external_network=$external_network" # delete VM nova delete VM1 nova delete VM2 @@ -36,8 +40,8 @@ neutron subnet-delete --name ipv6-int-subnet2 neutron subnet-delete --name ipv4-int-subnet2 #clear gateway -neutron router-gateway-clear ipv4-router ext-net -neutron router-gateway-clear ipv6-router ext-net +neutron router-gateway-clear ipv4-router $external_network +neutron router-gateway-clear ipv6-router $external_network #delete ipv4 router interface neutron router-interface-delete ipv4-router ipv4-int-subnet1 diff --git a/yardstick/benchmark/scenarios/networking/pktgen.py b/yardstick/benchmark/scenarios/networking/pktgen.py index 9dac4c90c..e2df706a2 100644 --- a/yardstick/benchmark/scenarios/networking/pktgen.py +++ b/yardstick/benchmark/scenarios/networking/pktgen.py @@ -49,26 +49,29 @@ class Pktgen(base.Scenario): Pktgen.TARGET_SCRIPT) host = self.context_cfg['host'] host_user = host.get('user', 'ubuntu') + host_ssh_port = host.get('ssh_port', ssh.DEFAULT_PORT) host_ip = host.get('ip', None) host_key_filename = host.get('key_filename', '~/.ssh/id_rsa') target = self.context_cfg['target'] target_user = target.get('user', 'ubuntu') + target_ssh_port = target.get('ssh_port', ssh.DEFAULT_PORT) target_ip = target.get('ip', None) target_key_filename = target.get('key_filename', '~/.ssh/id_rsa') LOG.info("user:%s, target:%s", target_user, target_ip) self.server = ssh.SSH(target_user, target_ip, - key_filename=target_key_filename) + key_filename=target_key_filename, + port=target_ssh_port) self.server.wait(timeout=600) LOG.info("user:%s, host:%s", host_user, host_ip) self.client = ssh.SSH(host_user, host_ip, - key_filename=host_key_filename) + key_filename=host_key_filename, + port=host_ssh_port) self.client.wait(timeout=600) # copy script to host - self.client.run("cat > ~/pktgen.sh", - stdin=open(self.target_script, "rb")) + self.client._put_file_shell(self.target_script, '~/pktgen.sh') self.setup_done = True @@ -169,5 +172,6 @@ def _test(): p.run(result) print result + if __name__ == '__main__': _test() diff --git a/yardstick/benchmark/scenarios/networking/pktgen_dpdk.py b/yardstick/benchmark/scenarios/networking/pktgen_dpdk.py index 86585eca3..503ea97e1 100644 --- a/yardstick/benchmark/scenarios/networking/pktgen_dpdk.py +++ b/yardstick/benchmark/scenarios/networking/pktgen_dpdk.py @@ -45,29 +45,32 @@ class PktgenDPDKLatency(base.Scenario): PktgenDPDKLatency.TESTPMD_SCRIPT) host = self.context_cfg['host'] host_user = host.get('user', 'ubuntu') + host_ssh_port = host.get('ssh_port', ssh.DEFAULT_PORT) host_ip = host.get('ip', None) host_key_filename = host.get('key_filename', '~/.ssh/id_rsa') target = self.context_cfg['target'] target_user = target.get('user', 'ubuntu') + target_ssh_port = target.get('ssh_port', ssh.DEFAULT_PORT) target_ip = target.get('ip', None) target_key_filename = target.get('key_filename', '~/.ssh/id_rsa') LOG.info("user:%s, target:%s", target_user, target_ip) self.server = ssh.SSH(target_user, target_ip, - key_filename=target_key_filename) + key_filename=target_key_filename, + port=target_ssh_port) self.server.wait(timeout=600) # copy script to host - self.server.run("cat > ~/testpmd_fwd.sh", - stdin=open(self.testpmd_script, "rb")) + self.server._put_file_shell(self.testpmd_script, '~/testpmd_fwd.sh') LOG.info("user:%s, host:%s", host_user, host_ip) self.client = ssh.SSH(host_user, host_ip, - key_filename=host_key_filename) + key_filename=host_key_filename, + port=host_ssh_port) self.client.wait(timeout=600) # copy script to host - self.client.run("cat > ~/pktgen_dpdk.sh", - stdin=open(self.pktgen_dpdk_script, "rb")) + self.client._put_file_shell( + self.pktgen_dpdk_script, '~/pktgen_dpdk.sh') self.setup_done = True self.testpmd_args = '' @@ -149,7 +152,7 @@ class PktgenDPDKLatency(base.Scenario): latency_sum = 0 for i in latency_list: latency_sum += int(i) - avg_latency = latency_sum/len(latency_list) + avg_latency = latency_sum / len(latency_list) result.update({"avg_latency": avg_latency}) diff --git a/yardstick/benchmark/scenarios/networking/sfc.py b/yardstick/benchmark/scenarios/networking/sfc.py index a126bb52a..1bd99b957 100644 --- a/yardstick/benchmark/scenarios/networking/sfc.py +++ b/yardstick/benchmark/scenarios/networking/sfc.py @@ -41,15 +41,16 @@ class Sfc(base.Scenario): # pragma: no cover target = self.context_cfg['target'] target_user = target.get('user', 'root') + target_ssh_port = target.get('ssh_port', ssh.DEFAULT_PORT) target_pwd = target.get('password', 'opnfv') target_ip = target.get('ip', None) ''' webserver start automatically during the vm boot ''' LOG.info("user:%s, target:%s", target_user, target_ip) - self.server = ssh.SSH(target_user, target_ip, password=target_pwd) + self.server = ssh.SSH(target_user, target_ip, password=target_pwd, + port=target_ssh_port) self.server.wait(timeout=600) - self.server.run("cat > ~/server.sh", - stdin=open(self.server_script, "rb")) + self.server._put_file_shell(self.server_script, '~/server.sh') cmd_server = "sudo bash server.sh" LOG.debug("Executing command: %s", cmd_server) status, stdout, stderr = self.server.execute(cmd_server) @@ -59,11 +60,13 @@ class Sfc(base.Scenario): # pragma: no cover target = self.context_cfg['target'] SF1_user = target.get('user', 'root') + SF1_ssh_port = target.get('ssh_port', ssh.DEFAULT_PORT) SF1_pwd = target.get('password', 'opnfv') SF1_ip = ips[0] LOG.info("user:%s, host:%s", SF1_user, SF1_ip) - self.server = ssh.SSH(SF1_user, SF1_ip, password=SF1_pwd) + self.server = ssh.SSH(SF1_user, SF1_ip, password=SF1_pwd, + port=SF1_ssh_port) self.server.wait(timeout=600) cmd_SF1 = ("nohup python vxlan_tool.py -i eth0 " "-d forward -v off -b 80 &") @@ -74,11 +77,13 @@ class Sfc(base.Scenario): # pragma: no cover LOG.debug("HTTP firewall started") SF2_user = target.get('user', 'root') + SF2_ssh_port = target.get('ssh_port', ssh.DEFAULT_PORT) SF2_pwd = target.get('password', 'opnfv') SF2_ip = ips[1] LOG.info("user:%s, host:%s", SF2_user, SF2_ip) - self.server = ssh.SSH(SF2_user, SF2_ip, password=SF2_pwd) + self.server = ssh.SSH(SF2_user, SF2_ip, password=SF2_pwd, + port=SF2_ssh_port) self.server.wait(timeout=600) cmd_SF2 = ("nohup python vxlan_tool.py -i eth0 " "-d forward -v off -b 22 &") @@ -95,11 +100,13 @@ class Sfc(base.Scenario): # pragma: no cover ''' Creating client and server VMs to perform the test''' host = self.context_cfg['host'] host_user = host.get('user', 'root') + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) host_pwd = host.get('password', 'opnfv') host_ip = host.get('ip', None) LOG.info("user:%s, host:%s", host_user, host_ip) - self.client = ssh.SSH(host_user, host_ip, password=host_pwd) + self.client = ssh.SSH(host_user, host_ip, password=host_pwd, + port=ssh_port) self.client.wait(timeout=600) if not self.setup_done: # pragma: no cover diff --git a/yardstick/benchmark/scenarios/networking/vsperf.py b/yardstick/benchmark/scenarios/networking/vsperf.py index d3123083a..4f4ef21eb 100644 --- a/yardstick/benchmark/scenarios/networking/vsperf.py +++ b/yardstick/benchmark/scenarios/networking/vsperf.py @@ -32,14 +32,11 @@ class Vsperf(base.Scenario): the valid values are "rfc2544", "continuous", "back2back" type: string default: "rfc2544" - pkt_sizes - a packet size for which test should be executed; - Multiple packet sizes can be tested by modification of Sequence runner + frame_size - a frame size for which test should be executed; + Multiple frame sizes can be tested by modification of sequence runner section inside TC YAML definition. type: string default: "64" - duration - sets duration for which traffic will be generated - type: int - default: 30 bidirectional - speficies if traffic will be uni (False) or bi-directional (True) type: string @@ -47,9 +44,6 @@ class Vsperf(base.Scenario): iload - specifies frame rate type: string default: 100 - rfc2544_trials - the number of trials performed for each packet size - type: string - default: NA multistream - the number of simulated streams type: string default: 0 (disabled) @@ -57,11 +51,24 @@ class Vsperf(base.Scenario): the valid values are "L4", "L3" and "L2" type: string default: "L4" - conf-file - path to the vsperf configuration file, which will be uploaded - to the VM + test_params - specifies a string with a list of vsperf configuration + parameters, which will be passed to the '--test-params' CLI argument; + Parameters should be stated in the form of 'param=value' and separated + by a semicolon. Please check VSPERF documentation for details about + available configuration parameters and their data types. + In case that both 'test_params' and 'conf_file' are specified, + then values from 'test_params' will override values defined + in the configuration file. + type: string + default: NA + conf_file - path to the vsperf configuration file, which will be uploaded + to the VM; + In case that both 'test_params' and 'conf_file' are specified, + then values from 'test_params' will override values defined + in configuration file. type: string default: NA - setup-script - path to the setup script, which will be executed during + setup_script - path to the setup script, which will be executed during setup and teardown phases type: string default: NA @@ -80,8 +87,6 @@ class Vsperf(base.Scenario): """ __scenario_type__ = "Vsperf" - VSPERF_CONF = '~/vsperf-yardstick.conf' - def __init__(self, scenario_cfg, context_cfg): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg @@ -93,17 +98,23 @@ class Vsperf(base.Scenario): None) self.br_ex = self.scenario_cfg['options'].get('external_bridge', 'br-ex') - self.vsperf_conf = os.path.expanduser( - self.scenario_cfg['options'].get('conf-file', Vsperf.VSPERF_CONF)) - self.setup_script = self.scenario_cfg['options'].get('setup-script', + self.vsperf_conf = self.scenario_cfg['options'].get('conf_file', None) + if self.vsperf_conf: + self.vsperf_conf = os.path.expanduser(self.vsperf_conf) + + self.setup_script = self.scenario_cfg['options'].get('setup_script', None) if self.setup_script: self.setup_script = os.path.expanduser(self.setup_script) + self.test_params = self.scenario_cfg['options'].get('test-params', + None) + def setup(self): '''scenario setup''' vsperf = self.context_cfg['host'] vsperf_user = vsperf.get('user', 'ubuntu') + vsperf_ssh_port = vsperf.get('ssh_port', ssh.DEFAULT_PORT) vsperf_password = vsperf.get('password', 'ubuntu') vsperf_ip = vsperf.get('ip', None) @@ -118,13 +129,12 @@ class Vsperf(base.Scenario): # copy vsperf conf to VM LOG.info("user:%s, host:%s", vsperf_user, vsperf_ip) self.client = ssh.SSH(vsperf_user, vsperf_ip, - password=vsperf_password) + password=vsperf_password, port=vsperf_ssh_port) # traffic generation could last long self.client.wait(timeout=1800) # copy script to host - self.client.run("cat > ~/vsperf.conf", - stdin=open(self.vsperf_conf, "rb")) + self.client._put_file_shell(self.vsperf_conf, '~/vsperf.conf') # execute external setup script if self.setup_script: @@ -165,18 +175,26 @@ class Vsperf(base.Scenario): options = self.scenario_cfg['options'] test_params = [] test_params.append(add_test_params(options, "traffic_type", "rfc2544")) - test_params.append(add_test_params(options, "pkt_sizes", "64")) - test_params.append(add_test_params(options, "duration", None)) test_params.append(add_test_params(options, "bidirectional", "False")) test_params.append(add_test_params(options, "iload", 100)) - test_params.append(add_test_params(options, "rfc2544_trials", None)) test_params.append(add_test_params(options, "multistream", None)) test_params.append(add_test_params(options, "stream_type", None)) + if 'frame_size' in options: + test_params.append("%s=(%s,)" % ('TRAFFICGEN_PKT_SIZES', + options['frame_size'])) + if 'test_params' in options: + test_params.append(options['test_params']) + + # filter empty parameters and escape quotes and double quotes + test_params = [tp.replace('"', '\\"').replace("'", "\\'") + for tp in test_params if tp] # execute vsperf cmd = "source ~/vsperfenv/bin/activate ; cd vswitchperf ; " - cmd += "./vsperf --mode trafficgen --conf-file ~/vsperf.conf " - cmd += "--test-params=\"%s\"" % (';'.join(filter(None, test_params))) + cmd += "./vsperf --mode trafficgen " + if self.vsperf_conf: + cmd += "--conf-file ~/vsperf.conf " + cmd += "--test-params=\"%s\"" % (';'.join(test_params)) LOG.debug("Executing command: %s", cmd) status, stdout, stderr = self.client.execute(cmd) diff --git a/yardstick/benchmark/scenarios/storage/fio.py b/yardstick/benchmark/scenarios/storage/fio.py index a8d27faba..4e004235d 100644 --- a/yardstick/benchmark/scenarios/storage/fio.py +++ b/yardstick/benchmark/scenarios/storage/fio.py @@ -60,16 +60,17 @@ class Fio(base.Scenario): Fio.TARGET_SCRIPT) host = self.context_cfg["host"] user = host.get("user", "root") + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) ip = host.get("ip", None) key_filename = host.get("key_filename", "~/.ssh/id_rsa") LOG.info("user:%s, host:%s", user, ip) - self.client = ssh.SSH(user, ip, key_filename=key_filename) + self.client = ssh.SSH(user, ip, key_filename=key_filename, + port=ssh_port) self.client.wait(timeout=600) # copy script to host - self.client.run("cat > ~/fio.sh", - stdin=open(self.target_script, "rb")) + self.client._put_file_shell(self.target_script, '~/fio.sh') self.setup_done = True diff --git a/yardstick/benchmark/scenarios/storage/storagecapacity.py b/yardstick/benchmark/scenarios/storage/storagecapacity.py index 49e3a0339..bf5bc2810 100644 --- a/yardstick/benchmark/scenarios/storage/storagecapacity.py +++ b/yardstick/benchmark/scenarios/storage/storagecapacity.py @@ -54,16 +54,17 @@ class StorageCapacity(base.Scenario): if host is None: raise RuntimeError('No right node.Please check the configuration') host_user = host.get('user', 'ubuntu') + ssh_port = host.get("ssh_port", ssh.DEFAULT_PORT) host_ip = host.get('ip', None) host_pwd = host.get('password', 'root') LOG.debug("user:%s, host:%s", host_user, host_ip) - self.client = ssh.SSH(host_user, host_ip, password=host_pwd) + self.client = ssh.SSH(host_user, host_ip, password=host_pwd, + port=ssh_port) self.client.wait(timeout=600) # copy script to host - self.client.run("cat > ~/storagecapacity.sh", - stdin=open(self.target_script, 'rb')) + self.client._put_file_shell(self.target_script, '~/storagecapacity.sh') self.setup_done = True @@ -107,7 +108,7 @@ class StorageCapacity(base.Scenario): for i in range(len(device_name_arr)): r[device_name_arr[i]] = {"min_util": min_util_arr[i], "max_util": max_util_arr[i], - "avg_util": avg_util_arr[i]/count} + "avg_util": avg_util_arr[i] / count} return r def run(self, result): diff --git a/yardstick/benchmark/scenarios/storage/storperf.py b/yardstick/benchmark/scenarios/storage/storperf.py index d39c23aa2..72ceff7ce 100644 --- a/yardstick/benchmark/scenarios/storage/storperf.py +++ b/yardstick/benchmark/scenarios/storage/storperf.py @@ -54,6 +54,7 @@ class StorPerf(base.Scenario): def __init__(self, scenario_cfg, context_cfg): """Scenario construction.""" + super(StorPerf, self).__init__() self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg self.options = self.scenario_cfg["options"] @@ -75,8 +76,8 @@ class StorPerf(base.Scenario): setup_query_content = json.loads(setup_query.content) if setup_query_content["stack_created"]: self.setup_done = True - LOG.debug("stack_created: %s" - % setup_query_content["stack_created"]) + LOG.debug("stack_created: %s", + setup_query_content["stack_created"]) def setup(self): """Set the configuration.""" @@ -85,45 +86,44 @@ class StorPerf(base.Scenario): "agent_image", "volume_size"] for env_argument in env_args_payload_list: - if env_argument in self.options: + try: env_args[env_argument] = self.options[env_argument] + except KeyError: + pass - LOG.info("Creating a stack on node %s with parameters %s" % - (self.target, env_args)) + LOG.info("Creating a stack on node %s with parameters %s", + self.target, env_args) setup_res = requests.post('http://%s:5000/api/v1.0/configurations' % self.target, json=env_args) setup_res_content = json.loads(setup_res.content) - if setup_res.status_code == 400: + if setup_res.status_code != 200: raise RuntimeError("Failed to create a stack, error message:", setup_res_content["message"]) elif setup_res.status_code == 200: - LOG.info("stack_id: %s" % setup_res_content["stack_id"]) + LOG.info("stack_id: %s", setup_res_content["stack_id"]) while not self.setup_done: self._query_setup_state() time.sleep(self.query_interval) - # TODO: Support Storperf job status. + def _query_job_state(self, job_id): + """Query the status of the supplied job_id and report on metrics""" + LOG.info("Fetching report for %s...", job_id) + report_res = requests.get('http://{}:5000/api/v1.0/jobs'.format + (self.target), params={'id': job_id}) - # def _query_job_state(self, job_id): - # """Query the status of the supplied job_id and report on metrics""" - # LOG.info("Fetching report for %s..." % job_id) - # report_res = requests.get('http://%s:5000/api/v1.0/jobs?id=%s' % - # (self.target, job_id)) + report_res_content = json.loads(report_res.content) - # report_res_content = json.loads(report_res.content) + if report_res.status_code != 200: + raise RuntimeError("Failed to fetch report, error message:", + report_res_content["message"]) + else: + job_status = report_res_content["status"] - # if report_res.status_code == 400: - # raise RuntimeError("Failed to fetch report, error message:", - # report_res_content["message"]) - # else: - # job_status = report_res_content["status"] - - # LOG.debug("Job is: %s..." % job_status) - # if job_status == "completed": - # self.job_completed = True + LOG.debug("Job is: %s...", job_status) + self.job_completed = job_status == "completed" # TODO: Support using StorPerf ReST API to read Job ETA. @@ -145,37 +145,36 @@ class StorPerf(base.Scenario): "target", "nossd", "nowarm", "workload"] for job_argument in job_args_payload_list: - if job_argument in self.options: + try: job_args[job_argument] = self.options[job_argument] + except KeyError: + pass - LOG.info("Starting a job with parameters %s" % job_args) + LOG.info("Starting a job with parameters %s", job_args) job_res = requests.post('http://%s:5000/api/v1.0/jobs' % self.target, json=job_args) job_res_content = json.loads(job_res.content) - if job_res.status_code == 400: + if job_res.status_code != 200: raise RuntimeError("Failed to start a job, error message:", job_res_content["message"]) elif job_res.status_code == 200: job_id = job_res_content["job_id"] - LOG.info("Started job id: %s..." % job_id) + LOG.info("Started job id: %s...", job_id) + + while not self.job_completed: + self._query_job_state(job_id) + time.sleep(self.query_interval) - time.sleep(self.timeout) terminate_res = requests.delete('http://%s:5000/api/v1.0/jobs' % self.target) - if terminate_res.status_code == 400: + if terminate_res.status_code != 200: terminate_res_content = json.loads(terminate_res.content) raise RuntimeError("Failed to start a job, error message:", terminate_res_content["message"]) - # TODO: Support Storperf job status. - - # while not self.job_completed: - # self._query_job_state(job_id) - # time.sleep(self.query_interval) - # TODO: Support using ETA to polls for completion. # Read ETA, next poll in 1/2 ETA time slot. # If ETA is greater than the maximum allowed job time, diff --git a/yardstick/cmd/cli.py b/yardstick/cmd/cli.py index dd74836cb..beaa187aa 100644 --- a/yardstick/cmd/cli.py +++ b/yardstick/cmd/cli.py @@ -19,11 +19,13 @@ from pkg_resources import get_distribution from argparse import RawDescriptionHelpFormatter from oslo_config import cfg +from yardstick import _init_logging, LOG from yardstick.cmd.commands import task from yardstick.cmd.commands import runner from yardstick.cmd.commands import scenario from yardstick.cmd.commands import testcase from yardstick.cmd.commands import plugin +from yardstick.cmd.commands import env CONF = cfg.CONF cli_opts = [ @@ -62,10 +64,12 @@ class YardstickCLI(): 'runner': runner.RunnerCommands, 'scenario': scenario.ScenarioCommands, 'testcase': testcase.TestcaseCommands, - 'plugin': plugin.PluginCommands + 'plugin': plugin.PluginCommands, + 'env': env.EnvCommand } def __init__(self): + self.opts = [] self._version = 'yardstick version %s ' % \ get_distribution('yardstick').version @@ -101,8 +105,7 @@ class YardstickCLI(): cmd_subparsers = subparser.add_subparsers(title='subcommands') self._find_actions(cmd_subparsers, command_object) - def main(self, argv): - '''run the command line interface''' + def _register_cli_opt(self): # register subcommands to parse additional command line arguments def parser(subparsers): @@ -112,22 +115,67 @@ class YardstickCLI(): title="Command categories", help="Available categories", handler=parser) - CONF.register_cli_opt(category_opt) + self._register_opt(category_opt) + + def _register_opt(self, opt): + + CONF.register_cli_opt(opt) + self.opts.append(opt) + + def _load_cli_config(self, argv): # load CLI args and config files CONF(argv, project="yardstick", version=self._version, default_config_files=find_config_files(CONFIG_SEARCH_PATHS)) - # handle global opts - logger = logging.getLogger('yardstick') - logger.setLevel(logging.WARNING) + def _handle_global_opts(self): + _init_logging() if CONF.verbose: - logger.setLevel(logging.INFO) + LOG.setLevel(logging.INFO) if CONF.debug: - logger.setLevel(logging.DEBUG) + LOG.setLevel(logging.DEBUG) + + def _dispath_func_notask(self): # dispatch to category parser func = CONF.category.func func(CONF.category) + + def _dispath_func_task(self, task_id): + + # dispatch to category parser + func = CONF.category.func + func(CONF.category, task_id=task_id) + + def _clear_config_opts(self): + + CONF.clear() + CONF.unregister_opts(self.opts) + + def main(self, argv): # pragma: no cover + '''run the command line interface''' + try: + self._register_cli_opt() + + self._load_cli_config(argv) + + self._handle_global_opts() + + self._dispath_func_notask() + finally: + self._clear_config_opts() + + def api(self, argv, task_id): # pragma: no cover + '''run the api interface''' + try: + self._register_cli_opt() + + self._load_cli_config(argv) + + self._handle_global_opts() + + self._dispath_func_task(task_id) + finally: + self._clear_config_opts() diff --git a/yardstick/cmd/commands/env.py b/yardstick/cmd/commands/env.py new file mode 100644 index 000000000..098379ae1 --- /dev/null +++ b/yardstick/cmd/commands/env.py @@ -0,0 +1,39 @@ +############################################################################## +# Copyright (c) 2016 Huawei Technologies Co.,Ltd 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 +############################################################################## +import logging + +from yardstick.common.httpClient import HttpClient +from yardstick.common import constants + +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) + + +class EnvCommand(object): + ''' + + Set of commands to prepare environment + ''' + def do_influxdb(self, args): + url = constants.YARDSTICK_ENV_ACTION_API + data = {'action': 'createInfluxDBContainer'} + HttpClient().post(url, data) + logger.debug('Now creating and configing influxdb') + + def do_grafana(self, args): + url = constants.YARDSTICK_ENV_ACTION_API + data = {'action': 'createGrafanaContainer'} + HttpClient().post(url, data) + logger.debug('Now creating and configing grafana') + + def do_prepare(self, args): + url = constants.YARDSTICK_ENV_ACTION_API + data = {'action': 'prepareYardstickEnv'} + HttpClient().post(url, data) + logger.debug('Now preparing environment') diff --git a/yardstick/cmd/commands/plugin.py b/yardstick/cmd/commands/plugin.py index 9936942d8..10e5cdfbe 100644 --- a/yardstick/cmd/commands/plugin.py +++ b/yardstick/cmd/commands/plugin.py @@ -84,6 +84,7 @@ class PluginCommands(object): 'yardstick.resources', 'scripts/install/' + target_script) deployment_user = deployment.get("user") + deployment_ssh_port = deployment.get("ssh_port", ssh.DEFAULT_PORT) deployment_ip = deployment.get("ip") deployment_password = deployment.get("password") @@ -92,12 +93,14 @@ class PluginCommands(object): LOG.info("user:%s, host:%s", deployment_user, installer_ip) self.client = ssh.SSH(deployment_user, installer_ip, - password=deployment_password) + password=deployment_password, + port=deployment_ssh_port) self.client.wait(timeout=600) else: LOG.info("user:%s, host:%s", deployment_user, deployment_ip) self.client = ssh.SSH(deployment_user, deployment_ip, - password=deployment_password) + password=deployment_password, + port=deployment_ssh_port) self.client.wait(timeout=600) # copy script to host @@ -113,6 +116,7 @@ class PluginCommands(object): 'yardstick.resources', 'scripts/remove/' + target_script) deployment_user = deployment.get("user") + deployment_ssh_port = deployment.get("ssh_port", ssh.DEFAULT_PORT) deployment_ip = deployment.get("ip") deployment_password = deployment.get("password") @@ -121,12 +125,14 @@ class PluginCommands(object): LOG.info("user:%s, host:%s", deployment_user, installer_ip) self.client = ssh.SSH(deployment_user, installer_ip, - password=deployment_password) + password=deployment_password, + port=deployment_ssh_port) self.client.wait(timeout=600) else: LOG.info("user:%s, host:%s", deployment_user, deployment_ip) self.client = ssh.SSH(deployment_user, deployment_ip, - password=deployment_password) + password=deployment_password, + port=deployment_ssh_port) self.client.wait(timeout=600) # copy script to host @@ -145,6 +151,7 @@ class PluginCommands(object): class PluginParser(object): '''Parser for plugin configration files in yaml format''' + def __init__(self, path): self.path = path diff --git a/yardstick/cmd/commands/task.py b/yardstick/cmd/commands/task.py index b38e084ac..9524778ba 100644 --- a/yardstick/cmd/commands/task.py +++ b/yardstick/cmd/commands/task.py @@ -17,12 +17,15 @@ import ipaddress import time import logging import uuid +import errno from itertools import ifilter from yardstick.benchmark.contexts.base import Context from yardstick.benchmark.runners import base as base_runner from yardstick.common.task_template import TaskTemplate from yardstick.common.utils import cliargs +from yardstick.common.utils import source_env +from yardstick.common import constants output_file_default = "/tmp/yardstick.out" test_cases_dir_default = "tests/opnfv/test_cases/" @@ -51,11 +54,15 @@ class TaskCommands(object): output_file_default, default=output_file_default) @cliargs("--suite", help="process test suite file instead of a task file", action="store_true") - def do_start(self, args): + def do_start(self, args, **kwargs): '''Start a benchmark scenario.''' atexit.register(atexit_handler) + self.task_id = kwargs.get('task_id', str(uuid.uuid4())) + + check_environment() + total_start_time = time.time() parser = TaskParser(args.inputfile[0]) @@ -81,7 +88,7 @@ class TaskCommands(object): one_task_start_time = time.time() parser.path = task_files[i] scenarios, run_in_parallel, meet_precondition = parser.parse_task( - task_args[i], task_args_fnames[i]) + self.task_id, task_args[i], task_args_fnames[i]) if not meet_precondition: LOG.info("meet_precondition is %s, please check envrionment", @@ -232,7 +239,7 @@ class TaskParser(object): return valid_task_files, valid_task_args, valid_task_args_fnames - def parse_task(self, task_args=None, task_args_file=None): + def parse_task(self, task_id, task_args=None, task_args_file=None): '''parses the task file and return an context and scenario instances''' print "Parsing task config:", self.path @@ -291,7 +298,6 @@ class TaskParser(object): run_in_parallel = cfg.get("run_in_parallel", False) # add tc and task id for influxdb extended tags - task_id = str(uuid.uuid4()) for scenario in cfg["scenarios"]: task_name = os.path.splitext(os.path.basename(self.path))[0] scenario["tc"] = task_name @@ -482,3 +488,14 @@ def parse_task_args(src_name, args): % {"src": src_name, "src_type": type(kw)}) raise TypeError() return kw + + +def check_environment(): + auth_url = os.environ.get('OS_AUTH_URL', None) + if not auth_url: + try: + source_env(constants.OPENSTACK_RC_FILE) + except IOError as e: + if e.errno != errno.EEXIST: + raise + LOG.debug('OPENRC file not found') diff --git a/yardstick/cmd/commands/testcase.py b/yardstick/cmd/commands/testcase.py index 5205eb93e..cb76c7ae3 100644 --- a/yardstick/cmd/commands/testcase.py +++ b/yardstick/cmd/commands/testcase.py @@ -8,13 +8,15 @@ ############################################################################## """ Handler for yardstick command 'testcase' """ -from yardstick.cmd import print_hbar -from yardstick.common.task_template import TaskTemplate -from yardstick.common.utils import cliargs import os import yaml import sys +from yardstick.cmd import print_hbar +from yardstick.common.task_template import TaskTemplate +from yardstick.common.utils import cliargs +from yardstick.definitions import YARDSTICK_ROOT_PATH + class TestcaseCommands(object): '''Testcase commands. @@ -22,7 +24,7 @@ class TestcaseCommands(object): Set of commands to discover and display test cases. ''' def __init__(self): - self.test_case_path = 'tests/opnfv/test_cases/' + self.test_case_path = YARDSTICK_ROOT_PATH + 'tests/opnfv/test_cases/' self.testcase_list = [] def do_list(self, args): diff --git a/yardstick/common/constants.py b/yardstick/common/constants.py new file mode 100644 index 000000000..443b3e810 --- /dev/null +++ b/yardstick/common/constants.py @@ -0,0 +1,38 @@ +import os + +DOCKER_URL = 'unix://var/run/docker.sock' + +# database config +USER = 'root' +PASSWORD = 'root' +DATABASE = 'yardstick' + +INFLUXDB_IMAGE = 'tutum/influxdb' +INFLUXDB_TAG = '0.13' + +GRAFANA_IMAGE = 'grafana/grafana' +GRAFANA_TAGS = '3.1.1' + +dirname = os.path.dirname +abspath = os.path.abspath +sep = os.path.sep + +INSTALLERS = ['apex', 'compass', 'fuel', 'joid'] + +YARDSTICK_ROOT_PATH = dirname(dirname(dirname(abspath(__file__)))) + sep + +YARDSTICK_REPOS_DIR = '/home/opnfv/repos/yardstick' + +YARDSTICK_CONFIG_DIR = '/etc/yardstick/' + +YARDSTICK_CONFIG_FILE = os.path.join(YARDSTICK_CONFIG_DIR, 'yardstick.conf') + +RELENG_DIR = '/home/opnfv/repos/releng' + +OS_FETCH_SCRIPT = 'utils/fetch_os_creds.sh' + +LOAD_IMAGES_SCRIPT = 'tests/ci/load_images.sh' + +OPENSTACK_RC_FILE = os.path.join(YARDSTICK_CONFIG_DIR, 'openstack.creds') + +YARDSTICK_ENV_ACTION_API = 'http://localhost:5000/yardstick/env/action' diff --git a/yardstick/common/httpClient.py b/yardstick/common/httpClient.py new file mode 100644 index 000000000..ab2e9a379 --- /dev/null +++ b/yardstick/common/httpClient.py @@ -0,0 +1,30 @@ +############################################################################## +# Copyright (c) 2016 Huawei Technologies Co.,Ltd 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 +############################################################################## +import json +import logging + +import requests + +logger = logging.getLogger(__name__) + + +class HttpClient(object): + + def post(self, url, data): + data = json.dumps(data) + headers = {'Content-Type': 'application/json'} + try: + response = requests.post(url, data=data, headers=headers) + result = response.json() + logger.debug('The result is: %s', result) + + return result + except Exception as e: + logger.debug('Failed: %s', e) + raise diff --git a/yardstick/common/utils.py b/yardstick/common/utils.py index c482b4da4..3ecb0ae20 100644 --- a/yardstick/common/utils.py +++ b/yardstick/common/utils.py @@ -17,10 +17,21 @@ import os import sys +import yaml +import errno +import subprocess +import logging + from oslo_utils import importutils +from keystoneauth1 import identity +from keystoneauth1 import session +from neutronclient.v2_0 import client import yardstick +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) + # Decorator for cli-args def cliargs(*args, **kwargs): @@ -68,3 +79,65 @@ def import_modules_from_package(package): new_package = ".".join(root.split(os.sep)).split("....")[1] module_name = "%s.%s" % (new_package, filename[:-3]) try_append_module(module_name, sys.modules) + + +def get_para_from_yaml(file_path, args): + + def func(a, b): + if a is None: + return None + return a.get(b) + + if os.path.exists(file_path): + with open(file_path) as f: + value = yaml.safe_load(f) + value = reduce(func, args.split('.'), value) + + if value is None: + print 'parameter not found' + return None + + return value + else: + print 'file not exist' + return None + + +def makedirs(d): + try: + os.makedirs(d) + except OSError as e: + if e.errno != errno.EEXIST: + raise + + +def execute_command(cmd): + exec_msg = "Executing command: '%s'" % cmd + logger.debug(exec_msg) + + output = subprocess.check_output(cmd.split()).split(os.linesep) + + return output + + +def source_env(env_file): + p = subprocess.Popen(". %s; env" % env_file, stdout=subprocess.PIPE, + shell=True) + output = p.communicate()[0] + env = dict((line.split('=', 1) for line in output.splitlines())) + os.environ.update(env) + return env + + +def get_openstack_session(): + auth = identity.Password(auth_url=os.environ.get('OS_AUTH_URL'), + username=os.environ.get('OS_USERNAME'), + password=os.environ.get('OS_PASSWORD'), + tenant_name=os.environ.get('OS_TENANT_NAME')) + return session.Session(auth=auth) + + +def get_neutron_client(): + sess = get_openstack_session() + neutron_client = client.Client(session=sess) + return neutron_client diff --git a/yardstick/definitions.py b/yardstick/definitions.py new file mode 100644 index 000000000..300a78e58 --- /dev/null +++ b/yardstick/definitions.py @@ -0,0 +1,5 @@ +import os + +dirname = os.path.dirname +YARDSTICK_ROOT_PATH = dirname(dirname(os.path.abspath(__file__))) +YARDSTICK_ROOT_PATH += os.path.sep diff --git a/yardstick/dispatcher/file.py b/yardstick/dispatcher/file.py index ab67796e9..c2cc265ba 100644 --- a/yardstick/dispatcher/file.py +++ b/yardstick/dispatcher/file.py @@ -17,6 +17,7 @@ # ceilometer/ceilometer/dispatcher/file.py import logging +import logging.handlers import json from oslo_config import cfg diff --git a/yardstick/dispatcher/http.py b/yardstick/dispatcher/http.py index 2298d00cc..98e772dd8 100644 --- a/yardstick/dispatcher/http.py +++ b/yardstick/dispatcher/http.py @@ -81,14 +81,14 @@ class HttpDispatcher(DispatchBase): case_name = v["scenario_cfg"]["tc"] break if case_name == "": - LOG.error('Test result : %s' % json.dumps(self.result)) + LOG.error('Test result : %s', json.dumps(self.result)) LOG.error('The case_name cannot be found, no data will be posted.') return self.result["case_name"] = case_name try: - LOG.debug('Test result : %s' % json.dumps(self.result)) + LOG.debug('Test result : %s', json.dumps(self.result)) res = requests.post(self.target, data=json.dumps(self.result), headers=self.headers, diff --git a/yardstick/dispatcher/influxdb.py b/yardstick/dispatcher/influxdb.py index a9825fa35..fc9f3e932 100644 --- a/yardstick/dispatcher/influxdb.py +++ b/yardstick/dispatcher/influxdb.py @@ -16,7 +16,7 @@ import time from oslo_config import cfg from yardstick.dispatcher.base import Base as DispatchBase -from yardstick.dispatcher.influxdb_line_protocol import make_lines +from third_party.influxdb.influxdb_line_protocol import make_lines LOG = logging.getLogger(__name__) @@ -68,7 +68,9 @@ class InfluxdbDispatcher(DispatchBase): "pod_name": os.environ.get('NODE_NAME', 'unknown'), "installer": os.environ.get('INSTALLER_TYPE', 'unknown'), "deploy_scenario": os.environ.get('DEPLOY_SCENARIO', 'unknown'), - "version": os.environ.get('YARDSTICK_VERSION', 'unknown') + "version": os.path.basename(os.environ.get('YARDSTICK_BRANCH', + 'unknown')) + } def _dict_key_flatten(self, data): @@ -125,7 +127,7 @@ class InfluxdbDispatcher(DispatchBase): return make_lines(msg).encode('utf-8') def record_result_data(self, data): - LOG.debug('Test result : %s' % json.dumps(data)) + LOG.debug('Test result : %s', json.dumps(data)) self.raw_result.append(data) if self.target == '': # if the target was not set, do not do anything @@ -146,13 +148,13 @@ class InfluxdbDispatcher(DispatchBase): return 0 if self.tc == "": - LOG.error('Test result : %s' % json.dumps(data)) + LOG.error('Test result : %s', json.dumps(data)) LOG.error('The case_name cannot be found, no data will be posted.') return -1 try: line = self._data_to_line_protocol(data) - LOG.debug('Test result line format : %s' % line) + LOG.debug('Test result line format : %s', line) res = requests.post(self.influxdb_url, data=line, auth=(self.username, self.password), @@ -169,5 +171,5 @@ class InfluxdbDispatcher(DispatchBase): return 0 def flush_result_data(self): - LOG.debug('Test result all : %s' % json.dumps(self.raw_result)) + LOG.debug('Test result all : %s', json.dumps(self.raw_result)) return 0 diff --git a/yardstick/dispatcher/influxdb_line_protocol.py b/yardstick/dispatcher/influxdb_line_protocol.py deleted file mode 100644 index eee982163..000000000 --- a/yardstick/dispatcher/influxdb_line_protocol.py +++ /dev/null @@ -1,137 +0,0 @@ -# The MIT License (MIT) - -# Copyright (c) 2013 InfluxDB - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in -# the Software without restriction, including without limitation the rights to -# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -# of the Software, and to permit persons to whom the Software is furnished to -# do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -# yardstick comment: this file is a modified copy of -# influxdb-python/influxdb/line_protocol.py - -from __future__ import unicode_literals -from copy import copy - -from six import binary_type, text_type, integer_types - - -def _escape_tag(tag): - tag = _get_unicode(tag, force=True) - return tag.replace( - "\\", "\\\\" - ).replace( - " ", "\\ " - ).replace( - ",", "\\," - ).replace( - "=", "\\=" - ) - - -def _escape_value(value): - value = _get_unicode(value) - if isinstance(value, text_type) and value != '': - return "\"{}\"".format( - value.replace( - "\"", "\\\"" - ).replace( - "\n", "\\n" - ) - ) - elif isinstance(value, integer_types) and not isinstance(value, bool): - return str(value) + 'i' - else: - return str(value) - - -def _get_unicode(data, force=False): - """ - Try to return a text aka unicode object from the given data. - """ - if isinstance(data, binary_type): - return data.decode('utf-8') - elif data is None: - return '' - elif force: - return str(data) - else: - return data - - -def make_lines(data): - """ - Extracts the points from the given dict and returns a Unicode string - matching the line protocol introduced in InfluxDB 0.9.0. - - line protocol format: - <measurement>[,<tag-key>=<tag-value>...] <field-key>=<field-value>\ - [,<field2-key>=<field2-value>...] [unix-nano-timestamp] - - Ref: - https://influxdb.com/docs/v0.9/write_protocols/write_syntax.html - https://influxdb.com/docs/v0.9/write_protocols/line.html - """ - lines = [] - static_tags = data.get('tags', None) - for point in data['points']: - elements = [] - - # add measurement name - measurement = _escape_tag(_get_unicode( - point.get('measurement', data.get('measurement')) - )) - key_values = [measurement] - - # add tags - if static_tags is None: - tags = point.get('tags', {}) - else: - tags = copy(static_tags) - tags.update(point.get('tags', {})) - - # tags should be sorted client-side to take load off server - for tag_key in sorted(tags.keys()): - key = _escape_tag(tag_key) - value = _escape_tag(tags[tag_key]) - - if key != '' and value != '': - key_values.append("{key}={value}".format(key=key, value=value)) - key_values = ','.join(key_values) - elements.append(key_values) - - # add fields - field_values = [] - for field_key in sorted(point['fields'].keys()): - key = _escape_tag(field_key) - value = _escape_value(point['fields'][field_key]) - if key != '' and value != '': - field_values.append("{key}={value}".format( - key=key, - value=value - )) - field_values = ','.join(field_values) - elements.append(field_values) - - # add timestamp - if 'time' in point: - elements.append(point['time']) - - line = ' '.join(elements) - lines.append(line) - lines = '\n'.join(lines) - return lines + '\n' diff --git a/yardstick/resources/files/yardstick_key b/yardstick/resources/files/yardstick_key deleted file mode 100644 index 32e860f3f..000000000 --- a/yardstick/resources/files/yardstick_key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEA9EZF31uqZLHdXGZl7r12RfzJaqqt2oSBnBqFCzgve1zKbtL3 -cTKXFMHY8BqjMBF01cnx4nbtJffWy6jgqUlCgpm1sdzjSftZKhceB8LChFi4sg2K -rLjKw3mU9XhYwuWrwqE3KyMNsKuTWgW9NJQxmoDWTnqKWi+WCGuPj4sxGNt/nIq9 -uA+uzVNtRYNyRPdgCHhpTWuI+ui92vpS9IWau+A4pZqeNsJuBrG6ZUTuiiX8mq2q -MB29V/k5oQowYB5OjPzifcjwK6GciTXMIzALrsYQGFkbk90nW56FEdERtlYXw4dK -jYne7zqi24Sj3miyxZs5DfvcN1nQqei20mLfOwIDAQABAoIBACdWccYoguY4ZoeM -zfmGdVeL//u3hMvd7ulus+I8qBjbtpXmT4bhOMdU+FSiVYlWJlSPcu6fbE1i/ipK -BfP9IkLZ8hK0mb2+RnuqwWFKkfyyNPwnhh+Omsij+cMWIGUyi1iKkdHWkUvUNaSX -rAKdoudYvCpjPYiMhULR34qkRcHUtsswOeRHvxC8CXqk3fJJ/oLqCz2E4gNJs4v9 -aadxNu51ooK+srb2FcJ1zItg+NaG+Yp7aPbz+n1byH46lM4S2n9RkaoXPxUAmW9z -RxHUDDQJ6d2hP6lNDlo21Z0vINazUOjUycZ8iS7vusA6vxkfIHhmX/4XGy0/1kEs -JiUxEmECgYEA+wTqwY/LSCpcGkq+VUWG64c812ogPiRI+Wa/zJvZPL4wve3uy2e2 -Cx5auwwedracdigYr3jl85TSrXEhm2rWMkUhek+IY4jEzl2RH6/BeMenl5+Fh2Qw -ZGg7Rukn60WVArgi3KH2ipzW33YZEb3cGLHSFPG79w31Aa0mqsBZVJMCgYEA+R8Y -akSn3gOTevxczBl97BDdTndZ23+NHk52cj3TKwMnVHsAWF8ozBG7S/gjHY6Ongms -z/erBMT8yDJbSeS/SqeFnPhuBoq2CIebAc5RLK9gHDZizf/r1gin5Fyl5jbTn5em -JiOyYqVS43bAVpsJoNT9efdOFBzzNFqSOv9527kCgYEAmJ8huTSbrbILs/S0Cxat -9PCSHoupNP9M208M2PP9PoCJFEHhigzx04rOMaIpt5ZKRVEVyULh1ZssCUaa32sy -9vevZjWLQLF8r9iWD0UGhlAmZvsX7f0Nq07wk6nZmqQA+NlKYQmc5CR+RPoCPhZJ -Bz6+8/sShSEYUb+cnf87kT8CgYAPTcO4M4OEdf/HXF1vBFnh+J8/xME2ZL2MkRFh -rz6bs9PksrGwvBfLgYNaBWJS3IESYFHHbNWKs3c77SwCfBTsRyJEJFbN/BN2rq3t -DHmcHyHuWcD0GraoLVvzAWYHoHKbqTtBuIuq17Eh3BewulF7GdqAdZrMTYL7Ql0d -VrhrsQKBgBT3TOSJqc+idx58sMfZI/18GEI5PIkOuDtzgtqdwjUsIHaVnI0bVuzo -tiEl8Ma36ZsDD5JLRUF90ckeMtjHawE4KimyO51dnE4AXsMACfbdtDc5KO+BNKJz -6qw2SjRD7zlD6JYPVRERNFLGMIWLJbmD9tkswjuIOG/9ctWUC5FC ------END RSA PRIVATE KEY----- diff --git a/yardstick/resources/files/yardstick_key.pub b/yardstick/resources/files/yardstick_key.pub deleted file mode 100644 index e0d0eb580..000000000 --- a/yardstick/resources/files/yardstick_key.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD0RkXfW6pksd1cZmXuvXZF/Mlqqq3ahIGcGoULOC97XMpu0vdxMpcUwdjwGqMwEXTVyfHidu0l99bLqOCpSUKCmbWx3ONJ+1kqFx4HwsKEWLiyDYqsuMrDeZT1eFjC5avCoTcrIw2wq5NaBb00lDGagNZOeopaL5YIa4+PizEY23+cir24D67NU21Fg3JE92AIeGlNa4j66L3a+lL0hZq74Dilmp42wm4GsbplRO6KJfyaraowHb1X+TmhCjBgHk6M/OJ9yPAroZyJNcwjMAuuxhAYWRuT3SdbnoUR0RG2VhfDh0qNid7vOqLbhKPeaLLFmzkN+9w3WdCp6LbSYt87 yardstick@yardstick.opnfv.org diff --git a/yardstick/ssh.py b/yardstick/ssh.py index cf890df6f..46d53b7d2 100644 --- a/yardstick/ssh.py +++ b/yardstick/ssh.py @@ -29,24 +29,29 @@ Execute command and get output: Execute command with huge output: - class PseudoFile(object): + class PseudoFile(io.RawIOBase): def write(chunk): if "error" in chunk: email_admin(chunk) - ssh = sshclient.SSH("root", "example.com") - ssh.run("tail -f /var/log/syslog", stdout=PseudoFile(), timeout=False) + ssh = SSH("root", "example.com") + with PseudoFile() as p: + ssh.run("tail -f /var/log/syslog", stdout=p, timeout=False) Execute local script on remote side: ssh = sshclient.SSH("user", "example.com") - status, out, err = ssh.execute("/bin/sh -s arg1 arg2", - stdin=open("~/myscript.sh", "r")) + + with open("~/myscript.sh", "r") as stdin_file: + status, out, err = ssh.execute('/bin/sh -s "arg1" "arg2"', + stdin=stdin_file) Upload file: - ssh = sshclient.SSH("user", "example.com") - ssh.run("cat > ~/upload/file.gz", stdin=open("/store/file.gz", "rb")) + ssh = SSH("user", "example.com") + # use rb for binary files + with open("/store/file.gz", "rb") as stdin_file: + ssh.run("cat > ~/upload/file.gz", stdin=stdin_file) Eventlet: @@ -54,20 +59,21 @@ Eventlet: or eventlet.monkey_patch() or - sshclient = eventlet.import_patched("opentstack.common.sshclient") + sshclient = eventlet.import_patched("yardstick.ssh") """ - +import os import select import socket import time +import logging import paramiko from scp import SCPClient import six -import logging -LOG = logging.getLogger(__name__) + +DEFAULT_PORT = 22 class SSHError(Exception): @@ -81,8 +87,8 @@ class SSHTimeout(SSHError): class SSH(object): """Represent ssh connection.""" - def __init__(self, user, host, port=22, pkey=None, - key_filename=None, password=None): + def __init__(self, user, host, port=DEFAULT_PORT, pkey=None, + key_filename=None, password=None, name=None): """Initialize SSH client. :param user: ssh username @@ -92,14 +98,27 @@ class SSH(object): :param key_filename: private key filename :param password: password """ + self.name = name + if name: + self.log = logging.getLogger(__name__ + '.' + self.name) + else: + self.log = logging.getLogger(__name__) self.user = user self.host = host - self.port = port + # we may get text port from YAML, convert to int + self.port = int(port) self.pkey = self._get_pkey(pkey) if pkey else None self.password = password self.key_filename = key_filename self._client = False + # paramiko loglevel debug will output ssh protocl debug + # we don't ever really want that unless we are debugging paramiko + # ssh issues + if os.environ.get("PARAMIKO_DEBUG", "").lower() == "true": + logging.getLogger("paramiko").setLevel(logging.DEBUG) + else: + logging.getLogger("paramiko").setLevel(logging.WARN) def _get_pkey(self, key): if isinstance(key, six.string_types): @@ -137,10 +156,12 @@ class SSH(object): self._client = False def run(self, cmd, stdin=None, stdout=None, stderr=None, - raise_on_error=True, timeout=3600): + raise_on_error=True, timeout=3600, + keep_stdin_open=False): """Execute specified command on the server. :param cmd: Command to be executed. + :type cmd: str :param stdin: Open file or string to pass to stdin. :param stdout: Open file to connect to stdout. :param stderr: Open file to connect to stderr. @@ -148,6 +169,8 @@ class SSH(object): then exception will be raized if non-zero code. :param timeout: Timeout in seconds for command execution. Default 1 hour. No timeout if set to 0. + :param keep_stdin_open: don't close stdin on empty reads + :type keep_stdin_open: bool """ client = self._get_client() @@ -157,10 +180,12 @@ class SSH(object): return self._run(client, cmd, stdin=stdin, stdout=stdout, stderr=stderr, raise_on_error=raise_on_error, - timeout=timeout) + timeout=timeout, + keep_stdin_open=keep_stdin_open) def _run(self, client, cmd, stdin=None, stdout=None, stderr=None, - raise_on_error=True, timeout=3600): + raise_on_error=True, timeout=3600, + keep_stdin_open=False): transport = client.get_transport() session = transport.open_session() @@ -183,14 +208,14 @@ class SSH(object): if session.recv_ready(): data = session.recv(4096) - LOG.debug("stdout: %r" % data) + self.log.debug("stdout: %r", data) if stdout is not None: stdout.write(data) continue if session.recv_stderr_ready(): stderr_data = session.recv_stderr(4096) - LOG.debug("stderr: %r" % stderr_data) + self.log.debug("stderr: %r", stderr_data) if stderr is not None: stderr.write(stderr_data) continue @@ -200,13 +225,15 @@ class SSH(object): if not data_to_send: data_to_send = stdin.read(4096) if not data_to_send: - stdin.close() - session.shutdown_write() - writes = [] - continue - sent_bytes = session.send(data_to_send) - # LOG.debug("sent: %s" % data_to_send[:sent_bytes]) - data_to_send = data_to_send[sent_bytes:] + # we may need to keep stdin open + if not keep_stdin_open: + stdin.close() + session.shutdown_write() + writes = [] + if data_to_send: + sent_bytes = session.send(data_to_send) + # LOG.debug("sent: %s" % data_to_send[:sent_bytes]) + data_to_send = data_to_send[sent_bytes:] if session.exit_status_ready(): break @@ -253,10 +280,10 @@ class SSH(object): try: return self.execute("uname") except (socket.error, SSHError) as e: - LOG.debug("Ssh is still unavailable: %r" % e) + self.log.debug("Ssh is still unavailable: %r", e) time.sleep(interval) if time.time() > (start_time + timeout): - raise SSHTimeout("Timeout waiting for '%s'" % self.host) + raise SSHTimeout("Timeout waiting for '%s'", self.host) def put(self, files, remote_path=b'.', recursive=False): client = self._get_client() @@ -268,3 +295,37 @@ class SSH(object): def send_command(self, command): client = self._get_client() client.exec_command(command, get_pty=True) + + def _put_file_sftp(self, localpath, remotepath, mode=None): + client = self._get_client() + + with client.open_sftp() as sftp: + sftp.put(localpath, remotepath) + if mode is None: + mode = 0o777 & os.stat(localpath).st_mode + sftp.chmod(remotepath, mode) + + def _put_file_shell(self, localpath, remotepath, mode=None): + # quote to stop wordpslit + cmd = ['cat > "%s"' % remotepath] + if mode is not None: + # use -- so no options + cmd.append('chmod -- 0%o "%s"' % (mode, remotepath)) + + with open(localpath, "rb") as localfile: + # only chmod on successful cat + cmd = "&& ".join(cmd) + self.run(cmd, stdin=localfile) + + def put_file(self, localpath, remotepath, mode=None): + """Copy specified local file to the server. + + :param localpath: Local filename. + :param remotepath: Remote filename. + :param mode: Permissions to set after upload + """ + import socket + try: + self._put_file_sftp(localpath, remotepath, mode=mode) + except (paramiko.SSHException, socket.error): + self._put_file_shell(localpath, remotepath, mode=mode) |