modified to add load balancer kubernetes.
[joid.git] / ci / genK8Bundle.py
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3
4 """
5 This script generates a juju deployer bundle based on
6 scenario name, and lab config file.
7
8 Parameters:
9  -s, --scenario : scenario name
10  -l, --lab      : lab config file
11 """
12
13 from optparse import OptionParser
14 from jinja2 import Environment, FileSystemLoader
15 from distutils.version import LooseVersion, StrictVersion
16 import os
17 import subprocess
18 import random
19 import yaml
20 import sys
21
22 #
23 # Parse parameters
24 #
25
26 parser = OptionParser()
27 parser.add_option("-s", "--scenario", dest="scenario", help="scenario name")
28 parser.add_option("-l", "--lab", dest="lab", help="lab config file")
29 (options, args) = parser.parse_args()
30 scenario = options.scenario
31 labconfig_file = options.lab
32
33 #
34 # Set Path and configs path
35 #
36
37 scenarioconfig_file = 'default_deployment_config.yaml'
38 # Capture our current directory
39 jujuver = subprocess.check_output(["juju", "--version"])
40
41 TPL_DIR = os.path.dirname(os.path.abspath(__file__))+'/config_tpl/juju2/bundlek8_tpl'
42
43 #
44 # Prepare variables
45 #
46
47 # Prepare a storage for passwords
48 passwords_store = dict()
49
50 #
51 # Local Functions
52 #
53
54
55 def load_yaml(filepath):
56     """Load YAML file"""
57     with open(filepath, 'r') as stream:
58         try:
59             return yaml.load(stream)
60         except yaml.YAMLError as exc:
61             print(exc)
62
63 #
64 # Templates functions
65 #
66
67
68 def unit_qty():
69     """Return quantity of units to deploy"""
70     global config
71     if config['os']['ha']['mode'] == 'ha':
72         return config['os']['ha']['cluster_size']
73     else:
74         return 1
75
76
77 def unit_ceph_qty():
78     """Return size of the ceph cluster"""
79     global config
80     if config['os']['ha']['mode'] == 'ha':
81         return config['os']['ha']['cluster_size']
82     else:
83         if config['opnfv']['units'] >= 3:
84             return config['os']['ha']['cluster_size']
85         else:
86             return 2
87
88 def unit_scaleio_qty():
89     """Return size of the scaleio cluster"""
90     return 3
91
92 def to_select(qty=False):
93     """Return a random list of machines numbers to deploy"""
94     global config
95     if not qty:
96         qty = config['os']['ha']['cluster_size'] if \
97                 config['os']['ha']['mode'] == 'ha' else 1
98     if config['os']['hyperconverged']:
99         return random.sample(range(0, config['opnfv']['units']), qty)
100     else:
101         return random.sample(range(0, qty), qty)
102
103
104 def get_password(key, length=16, special=False):
105     """Return a new random password or a already created one"""
106     global passwords_store
107     if key not in passwords_store.keys():
108         alphabet = "abcdefghijklmnopqrstuvwxyz"
109         upperalphabet = alphabet.upper()
110         char_list = alphabet + upperalphabet + '0123456789'
111         pwlist = []
112         if special:
113             char_list += "+-,;./:?!*"
114         for i in range(length):
115             pwlist.append(char_list[random.randrange(len(char_list))])
116         random.shuffle(pwlist)
117         passwords_store[key] = "".join(pwlist)
118     return passwords_store[key]
119
120 #
121 # Config import
122 #
123
124 # Load scenario Config
125 config = load_yaml(scenarioconfig_file)
126 # Load lab Config
127 config.update(load_yaml(labconfig_file))
128
129 # We transform array to hash for an easier work
130 config['opnfv']['spaces_dict'] = dict()
131 for space in config['opnfv']['spaces']:
132     config['opnfv']['spaces_dict'][space['type']] = space
133 config['opnfv']['storage_dict'] = dict()
134 for storage in config['opnfv']['storage']:
135     config['opnfv']['storage_dict'][storage['type']] = storage
136
137 #
138 # Parse scenario name
139 #
140
141 # Set default scenario name
142 if not scenario:
143     scenario = "k8-nosdn-baremetal-core"
144
145 # Parse scenario name
146 try:
147     sc = scenario.split('-')
148     (sdn, features, hamode) = sc[1:4]
149     features = features.split('_')
150     if len(sc) > 4:
151         extra = sc[4].split('_')
152     else:
153         extra = []
154 except ValueError as err:
155     print('Error: Bad scenario name syntax, use '
156           '"k8-nosdn-baremetal-core" format')
157     sys.exit(1)
158
159 #
160 # Update config with scenario name
161 #
162
163 if 'dpdk' in features:
164     config['os']['network']['dpdk'] = True
165 if 'lb' in features:
166     config['os']['kubernetes']['loadbalancer'] = True
167
168 # Set beta option from extra
169 if 'hugepages' in extra:
170     config['os']['beta']['huge_pages'] = True
171 if 'lb' in extra:
172     config['os']['kubernetes']['loadbalancer'] = True
173 if 'mitaka' in extra:
174     config['os']['release'] = 'mitaka'
175 if 'xenial' in extra:
176     config['ubuntu']['release'] = 'xenial'
177
178 #
179 # Transform template to bundle.yaml according to config
180 #
181
182 # Create the jinja2 environment.
183 env = Environment(loader=FileSystemLoader(TPL_DIR),
184                   trim_blocks=True)
185 template = env.get_template('bundle.yaml')
186
187 # Add functions
188 env.globals.update(get_password=get_password)
189 env.globals.update(unit_qty=unit_qty)
190 env.globals.update(unit_ceph_qty=unit_ceph_qty)
191 env.globals.update(unit_scaleio_qty=unit_scaleio_qty)
192 env.globals.update(to_select=to_select)
193
194 # Render the template
195 output = template.render(**config)
196
197 # Check output syntax
198 try:
199     yaml.load(output)
200 except yaml.YAMLError as exc:
201     print(exc)
202
203 # print output
204 print(output)