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