diff options
author | Yiting.Li <liyiting@huawei.com> | 2015-12-22 17:11:12 -0800 |
---|---|---|
committer | Yiting.Li <liyiting@huawei.com> | 2015-12-22 17:11:12 -0800 |
commit | 8f1101df131a4d3e03b377738507d88b745831c0 (patch) | |
tree | 73f140474fcec2a77c85a453f6946957ca0742d1 /vstf/vstf/controller/settings | |
parent | 1a24ebbda3f95600c0e7d5ed8661317a8ff7e265 (diff) |
Upload the contribution of vstf as bottleneck network framework.
End to End Performance test
JIRA:BOTTLENECK-29
Change-Id: Ib2c553c8b60d6cda9e7a7b52b737c9139f706ebd
Signed-off-by: Yiting.Li <liyiting@huawei.com>
Diffstat (limited to 'vstf/vstf/controller/settings')
-rwxr-xr-x | vstf/vstf/controller/settings/README | 61 | ||||
-rwxr-xr-x | vstf/vstf/controller/settings/__init__.py | 14 | ||||
-rwxr-xr-x | vstf/vstf/controller/settings/cpu_settings.py | 63 | ||||
-rwxr-xr-x | vstf/vstf/controller/settings/data_settings.py | 31 | ||||
-rwxr-xr-x | vstf/vstf/controller/settings/device_settings.py | 18 | ||||
-rwxr-xr-x | vstf/vstf/controller/settings/flows_settings.py | 122 | ||||
-rwxr-xr-x | vstf/vstf/controller/settings/forwarding_settings.py | 18 | ||||
-rwxr-xr-x | vstf/vstf/controller/settings/html_settings.py | 51 | ||||
-rwxr-xr-x | vstf/vstf/controller/settings/mail_settings.py | 121 | ||||
-rwxr-xr-x | vstf/vstf/controller/settings/perf_settings.py | 102 | ||||
-rwxr-xr-x | vstf/vstf/controller/settings/settings.py | 286 | ||||
-rwxr-xr-x | vstf/vstf/controller/settings/settings_input.py | 44 | ||||
-rwxr-xr-x | vstf/vstf/controller/settings/tester_settings.py | 18 | ||||
-rwxr-xr-x | vstf/vstf/controller/settings/tool_settings.py | 84 |
14 files changed, 1033 insertions, 0 deletions
diff --git a/vstf/vstf/controller/settings/README b/vstf/vstf/controller/settings/README new file mode 100755 index 00000000..febac1c9 --- /dev/null +++ b/vstf/vstf/controller/settings/README @@ -0,0 +1,61 @@ +This module providers a set of profile management solution +File: + settings.py +Interface: + Settings + + 1. it is a base class and supports two modes "Default" and "Single" + if the mode is "Default", the program will load the 'json' file from 'default' + and 'user' , merge the input, save only the 'json' file from 'user' + if the mode is "Single", the program will only load and save the 'json' file + 2. it saves a file two, one is only in memory and the other is in file + 3. it provides two types of functions, one is like "set_" and "add_" and the + other is like "mset" and "madd". the functions are automatically registered. + + 4. You can overload the function _register_func to achieve the functions what you desire + by function "_setting_file","_adding_file","_setting_memory" and "_addting_memory" + + 5. it provides "settings" to show the result in memory + 6. it provides "reset" to reload the file + +Example: + + 1. create your-settings file and paste the contents + + { + "items1": "value1", + "items2": "value2" + } + + + 2. create your_settings file and paste the codes + + import vstf.controller.settings.settings as sets + class YourSettings(sets.Settings): + def __init__(self, path="./", filename="your-settings", mode=sets.SETS_SINGLE): + super(MailSettings, self).__init__(path, filename, mode) + + def unit_test(): + setting = YourSettings() + print setting.settings() + value1 = "test_set_items1" + setting.set_items1(value1) + print setting.settings() + value2 = "test_set_items2" + setting.mset_items2(value2) + print setting.settings() + settings.reset() + print setting.settings() + + if __name__ == '__main__': + unit_test() + +Tree: + + data_settings.py + flows_settings.py + perf_settings.py + + mail_settings.py + tool_settings.py + html_settings.py
\ No newline at end of file diff --git a/vstf/vstf/controller/settings/__init__.py b/vstf/vstf/controller/settings/__init__.py new file mode 100755 index 00000000..89dcd4e2 --- /dev/null +++ b/vstf/vstf/controller/settings/__init__.py @@ -0,0 +1,14 @@ +# Copyright Huawei Technologies Co., Ltd. 1998-2015. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. diff --git a/vstf/vstf/controller/settings/cpu_settings.py b/vstf/vstf/controller/settings/cpu_settings.py new file mode 100755 index 00000000..c69742ad --- /dev/null +++ b/vstf/vstf/controller/settings/cpu_settings.py @@ -0,0 +1,63 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- +# author: wly +# date: 2015/11/19 +# see license for license details + +import logging +import pprint + +import vstf.controller.settings.settings as sets +import vstf.common.decorator as deco +from vstf.common.input import raw_choice + +LOG = logging.getLogger(__name__) + + +class CpuSettings(sets.Settings): + def __init__(self, path="/etc/vstf/perf/", + filename="sw_perf.cpu-settings", + mode=sets.SETS_SINGLE): + super(CpuSettings, self).__init__(path, filename, mode) + + def _register_func(self): + super(CpuSettings, self)._register_func() + body = set( + self._fset['affctl'].keys() + ) + LOG.debug(body) + for item in body: + item = item.encode() + func_name = "set_%s" % item + setattr(self, func_name, self._setting_file(func_name, self._mset['affctl'], self._fset['affctl'], item)) + func_name = "mset_%s" % item + setattr(self, func_name, self._setting_memory(func_name, self._mset['affctl'], item)) + + LOG.debug(self.__dict__) + + def sinput(self, info=None): + if raw_choice("if set cpu affability by affctl"): + affctl = self.raw_affctl(info) + self.set_affctl(affctl) + + print "%s set finish: " % self._filename + print "+++++++++++++++++++++++++++++++++++++++++" + pprint.pprint(self.settings, indent=4) + print "+++++++++++++++++++++++++++++++++++++++++" + + @deco.vstf_input('policy', types=int) + def raw_affctl(self, info): + print info + print "---------------------------------------" + print "Please vstf set cpu affctl params like:" + print " 'policy': 2," + print "---------------------------------------" + + +def unit_test(): + from vstf.common.log import setup_logging + setup_logging(level=logging.DEBUG, log_file="/var/log/vstf/vstf-cpu-settings.log", clevel=logging.INFO) + +if __name__ == '__main__': + unit_test() + diff --git a/vstf/vstf/controller/settings/data_settings.py b/vstf/vstf/controller/settings/data_settings.py new file mode 100755 index 00000000..d9878bf2 --- /dev/null +++ b/vstf/vstf/controller/settings/data_settings.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# -*- coding: utf8 -*- +# author: wly +# date: 2015-09-25 +# see license for license details + +import logging + +import vstf.controller.settings.settings as sets + +LOG = logging.getLogger(__name__) + + +class DataSettings(sets.Settings): + def __init__(self, path="/etc/vstf/reporter/", + filename="reporters.html.data-settings", + mode=sets.SETS_SINGLE): + super(DataSettings, self).__init__(path, filename, mode) + + def _register_func(self): + super(DataSettings, self)._register_func() + items = {"ovs", "result"} + fkeys = {"title", "content"} + for item in items: + item = item.encode() + for key in fkeys: + key = key.encode() + func_name = "set_%s_%s" % (item, key) + setattr(self, func_name, self._setting_file(func_name, self._mset[item], self._fset[item], key)) + func_name = "mset_%s_%s" % (item, key) + setattr(self, func_name, self._setting_memory(func_name, self._mset[item], key))
\ No newline at end of file diff --git a/vstf/vstf/controller/settings/device_settings.py b/vstf/vstf/controller/settings/device_settings.py new file mode 100755 index 00000000..45bc9eb1 --- /dev/null +++ b/vstf/vstf/controller/settings/device_settings.py @@ -0,0 +1,18 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- +# author: wly +# date: 2015/11/19 +# see license for license details + +import logging + +import vstf.controller.settings.settings as sets + +LOG = logging.getLogger(__name__) + + +class DeviceSettings(sets.Settings): + def __init__(self, path="/etc/vstf/perf/", + filename="sw_perf.device-settings", + mode=sets.SETS_SINGLE): + super(DeviceSettings, self).__init__(path, filename, mode) diff --git a/vstf/vstf/controller/settings/flows_settings.py b/vstf/vstf/controller/settings/flows_settings.py new file mode 100755 index 00000000..b2bec625 --- /dev/null +++ b/vstf/vstf/controller/settings/flows_settings.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python +# -*- coding: utf8 -*- +# author: wly +# date: 2015-09-18 +# see license for license details + +import logging + +import vstf.controller.settings.settings as sets + +LOG = logging.getLogger(__name__) + + +class FlowsSettings(sets.Settings): + def __init__(self, path="/etc/vstf/perf/", + filename="sw_perf.flownodes-settings", + mode=sets.SETS_SINGLE): + self._check_actors = {'namespaces', 'senders', 'receivers', 'watchers'} + self._nocheck_actors = {"cpu_listens"} + super(FlowsSettings, self).__init__(path, filename, mode) + + def _register_func(self): + super(FlowsSettings, self)._register_func() + for actor in self._check_actors: + actor = actor.encode() + func_name = "add_%s" % actor + setattr(self, func_name, self._adding_file(func_name, self._mset, self._fset, actor, self._check_add)) + func_name = "madd_%s" % actor + setattr(self, func_name, self._adding_memory(func_name, self._mset, actor, self._check_add)) + + for actor in self._nocheck_actors: + actor = actor.encode() + func_name = "add_%s" % actor + setattr(self, func_name, self._adding_file(func_name, self._mset, self._fset, actor)) + func_name = "madd_%s" % actor + setattr(self, func_name, self._adding_memory(func_name, self._mset, actor)) + + LOG.debug(self.__dict__.keys()) + + def clear_all(self): + actors = self._check_actors | self._nocheck_actors + for actor in actors: + func_name = "set_%s" % actor + func = getattr(self, func_name) + func([]) + + def mclear_all(self): + actors = self._check_actors | self._nocheck_actors + for actor in actors: + func_name = "mset_%s" % actor + func = getattr(self, func_name) + func([]) + + def _check_add(self, value): + flows = ['agent', 'dev'] + if not isinstance(value, dict): + raise Exception("type is error: %s" % (str(value))) + for flow in flows: + if flow not in value.keys(): + raise Exception("keys[%s] is missing: %s" % (flow, str(value))) + + items = ["ip", "namespace", "mac", "iface", "bdf"] + for item in items: + if item not in value['dev'].keys(): + raise Exception("keys[%s] is error: %s" % (item, str(value))) + + +def unit_test(): + from vstf.common.log import setup_logging + setup_logging(level=logging.DEBUG, log_file="/var/log/vstf/vstf-flows-settings.log", clevel=logging.INFO) + + flows_settings = FlowsSettings() + LOG.info(flows_settings.settings) + + flows_settings.clear_all() + flows_settings.set_flows(2) + LOG.info(flows_settings.settings) + + flow_1 = { + "agent": "192.168.188.14", + "dev": { + "ip": "192.168.1.100", + "namespace": "vstf-space-1", + "mac": "90:e2:ba:20:1f:d8", + "iface": "eth4", + "bdf": "04:00.0" + } + } + flow_2 = { + "agent": "192.168.188.14", + "dev": { + "ip": "192.168.1.101", + "namespace": "vstf-space-2", + "mac": "90:e2:ba:20:1f:d9", + "iface": "p57p2", + "bdf": "04:00.1" + } + } + + flows_settings.add_senders(flow_1) + flows_settings.add_senders(flow_2) + flows_settings.add_receivers(flow_2) + flows_settings.add_receivers(flow_1) + + flows_settings.add_watchers(flow_1) + flows_settings.add_watchers(flow_2) + + flows_settings.add_namespaces(flow_1) + flows_settings.add_namespaces(flow_2) + + cpu = { + "agent": "192.168.188.16", + "affctl":{ + "policy": 2 + } + } + flows_settings.add_cpu_listens(cpu) + LOG.info(flows_settings.settings) + + +if __name__ == '__main__': + unit_test() diff --git a/vstf/vstf/controller/settings/forwarding_settings.py b/vstf/vstf/controller/settings/forwarding_settings.py new file mode 100755 index 00000000..67ec3f85 --- /dev/null +++ b/vstf/vstf/controller/settings/forwarding_settings.py @@ -0,0 +1,18 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- +# author: wly +# date: 2015/11/19 +# see license for license details + +import logging + +import vstf.controller.settings.settings as sets + +LOG = logging.getLogger(__name__) + + +class ForwardingSettings(sets.Settings): + def __init__(self, path="/etc/vstf/perf/", + filename="sw_perf.forwarding-settings", + mode=sets.SETS_SINGLE): + super(ForwardingSettings, self).__init__(path, filename, mode) diff --git a/vstf/vstf/controller/settings/html_settings.py b/vstf/vstf/controller/settings/html_settings.py new file mode 100755 index 00000000..7e715100 --- /dev/null +++ b/vstf/vstf/controller/settings/html_settings.py @@ -0,0 +1,51 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- +# author: wly +# date: 2015-09-25 +# see license for license details +__version__ = ''' ''' + +import logging + +import vstf.controller.settings.settings as sets + +LOG = logging.getLogger(__name__) + + +class HtmlSettings(sets.Settings): + def __init__(self, path="/etc/vstf/", filename="reporters.html-settings", mode=sets.SETS_DEFAULT): + super(HtmlSettings, self).__init__(path, filename, mode) + + +def unit_test(): + from vstf.common.log import setup_logging + setup_logging(level=logging.DEBUG, log_file="/var/log/html-settings.log", clevel=logging.DEBUG) + html_settings = HtmlSettings() + style = { + 'table': { + 'font-family': '"Trebuchet MS", Arial, Helvetica, sans-serif', + 'border-collapse': 'collapse', + 'border': '1px solid green', + 'padding': '8px', + 'text-align': 'center' + }, + 'td': + { + 'border': '1px solid green', + 'padding': '8px', + 'word-wrap': 'break-all' + }, + 'th': + { + 'background-color': '#EAF2D3', + 'border': '1px solid green', + 'padding': '8px' + } + } + + html_settings.set_style(style) + LOG.info(html_settings.settings) + + +if __name__ == '__main__': + unit_test() diff --git a/vstf/vstf/controller/settings/mail_settings.py b/vstf/vstf/controller/settings/mail_settings.py new file mode 100755 index 00000000..fd66b5c2 --- /dev/null +++ b/vstf/vstf/controller/settings/mail_settings.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# -*- coding: utf8 -*- +# author: wly +# date: 2015-09-06 +# see license for license details + +import logging +import pprint + +import vstf.controller.settings.settings as sets +import vstf.common.decorator as deco +from vstf.common.input import raw_choice + +LOG = logging.getLogger(__name__) + + +class MailSettings(sets.Settings): + def __init__(self, path="/etc/vstf", filename="reporters.mail.mail-settings", mode=sets.SETS_DEFAULT): + super(MailSettings, self).__init__(path, filename, mode) + + def _register_func(self): + super(MailSettings, self)._register_func() + body = set( + self._fset['body'].keys() + ) + LOG.debug(body) + for item in body: + item = item.encode() + func_name = "set_%s" % item + setattr(self, func_name, self._setting_file(func_name, self._mset['body'], self._fset['body'], item)) + other = {"attach", "content", "subtype"} + for item in other: + func_name = "mset_%s" % item + setattr(self, func_name, self._setting_memory(func_name, self._mset['body'], item)) + + LOG.debug(self.__dict__) + + def sinput(self): + if raw_choice("if set mail server"): + server = self.raw_server() + self.set_server(server) + + if raw_choice("if set mail body"): + body = self.raw_body() + self.set_body(body) + print "%s set finish: " % (self._filename) + print "+++++++++++++++++++++++++++++++++++++++++" + pprint.pprint(self.settings, indent=4) + print "+++++++++++++++++++++++++++++++++++++++++" + + @deco.vstf_input("password", types=str) + @deco.vstf_input("username", types=str) + @deco.vstf_input('host', types=str) + def raw_server(self): + print "---------------------------------------" + print "Please vstf set mail server info like:" + print " 'host': 'localhost'," + print " 'username': 'user',['\\n' = None]" + print " 'password': '******',['\\n' = None]" + print "---------------------------------------" + + @deco.vstf_input("subject", types=str, default='vstf mail') + @deco.vstf_input("bcc", types=list, default=[]) + @deco.vstf_input("cc", types=list, default=[]) + @deco.vstf_input("to", types=list, default=[]) + @deco.vstf_input('from', types=list, default=['vstf_from@vstf.com']) + def raw_body(self): + print "----------------------------------------------------" + print "Please vstf set mail server info like:" + print " 'from': ['vstf_from@vstf.com']," + print " 'to': ['vstf_to@vstf.com']," + print " 'cc': ['vstf_cc@vstf.com']" + print " 'bcc': ['vstf_bcc@vstf.com']" + print " 'subject': Vstf Performance Test Report" + print "----------------------------------------------------" + + +def unit_test(): + from vstf.common.log import setup_logging + setup_logging(level=logging.DEBUG, log_file="/var/log/vstf/vstf-mail-settings.log", clevel=logging.INFO) + + mail_settings = MailSettings() + mail_settings.sinput() + + return + + mail_server = { + "host": "localhost", + "username": None, + "password": None + } + mail_settings.set_server(mail_server) + + from_list = ['vstf_from@vstf.com'] + mail_settings.set_from(from_list) + to_list = ['wangli11@huawei.com'] + mail_settings.set_to(to_list) + cc_list = ['wangli11@huawei.com'] + mail_settings.set_cc(cc_list) + bcc_list = ['wangli11@huawei.com'] + mail_settings.set_bcc(bcc_list) + bcc_list = ['wangli11@huawei.com'] + mail_settings.set_bcc(bcc_list) + + subject = "Virtual Switching Performance Test Report" + mail_settings.set_subject(subject) + + subtype = "plain" + mail_settings.mset_subtype(subtype) + + attach_list = [] + mail_settings.mset_attach(attach_list) + + content = "this is a test" + mail_settings.mset_content(content) + + LOG.info(mail_settings.settings) + + +if __name__ == '__main__': + unit_test() diff --git a/vstf/vstf/controller/settings/perf_settings.py b/vstf/vstf/controller/settings/perf_settings.py new file mode 100755 index 00000000..c0c8123b --- /dev/null +++ b/vstf/vstf/controller/settings/perf_settings.py @@ -0,0 +1,102 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- +# author: wly +# date: 2015-09-28 +# see license for license details + +import pprint +import logging + +import vstf.common.decorator as deco +import vstf.common.constants as cst +import vstf.controller.settings.settings as sets +from vstf.common.input import raw_choice +from vstf.controller.database.dbinterface import DbManage + +LOG = logging.getLogger(__name__) + + +class PerfSettings(sets.Settings): + def __init__(self, path="/etc/vstf/perf/", + filename="sw_perf.batch-settings", + mode=sets.SETS_SINGLE): + self.dbconn = DbManage() + super(PerfSettings, self).__init__(path, filename, mode) + + def clear(self): + for item in cst.SCENARIOS: + func = getattr(self, "set_" + item) + func([]) + + def mclear(self): + for item in cst.SCENARIOS: + func = getattr(self, "mset_" + item) + func([]) + + def add_case(self, value): + scenario = self.dbconn.query_scenario(value["case"]) + LOG.info(scenario) + if not scenario: + LOG.warn("not support the case:%s", value["case"]) + return + self._adding_file("add", self._mset, self._fset, scenario, check=self._check_add)(value) + + def madd_case(self, case): + scenario = self.dbconn.query_scenario(case) + if not scenario: + LOG.warn("not support the case:%s", case) + return + self._adding_memory("madd", self._mset, scenario, check=self._check_add)(case) + + @deco.dcheck('sizes') + @deco.dcheck("type", choices=cst.TTYPES) + @deco.dcheck("profile", choices=cst.PROFILES) + @deco.dcheck("protocol", choices=cst.TPROTOCOLS) + @deco.dcheck("tool", choices=cst.TOOLS) + @deco.dcheck('case') + def _check_add(self, value): + LOG.info("check successfully") + + def sinput(self): + if raw_choice("if clean all Test case"): + self.clear() + while True: + if raw_choice("if add a new Test case"): + case = self.raw_addcase() + self.add_case(case) + else: + break + print "%s set finish: " % (self._filename) + print "+++++++++++++++++++++++++++++++++++" + pprint.pprint(self.settings) + print "+++++++++++++++++++++++++++++++++++" + return True + + @deco.vstf_input('sizes', types=list) + @deco.vstf_input("type", types=str, choices=cst.TTYPES) + @deco.vstf_input("profile", types=str, choices=cst.PROFILES) + @deco.vstf_input("protocol", types=str, choices=cst.TPROTOCOLS) + @deco.vstf_input("tool", types=str, choices=cst.TOOLS) + @deco.vstf_input('case') + def raw_addcase(self): + print "---------------------------------------" + print "Please vstf add case info like:" + print " 'case': 'Ti-1'," + print " 'tool': 'netperf'," + print " 'protocol': 'udp'," + print " 'profile': 'rdp'," + print " 'type': 'latency'," + print " 'sizes': [64, 128, 512, 1024]" + print "---------------------------------------" + + +def unit_test(): + perf_settings = PerfSettings() + perf_settings.sinput() + + from vstf.common.log import setup_logging + setup_logging(level=logging.DEBUG, log_file="/var/log/vstf/vstf-perf-settings.log", clevel=logging.DEBUG) + + +if __name__ == '__main__': + unit_test() diff --git a/vstf/vstf/controller/settings/settings.py b/vstf/vstf/controller/settings/settings.py new file mode 100755 index 00000000..4730c8db --- /dev/null +++ b/vstf/vstf/controller/settings/settings.py @@ -0,0 +1,286 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- +# author: wly +# date: 2015-09-06 +# see license for license details + +import json +import re +import os +import copy +import logging +import sys + +LOG = logging.getLogger(__name__) + + +def object2dict(obj): + # convert object to a dict + dic = {'__class__': obj.__class__.__name__, '__module__': obj.__module__} + dic.update(obj.__dict__) + return dic + + +def dict2object(dic): + # convert dict to object + if '__class__' in dic: + class_name = dic.pop('__class__') + module_name = dic.pop('__module__') + module = __import__(module_name) + class_ = getattr(module, class_name) + args = dict((key.encode('ascii'), value) for key, value in dic.items()) # get args + inst = class_(**args) # create new instance + else: + inst = dic + return inst + + +def filter_comments(filename, flags="//"): + result = [] + with open(filename, "r") as ifile: + lines = ifile.readlines() + for data in lines: + data = re.sub("%s.*$" % (flags), '', data) + data = re.sub("^\s*$", '', data) + if data: + result.append(data) + LOG.debug(result) + return ''.join(result) + + +class BaseSettings(object): + def _load(self, fullname): + data = filter_comments(fullname) + LOG.debug(fullname) + LOG.debug(data) + jparams = None + if data: + jparams = json.loads(data) + return jparams + + def _sub(self, ldata, rdata): + if isinstance(ldata, list) and isinstance(rdata, list): + data = [] + if ldata: + for litem in ldata: + if rdata: + for ritem in rdata: + if isinstance(litem, dict) or isinstance(litem, list): + tmp = self._sub(litem, ritem) + else: + tmp = ritem + if tmp and tmp not in data: + data.append(tmp) + else: + data.append(litem) + + else: + data = rdata + + elif isinstance(ldata, dict) and isinstance(rdata, dict): + data = {} + rdata_bak = copy.deepcopy(rdata) + for rkey, rvalue in rdata_bak.items(): + if rkey not in ldata: + rdata_bak.pop(rkey) + for lkey, lvalue in ldata.items(): + if lkey in rdata: + if isinstance(lvalue, dict) or isinstance(lvalue, list): + data[lkey] = self._sub(lvalue, rdata[lkey]) + else: + data[lkey] = rdata[lkey] + else: + if rdata_bak: + data[lkey] = lvalue + else: + data = rdata + + return data + + def _save(self, data, filename): + if os.path.exists(filename): + os.remove(filename) + with open(filename, 'w') as ofile: + content = json.dumps(data, sort_keys=True, indent=4, separators=(',', ':')) + ofile.write(content) + + +class DefaultSettings(BaseSettings): + def __init__(self, path): + self._default = os.path.join(path, 'default') + self._user = os.path.join(path, 'user') + + def load(self, filename): + dfile = os.path.join(self._default, filename) + if os.path.exists(dfile): + ddata = self._load(dfile) + data = ddata + else: + err = "default file is missing : %s" % (dfile) + LOG.error(err) + raise Exception(err) + ufile = os.path.join(self._user, filename) + if os.path.exists(ufile): + udata = self._load(ufile) + if udata: + data = self._sub(ddata, udata) + else: + LOG.info("no user file :%s" % (ufile)) + return data + + def save(self, data, filename): + ufile = os.path.join(self._user, filename) + self._save(data, ufile) + + +class SingleSettings(BaseSettings): + def __init__(self, path): + self._path = path + + def load(self, filename): + pfile = os.path.join(self._path, filename) + if os.path.exists(pfile): + ddata = self._load(pfile) + data = ddata + else: + err = "settings file is missing : %s" % (pfile) + LOG.error(err) + raise Exception(err) + return data + + def save(self, data, filename): + pfile = os.path.join(self._path, filename) + self._save(data, pfile) + +SETS_DEFAULT = "Default" +SETS_SINGLE = "Single" +SETTINGS = [SETS_SINGLE, SETS_DEFAULT] + + +class Settings(object): + def __init__(self, path, filename, mode=SETS_SINGLE): + if mode not in SETTINGS: + raise Exception("error Settings mode : %s" % (mode)) + cls_name = mode + "Settings" + thismodule = sys.modules[__name__] + cls = getattr(thismodule, cls_name) + self._settings = cls(path) + self._filename = filename + self._fset = self._settings.load(filename) + self._mset = copy.deepcopy(self._fset) + self._register_func() + + def reset(self): + self._fset = self._settings.load(self._filename) + self._mset = copy.deepcopy(self._fset) + + @property + def settings(self): + return self._mset + + def _setting_file(self, func_name, mset, fset, key, check=None): + def infunc(value): + if hasattr(check, '__call__'): + check(value) + if isinstance(fset, dict): + mset[key] = copy.deepcopy(value) + fset[key] = copy.deepcopy(value) + elif isinstance(fset, list): + del (mset[:]) + del (fset[:]) + mset.extend(copy.deepcopy(value)) + fset.extend(copy.deepcopy(value)) + self._settings.save(self._fset, self._filename) + infunc.__name__ = func_name + LOG.debug(self._mset) + LOG.debug(self._fset) + + return infunc + + def _setting_memory(self, func_name, mset, key, check=None): + def infunc(value): + if hasattr(check, '__call__'): + check(value) + if isinstance(mset, dict): + mset[key] = copy.deepcopy(value) + elif isinstance(mset, list): + for i in range(len(mset)): + mset.pop() + mset.extend(copy.deepcopy(value)) + + infunc.__name__ = func_name + LOG.debug(self._mset) + LOG.debug(self._fset) + + return infunc + + def _adding_file(self, func_name, mset, fset, key, check=None): + def infunc(value): + if hasattr(check, '__call__'): + check(value) + if key: + mset[key].append(copy.deepcopy(value)) + fset[key].append(copy.deepcopy(value)) + else: + mset.append(copy.deepcopy(value)) + fset.append(copy.deepcopy(value)) + + self._settings.save(self._fset, self._filename) + infunc.__name__ = func_name + LOG.debug(self._mset) + LOG.debug(self._fset) + + return infunc + + def _adding_memory(self, func_name, mset, key, check=None): + def infunc(value): + if hasattr(check, '__call__'): + check(value) + if key: + mset[key].append(copy.deepcopy(value)) + else: + mset.append(copy.deepcopy(value)) + infunc.__name__ = func_name + LOG.debug(self._mset) + LOG.debug(self._fset) + + return infunc + + def _register_func(self): + if isinstance(self._fset, dict): + items = set( + self._fset.keys() + ) + for item in items: + item = item.encode() + func_name = "set_%s" % item + setattr(self, func_name, self._setting_file(func_name, self._mset, self._fset, item)) + func_name = "mset_%s" % item + setattr(self, func_name, self._setting_memory(func_name, self._mset, item)) + elif isinstance(self._fset, list): + func_name = "set" + setattr(self, func_name, self._setting_file(func_name, self._mset, self._fset, None)) + func_name = "mset" + setattr(self, func_name, self._setting_memory(func_name, self._mset, None)) + func_name = "add" + setattr(self, func_name, self._adding_file(func_name, self._mset, self._fset, None)) + func_name = "madd" + setattr(self, func_name, self._adding_memory(func_name, self._mset, None)) + + +def unit_test(): + from vstf.common.log import setup_logging + setup_logging(level=logging.DEBUG, log_file="/var/log/vstf-settings.log", clevel=logging.INFO) + + path = '/etc/vstf' + setting = DefaultSettings(path) + filename = 'reporters.mail.mail-settings' + data = setting.load(filename) + + setting.save(data, filename) + LOG.info(type(data)) + LOG.info(data) + + +if __name__ == '__main__': + unit_test() diff --git a/vstf/vstf/controller/settings/settings_input.py b/vstf/vstf/controller/settings/settings_input.py new file mode 100755 index 00000000..2c262842 --- /dev/null +++ b/vstf/vstf/controller/settings/settings_input.py @@ -0,0 +1,44 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- +# author: wly +# date: 2015-10-16 +# see license for license details + + +import clize +from sigtools.modifiers import autokwoargs +from vstf.controller.settings.mail_settings import MailSettings +from vstf.controller.settings.perf_settings import PerfSettings +from vstf.controller.settings.cpu_settings import CpuSettings +from vstf.controller.settings.tool_settings import ToolSettings + + +@autokwoargs +def sinput(mail=False, perf=False, affctl=False, tool=False): + """Settings command line input + + mail: if start mail settings + + perf: if start perf settings + + affctl: if start set cpu affability + + tool: if start set tool properties + + """ + + if mail: + MailSettings().sinput() + if perf: + PerfSettings().sinput() + if affctl: + CpuSettings().sinput() + if tool: + ToolSettings().sinput() + + +def main(): + clize.run(sinput) + +if __name__ == '__main__': + main() diff --git a/vstf/vstf/controller/settings/tester_settings.py b/vstf/vstf/controller/settings/tester_settings.py new file mode 100755 index 00000000..fb116a8d --- /dev/null +++ b/vstf/vstf/controller/settings/tester_settings.py @@ -0,0 +1,18 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- +# author: wly +# date: 2015/11/17 +# see license for license details + +import logging + +import vstf.controller.settings.settings as sets + +LOG = logging.getLogger(__name__) + + +class TesterSettings(sets.Settings): + def __init__(self, path="/etc/vstf/env/", + filename="tester.json", + mode=sets.SETS_SINGLE): + super(TesterSettings, self).__init__(path, filename, mode) diff --git a/vstf/vstf/controller/settings/tool_settings.py b/vstf/vstf/controller/settings/tool_settings.py new file mode 100755 index 00000000..1d543e6a --- /dev/null +++ b/vstf/vstf/controller/settings/tool_settings.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +# -*- coding: utf8 -*- +# author: wly +# date: 2015-09-18 +# see license for license details + +import logging +import pprint +import vstf.controller.settings.settings as sets +import vstf.common.decorator as deco +from vstf.common.input import raw_choice + +LOG = logging.getLogger(__name__) + + +class ToolSettings(sets.Settings): + def __init__(self, path="/etc/vstf", filename="sw_perf.tool-settings", mode=sets.SETS_DEFAULT): + super(ToolSettings, self).__init__(path, filename, mode) + + def _register_func(self): + body = set( + self._fset.keys() + ) + LOG.debug(body) + for item in body: + item = item.encode() + func_name = "set_%s" % (item) + setattr(self, func_name, + self._setting_file(func_name, self._mset, self._fset, item, check=self._check_keys)) + + def _check_keys(self, value): + keys = ['threads', 'wait', 'time'] + if not isinstance(value, dict): + raise Exception("type is error: %s" % (str(value))) + for key in keys: + if key not in value.keys(): + raise Exception("keys[%s] is missing: %s" % (key, str(value))) + + def sinput(self): + body = set( + self._fset.keys() + ) + for tool in body: + info = "if set %s properties" % tool + if raw_choice(info): + properties = self.raw_properties() + func = getattr(self, "set_%s" % tool) + func(properties) + + print "%s set finish: " % self._filename + print "+++++++++++++++++++++++++++++++++++++++++" + pprint.pprint(self.settings, indent=4) + print "+++++++++++++++++++++++++++++++++++++++++" + + @deco.vstf_input("time", types=int) + @deco.vstf_input("wait", types=int) + @deco.vstf_input("threads", types=int) + def raw_properties(self): + print "---------------------------------------" + print "Please vstf set tool properties like:" + print " 'threads': 2," + print " 'wait': 2," + print " 'time': 10," + print "---------------------------------------" + + +def unit_test(): + from vstf.common.log import setup_logging + setup_logging(level=logging.DEBUG, log_file="/var/log/vstf/tool-settings.log", clevel=logging.INFO) + tool_settings = ToolSettings() + value = { + "time": 10, + "wait": 4, + "threads": 1 + } + tool_settings.set_pktgen(value) + tool_settings.set_netperf(value) + tool_settings.set_iperf(value) + tool_settings.set_qperf(value) + LOG.info(tool_settings.settings) + + +if __name__ == '__main__': + unit_test() |