blob: 391eab4a47b6119e18d5d102183a22c211197933 [file] [log] [blame]
Vladyslav Drokcb8d0fb2018-06-27 19:28:14 +03001# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12
13import six
14import logging
15import uuid
16
17import os_client_config
18from salt import exceptions
19
20
21log = logging.getLogger(__name__)
22
23SERVICE_KEY = 'compute'
24
25
26def get_raw_client(cloud_name):
27 config = os_client_config.OpenStackConfig()
28 cloud = config.get_one_cloud(cloud_name)
29 adapter = cloud.get_session_client(SERVICE_KEY)
30 adapter.version = '2.1'
31 endpoints = []
32 try:
33 access_info = adapter.session.auth.get_access(adapter.session)
34 endpoints = access_info.service_catalog.get_endpoints()
35 except (AttributeError, ValueError) as exc:
36 six.raise_from(exc, exceptions.SaltInvocationError(
37 "Cannot load keystoneauth plugin. Please check your environment "
38 "configuration."))
39 if SERVICE_KEY not in endpoints:
40 raise exceptions.SaltInvocationError("Cannot find compute endpoint in "
41 "environment endpoint list.")
42 return adapter
43
44
45def send(method):
46 def wrap(func):
47 @six.wraps(func)
48 def wrapped_f(*args, **kwargs):
49 cloud_name = kwargs.pop('cloud_name', None)
50 if not cloud_name:
51 raise exceptions.SaltInvocationError(
52 "No cloud_name specified. Please provide cloud_name "
53 "parameter")
54 adapter = get_raw_client(cloud_name)
55 kwarg_keys = list(kwargs.keys())
56 for k in kwarg_keys:
57 if k.startswith('__'):
58 kwargs.pop(k)
59 url, request_kwargs = func(*args, **kwargs)
60 try:
61 response = getattr(adapter, method.lower())(url,
62 **request_kwargs)
63 except Exception as e:
64 log.exception("Error occurred when executing request")
65 return {"result": False,
66 "comment": six.text_type(e),
67 "status_code": getattr(e, "http_status", 500)}
68 return {"result": True,
69 "body": response.json() if response.content else {},
70 "status_code": response.status_code}
71 return wrapped_f
72 return wrap
73
74
75def _check_uuid(val):
76 try:
77 return str(uuid.UUID(val)) == val
78 except (TypeError, ValueError, AttributeError):
79 return False
80
81
82def get_by_name_or_uuid(resource_list, resp_key):
83 def wrap(func):
84 @six.wraps(func)
85 def wrapped_f(*args, **kwargs):
86 if 'name' in kwargs:
87 ref = kwargs.pop('name', None)
88 start_arg = 0
89 else:
90 start_arg = 1
91 ref = args[0]
92 item_id = None
93 if _check_uuid(ref):
94 item_id = ref
95 else:
96 cloud_name = kwargs['cloud_name']
97 resp = resource_list(cloud_name=cloud_name)["body"][resp_key]
98 for item in resp:
99 if item["name"] == ref:
100 if item_id is not None:
101 return {
102 "name": ref,
103 "changes": {},
104 "result": False,
105 "comment": "Multiple resources ({resource}) "
106 "with requested name found ".format(
107 resource=resp_key)}
108 item_id = item["id"]
109 if not item_id:
110 return {
111 "name": ref,
112 "changes": {},
113 "result": False,
114 "comment": "Resource ({resource}) "
115 "with requested name not found ".format(
116 resource=resp_key)}
117 return func(item_id, *args[start_arg:], **kwargs)
118 return wrapped_f
119 return wrap
120
121
122def function_descriptor(action_type, resource_human_readable_name,
123 body_response_key=None):
124 def decorator(fun):
125 fun._action_type = action_type
126 fun._body_response_key = body_response_key or ''
127 fun._resource_human_readable_name = resource_human_readable_name
128 return fun
129 return decorator