blob: 4230cd482db1f0af550200f995d5b8c7b8640e97 [file] [log] [blame]
Mike Marchettie84eb312017-05-04 15:06:26 -04001# 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"""
18OSM vim API handling
19"""
20
21from osmclient.common.exceptions import ClientException
22from osmclient.common.exceptions import NotFound
Mike Marchettif68f84f2017-11-13 10:51:42 -050023import yaml
Mike Marchettiafc2e172017-10-16 16:42:44 -040024import time
Mike Marchettie84eb312017-05-04 15:06:26 -040025
26
27class Vim(object):
Mike Marchetti4c7e2372017-05-08 16:07:20 -040028 def __init__(self, http=None, ro_http=None, client=None):
29 self._client = client
30 self._ro_http = ro_http
31 self._http = http
Mike Marchettie84eb312017-05-04 15:06:26 -040032
kasar96517752017-09-08 04:28:15 -070033 def _attach(self, vim_name, vim_account):
Mike Marchetti4c7e2372017-05-08 16:07:20 -040034 tenant_name = 'osm'
35 tenant = self._get_ro_tenant()
Mike Marchettie84eb312017-05-04 15:06:26 -040036 if tenant is None:
37 raise ClientException("tenant {} not found".format(tenant_name))
kasar96517752017-09-08 04:28:15 -070038
Mike Marchetti4c7e2372017-05-08 16:07:20 -040039 datacenter = self._get_ro_datacenter(vim_name)
Mike Marchettie84eb312017-05-04 15:06:26 -040040 if datacenter is None:
41 raise Exception('datacenter {} not found'.format(vim_name))
42
Mike Marchetti4c7e2372017-05-08 16:07:20 -040043 return self._ro_http.post_cmd('openmano/{}/datacenters/{}'
44 .format(tenant['uuid'],
45 datacenter['uuid']), vim_account)
Mike Marchettie84eb312017-05-04 15:06:26 -040046
Mike Marchetti4c7e2372017-05-08 16:07:20 -040047 def _detach(self, vim_name):
tierno3a1237e2017-10-11 14:25:33 +020048 tenant_name = 'osm'
49 tenant = self._get_ro_tenant()
50 if tenant is None:
51 raise ClientException("tenant {} not found".format(tenant_name))
Mike Marchetti4c7e2372017-05-08 16:07:20 -040052 return self._ro_http.delete_cmd('openmano/{}/datacenters/{}'
tierno3a1237e2017-10-11 14:25:33 +020053 .format(tenant["uuid"], vim_name))
Mike Marchettie84eb312017-05-04 15:06:26 -040054
55 def create(self, name, vim_access):
Mike Marchetti4c7e2372017-05-08 16:07:20 -040056 vim_account = {}
57 vim_account['datacenter'] = {}
Mike Marchettie84eb312017-05-04 15:06:26 -040058
59 # currently assumes vim_acc
kasar96517752017-09-08 04:28:15 -070060 if ('vim-type' not in vim_access):
61 #'openstack' not in vim_access['vim-type']):
62 raise Exception("vim type not provided")
Mike Marchettie84eb312017-05-04 15:06:26 -040063
64 vim_account['datacenter']['name'] = name
65 vim_account['datacenter']['type'] = vim_access['vim-type']
Mike Marchettie84eb312017-05-04 15:06:26 -040066
67 vim_config = {}
Mike Marchettif68f84f2017-11-13 10:51:42 -050068 if 'config' in vim_access and vim_access['config'] is not None:
69 vim_config = yaml.load(vim_access['config'])
Mike Marchettie84eb312017-05-04 15:06:26 -040070
Mike Marchetti3664c8a2017-11-15 16:22:14 -050071 if vim_config:
72 vim_account['datacenter']['config'] = vim_config
Mike Marchettie84eb312017-05-04 15:06:26 -040073
kasar96517752017-09-08 04:28:15 -070074 vim_account = self.update_vim_account_dict(vim_account, vim_access, vim_config)
75
Mike Marchetti4c7e2372017-05-08 16:07:20 -040076 resp = self._ro_http.post_cmd('openmano/datacenters', vim_account)
Mike Marchettie84eb312017-05-04 15:06:26 -040077 if resp and 'error' in resp:
78 raise ClientException("failed to create vim")
79 else:
kasar96517752017-09-08 04:28:15 -070080 self._attach(name, vim_account)
Anurag Dwivedifa7254b2017-10-04 14:19:01 -040081 self._update_ro_accounts()
82
83
84 def _update_ro_accounts(self):
85 get_ro_accounts = self._http.get_cmd('api/operational/{}ro-account'
86 .format(self._client.so_rbac_project_path))
87 if not get_ro_accounts or 'rw-ro-account:ro-account' not in get_ro_accounts:
88 return
89 for account in get_ro_accounts['rw-ro-account:ro-account']['account']:
90 if account['ro-account-type'] == 'openmano':
91 # Refresh the Account Status
92 refresh_body = {"input": {
93 "ro-account": account['name'],
94 "project-name": self._client._so_project
95 }
96 }
97 refresh_status = self._http.post_cmd('api/operations/update-ro-account-status',
98 refresh_body)
99 if refresh_status and 'error' in refresh_status:
100 raise ClientException("Failed to refersh RO Account Status")
101
kasar96517752017-09-08 04:28:15 -0700102
103 def update_vim_account_dict(self, vim_account, vim_access, vim_config):
104 if vim_access['vim-type'] == 'vmware':
105 if 'admin_username' in vim_config:
106 vim_account['datacenter']['admin_username'] = vim_config['admin_username']
107 if 'admin_password' in vim_config:
108 vim_account['datacenter']['admin_password'] = vim_config['admin_password']
109 if 'nsx_manager' in vim_config:
110 vim_account['datacenter']['nsx_manager'] = vim_config['nsx_manager']
111 if 'nsx_user' in vim_config:
112 vim_account['datacenter']['nsx_user'] = vim_config['nsx_user']
113 if 'nsx_password' in vim_config:
114 vim_account['datacenter']['nsx_password'] = vim_config['nsx_password']
115 if 'orgname' in vim_config:
116 vim_account['datacenter']['orgname'] = vim_config['orgname']
117 if 'vcenter_ip' in vim_config:
118 vim_account['datacenter']['vcenter_ip'] = vim_config['vcenter_ip']
119 if 'vcenter_user' in vim_config:
120 vim_account['datacenter']['vcenter_user'] = vim_config['vcenter_user']
121 if 'vcenter_password' in vim_config:
122 vim_account['datacenter']['vcenter_password'] = vim_config['vcenter_password']
123 if 'vcenter_port' in vim_config:
124 vim_account['datacenter']['vcenter_port'] = vim_config['vcenter_port']
125 vim_account['datacenter']['vim_url'] = vim_access['vim-url']
126 vim_account['datacenter']['vim_url_admin'] = vim_access['vim-url']
127 vim_account['datacenter']['description'] = vim_access['description']
128 vim_account['datacenter']['vim_username'] = vim_access['vim-username']
129 vim_account['datacenter']['vim_password'] = vim_access['vim-password']
130 vim_account['datacenter']['vim_tenant_name'] = vim_access['vim-tenant-name']
131 else:
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 return vim_account
Mike Marchettie84eb312017-05-04 15:06:26 -0400139
Mike Marchetti4c7e2372017-05-08 16:07:20 -0400140 def delete(self, vim_name):
Mike Marchettie84eb312017-05-04 15:06:26 -0400141 # first detach
Mike Marchetti4c7e2372017-05-08 16:07:20 -0400142 self._detach(vim_name)
143 # detach. continue if error,
144 # it could be the datacenter is left without attachment
Anurag Dwivedifa7254b2017-10-04 14:19:01 -0400145 resp = self._ro_http.delete_cmd('openmano/datacenters/{}'
146 .format(vim_name))
147 if 'result' not in resp:
148 raise ClientException("failed to delete vim {} - {}".format(vim_name, resp))
149 self._update_ro_accounts()
Mike Marchettie84eb312017-05-04 15:06:26 -0400150
Mike Marchettiafc2e172017-10-16 16:42:44 -0400151 def list(self, ro_update):
152 if ro_update:
153 self._update_ro_accounts()
154 # the ro_update needs to be made synchronous, for now this works around the issue
155 # and waits a resonable amount of time for the update to finish
156 time.sleep(2)
157
Anurag Dwivedi1e4e6fe2017-10-02 10:15:31 -0400158 if self._client._so_version == 'v3':
159 resp = self._http.get_cmd('v1/api/operational/{}ro-account-state'
160 .format(self._client.so_rbac_project_path))
161 datacenters = []
162 if not resp or 'rw-ro-account:ro-account-state' not in resp:
163 return list()
Mike Marchettie84eb312017-05-04 15:06:26 -0400164
Anurag Dwivedi1e4e6fe2017-10-02 10:15:31 -0400165 ro_accounts = resp['rw-ro-account:ro-account-state']
166 for ro_account in ro_accounts['account']:
Anurag Dwivedifa7254b2017-10-04 14:19:01 -0400167 if 'datacenters' not in ro_account:
168 continue
169 if 'datacenters' not in ro_account['datacenters']:
170 continue
Anurag Dwivedi1e4e6fe2017-10-02 10:15:31 -0400171 for datacenter in ro_account['datacenters']['datacenters']:
172 datacenters.append({"name": datacenter['name'], "uuid": datacenter['uuid']
173 if 'uuid' in datacenter else None})
Mike Marchettie84eb312017-05-04 15:06:26 -0400174
Anurag Dwivedi1e4e6fe2017-10-02 10:15:31 -0400175 vim_accounts = datacenters
Mike Marchettie84eb312017-05-04 15:06:26 -0400176 return vim_accounts
Anurag Dwivedi1e4e6fe2017-10-02 10:15:31 -0400177 else:
178 # Backwards Compatibility
179 resp = self._http.get_cmd('v1/api/operational/datacenters')
180 if not resp or 'rw-launchpad:datacenters' not in resp:
181 return list()
182
183 datacenters = resp['rw-launchpad:datacenters']
184
185 vim_accounts = list()
186 if 'ro-accounts' not in datacenters:
187 return vim_accounts
188
189 tenant = self._get_ro_tenant()
190 if tenant is None:
191 return vim_accounts
192
193 for roaccount in datacenters['ro-accounts']:
194 if 'datacenters' not in roaccount:
195 continue
196 for datacenter in roaccount['datacenters']:
197 vim_accounts.append(self._get_ro_datacenter(datacenter['name'],
198 tenant['uuid']))
Mike Marchettie84eb312017-05-04 15:06:26 -0400199 return vim_accounts
200
Mike Marchetti4c7e2372017-05-08 16:07:20 -0400201 def _get_ro_tenant(self, name='osm'):
202 resp = self._ro_http.get_cmd('openmano/tenants/{}'.format(name))
Mike Marchettie84eb312017-05-04 15:06:26 -0400203
204 if not resp:
205 return None
206
207 if 'tenant' in resp and 'uuid' in resp['tenant']:
208 return resp['tenant']
209 else:
210 return None
211
Mike Marchetti4c7e2372017-05-08 16:07:20 -0400212 def _get_ro_datacenter(self, name, tenant_uuid='any'):
213 resp = self._ro_http.get_cmd('openmano/{}/datacenters/{}'
214 .format(tenant_uuid, name))
Mike Marchettie84eb312017-05-04 15:06:26 -0400215 if not resp:
216 raise NotFound("datacenter {} not found".format(name))
Mike Marchetti4c7e2372017-05-08 16:07:20 -0400217
Mike Marchettie84eb312017-05-04 15:06:26 -0400218 if 'datacenter' in resp and 'uuid' in resp['datacenter']:
219 return resp['datacenter']
220 else:
221 raise NotFound("datacenter {} not found".format(name))
222
Mike Marchetti4c7e2372017-05-08 16:07:20 -0400223 def get(self, name):
224 tenant = self._get_ro_tenant()
Mike Marchettie84eb312017-05-04 15:06:26 -0400225 if tenant is None:
226 raise NotFound("no ro tenant found")
227
Mike Marchetti4c7e2372017-05-08 16:07:20 -0400228 return self._get_ro_datacenter(name, tenant['uuid'])
Mike Marchettie84eb312017-05-04 15:06:26 -0400229
Mike Marchetti4c7e2372017-05-08 16:07:20 -0400230 def get_datacenter(self, name):
Anurag Dwivedi1e4e6fe2017-10-02 10:15:31 -0400231 if self._client._so_version == 'v3':
232 resp = self._http.get_cmd('v1/api/operational/{}ro-account-state'
233 .format(self._client.so_rbac_project_path))
234 if not resp:
235 return None, None
Mike Marchettie84eb312017-05-04 15:06:26 -0400236
Anurag Dwivedi1e4e6fe2017-10-02 10:15:31 -0400237 if not resp or 'rw-ro-account:ro-account-state' not in resp:
238 return None, None
239
240 ro_accounts = resp['rw-ro-account:ro-account-state']
241 for ro_account in ro_accounts['account']:
Anurag Dwivedifa7254b2017-10-04 14:19:01 -0400242 if 'datacenters' not in ro_account:
243 continue
244 if 'datacenters' not in ro_account['datacenters']:
245 continue
Anurag Dwivedi1e4e6fe2017-10-02 10:15:31 -0400246 for datacenter in ro_account['datacenters']['datacenters']:
247 if datacenter['name'] == name:
248 return datacenter, ro_account['name']
249 return None, None
250 else:
251 # Backwards Compatibility
252 resp = self._http.get_cmd('v1/api/operational/datacenters')
253 if not resp:
254 return None
255
256 if not resp or 'rw-launchpad:datacenters' not in resp:
257 return None
258 if 'ro-accounts' not in resp['rw-launchpad:datacenters']:
259 return None
260 for roaccount in resp['rw-launchpad:datacenters']['ro-accounts']:
261 if 'datacenters' not in roaccount:
262 continue
263 for datacenter in roaccount['datacenters']:
264 if datacenter['name'] == name:
265 return datacenter
Mike Marchettie84eb312017-05-04 15:06:26 -0400266 return None
Mike Marchettie84eb312017-05-04 15:06:26 -0400267
268 def get_resource_orchestrator(self):
Anurag Dwivedi1e4e6fe2017-10-02 10:15:31 -0400269 resp = self._http.get_cmd('v1/api/operational/{}resource-orchestrator'
270 .format(self._client.so_rbac_project_path))
271
Mike Marchettie84eb312017-05-04 15:06:26 -0400272 if not resp or 'rw-launchpad:resource-orchestrator' not in resp:
273 return None
274 return resp['rw-launchpad:resource-orchestrator']