bug 370 bug 364 Use tenant uuid instead of name for RO NBI
[osm/osmclient.git] / osmclient / v1 / vim.py
1 # Copyright 2017 Sandvine
2 #
3 # All Rights Reserved.
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License"); you may
6 # not use this file except in compliance with the License. You may obtain
7 # a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 # License for the specific language governing permissions and limitations
15 # under the License.
16
17 """
18 OSM vim API handling
19 """
20
21 from osmclient.common.exceptions import ClientException
22 from osmclient.common.exceptions import NotFound
23 import json
24
25
26 class Vim(object):
27 def __init__(self, http=None, ro_http=None, client=None):
28 self._client = client
29 self._ro_http = ro_http
30 self._http = http
31
32 def _attach(self, vim_name, vim_account):
33 tenant_name = 'osm'
34 tenant = self._get_ro_tenant()
35 if tenant is None:
36 raise ClientException("tenant {} not found".format(tenant_name))
37
38 datacenter = self._get_ro_datacenter(vim_name)
39 if datacenter is None:
40 raise Exception('datacenter {} not found'.format(vim_name))
41
42 return self._ro_http.post_cmd('openmano/{}/datacenters/{}'
43 .format(tenant['uuid'],
44 datacenter['uuid']), vim_account)
45
46 def _detach(self, vim_name):
47 tenant_name = 'osm'
48 tenant = self._get_ro_tenant()
49 if tenant is None:
50 raise ClientException("tenant {} not found".format(tenant_name))
51 return self._ro_http.delete_cmd('openmano/{}/datacenters/{}'
52 .format(tenant["uuid"], vim_name))
53
54 def create(self, name, vim_access):
55 vim_account = {}
56 vim_account['datacenter'] = {}
57
58 # currently assumes vim_acc
59 if ('vim-type' not in vim_access):
60 #'openstack' not in vim_access['vim-type']):
61 raise Exception("vim type not provided")
62
63 vim_account['datacenter']['name'] = name
64 vim_account['datacenter']['type'] = vim_access['vim-type']
65
66 vim_config = {}
67 vim_config['use_floating_ip'] = False
68
69 if ('floating_ip_pool' in vim_access and
70 vim_access['floating_ip_pool'] is not None):
71 vim_config['use_floating_ip'] = True
72
73 if 'keypair' in vim_access and vim_access['keypair'] is not None:
74 vim_config['keypair'] = vim_access['keypair']
75 elif 'config' in vim_access and vim_access['config'] is not None:
76 if any(var in vim_access['config'] for var in ["admin_password","admin_username","orgname","nsx_user","nsx_password","nsx_manager","vcenter_ip","vcenter_port","vcenter_user","vcenter_password"]):
77 vim_config = json.loads(vim_access['config'])
78
79 vim_account['datacenter']['config'] = vim_config
80
81 vim_account = self.update_vim_account_dict(vim_account, vim_access, vim_config)
82
83 resp = self._ro_http.post_cmd('openmano/datacenters', vim_account)
84 if resp and 'error' in resp:
85 raise ClientException("failed to create vim")
86 else:
87 self._attach(name, vim_account)
88 self._update_ro_accounts()
89
90
91 def _update_ro_accounts(self):
92 get_ro_accounts = self._http.get_cmd('api/operational/{}ro-account'
93 .format(self._client.so_rbac_project_path))
94 if not get_ro_accounts or 'rw-ro-account:ro-account' not in get_ro_accounts:
95 return
96 for account in get_ro_accounts['rw-ro-account:ro-account']['account']:
97 if account['ro-account-type'] == 'openmano':
98 # Refresh the Account Status
99 refresh_body = {"input": {
100 "ro-account": account['name'],
101 "project-name": self._client._so_project
102 }
103 }
104 refresh_status = self._http.post_cmd('api/operations/update-ro-account-status',
105 refresh_body)
106 if refresh_status and 'error' in refresh_status:
107 raise ClientException("Failed to refersh RO Account Status")
108
109
110 def update_vim_account_dict(self, vim_account, vim_access, vim_config):
111 if vim_access['vim-type'] == 'vmware':
112 if 'admin_username' in vim_config:
113 vim_account['datacenter']['admin_username'] = vim_config['admin_username']
114 if 'admin_password' in vim_config:
115 vim_account['datacenter']['admin_password'] = vim_config['admin_password']
116 if 'nsx_manager' in vim_config:
117 vim_account['datacenter']['nsx_manager'] = vim_config['nsx_manager']
118 if 'nsx_user' in vim_config:
119 vim_account['datacenter']['nsx_user'] = vim_config['nsx_user']
120 if 'nsx_password' in vim_config:
121 vim_account['datacenter']['nsx_password'] = vim_config['nsx_password']
122 if 'orgname' in vim_config:
123 vim_account['datacenter']['orgname'] = vim_config['orgname']
124 if 'vcenter_ip' in vim_config:
125 vim_account['datacenter']['vcenter_ip'] = vim_config['vcenter_ip']
126 if 'vcenter_user' in vim_config:
127 vim_account['datacenter']['vcenter_user'] = vim_config['vcenter_user']
128 if 'vcenter_password' in vim_config:
129 vim_account['datacenter']['vcenter_password'] = vim_config['vcenter_password']
130 if 'vcenter_port' in vim_config:
131 vim_account['datacenter']['vcenter_port'] = vim_config['vcenter_port']
132 vim_account['datacenter']['vim_url'] = vim_access['vim-url']
133 vim_account['datacenter']['vim_url_admin'] = vim_access['vim-url']
134 vim_account['datacenter']['description'] = vim_access['description']
135 vim_account['datacenter']['vim_username'] = vim_access['vim-username']
136 vim_account['datacenter']['vim_password'] = vim_access['vim-password']
137 vim_account['datacenter']['vim_tenant_name'] = vim_access['vim-tenant-name']
138 else:
139 vim_account['datacenter']['vim_url'] = vim_access['vim-url']
140 vim_account['datacenter']['vim_url_admin'] = vim_access['vim-url']
141 vim_account['datacenter']['description'] = vim_access['description']
142 vim_account['datacenter']['vim_username'] = vim_access['vim-username']
143 vim_account['datacenter']['vim_password'] = vim_access['vim-password']
144 vim_account['datacenter']['vim_tenant_name'] = vim_access['vim-tenant-name']
145 return vim_account
146
147 def delete(self, vim_name):
148 # first detach
149 self._detach(vim_name)
150 # detach. continue if error,
151 # it could be the datacenter is left without attachment
152 resp = self._ro_http.delete_cmd('openmano/datacenters/{}'
153 .format(vim_name))
154 if 'result' not in resp:
155 raise ClientException("failed to delete vim {} - {}".format(vim_name, resp))
156 self._update_ro_accounts()
157
158 def list(self):
159 self._update_ro_accounts()
160 if self._client._so_version == 'v3':
161 resp = self._http.get_cmd('v1/api/operational/{}ro-account-state'
162 .format(self._client.so_rbac_project_path))
163 datacenters = []
164 if not resp or 'rw-ro-account:ro-account-state' not in resp:
165 return list()
166
167 ro_accounts = resp['rw-ro-account:ro-account-state']
168 for ro_account in ro_accounts['account']:
169 if 'datacenters' not in ro_account:
170 continue
171 if 'datacenters' not in ro_account['datacenters']:
172 continue
173 for datacenter in ro_account['datacenters']['datacenters']:
174 datacenters.append({"name": datacenter['name'], "uuid": datacenter['uuid']
175 if 'uuid' in datacenter else None})
176
177 vim_accounts = datacenters
178 return vim_accounts
179 else:
180 # Backwards Compatibility
181 resp = self._http.get_cmd('v1/api/operational/datacenters')
182 if not resp or 'rw-launchpad:datacenters' not in resp:
183 return list()
184
185 datacenters = resp['rw-launchpad:datacenters']
186
187 vim_accounts = list()
188 if 'ro-accounts' not in datacenters:
189 return vim_accounts
190
191 tenant = self._get_ro_tenant()
192 if tenant is None:
193 return vim_accounts
194
195 for roaccount in datacenters['ro-accounts']:
196 if 'datacenters' not in roaccount:
197 continue
198 for datacenter in roaccount['datacenters']:
199 vim_accounts.append(self._get_ro_datacenter(datacenter['name'],
200 tenant['uuid']))
201 return vim_accounts
202
203 def _get_ro_tenant(self, name='osm'):
204 resp = self._ro_http.get_cmd('openmano/tenants/{}'.format(name))
205
206 if not resp:
207 return None
208
209 if 'tenant' in resp and 'uuid' in resp['tenant']:
210 return resp['tenant']
211 else:
212 return None
213
214 def _get_ro_datacenter(self, name, tenant_uuid='any'):
215 resp = self._ro_http.get_cmd('openmano/{}/datacenters/{}'
216 .format(tenant_uuid, name))
217 if not resp:
218 raise NotFound("datacenter {} not found".format(name))
219
220 if 'datacenter' in resp and 'uuid' in resp['datacenter']:
221 return resp['datacenter']
222 else:
223 raise NotFound("datacenter {} not found".format(name))
224
225 def get(self, name):
226 tenant = self._get_ro_tenant()
227 if tenant is None:
228 raise NotFound("no ro tenant found")
229
230 return self._get_ro_datacenter(name, tenant['uuid'])
231
232 def get_datacenter(self, name):
233 if self._client._so_version == 'v3':
234 resp = self._http.get_cmd('v1/api/operational/{}ro-account-state'
235 .format(self._client.so_rbac_project_path))
236 if not resp:
237 return None, None
238
239 if not resp or 'rw-ro-account:ro-account-state' not in resp:
240 return None, None
241
242 ro_accounts = resp['rw-ro-account:ro-account-state']
243 for ro_account in ro_accounts['account']:
244 if 'datacenters' not in ro_account:
245 continue
246 if 'datacenters' not in ro_account['datacenters']:
247 continue
248 for datacenter in ro_account['datacenters']['datacenters']:
249 if datacenter['name'] == name:
250 return datacenter, ro_account['name']
251 return None, None
252 else:
253 # Backwards Compatibility
254 resp = self._http.get_cmd('v1/api/operational/datacenters')
255 if not resp:
256 return None
257
258 if not resp or 'rw-launchpad:datacenters' not in resp:
259 return None
260 if 'ro-accounts' not in resp['rw-launchpad:datacenters']:
261 return None
262 for roaccount in resp['rw-launchpad:datacenters']['ro-accounts']:
263 if 'datacenters' not in roaccount:
264 continue
265 for datacenter in roaccount['datacenters']:
266 if datacenter['name'] == name:
267 return datacenter
268 return None
269
270 def get_resource_orchestrator(self):
271 resp = self._http.get_cmd('v1/api/operational/{}resource-orchestrator'
272 .format(self._client.so_rbac_project_path))
273
274 if not resp or 'rw-launchpad:resource-orchestrator' not in resp:
275 return None
276 return resp['rw-launchpad:resource-orchestrator']