From 8f1101df131a4d3e03b377738507d88b745831c0 Mon Sep 17 00:00:00 2001 From: "Yiting.Li" Date: Tue, 22 Dec 2015 17:11:12 -0800 Subject: 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 --- vstf/vstf/controller/env_build/README | 15 +++ vstf/vstf/controller/env_build/__init__.py | 14 +++ vstf/vstf/controller/env_build/cfg_intent_parse.py | 130 +++++++++++++++++++++ vstf/vstf/controller/env_build/env_build.py | 77 ++++++++++++ vstf/vstf/controller/env_build/env_collect.py | 30 +++++ 5 files changed, 266 insertions(+) create mode 100755 vstf/vstf/controller/env_build/README create mode 100755 vstf/vstf/controller/env_build/__init__.py create mode 100755 vstf/vstf/controller/env_build/cfg_intent_parse.py create mode 100755 vstf/vstf/controller/env_build/env_build.py create mode 100755 vstf/vstf/controller/env_build/env_collect.py (limited to 'vstf/vstf/controller/env_build') diff --git a/vstf/vstf/controller/env_build/README b/vstf/vstf/controller/env_build/README new file mode 100755 index 00000000..ecb4e118 --- /dev/null +++ b/vstf/vstf/controller/env_build/README @@ -0,0 +1,15 @@ + env_build.py contains a quick test code for create virtual network in a remote host. + + usage: + + python env_build.py --rpc_server 192.168.188.10 --config /etc/vstf/env/Tn.json + + --rpc_server RPC_SERVER + the rabbitmq server for deliver messages. + --config CONFIG + env-build config file to parse + +the above command will build a 'Tn-type' network according to config file: /etc/vstf/env/Tn.json. + + + diff --git a/vstf/vstf/controller/env_build/__init__.py b/vstf/vstf/controller/env_build/__init__.py new file mode 100755 index 00000000..89dcd4e2 --- /dev/null +++ b/vstf/vstf/controller/env_build/__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/env_build/cfg_intent_parse.py b/vstf/vstf/controller/env_build/cfg_intent_parse.py new file mode 100755 index 00000000..8c7c10b8 --- /dev/null +++ b/vstf/vstf/controller/env_build/cfg_intent_parse.py @@ -0,0 +1,130 @@ +""" +Created on 2015-10-13 + +@author: y00228926 +""" +import json +import logging +from vstf.common.utils import randomMAC + +LOG = logging.getLogger(__name__) + + +class IntentParser(object): + def __init__(self, cfg_file): + self.cfg_file = cfg_file + with file(cfg_file) as fp: + self.cfg_intent = json.load(fp) + + def parse_cfg_file(self): + self.set_default() + self.parse_br_type() + self.parse_vms_cfg() + return self.cfg_intent + + def set_default(self): + for host_cfg in self.cfg_intent['env-build']: + host_cfg.setdefault("scheme", 'libvirt') + host_cfg.setdefault("drivers", []) + host_cfg.setdefault("vms", []) + host_cfg.setdefault("bridges", []) + for vm_cfg in host_cfg["vms"]: + vm_cfg.setdefault("init_config", {}) + vm_cfg["init_config"].setdefault('amqp_port', 5672) + vm_cfg["init_config"].setdefault('amqp_user', "guest") + vm_cfg["init_config"].setdefault('amqp_passwd', "guest") + vm_cfg["init_config"].setdefault('amqp_id', "") + + def _nomornize_boolean(self, flag): + if isinstance(flag, bool): + return flag + lflag = flag.lower() + if lflag == 'true': + return True + if lflag == 'false': + return False + raise Exception("flag %s cannot be nomonized to bool value" % flag) + + def parse_br_type(self): + for host_cfg in self.cfg_intent['env-build']: + br_cfgs = host_cfg['bridges'] + br_type_set = set() + for br_cfg in br_cfgs: + br_type_set.add(br_cfg["type"]) + for vm_cfg in host_cfg['vms']: + for tap_cfg in vm_cfg['taps']: + br_type_set.add(tap_cfg["br_type"]) + if len(br_type_set) > 1: + raise Exception("specified more than one type of vswitchfor host:%s" % host_cfg['ip']) + if len(br_type_set) > 0: + br_type = br_type_set.pop() + host_cfg['br_type'] = br_type + + def parse_vms_cfg(self): + for host_cfg in self.cfg_intent['env-build']: + vm_cfgs = host_cfg["vms"] + self._parse_vm_init_cfg(vm_cfgs) + self._parse_vm_ctrl_cfg(vm_cfgs) + for vm_cfg in vm_cfgs: + self._parse_taps_cfg(vm_cfg['taps']) + + def _parse_taps_cfg(self, tap_cfgs): + tap_name_set = set() + tap_mac_set = set() + count = 0 + for tap_cfg in tap_cfgs: + count += 1 + tap_name_set.add(tap_cfg["tap_mac"]) + tap_mac_set.add(tap_cfg["tap_name"]) + if len(tap_mac_set) != len(tap_name_set) != count: + raise Exception('config same tap_mac/tap_name for different taps') + LOG.info("tap_name_set: %s", tap_name_set) + LOG.info("tap_mac_set: %s", tap_mac_set) + + def _parse_vm_init_cfg(self, vm_cfgs): + count = 0 + ip_set = set() + gw_set = set() + required_options = {"ctrl_ip_setting", "ctrl_gw", "amqp_server"} + for vm_cfg in vm_cfgs: + init_cfg = vm_cfg["init_config"] + sub = required_options - set(init_cfg.keys()) + if sub: + raise Exception("unset required options:%s" % sub) + count += 1 + ip_set.add(init_cfg["ctrl_ip_setting"]) + gw_set.add(init_cfg["ctrl_gw"]) + if len(gw_set) > 1: + raise Exception("cannot config more than one gw for vm") + if len(ip_set) < count: + raise Exception("config same ip for different vm") + LOG.info("ip_set: %s", ip_set) + LOG.info("gw_set: %s", gw_set) + + def _parse_vm_ctrl_cfg(self, vm_cfgs): + count = 0 + ctrl_mac_set = set() + ctrl_br_set = set() + for vm_cfg in vm_cfgs: + count += 1 + vm_cfg.setdefault("ctrl_mac", randomMAC()) + vm_cfg.setdefault("ctrl_br", 'br0') + ctrl_mac_set.add(vm_cfg['ctrl_mac']) + ctrl_br_set.add(vm_cfg['ctrl_br']) + if len(ctrl_br_set) > 1: + raise Exception("cannot config more than one ctrl_br_set.") + if len(ctrl_mac_set) < count: + raise Exception("config same ctrl_mac_set for different vm.") + LOG.info("ctrl_mac_set: %s", ctrl_mac_set) + LOG.info("ctrl_br_set: %s", ctrl_br_set) + + +if __name__ == '__main__': + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument('--config', help='config file to parse') + args = parser.parse_args() + logging.basicConfig(level=logging.INFO) + p = IntentParser(args.config) + LOG.info(json.dumps(p.parse_cfg_file(), indent=4)) diff --git a/vstf/vstf/controller/env_build/env_build.py b/vstf/vstf/controller/env_build/env_build.py new file mode 100755 index 00000000..85ad5d29 --- /dev/null +++ b/vstf/vstf/controller/env_build/env_build.py @@ -0,0 +1,77 @@ +""" +Created on 2015-8-27 + +@author: y00228926 +""" +import logging + +from vstf.controller.fabricant import Fabricant +from vstf.rpc_frame_work.rpc_producer import Server +from vstf.controller.env_build.cfg_intent_parse import IntentParser + +LOG = logging.getLogger(__name__) + + +class EnvBuildApi(object): + def __init__(self, conn, config_file): + LOG.info("welcome to EnvBuilder") + self.conn = conn + intent_parser = IntentParser(config_file) + self.cfg_intent = intent_parser.parse_cfg_file() + + def build(self): + LOG.info("start build") + for host_cfg in self.cfg_intent['env-build']: + rpc = Fabricant(host_cfg['ip'], self.conn) + rpc.build_env(timeout=1800, cfg_intent=host_cfg) + return True + + def clean(self): + for host_cfg in self.cfg_intent['env-build']: + rpc = Fabricant(host_cfg['ip'], self.conn) + rpc.clean_env(timeout=120) + return True + + def get_hosts(self): + result = [] + for host_cfg in self.cfg_intent['env-build']: + host = { + 'name': host_cfg['ip'], + 'nic': "82599ES 10-Gigabit" + } + result.append(host) + return result + + +class TransmitterBuild(object): + def __init__(self, conn, config_file): + LOG.info("welcome to TransmitterBuild") + self.conn = conn + self._cfg_intent = config_file["transmitter-build"] + + def build(self): + LOG.info("start build") + for cfg in self.cfg_intent: + rpc = Fabricant(cfg['ip'], self.conn) + cfg.setdefault("scheme", 'transmitter') + rpc.build_env(timeout=1800, cfg_intent=cfg) + return True + + def clean(self): + for cfg in self.cfg_intent: + rpc = Fabricant(cfg['ip'], self.conn) + rpc.clean_env(timeout=10) + return True + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument('--rpc_server', help='rabbitmq server for deliver messages.') + parser.add_argument('--config', help='config file to parse') + args = parser.parse_args() + logging.basicConfig(level=logging.INFO) + conn = Server(args.rpc_server) + tn = EnvBuildApi(conn, args.config) + tn.build() diff --git a/vstf/vstf/controller/env_build/env_collect.py b/vstf/vstf/controller/env_build/env_collect.py new file mode 100755 index 00000000..888f71c7 --- /dev/null +++ b/vstf/vstf/controller/env_build/env_collect.py @@ -0,0 +1,30 @@ +from vstf.rpc_frame_work import rpc_producer + + +class EnvCollectApi(object): + def __init__(self, rb_mq_server): + """ + When use collect, a connection of rabbitmq is needed. + """ + super(EnvCollectApi, self).__init__() + if rb_mq_server is None: + raise Exception("The connection of rabbitmq is None.") + self.conn = rb_mq_server + + def collect_host_info(self, host): + msg = self.conn.make_msg("collect_host_info") + return self.conn.call(msg, host, timeout=2) + + def get_device_detail(self, host, nic_identity): + msg = self.conn.make_msg("get_device_detail", identity=nic_identity) + return self.conn.call(msg, host, timeout=2) + + def list_nic_devices(self, host): + msg = self.conn.make_msg("list_nic_devices") + return self.conn.call(msg, host, timeout=2) + + +if __name__ == "__main__": + conn = rpc_producer.Server("192.168.188.10") + c = EnvCollectApi(conn) + print c.collect_host_info("local") -- cgit 1.2.3-korg