| garciadeblas | 017c4fb | 2018-02-13 11:58:29 +0100 | [diff] [blame] | 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 SDN controller API handling |
| 19 | """ |
| 20 | |
| 21 | from osmclient.common import utils |
| kuuse | 5da3f20 | 2019-05-30 09:42:05 +0200 | [diff] [blame] | 22 | from osmclient.common import wait as WaitForStatus |
| garciadeblas | 017c4fb | 2018-02-13 11:58:29 +0100 | [diff] [blame] | 23 | from osmclient.common.exceptions import ClientException |
| 24 | from osmclient.common.exceptions import NotFound |
| garciadeblas | f157128 | 2018-05-14 16:06:22 +0200 | [diff] [blame] | 25 | import json |
| garciadeblas | 017c4fb | 2018-02-13 11:58:29 +0100 | [diff] [blame] | 26 | |
| 27 | |
| 28 | class SdnController(object): |
| 29 | def __init__(self, http=None, client=None): |
| 30 | self._http = http |
| 31 | self._client = client |
| 32 | self._apiName = '/admin' |
| 33 | self._apiVersion = '/v1' |
| garciadeblas | 170b8fd | 2018-05-10 14:34:13 +0200 | [diff] [blame] | 34 | self._apiResource = '/sdns' |
| garciadeblas | 017c4fb | 2018-02-13 11:58:29 +0100 | [diff] [blame] | 35 | self._apiBase = '{}{}{}'.format(self._apiName, |
| 36 | self._apiVersion, self._apiResource) |
| garciadeblas | 6991001 | 2018-05-29 14:15:43 +0200 | [diff] [blame] | 37 | |
| kuuse | 5da3f20 | 2019-05-30 09:42:05 +0200 | [diff] [blame] | 38 | # SDNC '--wait' option |
| 39 | def _wait(self, id, deleteFlag=False): |
| pinoa | 93012ad | 2019-11-05 14:28:15 +0100 | [diff] [blame] | 40 | self._client.get_token() |
| kuuse | 5da3f20 | 2019-05-30 09:42:05 +0200 | [diff] [blame] | 41 | # Endpoint to get operation status |
| 42 | apiUrlStatus = '{}{}{}'.format(self._apiName, self._apiVersion, '/sdns') |
| 43 | # Wait for status for SDN instance creation/update/deletion |
| 44 | WaitForStatus.wait_for_status( |
| 45 | 'SDNC', |
| 46 | str(id), |
| 47 | WaitForStatus.TIMEOUT_SDNC_OPERATION, |
| 48 | apiUrlStatus, |
| 49 | self._http.get2_cmd, |
| 50 | deleteFlag=deleteFlag) |
| 51 | |
| 52 | def _get_id_for_wait(self, name): |
| 53 | # Returns id of name, or the id itself if given as argument |
| 54 | for sdnc in self.list(): |
| kuuse | 5da3f20 | 2019-05-30 09:42:05 +0200 | [diff] [blame] | 55 | if name == sdnc['_id']: |
| 56 | return sdnc['_id'] |
| kuuse | 5de571e | 2019-05-31 12:25:42 +0200 | [diff] [blame] | 57 | for sdnc in self.list(): |
| 58 | if name == sdnc['name']: |
| 59 | return sdnc['_id'] |
| kuuse | 5da3f20 | 2019-05-30 09:42:05 +0200 | [diff] [blame] | 60 | return '' |
| 61 | |
| 62 | def create(self, name, sdn_controller, wait=False): |
| pinoa | 93012ad | 2019-11-05 14:28:15 +0100 | [diff] [blame] | 63 | self._client.get_token() |
| garciadeblas | f157128 | 2018-05-14 16:06:22 +0200 | [diff] [blame] | 64 | http_code, resp = self._http.post_cmd(endpoint=self._apiBase, |
| garciadeblas | 017c4fb | 2018-02-13 11:58:29 +0100 | [diff] [blame] | 65 | postfields_dict=sdn_controller) |
| garciadeblas | 09fa3d4 | 2019-10-08 18:30:46 +0200 | [diff] [blame] | 66 | #print('HTTP CODE: {}'.format(http_code)) |
| 67 | #print('RESP: {}'.format(resp)) |
| garciadeblas | 061856b | 2018-05-22 00:49:13 +0200 | [diff] [blame] | 68 | if http_code in (200, 201, 202, 204): |
| 69 | if resp: |
| 70 | resp = json.loads(resp) |
| 71 | if not resp or 'id' not in resp: |
| 72 | raise ClientException('unexpected response from server - {}'.format( |
| 73 | resp)) |
| kuuse | 5da3f20 | 2019-05-30 09:42:05 +0200 | [diff] [blame] | 74 | if wait: |
| 75 | # Wait for status for SDNC instance creation |
| 76 | self._wait(resp.get('id')) |
| peusterm | be96096 | 2018-06-14 21:32:55 +0200 | [diff] [blame] | 77 | print(resp['id']) |
| garciadeblas | 061856b | 2018-05-22 00:49:13 +0200 | [diff] [blame] | 78 | else: |
| 79 | msg = "" |
| 80 | if resp: |
| 81 | try: |
| 82 | msg = json.loads(resp) |
| 83 | except ValueError: |
| 84 | msg = resp |
| 85 | raise ClientException("failed to create SDN controller {} - {}".format(name, msg)) |
| garciadeblas | 170b8fd | 2018-05-10 14:34:13 +0200 | [diff] [blame] | 86 | |
| kuuse | 5da3f20 | 2019-05-30 09:42:05 +0200 | [diff] [blame] | 87 | def update(self, name, sdn_controller, wait=False): |
| pinoa | 93012ad | 2019-11-05 14:28:15 +0100 | [diff] [blame] | 88 | self._client.get_token() |
| garciadeblas | 170b8fd | 2018-05-10 14:34:13 +0200 | [diff] [blame] | 89 | sdnc = self.get(name) |
| kuuse | 5da3f20 | 2019-05-30 09:42:05 +0200 | [diff] [blame] | 90 | sdnc_id_for_wait = self._get_id_for_wait(name) |
| garciadeblas | 0eefdeb | 2019-11-22 22:18:09 +0100 | [diff] [blame] | 91 | http_code, resp = self._http.patch_cmd(endpoint='{}/{}'.format(self._apiBase,sdnc['_id']), |
| garciadeblas | 170b8fd | 2018-05-10 14:34:13 +0200 | [diff] [blame] | 92 | postfields_dict=sdn_controller) |
| garciadeblas | 09fa3d4 | 2019-10-08 18:30:46 +0200 | [diff] [blame] | 93 | # print('HTTP CODE: {}'.format(http_code)) |
| 94 | # print('RESP: {}'.format(resp)) |
| garciadeblas | 061856b | 2018-05-22 00:49:13 +0200 | [diff] [blame] | 95 | if http_code in (200, 201, 202, 204): |
| kuuse | 5da3f20 | 2019-05-30 09:42:05 +0200 | [diff] [blame] | 96 | if wait: |
| kuuse | 5de571e | 2019-05-31 12:25:42 +0200 | [diff] [blame] | 97 | # In this case, 'resp' always returns None, so 'resp['id']' cannot be used. |
| 98 | # Use the previously obtained id instead. |
| 99 | wait_id = sdnc_id_for_wait |
| 100 | # Wait for status for VI instance update |
| 101 | self._wait(wait_id) |
| 102 | else: |
| 103 | pass |
| garciadeblas | 061856b | 2018-05-22 00:49:13 +0200 | [diff] [blame] | 104 | else: |
| 105 | msg = "" |
| 106 | if resp: |
| 107 | try: |
| 108 | msg = json.loads(resp) |
| 109 | except ValueError: |
| 110 | msg = resp |
| 111 | raise ClientException("failed to update SDN controller {} - {}".format(name, msg)) |
| garciadeblas | 017c4fb | 2018-02-13 11:58:29 +0100 | [diff] [blame] | 112 | |
| kuuse | 5da3f20 | 2019-05-30 09:42:05 +0200 | [diff] [blame] | 113 | def delete(self, name, force=False, wait=False): |
| pinoa | 93012ad | 2019-11-05 14:28:15 +0100 | [diff] [blame] | 114 | self._client.get_token() |
| garciadeblas | 017c4fb | 2018-02-13 11:58:29 +0100 | [diff] [blame] | 115 | sdn_controller = self.get(name) |
| kuuse | 5da3f20 | 2019-05-30 09:42:05 +0200 | [diff] [blame] | 116 | sdnc_id_for_wait = self._get_id_for_wait(name) |
| garciadeblas | 6d10e04 | 2018-05-16 17:21:59 +0200 | [diff] [blame] | 117 | querystring = '' |
| 118 | if force: |
| 119 | querystring = '?FORCE=True' |
| 120 | http_code, resp = self._http.delete_cmd('{}/{}{}'.format(self._apiBase, |
| 121 | sdn_controller['_id'], querystring)) |
| garciadeblas | 09fa3d4 | 2019-10-08 18:30:46 +0200 | [diff] [blame] | 122 | #print('HTTP CODE: {}'.format(http_code)) |
| 123 | #print('RESP: {}'.format(resp)) |
| garciadeblas | 74341f0 | 2018-05-03 18:46:46 +0200 | [diff] [blame] | 124 | if http_code == 202: |
| kuuse | 5da3f20 | 2019-05-30 09:42:05 +0200 | [diff] [blame] | 125 | if wait: |
| 126 | # Wait for status for SDNC instance deletion |
| 127 | self._wait(sdnc_id_for_wait, deleteFlag=True) |
| 128 | else: |
| 129 | print('Deletion in progress') |
| garciadeblas | 74341f0 | 2018-05-03 18:46:46 +0200 | [diff] [blame] | 130 | elif http_code == 204: |
| peusterm | be96096 | 2018-06-14 21:32:55 +0200 | [diff] [blame] | 131 | print('Deleted') |
| garciadeblas | 061856b | 2018-05-22 00:49:13 +0200 | [diff] [blame] | 132 | elif resp and 'result' in resp: |
| peusterm | be96096 | 2018-06-14 21:32:55 +0200 | [diff] [blame] | 133 | print('Deleted') |
| garciadeblas | 74341f0 | 2018-05-03 18:46:46 +0200 | [diff] [blame] | 134 | else: |
| garciadeblas | 061856b | 2018-05-22 00:49:13 +0200 | [diff] [blame] | 135 | msg = "" |
| 136 | if resp: |
| 137 | try: |
| 138 | msg = json.loads(resp) |
| 139 | except ValueError: |
| 140 | msg = resp |
| 141 | raise ClientException("failed to delete SDN controller {} - {}".format(name, msg)) |
| garciadeblas | 017c4fb | 2018-02-13 11:58:29 +0100 | [diff] [blame] | 142 | |
| 143 | def list(self, filter=None): |
| 144 | """Returns a list of SDN controllers |
| 145 | """ |
| pinoa | 93012ad | 2019-11-05 14:28:15 +0100 | [diff] [blame] | 146 | self._client.get_token() |
| garciadeblas | 017c4fb | 2018-02-13 11:58:29 +0100 | [diff] [blame] | 147 | filter_string = '' |
| 148 | if filter: |
| 149 | filter_string = '?{}'.format(filter) |
| 150 | resp = self._http.get_cmd('{}{}'.format(self._apiBase,filter_string)) |
| garciadeblas | 09fa3d4 | 2019-10-08 18:30:46 +0200 | [diff] [blame] | 151 | #print('RESP: {}'.format(resp)) |
| garciadeblas | 017c4fb | 2018-02-13 11:58:29 +0100 | [diff] [blame] | 152 | if resp: |
| 153 | return resp |
| 154 | return list() |
| 155 | |
| 156 | def get(self, name): |
| 157 | """Returns an SDN controller based on name or id |
| 158 | """ |
| pinoa | 93012ad | 2019-11-05 14:28:15 +0100 | [diff] [blame] | 159 | self._client.get_token() |
| garciadeblas | 017c4fb | 2018-02-13 11:58:29 +0100 | [diff] [blame] | 160 | if utils.validate_uuid4(name): |
| 161 | for sdnc in self.list(): |
| 162 | if name == sdnc['_id']: |
| 163 | return sdnc |
| 164 | else: |
| 165 | for sdnc in self.list(): |
| 166 | if name == sdnc['name']: |
| 167 | return sdnc |
| 168 | raise NotFound("SDN controller {} not found".format(name)) |
| 169 | |
| 170 | |