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