RBAC Support for OSMCLIENT
[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 return self._ro_http.delete_cmd('openmano/{}/datacenters/{}'
48 .format('osm', vim_name))
49
50 def create(self, name, vim_access):
51 vim_account = {}
52 vim_account['datacenter'] = {}
53
54 # currently assumes vim_acc
55 if ('vim-type' not in vim_access):
56 #'openstack' not in vim_access['vim-type']):
57 raise Exception("vim type not provided")
58
59 vim_account['datacenter']['name'] = name
60 vim_account['datacenter']['type'] = vim_access['vim-type']
61
62 vim_config = {}
63 vim_config['use_floating_ip'] = False
64
65 if ('floating_ip_pool' in vim_access and
66 vim_access['floating_ip_pool'] is not None):
67 vim_config['use_floating_ip'] = True
68
69 if 'keypair' in vim_access and vim_access['keypair'] is not None:
70 vim_config['keypair'] = vim_access['keypair']
71 elif 'config' in vim_access and vim_access['config'] is not None:
72 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"]):
73 vim_config = json.loads(vim_access['config'])
74
75 vim_account['datacenter']['config'] = vim_config
76
77 vim_account = self.update_vim_account_dict(vim_account, vim_access, vim_config)
78
79 resp = self._ro_http.post_cmd('openmano/datacenters', vim_account)
80 if resp and 'error' in resp:
81 raise ClientException("failed to create vim")
82 else:
83 self._attach(name, vim_account)
84
85 def update_vim_account_dict(self, vim_account, vim_access, vim_config):
86 if vim_access['vim-type'] == 'vmware':
87 if 'admin_username' in vim_config:
88 vim_account['datacenter']['admin_username'] = vim_config['admin_username']
89 if 'admin_password' in vim_config:
90 vim_account['datacenter']['admin_password'] = vim_config['admin_password']
91 if 'nsx_manager' in vim_config:
92 vim_account['datacenter']['nsx_manager'] = vim_config['nsx_manager']
93 if 'nsx_user' in vim_config:
94 vim_account['datacenter']['nsx_user'] = vim_config['nsx_user']
95 if 'nsx_password' in vim_config:
96 vim_account['datacenter']['nsx_password'] = vim_config['nsx_password']
97 if 'orgname' in vim_config:
98 vim_account['datacenter']['orgname'] = vim_config['orgname']
99 if 'vcenter_ip' in vim_config:
100 vim_account['datacenter']['vcenter_ip'] = vim_config['vcenter_ip']
101 if 'vcenter_user' in vim_config:
102 vim_account['datacenter']['vcenter_user'] = vim_config['vcenter_user']
103 if 'vcenter_password' in vim_config:
104 vim_account['datacenter']['vcenter_password'] = vim_config['vcenter_password']
105 if 'vcenter_port' in vim_config:
106 vim_account['datacenter']['vcenter_port'] = vim_config['vcenter_port']
107 vim_account['datacenter']['vim_url'] = vim_access['vim-url']
108 vim_account['datacenter']['vim_url_admin'] = vim_access['vim-url']
109 vim_account['datacenter']['description'] = vim_access['description']
110 vim_account['datacenter']['vim_username'] = vim_access['vim-username']
111 vim_account['datacenter']['vim_password'] = vim_access['vim-password']
112 vim_account['datacenter']['vim_tenant_name'] = vim_access['vim-tenant-name']
113 else:
114 vim_account['datacenter']['vim_url'] = vim_access['vim-url']
115 vim_account['datacenter']['vim_url_admin'] = vim_access['vim-url']
116 vim_account['datacenter']['description'] = vim_access['description']
117 vim_account['datacenter']['vim_username'] = vim_access['vim-username']
118 vim_account['datacenter']['vim_password'] = vim_access['vim-password']
119 vim_account['datacenter']['vim_tenant_name'] = vim_access['vim-tenant-name']
120 return vim_account
121
122 def delete(self, vim_name):
123 # first detach
124 self._detach(vim_name)
125 # detach. continue if error,
126 # it could be the datacenter is left without attachment
127
128 if 'result' not in self._ro_http.delete_cmd('openmano/datacenters/{}'
129 .format(vim_name)):
130 raise ClientException("failed to delete vim {}".format(vim_name))
131
132 def list(self):
133 if self._client._so_version == 'v3':
134 resp = self._http.get_cmd('v1/api/operational/{}ro-account-state'
135 .format(self._client.so_rbac_project_path))
136 datacenters = []
137 if not resp or 'rw-ro-account:ro-account-state' not in resp:
138 return list()
139
140 ro_accounts = resp['rw-ro-account:ro-account-state']
141 for ro_account in ro_accounts['account']:
142 for datacenter in ro_account['datacenters']['datacenters']:
143 datacenters.append({"name": datacenter['name'], "uuid": datacenter['uuid']
144 if 'uuid' in datacenter else None})
145
146 vim_accounts = datacenters
147 return vim_accounts
148 else:
149 # Backwards Compatibility
150 resp = self._http.get_cmd('v1/api/operational/datacenters')
151 if not resp or 'rw-launchpad:datacenters' not in resp:
152 return list()
153
154 datacenters = resp['rw-launchpad:datacenters']
155
156 vim_accounts = list()
157 if 'ro-accounts' not in datacenters:
158 return vim_accounts
159
160 tenant = self._get_ro_tenant()
161 if tenant is None:
162 return vim_accounts
163
164 for roaccount in datacenters['ro-accounts']:
165 if 'datacenters' not in roaccount:
166 continue
167 for datacenter in roaccount['datacenters']:
168 vim_accounts.append(self._get_ro_datacenter(datacenter['name'],
169 tenant['uuid']))
170 return vim_accounts
171
172 def _get_ro_tenant(self, name='osm'):
173 resp = self._ro_http.get_cmd('openmano/tenants/{}'.format(name))
174
175 if not resp:
176 return None
177
178 if 'tenant' in resp and 'uuid' in resp['tenant']:
179 return resp['tenant']
180 else:
181 return None
182
183 def _get_ro_datacenter(self, name, tenant_uuid='any'):
184 resp = self._ro_http.get_cmd('openmano/{}/datacenters/{}'
185 .format(tenant_uuid, name))
186 if not resp:
187 raise NotFound("datacenter {} not found".format(name))
188
189 if 'datacenter' in resp and 'uuid' in resp['datacenter']:
190 return resp['datacenter']
191 else:
192 raise NotFound("datacenter {} not found".format(name))
193
194 def get(self, name):
195 tenant = self._get_ro_tenant()
196 if tenant is None:
197 raise NotFound("no ro tenant found")
198
199 return self._get_ro_datacenter(name, tenant['uuid'])
200
201 def get_datacenter(self, name):
202 if self._client._so_version == 'v3':
203 resp = self._http.get_cmd('v1/api/operational/{}ro-account-state'
204 .format(self._client.so_rbac_project_path))
205 if not resp:
206 return None, None
207
208 if not resp or 'rw-ro-account:ro-account-state' not in resp:
209 return None, None
210
211 ro_accounts = resp['rw-ro-account:ro-account-state']
212 for ro_account in ro_accounts['account']:
213 for datacenter in ro_account['datacenters']['datacenters']:
214 if datacenter['name'] == name:
215 return datacenter, ro_account['name']
216 return None, None
217 else:
218 # Backwards Compatibility
219 resp = self._http.get_cmd('v1/api/operational/datacenters')
220 if not resp:
221 return None
222
223 if not resp or 'rw-launchpad:datacenters' not in resp:
224 return None
225 if 'ro-accounts' not in resp['rw-launchpad:datacenters']:
226 return None
227 for roaccount in resp['rw-launchpad:datacenters']['ro-accounts']:
228 if 'datacenters' not in roaccount:
229 continue
230 for datacenter in roaccount['datacenters']:
231 if datacenter['name'] == name:
232 return datacenter
233 return None
234
235 def get_resource_orchestrator(self):
236 resp = self._http.get_cmd('v1/api/operational/{}resource-orchestrator'
237 .format(self._client.so_rbac_project_path))
238
239 if not resp or 'rw-launchpad:resource-orchestrator' not in resp:
240 return None
241 return resp['rw-launchpad:resource-orchestrator']