From: sjiajiax <sunx.jiajia@intel.com>
To: dts@dpdk.org
Subject: [dts] [‘dts-v1’ 2/9] Optimize ssh connection
Date: Mon, 18 May 2015 13:07:19 +0800 [thread overview]
Message-ID: <1431925646-1314-3-git-send-email-sunx.jiajia@intel.com> (raw)
In-Reply-To: <1431925646-1314-1-git-send-email-sunx.jiajia@intel.com>
Optimize configure parse
Move some functions in dts to an common utils module
Signed-off-by: sjiajiax <sunx.jiajia@intel.com>
---
framework/config.py | 171 +++++++++++++++++++++++++++++++++++---------
framework/ssh_connection.py | 5 ++
framework/ssh_pexpect.py | 63 +++++++++++++---
framework/utils.py | 77 ++++++++++++++++++++
4 files changed, 270 insertions(+), 46 deletions(-)
mode change 100755 => 100644 framework/config.py
create mode 100644 framework/utils.py
diff --git a/framework/config.py b/framework/config.py
old mode 100755
new mode 100644
index d2548e8..927c846
--- a/framework/config.py
+++ b/framework/config.py
@@ -37,45 +37,133 @@ import re
import ConfigParser # config parse module
import argparse # prase arguments module
-portconf = "conf/ports.cfg"
-crbconf = "conf/crbs.cfg"
+PORTCONF = "conf/ports.cfg"
+CRBCONF = "conf/crbs.cfg"
+VIRTCONF = "conf/virt_global.cfg"
class UserConf():
- def __init__(self, port_conf=portconf, crb_conf=crbconf):
- self.port_config = port_conf
- self.crb_config = crb_conf
+ def __init__(self, config):
+ self.conf = ConfigParser.SafeConfigParser()
+ load_files = self.conf.read(config)
+ if load_files == []:
+ print "FAILED LOADING %s!!!" % config
+ self.conf = None
+ raise
+
+ def get_sections(self):
+ if self.conf is None:
+ return None
+
+ return self.conf.sections()
+
+ def load_section(self, section):
+ if self.conf is None:
+ return None
+
+ items = None
+ for conf_sect in self.conf.sections():
+ if conf_sect == section:
+ items = self.conf.items(section)
+
+ return items
+
+ def load_config(self, item):
+ confs = [conf.strip() for conf in item.split(';')]
+ if '' in confs:
+ confs.remove('')
+ return confs
+
+ def load_param(self, conf):
+ paramDict = dict()
+
+ for param in conf.split(','):
+ (key, _, value) = param.partition('=')
+ paramDict[key] = value
+ return paramDict
+
+
+class VirtConf(UserConf):
+
+ def __init__(self, virt_conf=VIRTCONF):
+ self.config_file = virt_conf
+ self.virt_cfg = {}
+ try:
+ self.virt_conf = UserConf(self.config_file)
+ except Exception as e:
+ print "FAILED LOADING VIRT CONFIG!!!"
+ self.virt_conf = None
+
+ def load_virt_config(self, name):
+ self.virt_cfgs = []
+
+ try:
+ virt_confs = self.virt_conf.load_section(name)
+ except:
+ print "FAILED FIND SECTION %s!!!" % name
+ return
+
+ for virt_conf in virt_confs:
+ virt_cfg = {}
+ virt_params = []
+ key, config = virt_conf
+ confs = self.virt_conf.load_config(config)
+ for config in confs:
+ virt_params.append(self.load_virt_param(config))
+ virt_cfg[key] = virt_params
+ self.virt_cfgs.append(virt_cfg)
+
+ def get_virt_config(self):
+ return self.virt_cfgs
+
+ def load_virt_param(self, config):
+ cfg_params = self.virt_conf.load_param(config)
+ return cfg_params
+
+
+class PortConf(UserConf):
+
+ def __init__(self, port_conf=PORTCONF):
+ self.config_file = port_conf
self.ports_cfg = {}
self.pci_regex = "([\da-f]{2}:[\da-f]{2}.\d{1})$"
try:
- self.port_conf = ConfigParser.SafeConfigParser()
- self.port_conf.read(self.port_config)
+ self.port_conf = UserConf(self.config_file)
except Exception as e:
print "FAILED LOADING PORT CONFIG!!!"
+ self.port_conf = None
def load_ports_config(self, crbIP):
- ports = []
- for crb in self.port_conf.sections():
- if crb != crbIP:
- continue
- ports = [port.strip()
- for port in self.port_conf.get(crb, 'ports').split(';')]
+ self.ports_cfg = {}
+ if self.port_conf is None:
+ return
+
+ ports = self.port_conf.load_section(crbIP)
+ if ports is None:
+ return
+ key, config = ports[0]
+ confs = self.port_conf.load_config(config)
+
+ for config in confs:
+ port_param = self.port_conf.load_param(config)
- for port in ports:
- port_cfg = self.__parse_port_param(port)
# check pci BDF validity
- if 'pci' not in port_cfg:
+ if 'pci' not in port_param:
print "NOT FOUND CONFIG FOR NO PCI ADDRESS!!!"
continue
- m = re.match(self.pci_regex, port_cfg['pci'])
+ m = re.match(self.pci_regex, port_param['pci'])
if m is None:
print "INVALID CONFIG FOR NO PCI ADDRESS!!!"
continue
- keys = port_cfg.keys()
+ keys = port_param.keys()
keys.remove('pci')
- self.ports_cfg[port_cfg['pci']] = {key: port_cfg[key] for key in keys}
+ self.ports_cfg[port_param['pci']] = {
+ key: port_param[key] for key in keys}
+ if 'numa' in self.ports_cfg[port_param['pci']]:
+ numa_str = self.ports_cfg[port_param['pci']]['numa']
+ self.ports_cfg[port_param['pci']]['numa'] = int(numa_str)
def get_ports_config(self):
return self.ports_cfg
@@ -86,23 +174,36 @@ class UserConf():
else:
return False
- def __parse_port_param(self, port):
- portDict = dict()
-
- for param in port.split(','):
- (key, _, value) = param.partition('=')
- if key == 'numa':
- portDict[key] = int(value)
- else:
- portDict[key] = value
- return portDict
+
if __name__ == '__main__':
- parser = argparse.ArgumentParser(description="Load DTS configuration files")
- parser.add_argument("-p", "--portconf", default=portconf)
- parser.add_argument("-c", "--crbconf", default=crbconf)
+ parser = argparse.ArgumentParser(
+ description="Load DTS configuration files")
+ parser.add_argument("-p", "--portconf", default=PORTCONF)
+ parser.add_argument("-c", "--crbconf", default=CRBCONF)
+ parser.add_argument("-v", "--virtconf", default=VIRTCONF)
args = parser.parse_args()
- conf = UserConf()
- conf.load_ports_config('192.168.1.1')
- conf.check_port_available('0000:86:00.0')
+
+ # not existed configuration file
+ VirtConf('/tmp/not-existed.cfg')
+
+ # example for basic use configuration file
+ conf = UserConf(PORTCONF)
+ for section in conf.get_sections():
+ items = conf.load_section(section)
+ key, value = items[0]
+ confs = conf.load_config(value)
+ for config in confs:
+ conf.load_param(config)
+
+ # example for port configuration file
+ portconf = PortConf(PORTCONF)
+ portconf.load_ports_config('DUT IP')
+ print portconf.get_ports_config()
+ portconf.check_port_available('86:00.0')
+
+ # example for global virtualization configuration file
+ virtconf = VirtConf(VIRTCONF)
+ virtconf.load_virt_config('LIBVIRT')
+ print virtconf.get_virt_config()
diff --git a/framework/ssh_connection.py b/framework/ssh_connection.py
index 18a6517..7286b14 100644
--- a/framework/ssh_connection.py
+++ b/framework/ssh_connection.py
@@ -62,6 +62,11 @@ class SSHConnection(object):
self.logger.debug(out)
return out
+ def get_session_before(self, timeout=15):
+ out = self.session.get_session_before(timeout)
+ self.logger.debug(out)
+ return out
+
def close(self):
self.session.close()
diff --git a/framework/ssh_pexpect.py b/framework/ssh_pexpect.py
index 735df44..4193020 100644
--- a/framework/ssh_pexpect.py
+++ b/framework/ssh_pexpect.py
@@ -2,7 +2,8 @@ import time
import pexpect
import pxssh
from debugger import ignore_keyintr, aware_keyintr
-from exception import TimeoutException, SSHConnectionException
+from exception import TimeoutException, SSHConnectionException, SSHSessionDeadException
+from utils import RED, GREEN
"""
Module handle ssh sessions between tester and DUT.
@@ -14,16 +15,28 @@ Aslo support transfer files to tester or DUT.
class SSHPexpect(object):
def __init__(self, host, username, password):
- self.magic_prompt = "[MAGIC PROMPT]"
+ self.magic_prompt = "MAGIC PROMPT"
try:
self.session = pxssh.pxssh()
- self.username = username
self.host = host
+ self.username = username
self.password = password
- self.session.login(self.host, self.username,
- self.password, original_prompt='[$#>]')
+ if ':' in host:
+ self.ip = host.split(':')[0]
+ self.port = int(host.split(':')[1])
+ self.session.login(self.ip, self.username,
+ self.password, original_prompt='[$#>]',
+ port=self.port, login_timeout=20)
+ else:
+ self.session.login(self.host, self.username,
+ self.password, original_prompt='[$#>]')
self.send_expect('stty -echo', '# ', timeout=2)
- except Exception:
+ except Exception, e:
+ print RED(e)
+ if getattr(self, 'port', None):
+ suggestion = "\nSuggession: Check if the fireware on [ %s ] " % \
+ self.ip + "is stoped\n"
+ print GREEN(suggestion)
raise SSHConnectionException(host)
def init_log(self, logger, name):
@@ -33,7 +46,7 @@ class SSHPexpect(object):
def send_expect_base(self, command, expected, timeout=15):
ignore_keyintr()
- self.__flush() # clear buffer
+ self.__flush() # clear buffer
self.session.PROMPT = expected
self.__sendline(command)
self.__prompt(command, timeout)
@@ -45,7 +58,7 @@ class SSHPexpect(object):
def send_expect(self, command, expected, timeout=15, verify=False):
ret = self.send_expect_base(command, expected, timeout)
if verify:
- ret_status = self.send_expect_base("echo $?", expected)
+ ret_status = self.send_expect_base("echo $?", expected, timeout)
if not int(ret_status):
return ret
else:
@@ -54,21 +67,44 @@ class SSHPexpect(object):
else:
return ret
- def __flush(self):
+ def get_session_before(self, timeout=15):
+ """
+ Get all output before timeout
+ """
+ ignore_keyintr()
self.session.PROMPT = self.magic_prompt
- self.session.prompt(0.1)
+ try:
+ self.session.prompt(timeout)
+ except Exception as e:
+ pass
+
+ aware_keyintr()
+ before = self.get_output_before()
+ self.__flush()
+ return before
+
+ def __flush(self):
+ """
+ Clear all session buffer
+ """
+ self.session.buffer = ""
+ self.session.before = ""
def __prompt(self, command, timeout):
if not self.session.prompt(timeout):
raise TimeoutException(command, self.get_output_all())
def __sendline(self, command):
+ if not self.isalive():
+ raise SSHSessionDeadException(self.host)
if len(command) == 2 and command.startswith('^'):
self.session.sendcontrol(command[1])
else:
self.session.sendline(command)
def get_output_before(self):
+ if not self.isalive():
+ raise SSHSessionDeadException(self.host)
self.session.flush()
before = self.session.before.rsplit('\r\n', 1)
if before[0] == "[PEXPECT]":
@@ -103,7 +139,12 @@ class SSHPexpect(object):
"""
Sends a local file to a remote place.
"""
- command = 'scp {0} {1}@{2}:{3}'.format(src, self.username, self.host, dst)
+ if ':' in self.host:
+ command = 'scp -P {0} -o NoHostAuthenticationForLocalhost=yes {1} {2}@{3}:{4}'.format(
+ str(self.port), src, self.username, self.ip, dst)
+ else:
+ command = 'scp {0} {1}@{2}:{3}'.format(
+ src, self.username, self.host, dst)
if password == '':
self._spawn_scp(command, self.password)
else:
diff --git a/framework/utils.py b/framework/utils.py
new file mode 100644
index 0000000..57eb988
--- /dev/null
+++ b/framework/utils.py
@@ -0,0 +1,77 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import json # json format
+import re
+
+
+def RED(text):
+ return "\x1B[" + "31;1m" + str(text) + "\x1B[" + "0m"
+
+
+def BLUE(text):
+ return "\x1B[" + "36;1m" + str(text) + "\x1B[" + "0m"
+
+
+def GREEN(text):
+ return "\x1B[" + "32;1m" + str(text) + "\x1B[" + "0m"
+
+
+def pprint(some_dict):
+ """
+ Print JSON format dictionary object.
+ """
+ return json.dumps(some_dict, sort_keys=True, indent=4)
+
+
+def regexp(s, to_match, allString=False):
+ """
+ Ensure that the re `to_match' only has one group in it.
+ """
+
+ scanner = re.compile(to_match, re.DOTALL)
+ if allString:
+ return scanner.findall(s)
+ m = scanner.search(s)
+ if m is None:
+ print RED("Failed to match " + to_match + " in the string " + s)
+ return None
+ return m.group(1)
+
+
+def get_obj_funcs(obj, func_name_regex):
+ """
+ Return function list which name matched regex.
+ """
+ for func_name in dir(obj):
+ func = getattr(obj, func_name)
+ if callable(func) and re.match(func_name_regex, func.__name__):
+ yield func
--
1.9.0
next prev parent reply other threads:[~2015-05-18 5:07 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-05-18 5:07 [dts] [‘dts-v1’ 0/9] sjiajiax
2015-05-18 5:07 ` [dts] [‘dts-v1’ 1/9] Abstract the NIC device as the single class NetDevice sjiajiax
2015-05-18 7:46 ` Xu, HuilongX
2015-05-18 8:58 ` Jiajia, SunX
2015-05-18 5:07 ` sjiajiax [this message]
2015-05-18 7:06 ` [dts] [‘dts-v1’ 2/9] Optimize ssh connection Liu, Yong
2015-05-18 7:43 ` Jiajia, SunX
2015-05-19 0:38 ` Liu, Yong
2015-05-19 7:05 ` Jiajia, SunX
2015-05-18 5:07 ` [dts] [‘dts-v1’ 3/9] Add some params and functions related to the virtual test sjiajiax
2015-05-18 7:26 ` Liu, Yong
2015-05-18 8:08 ` Jiajia, SunX
2015-05-18 7:59 ` Xu, HuilongX
2015-05-18 9:08 ` Jiajia, SunX
2015-05-18 5:07 ` [dts] [‘dts-v1’ 4/9] Add VM class and the virtual DUT class and the virtual resource module sjiajiax
2015-05-18 8:23 ` Xu, HuilongX
2015-05-18 13:57 ` Liu, Yong
2015-05-19 5:46 ` Jiajia, SunX
2015-05-18 5:07 ` [dts] [‘dts-v1’ 5/9] Add qemu-agent-guest for QEMU VM sjiajiax
2015-05-18 14:00 ` Liu, Yong
2015-05-18 5:07 ` [dts] [‘dts-v1’ 6/9] Add a global virtual configure sjiajiax
2015-05-18 6:32 ` Liu, Yong
2015-05-18 6:48 ` Jiajia, SunX
2015-05-18 5:07 ` [dts] [‘dts-v1’ 7/9] add some pmd functions for tester to code the testpmd cases sjiajiax
2015-05-18 8:28 ` Xu, HuilongX
2015-05-18 8:45 ` Liu, Yong
2015-05-18 9:05 ` Jiajia, SunX
2015-05-18 9:20 ` Jiajia, SunX
2015-05-18 5:07 ` [dts] [‘dts-v1’ 8/9] Add two tar files for ACL testing sjiajiax
2015-05-18 14:02 ` Liu, Yong
2015-05-19 5:49 ` Jiajia, SunX
2015-05-18 5:07 ` [dts] [‘dts-v1’ 9/9] Add a suite to test SRIOV mirror with KVM sjiajiax
2015-05-18 6:29 ` [dts] [‘dts-v1’ 0/9] Liu, Yong
2015-05-18 6:47 ` Jiajia, SunX
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1431925646-1314-3-git-send-email-sunx.jiajia@intel.com \
--to=sunx.jiajia@intel.com \
--cc=dts@dpdk.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).