| # Copyright 2017 Sandvine |
| # |
| # All Rights Reserved. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); you may |
| # not use this file except in compliance with the License. You may obtain |
| # a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations |
| # under the License. |
| |
| """ |
| OSM vim API handling |
| """ |
| |
| from osmclient.common.exceptions import ClientException |
| from osmclient.common.exceptions import NotFound |
| import json |
| |
| |
| class Vim(object): |
| def __init__(self, http=None, ro_http=None, client=None): |
| self._client = client |
| self._ro_http = ro_http |
| self._http = http |
| |
| def _attach(self, vim_name, vim_account): |
| tenant_name = 'osm' |
| tenant = self._get_ro_tenant() |
| if tenant is None: |
| raise ClientException("tenant {} not found".format(tenant_name)) |
| |
| datacenter = self._get_ro_datacenter(vim_name) |
| if datacenter is None: |
| raise Exception('datacenter {} not found'.format(vim_name)) |
| |
| return self._ro_http.post_cmd('openmano/{}/datacenters/{}' |
| .format(tenant['uuid'], |
| datacenter['uuid']), vim_account) |
| |
| def _detach(self, vim_name): |
| tenant_name = 'osm' |
| tenant = self._get_ro_tenant() |
| if tenant is None: |
| raise ClientException("tenant {} not found".format(tenant_name)) |
| return self._ro_http.delete_cmd('openmano/{}/datacenters/{}' |
| .format(tenant["uuid"], vim_name)) |
| |
| def create(self, name, vim_access): |
| vim_account = {} |
| vim_account['datacenter'] = {} |
| |
| # currently assumes vim_acc |
| if ('vim-type' not in vim_access): |
| #'openstack' not in vim_access['vim-type']): |
| raise Exception("vim type not provided") |
| |
| vim_account['datacenter']['name'] = name |
| vim_account['datacenter']['type'] = vim_access['vim-type'] |
| |
| vim_config = {} |
| vim_config['use_floating_ip'] = False |
| |
| if ('floating_ip_pool' in vim_access and |
| vim_access['floating_ip_pool'] is not None): |
| vim_config['use_floating_ip'] = True |
| |
| if 'keypair' in vim_access and vim_access['keypair'] is not None: |
| vim_config['keypair'] = vim_access['keypair'] |
| elif 'config' in vim_access and vim_access['config'] is not None: |
| 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"]): |
| vim_config = json.loads(vim_access['config']) |
| |
| vim_account['datacenter']['config'] = vim_config |
| |
| vim_account = self.update_vim_account_dict(vim_account, vim_access, vim_config) |
| |
| resp = self._ro_http.post_cmd('openmano/datacenters', vim_account) |
| if resp and 'error' in resp: |
| raise ClientException("failed to create vim") |
| else: |
| self._attach(name, vim_account) |
| self._update_ro_accounts() |
| |
| |
| def _update_ro_accounts(self): |
| get_ro_accounts = self._http.get_cmd('api/operational/{}ro-account' |
| .format(self._client.so_rbac_project_path)) |
| if not get_ro_accounts or 'rw-ro-account:ro-account' not in get_ro_accounts: |
| return |
| for account in get_ro_accounts['rw-ro-account:ro-account']['account']: |
| if account['ro-account-type'] == 'openmano': |
| # Refresh the Account Status |
| refresh_body = {"input": { |
| "ro-account": account['name'], |
| "project-name": self._client._so_project |
| } |
| } |
| refresh_status = self._http.post_cmd('api/operations/update-ro-account-status', |
| refresh_body) |
| if refresh_status and 'error' in refresh_status: |
| raise ClientException("Failed to refersh RO Account Status") |
| |
| |
| def update_vim_account_dict(self, vim_account, vim_access, vim_config): |
| if vim_access['vim-type'] == 'vmware': |
| if 'admin_username' in vim_config: |
| vim_account['datacenter']['admin_username'] = vim_config['admin_username'] |
| if 'admin_password' in vim_config: |
| vim_account['datacenter']['admin_password'] = vim_config['admin_password'] |
| if 'nsx_manager' in vim_config: |
| vim_account['datacenter']['nsx_manager'] = vim_config['nsx_manager'] |
| if 'nsx_user' in vim_config: |
| vim_account['datacenter']['nsx_user'] = vim_config['nsx_user'] |
| if 'nsx_password' in vim_config: |
| vim_account['datacenter']['nsx_password'] = vim_config['nsx_password'] |
| if 'orgname' in vim_config: |
| vim_account['datacenter']['orgname'] = vim_config['orgname'] |
| if 'vcenter_ip' in vim_config: |
| vim_account['datacenter']['vcenter_ip'] = vim_config['vcenter_ip'] |
| if 'vcenter_user' in vim_config: |
| vim_account['datacenter']['vcenter_user'] = vim_config['vcenter_user'] |
| if 'vcenter_password' in vim_config: |
| vim_account['datacenter']['vcenter_password'] = vim_config['vcenter_password'] |
| if 'vcenter_port' in vim_config: |
| vim_account['datacenter']['vcenter_port'] = vim_config['vcenter_port'] |
| vim_account['datacenter']['vim_url'] = vim_access['vim-url'] |
| vim_account['datacenter']['vim_url_admin'] = vim_access['vim-url'] |
| vim_account['datacenter']['description'] = vim_access['description'] |
| vim_account['datacenter']['vim_username'] = vim_access['vim-username'] |
| vim_account['datacenter']['vim_password'] = vim_access['vim-password'] |
| vim_account['datacenter']['vim_tenant_name'] = vim_access['vim-tenant-name'] |
| else: |
| vim_account['datacenter']['vim_url'] = vim_access['vim-url'] |
| vim_account['datacenter']['vim_url_admin'] = vim_access['vim-url'] |
| vim_account['datacenter']['description'] = vim_access['description'] |
| vim_account['datacenter']['vim_username'] = vim_access['vim-username'] |
| vim_account['datacenter']['vim_password'] = vim_access['vim-password'] |
| vim_account['datacenter']['vim_tenant_name'] = vim_access['vim-tenant-name'] |
| return vim_account |
| |
| def delete(self, vim_name): |
| # first detach |
| self._detach(vim_name) |
| # detach. continue if error, |
| # it could be the datacenter is left without attachment |
| resp = self._ro_http.delete_cmd('openmano/datacenters/{}' |
| .format(vim_name)) |
| if 'result' not in resp: |
| raise ClientException("failed to delete vim {} - {}".format(vim_name, resp)) |
| self._update_ro_accounts() |
| |
| def list(self): |
| self._update_ro_accounts() |
| if self._client._so_version == 'v3': |
| resp = self._http.get_cmd('v1/api/operational/{}ro-account-state' |
| .format(self._client.so_rbac_project_path)) |
| datacenters = [] |
| if not resp or 'rw-ro-account:ro-account-state' not in resp: |
| return list() |
| |
| ro_accounts = resp['rw-ro-account:ro-account-state'] |
| for ro_account in ro_accounts['account']: |
| if 'datacenters' not in ro_account: |
| continue |
| if 'datacenters' not in ro_account['datacenters']: |
| continue |
| for datacenter in ro_account['datacenters']['datacenters']: |
| datacenters.append({"name": datacenter['name'], "uuid": datacenter['uuid'] |
| if 'uuid' in datacenter else None}) |
| |
| vim_accounts = datacenters |
| return vim_accounts |
| else: |
| # Backwards Compatibility |
| resp = self._http.get_cmd('v1/api/operational/datacenters') |
| if not resp or 'rw-launchpad:datacenters' not in resp: |
| return list() |
| |
| datacenters = resp['rw-launchpad:datacenters'] |
| |
| vim_accounts = list() |
| if 'ro-accounts' not in datacenters: |
| return vim_accounts |
| |
| tenant = self._get_ro_tenant() |
| if tenant is None: |
| return vim_accounts |
| |
| for roaccount in datacenters['ro-accounts']: |
| if 'datacenters' not in roaccount: |
| continue |
| for datacenter in roaccount['datacenters']: |
| vim_accounts.append(self._get_ro_datacenter(datacenter['name'], |
| tenant['uuid'])) |
| return vim_accounts |
| |
| def _get_ro_tenant(self, name='osm'): |
| resp = self._ro_http.get_cmd('openmano/tenants/{}'.format(name)) |
| |
| if not resp: |
| return None |
| |
| if 'tenant' in resp and 'uuid' in resp['tenant']: |
| return resp['tenant'] |
| else: |
| return None |
| |
| def _get_ro_datacenter(self, name, tenant_uuid='any'): |
| resp = self._ro_http.get_cmd('openmano/{}/datacenters/{}' |
| .format(tenant_uuid, name)) |
| if not resp: |
| raise NotFound("datacenter {} not found".format(name)) |
| |
| if 'datacenter' in resp and 'uuid' in resp['datacenter']: |
| return resp['datacenter'] |
| else: |
| raise NotFound("datacenter {} not found".format(name)) |
| |
| def get(self, name): |
| tenant = self._get_ro_tenant() |
| if tenant is None: |
| raise NotFound("no ro tenant found") |
| |
| return self._get_ro_datacenter(name, tenant['uuid']) |
| |
| def get_datacenter(self, name): |
| if self._client._so_version == 'v3': |
| resp = self._http.get_cmd('v1/api/operational/{}ro-account-state' |
| .format(self._client.so_rbac_project_path)) |
| if not resp: |
| return None, None |
| |
| if not resp or 'rw-ro-account:ro-account-state' not in resp: |
| return None, None |
| |
| ro_accounts = resp['rw-ro-account:ro-account-state'] |
| for ro_account in ro_accounts['account']: |
| if 'datacenters' not in ro_account: |
| continue |
| if 'datacenters' not in ro_account['datacenters']: |
| continue |
| for datacenter in ro_account['datacenters']['datacenters']: |
| if datacenter['name'] == name: |
| return datacenter, ro_account['name'] |
| return None, None |
| else: |
| # Backwards Compatibility |
| resp = self._http.get_cmd('v1/api/operational/datacenters') |
| if not resp: |
| return None |
| |
| if not resp or 'rw-launchpad:datacenters' not in resp: |
| return None |
| if 'ro-accounts' not in resp['rw-launchpad:datacenters']: |
| return None |
| for roaccount in resp['rw-launchpad:datacenters']['ro-accounts']: |
| if 'datacenters' not in roaccount: |
| continue |
| for datacenter in roaccount['datacenters']: |
| if datacenter['name'] == name: |
| return datacenter |
| return None |
| |
| def get_resource_orchestrator(self): |
| resp = self._http.get_cmd('v1/api/operational/{}resource-orchestrator' |
| .format(self._client.so_rbac_project_path)) |
| |
| if not resp or 'rw-launchpad:resource-orchestrator' not in resp: |
| return None |
| return resp['rw-launchpad:resource-orchestrator'] |