9cd882c5c56f3bb78c88c152b89cdb4da74e54da
[osm/osmclient.git] / osmclient / sol005 / vim.py
1 # Copyright 2018 Telefonica
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 import utils
22 from osmclient.common import wait as WaitForStatus
23 from osmclient.common.exceptions import ClientException
24 from osmclient.common.exceptions import NotFound
25 import yaml
26 import json
27 import logging
28
29
30 class Vim(object):
31 def __init__(self, http=None, client=None):
32 self._http = http
33 self._client = client
34 self._logger = logging.getLogger('osmclient')
35 self._apiName = '/admin'
36 self._apiVersion = '/v1'
37 self._apiResource = '/vim_accounts'
38 self._apiBase = '{}{}{}'.format(self._apiName,
39 self._apiVersion, self._apiResource)
40
41 # VIM '--wait' option
42 def _wait(self, id, deleteFlag=False):
43 self._logger.debug("")
44 self._client.get_token()
45 # Endpoint to get operation status
46 apiUrlStatus = '{}{}{}'.format(self._apiName, self._apiVersion, '/vim_accounts')
47 # Wait for status for VIM instance creation/deletion
48 WaitForStatus.wait_for_status(
49 'VIM',
50 str(id),
51 WaitForStatus.TIMEOUT_VIM_OPERATION,
52 apiUrlStatus,
53 self._http.get2_cmd,
54 deleteFlag=deleteFlag)
55
56 def _get_id_for_wait(self, name):
57 """ Returns id of name, or the id itself if given as argument
58 """
59 self._logger.debug("")
60 self._client.get_token()
61 for vim in self.list():
62 if name == vim['uuid']:
63 return vim['uuid']
64 for vim in self.list():
65 if name == vim['name']:
66 return vim['uuid']
67 return ''
68
69 def create(self, name, vim_access, sdn_controller=None, sdn_port_mapping=None, wait=False):
70 self._logger.debug("")
71 self._client.get_token()
72 if 'vim-type' not in vim_access:
73 #'openstack' not in vim_access['vim-type']):
74 raise Exception("vim type not provided")
75
76 vim_account = {}
77 vim_account['name'] = name
78 vim_account = self.update_vim_account_dict(vim_account, vim_access)
79
80 vim_config = {}
81 if 'config' in vim_access and vim_access['config'] is not None:
82 vim_config = yaml.safe_load(vim_access['config'])
83 if sdn_controller:
84 sdnc = self._client.sdnc.get(sdn_controller)
85 vim_config['sdn-controller'] = sdnc['_id']
86 if sdn_port_mapping:
87 with open(sdn_port_mapping, 'r') as f:
88 vim_config['sdn-port-mapping'] = yaml.safe_load(f.read())
89 if vim_config:
90 vim_account['config'] = vim_config
91 #vim_account['config'] = json.dumps(vim_config)
92
93 http_code, resp = self._http.post_cmd(endpoint=self._apiBase,
94 postfields_dict=vim_account)
95 #print('HTTP CODE: {}'.format(http_code))
96 #print('RESP: {}'.format(resp))
97 #if http_code in (200, 201, 202, 204):
98 if resp:
99 resp = json.loads(resp)
100 if not resp or 'id' not in resp:
101 raise ClientException('unexpected response from server - {}'.format(
102 resp))
103 if wait:
104 # Wait for status for VIM instance creation
105 self._wait(resp.get('id'))
106 print(resp['id'])
107 #else:
108 # msg = ""
109 # if resp:
110 # try:
111 # msg = json.loads(resp)
112 # except ValueError:
113 # msg = resp
114 # raise ClientException("failed to create vim {} - {}".format(name, msg))
115
116 def update(self, vim_name, vim_account, sdn_controller, sdn_port_mapping, wait=False):
117 self._logger.debug("")
118 self._client.get_token()
119 vim = self.get(vim_name)
120 vim_id_for_wait = self._get_id_for_wait(vim_name)
121 vim_config = {}
122 if 'config' in vim_account:
123 if vim_account.get('config')=="" and (sdn_controller or sdn_port_mapping):
124 raise ClientException("clearing config is incompatible with updating SDN info")
125 if vim_account.get('config')=="":
126 vim_config = None
127 else:
128 vim_config = yaml.safe_load(vim_account['config'])
129 if sdn_controller:
130 sdnc = self._client.sdnc.get(sdn_controller)
131 vim_config['sdn-controller'] = sdnc['_id']
132 if sdn_port_mapping:
133 with open(sdn_port_mapping, 'r') as f:
134 vim_config['sdn-port-mapping'] = yaml.safe_load(f.read())
135 vim_account['config'] = vim_config
136 #vim_account['config'] = json.dumps(vim_config)
137 http_code, resp = self._http.patch_cmd(endpoint='{}/{}'.format(self._apiBase,vim['_id']),
138 postfields_dict=vim_account)
139 # print('HTTP CODE: {}'.format(http_code))
140 # print('RESP: {}'.format(resp))
141 #if http_code in (200, 201, 202, 204):
142 if wait:
143 # In this case, 'resp' always returns None, so 'resp['id']' cannot be used.
144 # Use the previously obtained id instead.
145 wait_id = vim_id_for_wait
146 # Wait for status for VI instance update
147 self._wait(wait_id)
148 # else:
149 # pass
150 #else:
151 # msg = ""
152 # if resp:
153 # try:
154 # msg = json.loads(resp)
155 # except ValueError:
156 # msg = resp
157 # raise ClientException("failed to update vim {} - {}".format(vim_name, msg))
158
159 def update_vim_account_dict(self, vim_account, vim_access):
160 self._logger.debug("")
161 vim_account['vim_type'] = vim_access['vim-type']
162 vim_account['description'] = vim_access['description']
163 vim_account['vim_url'] = vim_access['vim-url']
164 vim_account['vim_user'] = vim_access['vim-username']
165 vim_account['vim_password'] = vim_access['vim-password']
166 vim_account['vim_tenant_name'] = vim_access['vim-tenant-name']
167 return vim_account
168
169 def get_id(self, name):
170 """Returns a VIM id from a VIM name
171 """
172 self._logger.debug("")
173 for vim in self.list():
174 if name == vim['name']:
175 return vim['uuid']
176 raise NotFound("vim {} not found".format(name))
177
178 def delete(self, vim_name, force=False, wait=False):
179 self._logger.debug("")
180 self._client.get_token()
181 vim_id = vim_name
182 if not utils.validate_uuid4(vim_name):
183 vim_id = self.get_id(vim_name)
184 querystring = ''
185 if force:
186 querystring = '?FORCE=True'
187 http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase,
188 vim_id, querystring))
189 #print('HTTP CODE: {}'.format(http_code))
190 #print('RESP: {}'.format(resp))
191 if http_code == 202:
192 if wait:
193 # When deleting an account, 'resp' may be None.
194 # In such a case, the 'id' from 'resp' cannot be used, so use 'vim_id' instead
195 wait_id = vim_id
196 if resp:
197 resp = json.loads(resp)
198 wait_id = resp.get('id')
199 # Wait for status for VIM account deletion
200 self._wait(wait_id, deleteFlag=True)
201 else:
202 print('Deletion in progress')
203 elif http_code == 204:
204 print('Deleted')
205 else:
206 msg = resp or ""
207 # if resp:
208 # try:
209 # msg = json.loads(resp)
210 # except ValueError:
211 # msg = resp
212 raise ClientException("failed to delete vim {} - {}".format(vim_name, msg))
213
214 def list(self, filter=None):
215 """Returns a list of VIM accounts
216 """
217 self._logger.debug("")
218 self._client.get_token()
219 filter_string = ''
220 if filter:
221 filter_string = '?{}'.format(filter)
222 _, resp = self._http.get2_cmd('{}{}'.format(self._apiBase,filter_string))
223 if not resp:
224 return list()
225 vim_accounts = []
226 for datacenter in json.loads(resp):
227 vim_accounts.append({"name": datacenter['name'], "uuid": datacenter['_id']
228 if '_id' in datacenter else None})
229 return vim_accounts
230
231 def get(self, name):
232 """Returns a VIM account based on name or id
233 """
234 self._logger.debug("")
235 self._client.get_token()
236 vim_id = name
237 if not utils.validate_uuid4(name):
238 vim_id = self.get_id(name)
239 try:
240 _, resp = self._http.get2_cmd('{}/{}'.format(self._apiBase,vim_id))
241 if resp:
242 resp = json.loads(resp)
243 if not resp or '_id' not in resp:
244 raise ClientException('failed to get vim info: {}'.format(resp))
245 return resp
246 except NotFound:
247 raise NotFound("vim '{}' not found".format(name))
248