merge from v1.0
[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 'guest_params' not in volume:
118 continue
119 if 'custom_meta_data' not in volume['guest_params']:
120 continue
121 vmd = dict()
122 for vol_md_item in volume['guest_params']['custom_meta_data']:
123 if 'value' not in vol_md_item:
124 continue
125 vmd[vol_md_item['name']] = vol_md_item['value']
126
127 # Get volume id
128 vol_id = get_volume_id(srv_volume_list, volume['name'])
129 if vol_id is None:
130 logger.error("Server %s Could not find volume %s" %(argument.server_id, volume['name']))
131 sys.exit(3)
132 drv.cinder_volume_set_metadata(vol_id, vmd)
133
134
135 def prepare_vm_after_boot(drv,argument):
136 ### Important to call create_port_metadata before assign_floating_ip_address
137 ### since assign_floating_ip_address can wait thus delaying port_metadata creation
138
139 ### Wait for a max of 5 minute for server to come up -- Needs fine tuning
140 wait_time = 500
141 sleep_time = 2
142 for i in range(int(wait_time/sleep_time)):
143 server = drv.nova_server_get(argument.server_id)
144 if server['status'] == 'ACTIVE':
145 logger.info("Server %s to reached active state" %(server['name']))
146 break
147 elif server['status'] == 'BUILD':
148 logger.info("Waiting for server: %s to build. Current state: %s" %(server['name'], server['status']))
149 time.sleep(sleep_time)
150 else:
151 logger.info("Server %s reached state: %s" %(server['name'], server['status']))
152 sys.exit(3)
153 else:
154 logger.error("Server %s did not reach active state in %d seconds. Current state: %s" %(server['name'], wait_time, server['status']))
155 sys.exit(4)
156
157 #create_port_metadata(drv, argument)
158 create_volume_metadata(drv, argument)
159 assign_floating_ip_address(drv, argument)
160
161
162 def main():
163 """
164 Main routine
165 """
166 parser = argparse.ArgumentParser(description='Script to create openstack resources')
167 parser.add_argument('--auth_url',
168 action = "store",
169 dest = "auth_url",
170 type = str,
171 help='Keystone Auth URL')
172
173 parser.add_argument('--username',
174 action = "store",
175 dest = "username",
176 type = str,
177 help = "Username for openstack installation")
178
179 parser.add_argument('--password',
180 action = "store",
181 dest = "password",
182 type = str,
183 help = "Password for openstack installation")
184
185 parser.add_argument('--tenant_name',
186 action = "store",
187 dest = "tenant_name",
188 type = str,
189 help = "Tenant name openstack installation")
190
191 parser.add_argument('--mgmt_network',
192 action = "store",
193 dest = "mgmt_network",
194 type = str,
195 help = "mgmt_network")
196
197 parser.add_argument('--server_id',
198 action = "store",
199 dest = "server_id",
200 type = str,
201 help = "Server ID on which boot operations needs to be performed")
202
203 parser.add_argument('--floating_ip',
204 action = "store",
205 dest = "floating_ip",
206 type = str,
207 help = "Floating IP to be assigned")
208
209 parser.add_argument('--port_metadata',
210 action = "store_true",
211 dest = "port_metadata",
212 default = False,
213 help = "Create Port Metadata")
214
215 parser.add_argument("--vol_metadata", type=argparse.FileType('r'))
216
217 argument = parser.parse_args()
218
219 if not argument.auth_url:
220 logger.error("ERROR: AuthURL is not configured")
221 sys.exit(1)
222 else:
223 logger.info("Using AuthURL: %s" %(argument.auth_url))
224
225 if not argument.username:
226 logger.error("ERROR: Username is not configured")
227 sys.exit(1)
228 else:
229 logger.info("Using Username: %s" %(argument.username))
230
231 if not argument.password:
232 logger.error("ERROR: Password is not configured")
233 sys.exit(1)
234 else:
235 logger.info("Using Password: %s" %(argument.password))
236
237 if not argument.tenant_name:
238 logger.error("ERROR: Tenant Name is not configured")
239 sys.exit(1)
240 else:
241 logger.info("Using Tenant Name: %s" %(argument.tenant_name))
242
243 if not argument.mgmt_network:
244 logger.error("ERROR: Management Network Name is not configured")
245 sys.exit(1)
246 else:
247 logger.info("Using Management Network: %s" %(argument.mgmt_network))
248
249 if not argument.server_id:
250 logger.error("ERROR: Server ID is not configured")
251 sys.exit(1)
252 else:
253 logger.info("Using Server ID : %s" %(argument.server_id))
254
255
256 try:
257 pid = os.fork()
258 if pid > 0:
259 # exit for parent
260 sys.exit(0)
261 except OSError as e:
262 logger.error("fork failed: %d (%s)\n" % (e.errno, e.strerror))
263 sys.exit(2)
264
265 drv = openstack_drv.OpenstackDriver(username = argument.username,
266 password = argument.password,
267 auth_url = argument.auth_url,
268 tenant_name = argument.tenant_name,
269 mgmt_network = argument.mgmt_network)
270 prepare_vm_after_boot(drv, argument)
271 sys.exit(0)
272
273 if __name__ == "__main__":
274 main()
275
276