| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 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 |
| Mike Marchetti | f68f84f | 2017-11-13 10:51:42 -0500 | [diff] [blame] | 23 | import yaml |
| Mike Marchetti | afc2e17 | 2017-10-16 16:42:44 -0400 | [diff] [blame] | 24 | import time |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 25 | |
| 26 | |
| 27 | class Vim(object): |
| Mike Marchetti | 4c7e237 | 2017-05-08 16:07:20 -0400 | [diff] [blame] | 28 | 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 Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 32 | |
| kasar | 9651775 | 2017-09-08 04:28:15 -0700 | [diff] [blame] | 33 | def _attach(self, vim_name, vim_account): |
| Mike Marchetti | 4c7e237 | 2017-05-08 16:07:20 -0400 | [diff] [blame] | 34 | tenant_name = 'osm' |
| 35 | tenant = self._get_ro_tenant() |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 36 | if tenant is None: |
| 37 | raise ClientException("tenant {} not found".format(tenant_name)) |
| kasar | 9651775 | 2017-09-08 04:28:15 -0700 | [diff] [blame] | 38 | |
| Mike Marchetti | 4c7e237 | 2017-05-08 16:07:20 -0400 | [diff] [blame] | 39 | datacenter = self._get_ro_datacenter(vim_name) |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 40 | if datacenter is None: |
| 41 | raise Exception('datacenter {} not found'.format(vim_name)) |
| 42 | |
| Mike Marchetti | 4c7e237 | 2017-05-08 16:07:20 -0400 | [diff] [blame] | 43 | return self._ro_http.post_cmd('openmano/{}/datacenters/{}' |
| 44 | .format(tenant['uuid'], |
| 45 | datacenter['uuid']), vim_account) |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 46 | |
| Mike Marchetti | 4c7e237 | 2017-05-08 16:07:20 -0400 | [diff] [blame] | 47 | def _detach(self, vim_name): |
| tierno | 3a1237e | 2017-10-11 14:25:33 +0200 | [diff] [blame] | 48 | tenant_name = 'osm' |
| 49 | tenant = self._get_ro_tenant() |
| 50 | if tenant is None: |
| 51 | raise ClientException("tenant {} not found".format(tenant_name)) |
| Mike Marchetti | 4c7e237 | 2017-05-08 16:07:20 -0400 | [diff] [blame] | 52 | return self._ro_http.delete_cmd('openmano/{}/datacenters/{}' |
| tierno | 3a1237e | 2017-10-11 14:25:33 +0200 | [diff] [blame] | 53 | .format(tenant["uuid"], vim_name)) |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 54 | |
| 55 | def create(self, name, vim_access): |
| Mike Marchetti | 4c7e237 | 2017-05-08 16:07:20 -0400 | [diff] [blame] | 56 | vim_account = {} |
| 57 | vim_account['datacenter'] = {} |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 58 | |
| 59 | # currently assumes vim_acc |
| kasar | 9651775 | 2017-09-08 04:28:15 -0700 | [diff] [blame] | 60 | if ('vim-type' not in vim_access): |
| 61 | #'openstack' not in vim_access['vim-type']): |
| 62 | raise Exception("vim type not provided") |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 63 | |
| 64 | vim_account['datacenter']['name'] = name |
| 65 | vim_account['datacenter']['type'] = vim_access['vim-type'] |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 66 | |
| 67 | vim_config = {} |
| Mike Marchetti | f68f84f | 2017-11-13 10:51:42 -0500 | [diff] [blame] | 68 | if 'config' in vim_access and vim_access['config'] is not None: |
| 69 | vim_config = yaml.load(vim_access['config']) |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 70 | |
| Mike Marchetti | 3664c8a | 2017-11-15 16:22:14 -0500 | [diff] [blame] | 71 | if vim_config: |
| 72 | vim_account['datacenter']['config'] = vim_config |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 73 | |
| kasar | 9651775 | 2017-09-08 04:28:15 -0700 | [diff] [blame] | 74 | vim_account = self.update_vim_account_dict(vim_account, vim_access, vim_config) |
| 75 | |
| Mike Marchetti | 4c7e237 | 2017-05-08 16:07:20 -0400 | [diff] [blame] | 76 | resp = self._ro_http.post_cmd('openmano/datacenters', vim_account) |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 77 | if resp and 'error' in resp: |
| 78 | raise ClientException("failed to create vim") |
| 79 | else: |
| kasar | 9651775 | 2017-09-08 04:28:15 -0700 | [diff] [blame] | 80 | self._attach(name, vim_account) |
| Anurag Dwivedi | fa7254b | 2017-10-04 14:19:01 -0400 | [diff] [blame] | 81 | 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 | |
| kasar | 9651775 | 2017-09-08 04:28:15 -0700 | [diff] [blame] | 102 | |
| 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 Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 139 | |
| Mike Marchetti | 4c7e237 | 2017-05-08 16:07:20 -0400 | [diff] [blame] | 140 | def delete(self, vim_name): |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 141 | # first detach |
| Mike Marchetti | 4c7e237 | 2017-05-08 16:07:20 -0400 | [diff] [blame] | 142 | self._detach(vim_name) |
| 143 | # detach. continue if error, |
| 144 | # it could be the datacenter is left without attachment |
| Anurag Dwivedi | fa7254b | 2017-10-04 14:19:01 -0400 | [diff] [blame] | 145 | 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 Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 150 | |
| Mike Marchetti | afc2e17 | 2017-10-16 16:42:44 -0400 | [diff] [blame] | 151 | 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 Dwivedi | 1e4e6fe | 2017-10-02 10:15:31 -0400 | [diff] [blame] | 158 | 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 Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 164 | |
| Anurag Dwivedi | 1e4e6fe | 2017-10-02 10:15:31 -0400 | [diff] [blame] | 165 | ro_accounts = resp['rw-ro-account:ro-account-state'] |
| 166 | for ro_account in ro_accounts['account']: |
| Anurag Dwivedi | fa7254b | 2017-10-04 14:19:01 -0400 | [diff] [blame] | 167 | if 'datacenters' not in ro_account: |
| 168 | continue |
| 169 | if 'datacenters' not in ro_account['datacenters']: |
| 170 | continue |
| Anurag Dwivedi | 1e4e6fe | 2017-10-02 10:15:31 -0400 | [diff] [blame] | 171 | for datacenter in ro_account['datacenters']['datacenters']: |
| 172 | datacenters.append({"name": datacenter['name'], "uuid": datacenter['uuid'] |
| 173 | if 'uuid' in datacenter else None}) |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 174 | |
| Anurag Dwivedi | 1e4e6fe | 2017-10-02 10:15:31 -0400 | [diff] [blame] | 175 | vim_accounts = datacenters |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 176 | return vim_accounts |
| Anurag Dwivedi | 1e4e6fe | 2017-10-02 10:15:31 -0400 | [diff] [blame] | 177 | 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 Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 199 | return vim_accounts |
| 200 | |
| Mike Marchetti | 4c7e237 | 2017-05-08 16:07:20 -0400 | [diff] [blame] | 201 | def _get_ro_tenant(self, name='osm'): |
| 202 | resp = self._ro_http.get_cmd('openmano/tenants/{}'.format(name)) |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 203 | |
| 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 Marchetti | 4c7e237 | 2017-05-08 16:07:20 -0400 | [diff] [blame] | 212 | def _get_ro_datacenter(self, name, tenant_uuid='any'): |
| 213 | resp = self._ro_http.get_cmd('openmano/{}/datacenters/{}' |
| 214 | .format(tenant_uuid, name)) |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 215 | if not resp: |
| 216 | raise NotFound("datacenter {} not found".format(name)) |
| Mike Marchetti | 4c7e237 | 2017-05-08 16:07:20 -0400 | [diff] [blame] | 217 | |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 218 | 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 Marchetti | 4c7e237 | 2017-05-08 16:07:20 -0400 | [diff] [blame] | 223 | def get(self, name): |
| 224 | tenant = self._get_ro_tenant() |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 225 | if tenant is None: |
| 226 | raise NotFound("no ro tenant found") |
| 227 | |
| Mike Marchetti | 4c7e237 | 2017-05-08 16:07:20 -0400 | [diff] [blame] | 228 | return self._get_ro_datacenter(name, tenant['uuid']) |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 229 | |
| Mike Marchetti | 4c7e237 | 2017-05-08 16:07:20 -0400 | [diff] [blame] | 230 | def get_datacenter(self, name): |
| Anurag Dwivedi | 1e4e6fe | 2017-10-02 10:15:31 -0400 | [diff] [blame] | 231 | 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 Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 236 | |
| Anurag Dwivedi | 1e4e6fe | 2017-10-02 10:15:31 -0400 | [diff] [blame] | 237 | 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 Dwivedi | fa7254b | 2017-10-04 14:19:01 -0400 | [diff] [blame] | 242 | if 'datacenters' not in ro_account: |
| 243 | continue |
| 244 | if 'datacenters' not in ro_account['datacenters']: |
| 245 | continue |
| Anurag Dwivedi | 1e4e6fe | 2017-10-02 10:15:31 -0400 | [diff] [blame] | 246 | 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 Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 266 | return None |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 267 | |
| 268 | def get_resource_orchestrator(self): |
| Anurag Dwivedi | 1e4e6fe | 2017-10-02 10:15:31 -0400 | [diff] [blame] | 269 | resp = self._http.get_cmd('v1/api/operational/{}resource-orchestrator' |
| 270 | .format(self._client.so_rbac_project_path)) |
| 271 | |
| Mike Marchetti | e84eb31 | 2017-05-04 15:06:26 -0400 | [diff] [blame] | 272 | if not resp or 'rw-launchpad:resource-orchestrator' not in resp: |
| 273 | return None |
| 274 | return resp['rw-launchpad:resource-orchestrator'] |