First set of OSM model changes for multi-disk/config-files/etc.
[osm/SO.git] / rwcal / plugins / vala / rwcal_openstack / rift / rwcal / openstack / prepare_vm.py
1 #!/usr/bin/env python3
2
3 #
4 # Copyright 2016 RIFT.IO Inc
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18
19 import rift.rwcal.openstack as openstack_drv
20 import logging
21 import argparse
22 import sys, os, time
23 import rwlogger
24 import yaml
25
26 logging.basicConfig(level=logging.DEBUG)
27 logger = logging.getLogger()
28
29 rwlog_handler = rwlogger.RwLogger(category="rw-cal-log",
30 subcategory="openstack",)
31 logger.addHandler(rwlog_handler)
32 #logger.setLevel(logging.DEBUG)
33
34
35 def assign_floating_ip_address(drv, argument):
36 if not argument.floating_ip:
37 return
38
39 server = drv.nova_server_get(argument.server_id)
40 logger.info("Assigning the floating_ip: %s to VM: %s" %(argument.floating_ip, server['name']))
41
42 for i in range(120):
43 server = drv.nova_server_get(argument.server_id)
44 for network_name,network_info in server['addresses'].items():
45 if network_info:
46 if network_name == argument.mgmt_network:
47 for n_info in network_info:
48 if 'OS-EXT-IPS:type' in n_info and n_info['OS-EXT-IPS:type'] == 'fixed':
49 management_ip = n_info['addr']
50 drv.nova_floating_ip_assign(argument.server_id,
51 argument.floating_ip,
52 management_ip)
53 logger.info("Assigned floating_ip: %s to management_ip: %s" %(argument.floating_ip, management_ip))
54 return
55 logger.info("Waiting for management_ip to be assigned to server: %s" %(server['name']))
56 time.sleep(1)
57 else:
58 logger.info("No management_ip IP available to associate floating_ip for server: %s" %(server['name']))
59 return
60
61
62 def create_port_metadata(drv, argument):
63 if argument.port_metadata == False:
64 return
65
66 ### Get Management Network ID
67 network_list = drv.neutron_network_list()
68 mgmt_network_id = [net['id'] for net in network_list if net['name'] == argument.mgmt_network][0]
69 port_list = [ port for port in drv.neutron_port_list(**{'device_id': argument.server_id})
70 if port['network_id'] != mgmt_network_id ]
71 meta_data = {}
72
73 meta_data['rift-meta-ports'] = str(len(port_list))
74 port_id = 0
75 for port in port_list:
76 info = []
77 info.append('"port_name":"'+port['name']+'"')
78 if 'mac_address' in port:
79 info.append('"hw_addr":"'+port['mac_address']+'"')
80 if 'network_id' in port:
81 #info.append('"network_id":"'+port['network_id']+'"')
82 net_name = [net['name'] for net in network_list if net['id'] == port['network_id']]
83 if net_name:
84 info.append('"network_name":"'+net_name[0]+'"')
85 if 'fixed_ips' in port:
86 ip_address = port['fixed_ips'][0]['ip_address']
87 info.append('"ip":"'+ip_address+'"')
88
89 meta_data['rift-meta-port-'+str(port_id)] = '{' + ','.join(info) + '}'
90 port_id += 1
91
92 nvconn = drv.nova_drv._get_nova_connection()
93 nvconn.servers.set_meta(argument.server_id, meta_data)
94
95 def get_volume_id(server_vol_list, name):
96 if server_vol_list is None:
97 return
98
99 for os_volume in server_vol_list:
100 try:
101 " Device name is of format /dev/vda"
102 vol_name = (os_volume['device']).split('/')[2]
103 except:
104 continue
105 if name == vol_name:
106 return os_volume['volumeId']
107
108 def create_volume_metadata(drv, argument):
109 if argument.vol_metadata is None:
110 return
111
112 yaml_vol_str = argument.vol_metadata.read()
113 yaml_vol_cfg = yaml.load(yaml_vol_str)
114
115 srv_volume_list = drv.nova_volume_list(argument.server_id)
116 for volume in yaml_vol_cfg:
117 if 'custom_meta_data' not in volume:
118 continue
119 vmd = dict()
120 for vol_md_item in volume['custom_meta_data']:
121 if 'value' not in vol_md_item:
122 continue
123 vmd[vol_md_item['name']] = vol_md_item['value']
124
125 # Get volume id
126 vol_id = get_volume_id(srv_volume_list, volume['name'])
127 if vol_id is None:
128 logger.error("Server %s Could not find volume %s" %(argument.server_id, volume['name']))
129 sys.exit(3)
130 drv.cinder_volume_set_metadata(vol_id, vmd)
131
132
133 def prepare_vm_after_boot(drv,argument):
134 ### Important to call create_port_metadata before assign_floating_ip_address
135 ### since assign_floating_ip_address can wait thus delaying port_metadata creation
136
137 ### Wait for a max of 5 minute for server to come up -- Needs fine tuning
138 wait_time = 500
139 sleep_time = 2
140 for i in range(int(wait_time/sleep_time)):
141 server = drv.nova_server_get(argument.server_id)
142 if server['status'] == 'ACTIVE':
143 logger.info("Server %s to reached active state" %(server['name']))
144 break
145 elif server['status'] == 'BUILD':
146 logger.info("Waiting for server: %s to build. Current state: %s" %(server['name'], server['status']))
147 time.sleep(sleep_time)
148 else:
149 logger.info("Server %s reached state: %s" %(server['name'], server['status']))
150 sys.exit(3)
151 else:
152 logger.error("Server %s did not reach active state in %d seconds. Current state: %s" %(server['name'], wait_time, server['status']))
153 sys.exit(4)
154
155 #create_port_metadata(drv, argument)
156 create_volume_metadata(drv, argument)
157 assign_floating_ip_address(drv, argument)
158
159
160 def main():
161 """
162 Main routine
163 """
164 parser = argparse.ArgumentParser(description='Script to create openstack resources')
165 parser.add_argument('--auth_url',
166 action = "store",
167 dest = "auth_url",
168 type = str,
169 help='Keystone Auth URL')
170
171 parser.add_argument('--username',
172 action = "store",
173 dest = "username",
174 type = str,
175 help = "Username for openstack installation")
176
177 parser.add_argument('--password',
178 action = "store",
179 dest = "password",
180 type = str,
181 help = "Password for openstack installation")
182
183 parser.add_argument('--tenant_name',
184 action = "store",
185 dest = "tenant_name",
186 type = str,
187 help = "Tenant name openstack installation")
188
189 parser.add_argument('--mgmt_network',
190 action = "store",
191 dest = "mgmt_network",
192 type = str,
193 help = "mgmt_network")
194
195 parser.add_argument('--server_id',
196 action = "store",
197 dest = "server_id",
198 type = str,
199 help = "Server ID on which boot operations needs to be performed")
200
201 parser.add_argument('--floating_ip',
202 action = "store",
203 dest = "floating_ip",
204 type = str,
205 help = "Floating IP to be assigned")
206
207 parser.add_argument('--port_metadata',
208 action = "store_true",
209 dest = "port_metadata",
210 default = False,
211 help = "Create Port Metadata")
212
213 parser.add_argument("--vol_metadata", type=argparse.FileType('r'))
214
215 argument = parser.parse_args()
216
217 if not argument.auth_url:
218 logger.error("ERROR: AuthURL is not configured")
219 sys.exit(1)
220 else:
221 logger.info("Using AuthURL: %s" %(argument.auth_url))
222
223 if not argument.username:
224 logger.error("ERROR: Username is not configured")
225 sys.exit(1)
226 else:
227 logger.info("Using Username: %s" %(argument.username))
228
229 if not argument.password:
230 logger.error("ERROR: Password is not configured")
231 sys.exit(1)
232 else:
233 logger.info("Using Password: %s" %(argument.password))
234
235 if not argument.tenant_name:
236 logger.error("ERROR: Tenant Name is not configured")
237 sys.exit(1)
238 else:
239 logger.info("Using Tenant Name: %s" %(argument.tenant_name))
240
241 if not argument.mgmt_network:
242 logger.error("ERROR: Management Network Name is not configured")
243 sys.exit(1)
244 else:
245 logger.info("Using Management Network: %s" %(argument.mgmt_network))
246
247 if not argument.server_id:
248 logger.error("ERROR: Server ID is not configured")
249 sys.exit(1)
250 else:
251 logger.info("Using Server ID : %s" %(argument.server_id))
252
253
254 try:
255 pid = os.fork()
256 if pid > 0:
257 # exit for parent
258 sys.exit(0)
259 except OSError as e:
260 logger.error("fork failed: %d (%s)\n" % (e.errno, e.strerror))
261 sys.exit(2)
262
263 drv = openstack_drv.OpenstackDriver(username = argument.username,
264 password = argument.password,
265 auth_url = argument.auth_url,
266 tenant_name = argument.tenant_name,
267 mgmt_network = argument.mgmt_network)
268 prepare_vm_after_boot(drv, argument)
269 sys.exit(0)
270
271 if __name__ == "__main__":
272 main()
273
274