Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 1 | import re |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 2 | import abc |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 3 | import json |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 4 | import logging |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 5 | import urllib.parse |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 6 | import urllib.error |
| 7 | import urllib.request |
| 8 | from typing import Dict, Any, Iterator, List, Callable, cast |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 9 | from functools import partial |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 10 | |
| 11 | import netaddr |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 12 | from keystoneclient import exceptions |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 13 | from keystoneclient.v2_0 import Client as keystoneclient |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 14 | |
| 15 | |
koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 16 | logger = logging.getLogger("wally") |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 17 | |
| 18 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 19 | class Connection(metaclass=abc.ABCMeta): |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 20 | host = None # type: str |
| 21 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 22 | @abc.abstractmethod |
| 23 | def do(self, method: str, path: str, params: Dict = None) -> Dict: |
| 24 | pass |
| 25 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 26 | def get(self, path: str, params: Dict = None) -> Dict: |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 27 | return self.do("GET", path, params) |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 28 | |
| 29 | |
| 30 | class Urllib2HTTP(Connection): |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 31 | """ |
| 32 | class for making HTTP requests |
| 33 | """ |
| 34 | |
| 35 | allowed_methods = ('get', 'put', 'post', 'delete', 'patch', 'head') |
| 36 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 37 | def __init__(self, root_url: str, headers: Dict[str, str] = None) -> None: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 38 | """ |
| 39 | """ |
| 40 | if root_url.endswith('/'): |
| 41 | self.root_url = root_url[:-1] |
| 42 | else: |
| 43 | self.root_url = root_url |
| 44 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 45 | self.host = urllib.parse.urlparse(self.root_url).hostname |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 46 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 47 | if headers is None: |
| 48 | self.headers = {} # type: Dict[str, str] |
| 49 | else: |
| 50 | self.headers = headers |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 51 | |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 52 | def do(self, method: str, path: str, params: Dict = None) -> Any: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 53 | if path.startswith('/'): |
| 54 | url = self.root_url + path |
| 55 | else: |
| 56 | url = self.root_url + '/' + path |
| 57 | |
| 58 | if method == 'get': |
| 59 | assert params == {} or params is None |
| 60 | data_json = None |
| 61 | else: |
| 62 | data_json = json.dumps(params) |
| 63 | |
koder aka kdanilov | 6b1341a | 2015-04-21 22:44:21 +0300 | [diff] [blame] | 64 | logger.debug("HTTP: {0} {1}".format(method.upper(), url)) |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 65 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 66 | request = urllib.request.Request(url, |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 67 | data=data_json.encode("utf8"), |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 68 | headers=self.headers) |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 69 | if data_json is not None: |
| 70 | request.add_header('Content-Type', 'application/json') |
| 71 | |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 72 | request.get_method = lambda: method.upper() # type: ignore |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 73 | response = urllib.request.urlopen(request) |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 74 | code = response.code # type: ignore |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 75 | |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 76 | logger.debug("HTTP Responce: {0}".format(code)) |
| 77 | if code < 200 or code > 209: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 78 | raise IndexError(url) |
| 79 | |
| 80 | content = response.read() |
| 81 | |
| 82 | if '' == content: |
| 83 | return None |
| 84 | |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 85 | return json.loads(content.decode("utf8")) |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 86 | |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 87 | def __getattr__(self, name: str) -> Any: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 88 | if name in self.allowed_methods: |
| 89 | return partial(self.do, name) |
| 90 | raise AttributeError(name) |
| 91 | |
| 92 | |
| 93 | class KeystoneAuth(Urllib2HTTP): |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame] | 94 | def __init__(self, root_url: str, creds: Dict[str, str], headers: Dict[str, str] = None) -> None: |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 95 | super(KeystoneAuth, self).__init__(root_url, headers) |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 96 | admin_node_ip = urllib.parse.urlparse(root_url).hostname |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 97 | self.keystone_url = "http://{0}:5000/v2.0".format(admin_node_ip) |
| 98 | self.keystone = keystoneclient( |
| 99 | auth_url=self.keystone_url, **creds) |
| 100 | self.refresh_token() |
| 101 | |
koder aka kdanilov | 22d134e | 2016-11-08 11:33:19 +0200 | [diff] [blame] | 102 | def refresh_token(self) -> None: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 103 | """Get new token from keystone and update headers""" |
| 104 | try: |
| 105 | self.keystone.authenticate() |
| 106 | self.headers['X-Auth-Token'] = self.keystone.auth_token |
| 107 | except exceptions.AuthorizationFailure: |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 108 | logger.warning( |
| 109 | 'Cant establish connection to keystone with url %s', |
| 110 | self.keystone_url) |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 111 | |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 112 | def do(self, method: str, path: str, params: Dict[str, str] = None) -> Any: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 113 | """Do request. If gets 401 refresh token""" |
| 114 | try: |
| 115 | return super(KeystoneAuth, self).do(method, path, params) |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 116 | except urllib.error.HTTPError as e: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 117 | if e.code == 401: |
koder aka kdanilov | cee4334 | 2015-04-14 22:52:53 +0300 | [diff] [blame] | 118 | logger.warning( |
| 119 | 'Authorization failure: {0}'.format(e.read())) |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 120 | self.refresh_token() |
| 121 | return super(KeystoneAuth, self).do(method, path, params) |
| 122 | else: |
| 123 | raise |
| 124 | |
| 125 | |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 126 | def get_inline_param_list(url: str) -> Iterator[str]: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 127 | format_param_rr = re.compile(r"\{([a-zA-Z_]+)\}") |
| 128 | for match in format_param_rr.finditer(url): |
| 129 | yield match.group(1) |
| 130 | |
| 131 | |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 132 | class RestObj: |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 133 | name = None # type: str |
| 134 | id = None # type: int |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 135 | |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 136 | def __init__(self, conn: Connection, **kwargs: Any) -> None: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 137 | self.__dict__.update(kwargs) |
| 138 | self.__connection__ = conn |
| 139 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 140 | def __str__(self) -> str: |
koder aka kdanilov | 6b1341a | 2015-04-21 22:44:21 +0300 | [diff] [blame] | 141 | res = ["{0}({1}):".format(self.__class__.__name__, self.name)] |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 142 | for k, v in sorted(self.__dict__.items()): |
| 143 | if k.startswith('__') or k.endswith('__'): |
| 144 | continue |
| 145 | if k != 'name': |
koder aka kdanilov | 6b1341a | 2015-04-21 22:44:21 +0300 | [diff] [blame] | 146 | res.append(" {0}={1!r}".format(k, v)) |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 147 | return "\n".join(res) |
| 148 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 149 | def __getitem__(self, item: str) -> Any: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 150 | return getattr(self, item) |
| 151 | |
| 152 | |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 153 | def make_call(method: str, url: str) -> Callable: |
| 154 | def closure(obj: Any, entire_obj: Any = None, **data: Any) -> Any: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 155 | inline_params_vals = {} |
| 156 | for name in get_inline_param_list(url): |
| 157 | if name in data: |
| 158 | inline_params_vals[name] = data[name] |
| 159 | del data[name] |
| 160 | else: |
| 161 | inline_params_vals[name] = getattr(obj, name) |
| 162 | result_url = url.format(**inline_params_vals) |
| 163 | |
| 164 | if entire_obj is not None: |
| 165 | if data != {}: |
| 166 | raise ValueError("Both entire_obj and data provided") |
| 167 | data = entire_obj |
| 168 | return obj.__connection__.do(method, result_url, params=data) |
| 169 | return closure |
| 170 | |
| 171 | |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 172 | RequestMethod = Callable[[str], Callable] |
| 173 | |
| 174 | |
| 175 | PUT = cast(RequestMethod, partial(make_call, 'put')) # type: RequestMethod |
| 176 | GET = cast(RequestMethod, partial(make_call, 'get')) # type: RequestMethod |
| 177 | DELETE = cast(RequestMethod, partial(make_call, 'delete')) # type: RequestMethod |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 178 | |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 179 | # ------------------------------- ORM ---------------------------------------- |
| 180 | |
| 181 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 182 | def get_fuel_info(url: str) -> 'FuelInfo': |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 183 | conn = Urllib2HTTP(url) |
| 184 | return FuelInfo(conn) |
| 185 | |
| 186 | |
| 187 | class FuelInfo(RestObj): |
| 188 | |
| 189 | """Class represents Fuel installation info""" |
| 190 | |
| 191 | get_nodes = GET('api/nodes') |
| 192 | get_clusters = GET('api/clusters') |
| 193 | get_cluster = GET('api/clusters/{id}') |
koder aka kdanilov | cff7b2e | 2015-04-18 20:48:15 +0300 | [diff] [blame] | 194 | get_info = GET('api/releases') |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 195 | |
| 196 | @property |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 197 | def nodes(self) -> 'NodeList': |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 198 | """Get all fuel nodes""" |
| 199 | return NodeList([Node(self.__connection__, **node) for node |
| 200 | in self.get_nodes()]) |
| 201 | |
| 202 | @property |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 203 | def free_nodes(self) -> 'NodeList': |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 204 | """Get unallocated nodes""" |
| 205 | return NodeList([Node(self.__connection__, **node) for node in |
| 206 | self.get_nodes() if not node['cluster']]) |
| 207 | |
| 208 | @property |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 209 | def clusters(self) -> List['Cluster']: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 210 | """List clusters in fuel""" |
| 211 | return [Cluster(self.__connection__, **cluster) for cluster |
| 212 | in self.get_clusters()] |
| 213 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 214 | def get_version(self) -> List[int]: |
koder aka kdanilov | cff7b2e | 2015-04-18 20:48:15 +0300 | [diff] [blame] | 215 | for info in self.get_info(): |
| 216 | vers = info['version'].split("-")[1].split('.') |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 217 | return list(map(int, vers)) |
koder aka kdanilov | cff7b2e | 2015-04-18 20:48:15 +0300 | [diff] [blame] | 218 | raise ValueError("No version found") |
| 219 | |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 220 | |
| 221 | class Node(RestObj): |
| 222 | """Represents node in Fuel""" |
| 223 | |
| 224 | get_info = GET('/api/nodes/{id}') |
| 225 | get_interfaces = GET('/api/nodes/{id}/interfaces') |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 226 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 227 | def get_network_data(self) -> Dict: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 228 | """Returns node network data""" |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 229 | return self.get_info().get('network_data') |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 230 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 231 | def get_roles(self) -> List[str]: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 232 | """Get node roles |
| 233 | |
| 234 | Returns: (roles, pending_roles) |
| 235 | """ |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 236 | return self.get_info().get('roles') |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 237 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 238 | def get_ip(self, network='public') -> netaddr.IPAddress: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 239 | """Get node ip |
| 240 | |
| 241 | :param network: network to pick |
| 242 | """ |
| 243 | nets = self.get_network_data() |
| 244 | for net in nets: |
| 245 | if net['name'] == network: |
| 246 | iface_name = net['dev'] |
| 247 | for iface in self.get_info()['meta']['interfaces']: |
| 248 | if iface['name'] == iface_name: |
| 249 | try: |
| 250 | return iface['ip'] |
| 251 | except KeyError: |
| 252 | return netaddr.IPNetwork(net['ip']).ip |
| 253 | raise Exception('Network %s not found' % network) |
| 254 | |
| 255 | |
| 256 | class NodeList(list): |
| 257 | """Class for filtering nodes through attributes""" |
| 258 | allowed_roles = ['controller', 'compute', 'cinder', 'ceph-osd', 'mongo', |
| 259 | 'zabbix-server'] |
| 260 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 261 | def __getattr__(self, name: str) -> List[Node]: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 262 | if name in self.allowed_roles: |
| 263 | return [node for node in self if name in node.roles] |
| 264 | |
| 265 | |
| 266 | class Cluster(RestObj): |
| 267 | """Class represents Cluster in Fuel""" |
| 268 | |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 269 | get_status = GET('api/clusters/{id}') |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 270 | get_networks = GET('api/clusters/{id}/network_configuration/neutron') |
| 271 | get_attributes = GET('api/clusters/{id}/attributes') |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 272 | _get_nodes = GET('api/nodes?cluster_id={id}') |
| 273 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 274 | def __init__(self, *dt, **mp) -> None: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 275 | super(Cluster, self).__init__(*dt, **mp) |
Yulia Portnova | d976704 | 2015-04-10 17:32:06 +0300 | [diff] [blame] | 276 | self.nodes = NodeList([Node(self.__connection__, **node) for node in |
| 277 | self._get_nodes()]) |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 278 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 279 | def check_exists(self) -> bool: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 280 | """Check if cluster exists""" |
| 281 | try: |
| 282 | self.get_status() |
| 283 | return True |
koder aka kdanilov | 7022706 | 2016-11-26 23:23:21 +0200 | [diff] [blame] | 284 | except urllib.error.HTTPError as err: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 285 | if err.code == 404: |
| 286 | return False |
| 287 | raise |
| 288 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 289 | def get_openrc(self) -> Dict[str, str]: |
Yulia Portnova | 00025a5 | 2015-04-07 12:17:32 +0300 | [diff] [blame] | 290 | access = self.get_attributes()['editable']['access'] |
koder aka kdanilov | 3b4da8b | 2016-10-17 00:17:53 +0300 | [diff] [blame] | 291 | creds = {'username': access['user']['value'], |
| 292 | 'password': access['password']['value'], |
| 293 | 'tenant_name': access['tenant']['value']} |
Michael Semenov | 8d6c057 | 2015-08-25 12:59:05 +0300 | [diff] [blame] | 294 | |
| 295 | version = FuelInfo(self.__connection__).get_version() |
koder aka kdanilov | 5ea9df0 | 2015-12-04 21:46:06 +0200 | [diff] [blame] | 296 | # only HTTPS since 7.0 |
| 297 | if version >= [7, 0]: |
Michael Semenov | 8d6c057 | 2015-08-25 12:59:05 +0300 | [diff] [blame] | 298 | creds['insecure'] = "True" |
| 299 | creds['os_auth_url'] = "https://{0}:5000/v2.0".format( |
| 300 | self.get_networks()['public_vip']) |
| 301 | else: |
| 302 | creds['os_auth_url'] = "http://{0}:5000/v2.0".format( |
| 303 | self.get_networks()['public_vip']) |
Yulia Portnova | 00025a5 | 2015-04-07 12:17:32 +0300 | [diff] [blame] | 304 | return creds |
| 305 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 306 | def get_nodes(self) -> Iterator[Node]: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 307 | for node_descr in self._get_nodes(): |
| 308 | yield Node(self.__connection__, **node_descr) |
| 309 | |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 310 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 311 | def reflect_cluster(conn: Connection, cluster_id: int) -> Cluster: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 312 | """Returns cluster object by id""" |
| 313 | c = Cluster(conn, id=cluster_id) |
| 314 | c.nodes = NodeList(list(c.get_nodes())) |
| 315 | return c |
| 316 | |
| 317 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 318 | def get_all_nodes(conn: Connection) -> Iterator[Node]: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 319 | """Get all nodes from Fuel""" |
| 320 | for node_desc in conn.get('api/nodes'): |
| 321 | yield Node(conn, **node_desc) |
| 322 | |
| 323 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 324 | def get_all_clusters(conn: Connection) -> Iterator[Cluster]: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 325 | """Get all clusters""" |
| 326 | for cluster_desc in conn.get('api/clusters'): |
| 327 | yield Cluster(conn, **cluster_desc) |
| 328 | |
| 329 | |
koder aka kdanilov | 7308462 | 2016-11-16 21:51:08 +0200 | [diff] [blame] | 330 | def get_cluster_id(conn: Connection, name: str) -> int: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 331 | """Get cluster id by name""" |
| 332 | for cluster in get_all_clusters(conn): |
| 333 | if cluster.name == name: |
Yulia Portnova | 3556a06 | 2015-03-17 16:30:11 +0200 | [diff] [blame] | 334 | return cluster.id |
| 335 | |
koder aka kdanilov | da45e88 | 2015-04-06 02:24:42 +0300 | [diff] [blame] | 336 | raise ValueError("Cluster {0} not found".format(name)) |
| 337 | |