cmodfiied to add juju 2.0 support.
[joid.git] / ci / genBundle.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 if LooseVersion(jujuver) >= LooseVersion('2'):
42     TPL_DIR = os.path.dirname(os.path.abspath(__file__))+'/config_tpl/juju2/bundle_tpl'
43 else:
44     TPL_DIR = os.path.dirname(os.path.abspath(__file__))+'/config_tpl/bundle_tpl'
45
46 #
47 # Prepare variables
48 #
49
50 # Prepare a storage for passwords
51 passwords_store = dict()
52
53 #
54 # Local Functions
55 #
56
57
58 def load_yaml(filepath):
59     """Load YAML file"""
60     with open(filepath, 'r') as stream:
61         try:
62             return yaml.load(stream)
63         except yaml.YAMLError as exc:
64             print(exc)
65
66 #
67 # Templates functions
68 #
69
70
71 def unit_qty():
72     """Return quantity of units to deploy"""
73     global config
74     if config['os']['ha']['mode'] == 'ha':
75         return config['os']['ha']['cluster_size']
76     else:
77         return 1
78
79
80 def unit_ceph_qty():
81     """Return size of the ceph cluster"""
82     global config
83     if config['os']['ha']['mode'] == 'ha':
84         return config['os']['ha']['cluster_size']
85     else:
86         if config['opnfv']['units'] >= 3:
87             return config['os']['ha']['cluster_size']
88         else:
89             return 2
90
91 def unit_scaleio_qty():
92     """Return size of the scaleio cluster"""
93     return 3
94
95 def to_select(qty=False):
96     """Return a random list of machines numbers to deploy"""
97     global config
98     if not qty:
99         qty = config['os']['ha']['cluster_size'] if \
100                 config['os']['ha']['mode'] == 'ha' else 1
101     if config['os']['hyperconverged']:
102         return random.sample(range(0, config['opnfv']['units']), qty)
103     else:
104         return random.sample(range(0, qty), qty)
105
106
107 def get_password(key, length=16, special=False):
108     """Return a new random password or a already created one"""
109     global passwords_store
110     if key not in passwords_store.keys():
111         alphabet = "abcdefghijklmnopqrstuvwxyz"
112         upperalphabet = alphabet.upper()
113         char_list = alphabet + upperalphabet + '0123456789'
114         pwlist = []
115         if special:
116             char_list += "+-,;./:?!*"
117         for i in range(length):
118             pwlist.append(char_list[random.randrange(len(char_list))])
119         random.shuffle(pwlist)
120         passwords_store[key] = "".join(pwlist)
121     return passwords_store[key]
122
123 #
124 # Config import
125 #
126
127 # Load scenario Config
128 config = load_yaml(scenarioconfig_file)
129 # Load lab Config
130 config.update(load_yaml(labconfig_file))
131
132 # We transform array to hash for an easier work
133 config['opnfv']['spaces_dict'] = dict()
134 for space in config['opnfv']['spaces']:
135     config['opnfv']['spaces_dict'][space['type']] = space
136 config['opnfv']['storage_dict'] = dict()
137 for storage in config['opnfv']['storage']:
138     config['opnfv']['storage_dict'][storage['type']] = storage
139
140 #
141 # Parse scenario name
142 #
143
144 # Set default scenario name
145 if not scenario:
146     scenario = "os-nosdn-nofeature-nonha"
147
148 # Parse scenario name
149 try:
150     sc = scenario.split('-')
151     (sdn, features, hamode) = sc[1:4]
152     features = features.split('_')
153     if len(sc) > 4:
154         extra = sc[4].split('_')
155     else:
156         extra = []
157 except ValueError as err:
158     print('Error: Bad scenario name syntax, use '
159           '"os-<controller>-<nfvfeature>-<mode>[-<extrastuff>]" format')
160     sys.exit(1)
161
162 #
163 # Update config with scenario name
164 #
165
166 # change ha mode
167 config['os']['ha']['mode'] = hamode
168
169 # change ha mode
170 config['os']['network']['controller'] = sdn
171
172 # Change features
173 if 'lxd' in features:
174     config['os']['lxd'] = True
175 if 'dvr' in features:
176     config['os']['network']['dvr'] = True
177 if 'ipv6' in features:
178     config['os']['network']['ipv6'] = True
179 if 'ovs' in features:
180     config['os']['network']['enhanced_ovs'] = True
181 if 'sfc' in features:
182     config['os']['network']['sfc'] = True
183 if 'dpdk' in features:
184     config['os']['network']['dpdk'] = True
185 if 'bgpvpn' in features:
186     config['os']['network']['bgpvpn'] = True
187 if 'odll3' in features:
188     config['os']['network']['odll3'] = True
189 if 'dishypcon' in features:
190     config['os']['hyperconverged'] = False
191
192 # Set beta option from extra
193 if 'publicapi' in extra:
194     config['os']['beta']['public_api'] = True
195 if 'radosgwcluster' in extra:
196     config['os']['beta']['hacluster_ceph_radosgw'] = True
197 if 'hugepages' in extra:
198     config['os']['beta']['huge_pages'] = True
199 if 'trusty' in extra:
200     config['ubuntu']['release'] = 'trusty'
201     if 'liberty' in extra:
202         config['os']['release'] = 'liberty'
203 if 'dishypcon' in extra:
204     config['os']['hyperconverged'] = False
205
206 #
207 # Transform template to bundle.yaml according to config
208 #
209
210 # Create the jinja2 environment.
211 env = Environment(loader=FileSystemLoader(TPL_DIR),
212                   trim_blocks=True)
213 template = env.get_template('bundle.yaml')
214
215 # Add functions
216 env.globals.update(get_password=get_password)
217 env.globals.update(unit_qty=unit_qty)
218 env.globals.update(unit_ceph_qty=unit_ceph_qty)
219 env.globals.update(unit_scaleio_qty=unit_scaleio_qty)
220 env.globals.update(to_select=to_select)
221
222 # Render the template
223 output = template.render(**config)
224
225 # Check output syntax
226 try:
227     yaml.load(output)
228 except yaml.YAMLError as exc:
229     print(exc)
230
231 # print output
232 print(output)