Bottlenecks stack config parser.
[bottlenecks.git] / utils / parser.py
1 #!/usr/bin/env python
2 ##############################################################################
3 # Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
4 #
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9 ##############################################################################
10 '''This file realize the function of how to parser a config file.
11 This contain Two part:
12 Frist is Init some variables the will be used.
13 Second is reading config file.'''
14
15 import os
16 import yaml
17
18
19 class Parser():
20
21     bottlenecks_config = {}
22     bottlenecks_test = {}
23
24     @classmethod
25     def config_init(cls):
26         cls.code_dir = os.path.dirname(os.path.abspath(__file__))
27         cls.root_dir = os.path.dirname(cls.code_dir)
28         cls.test_dir = os.path.join(cls.root_dir, 'testsuites')
29         config_dir = os.path.join(
30             cls.root_dir,
31             'config',
32             'config.yaml')
33
34         with open(config_dir) as file:
35             config_info = yaml.load(file)
36             common_config = config_info['common_config']
37             cls.bottlenecks_config["releng_dir"] = common_config["releng_dir"]
38             cls.bottlenecks_config["fetch_os"] = common_config["fetch_os_file"]
39             cls.bottlenecks_config["log_dir"] = common_config['log_dir']
40             cls.bottlenecks_config["rc_dir"] = common_config['rc_dir']
41             cls.config_dir_check(cls.bottlenecks_config["log_dir"])
42
43     @classmethod
44     def story_read(cls, testcase, story_name):
45         story_dir = os.path.join(
46             cls.test_dir,
47             testcase,
48             'testsuite_story',
49             story_name)
50         with open(story_dir) as file:
51             story_parser = yaml.load(file)
52         for case_name in story_parser['testcase']:
53             Parser.testcase_read(cls, testcase, case_name)
54
55         return cls.bottlenecks_test
56
57     @classmethod
58     def testcase_read(cls, testcase, testcase_name):
59
60         testcase_dir = os.path.join(
61             cls.test_dir,
62             testcase,
63             'testcase_cfg',
64             testcase_name)
65         testcase_local = testcase_dir + ".yaml"
66         with open(testcase_local) as f:
67             cls.bottlenecks_test[testcase_name] = yaml.load(f)
68
69         return cls.bottlenecks_test
70
71     @classmethod
72     def config_dir_check(cls, dirname):
73         if dirname is None:
74             dirname = '/tmp/'
75         if not os.path.exists(dirname):
76             os.makedirs(dirname)
77
78     @staticmethod
79     def config_parser(testcase_cfg, parameters):
80         test_cfg = testcase_cfg['test_config']
81         stack_cfg = testcase_cfg['stack_config']
82         # TO-DO add cli parameters to stack_config.
83         return test_cfg, stack_cfg
84
85
86 class HeatTemplate_Parser():
87     """parser a Heat template and a method to deploy template to a stack"""
88
89     def __init__(self):
90         self.heat_date = {}
91         self.heat_date["resources"] = {}
92         self.heat_date["outputs"] = {}
93         self.heat_date["heat_template_version"] = "2013-05-23"
94         self.heat_date["description"] = {"Stack built by the bottlenecks"
95                                          " framework for root."}
96
97     def add_security_group(self, name):
98         """add to the template a Neutron SecurityGroup"""
99         security_name = name + "-security_group"
100         self.heat_date["resources"][security_name] = {
101             "type": "OS::Neutron::SecurityGroup",
102             "properties": {
103                 "name": security_name,
104                 "description": "Group allowing icmp and upd/tcp on all ports",
105                 "rules": [
106                     {"remote_ip_prefix": "0.0.0.0/0",
107                      "protocol": "tcp",
108                      "port_range_min": "1",
109                      "port_range_max": "65535"},
110                     {"remote_ip_prefix": "0.0.0.0/0",
111                      "protocol": "udp",
112                      "port_range_min": "1",
113                      "port_range_max": "65535"},
114                     {"remote_ip_prefix": "0.0.0.0/0",
115                      "protocol": "icmp"}
116                 ]
117             }
118         }
119
120         self.heat_date["outputs"][security_name] = {
121             "description": "ID of Security Group",
122             "value": {"get_resource": security_name}
123         }
124
125     def add_keypair(self, name):
126         """add to the template a Nova KeyPair"""
127         key_name = name + "key"
128         with open(Parser.root_dir +
129                   "utils/infra_setup/"
130                   "bottlenecks_key/bottlenecks_key.pub") as f:
131             key_content = f.read()
132             self.heat_date["resources"][key_name] = {
133                 "type": "OS::Nova::KeyPair",
134                 "properties": {
135                     "name": key_name,
136                     "public_key": key_content
137                 }
138             }
139
140     def add_network(self, name):
141         """add to the template a Neutron Net"""
142         network_name = name + "-net"
143         self.heat_date["resources"][network_name] = {
144             "type": "OS::Neutron::Net",
145             "properties": {"name": network_name}
146         }
147
148     def add_subnet(self, name, cidr):
149         """add to the template a Neutron Subnet"""
150         network_name = name + "-net"
151         subnet_name = name + "-subnet"
152         self.heat_date["resources"][subnet_name] = {
153             "type": "OS::Neutron::Subnet",
154             "depends_on": network_name,
155             "properties": {
156                 "name": subnet_name,
157                 "cidr": cidr,
158                 "network_id": {"get_resource": network_name}
159             }
160         }
161
162         self.heat_date["outputs"][subnet_name] = {
163             "description": "subnet %s ID" % subnet_name,
164             "value": {"get_resource": subnet_name}
165         }
166
167     def add_router(self, name, ext_gw_net):
168         """add to the template a Neutron Router and interface"""
169         router_name = name + "-route"
170         subnet_name = name + "-subnet"
171
172         self.heat_date["resources"][router_name] = {
173             "type": "OS::Neutron::Router",
174             "depends_on": [subnet_name],
175             "properties": {
176                 "name": router_name,
177                 "external_gateway_info": {
178                     "network": ext_gw_net
179                 }
180             }
181         }
182
183     def add_router_interface(self, name):
184         """add to the template a Neutron RouterInterface and interface"""
185         router_name = name + "-route"
186         subnet_name = name + "-subnet"
187         router_if_name = name + "-interface"
188
189         self.heat_date["resources"][router_if_name] = {
190             "type": "OS::Neutron::RouterInterface",
191             "depends_on": [router_name, subnet_name],
192             "properties": {
193                 "router_id": {"get_resource": router_name},
194                 "subnet_id": {"get_resource": subnet_name}
195             }
196         }
197
198     def add_server(self, name, image, flavor, user, ports=None):
199         """add to the template a Nova Server"""
200
201         key_name = "bottlenecks-poscakey"
202         port_name = name + "-port"
203         self.heat_date["resources"][name] = {
204             "type": "OS::Nova::Server",
205             "properties": {
206                 "name": name,
207                 "flavor": flavor,
208                 "image": image,
209                 "key_name": {"get_resource": key_name},
210                 "admin_user": user,
211                 "networks": [{
212                     "port": {"get_resource": port_name}
213                 }]
214             }
215         }
216
217         self.heat_date["outputs"][name] = {
218             "description": "VM UUID",
219             "value": {"get_resource": name}
220         }
221
222     def add_port(self, name, stack_name=None):
223         """add to the template a named Neutron Port"""
224         network_name = stack_name + "-net"
225         subnet_name = stack_name + "-subnet"
226         port_name = name + "-port"
227         security_name = stack_name + "-security_group"
228
229         self.heat_date["resources"][port_name] = {
230             "type": "OS::Neutron::Port",
231             "depends_on": [subnet_name],
232             "properties": {
233                 "name": port_name,
234                 "fixed_ips": [{"subnet": {"get_resource": subnet_name}}],
235                 "network_id": {"get_resource": network_name},
236                 "replacement_policy": "AUTO",
237                 "security_groups": [{"get_resource": security_name}]
238             }
239         }
240
241         self.heat_date["outputs"][port_name] = {
242             "description": "Address for interface %s" % port_name,
243             "value": {"get_attr": [port_name, "fixed_ips", 0, "ip_address"]}
244         }
245
246     def add_floating_ip(self, name, stack_name, network_ext):
247         """add to the template a Nova FloatingIP resource
248         see: https://bugs.launchpad.net/heat/+bug/1299259
249         """
250         port_name = name + "-port"
251         floating_ip_name = name + "-floating"
252         router_if_name = stack_name + "-interface"
253
254         self.heat_date["resources"][floating_ip_name] = {
255             "depends_on": [router_if_name, port_name],
256             "type": "OS::Nova::FloatingIP",
257             "properties": {
258                 "pool": network_ext,
259             }
260         }
261         self.heat_date['outputs'][floating_ip_name] = {
262             'description': 'floating ip %s' % name,
263             'value': {'get_attr': [name, 'ip']}
264         }
265
266     def add_floating_ip_ass(self, name):
267         """add to the template a Nova FloatingIP resource
268         see: https://bugs.launchpad.net/heat/+bug/1299259
269         """
270         port_name = name + "-port"
271         floating_ip_name = name + "-floating"
272         floating_ass = name + "-floating_ass"
273
274         self.heat_date["resources"][floating_ass] = {
275             "type": 'OS::Neutron::FloatingIPAssociation',
276             "depends_on": [port_name, floating_ip_name],
277             "properties": {
278                 "floatingip_id": {'get_resource': floating_ip_name},
279                 "port_id": {"get_resource": port_name}
280             }
281         }
282
283     def get_template_date(self):
284         return self.heat_date
285