3 # Copyright 2016 RIFT.IO Inc
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
20 from gi
import require_version
21 require_version('RwCal', '1.0')
22 require_version('RwcalYang', '1.0')
23 require_version('RwTypes', '1.0')
24 require_version('RwCloudYang', '1.0')
25 require_version('RwCal', '1.0')
27 from gi
.repository
import (
34 if sys
.version_info
< (3, 4, 4):
35 asyncio
.ensure_future
= asyncio
.async
38 class PluginLoadingError(Exception):
42 class CloudAccountCalError(Exception):
46 class CloudAccount(object):
47 def __init__(self
, log
, rwlog_hdl
, account_msg
):
49 self
._account
_msg
= account_msg
.deep_copy()
51 self
._cal
_plugin
= None
54 self
._cal
= self
.plugin
.get_interface("Cloud")
55 self
._cal
.init(rwlog_hdl
)
57 self
._status
= RwCloudYang
.YangData_RwProject_Project_Cloud_Account_ConnectionStatus(
59 details
="Connection status lookup not started"
62 self
._validate
_task
= None
66 if self
._cal
_plugin
is None:
68 self
._cal
_plugin
= rw_peas
.PeasPlugin(
69 getattr(self
._account
_msg
, self
.account_type
).plugin_name
,
73 except AttributeError as e
:
74 raise PluginLoadingError(str(e
))
76 self
._engine
, _
, _
= self
._cal
_plugin
()
78 return self
._cal
_plugin
80 def _wrap_status_fn(self
, fn
, *args
, **kwargs
):
81 ret
= fn(*args
, **kwargs
)
83 if rw_status
!= RwTypes
.RwStatus
.SUCCESS
:
84 msg
= "%s returned %s" % (fn
.__name
__, str(rw_status
))
86 raise CloudAccountCalError(msg
)
88 # If there was only one other return value besides rw_status, then just
89 # return that element. Otherwise return the rest of the return values
91 return ret
[1] if len(ret
) == 2 else ret
[1:]
99 return self
._account
_msg
.name
102 def account_msg(self
):
103 return self
._account
_msg
106 def cal_account_msg(self
):
107 return RwcalYang
.YangData_RwProject_Project_CloudAccounts_CloudAccountList
.from_dict(
108 self
.account_msg
.as_dict(),
109 ignore_missing_keys
=True,
112 def cloud_account_msg(self
, account_dict
):
113 self
._account
_msg
= RwCloudYang
.YangData_RwProject_Project_CloudAccounts_CloudAccountList
.from_dict(account_dict
)
116 def account_type(self
):
117 return self
._account
_msg
.account_type
120 def connection_status(self
):
123 def update_from_cfg(self
, cfg
):
124 self
._log
.debug("Updating parent CloudAccount to %s", cfg
)
126 # Hack to catch updates triggered from apply_callback when a sdn-account is removed
127 # from a cloud-account. To be fixed properly when updates are handled
128 if (self
.account_msg
.name
== cfg
.name
129 and self
.account_msg
.account_type
== cfg
.account_type
):
132 if cfg
.has_field("sdn_account"):
133 self
.account_msg
.sdn_account
= cfg
.sdn_account
135 raise NotImplementedError("Update cloud account not yet supported")
137 def create_image(self
, image_info_msg
):
138 image_id
= self
._wrap
_status
_fn
(
139 self
.cal
.create_image
, self
.cal_account_msg
, image_info_msg
144 def get_image_list(self
):
145 self
._log
.debug("Getting image list from account: %s", self
.name
)
146 resources
= self
._wrap
_status
_fn
(
147 self
.cal
.get_image_list
, self
.cal_account_msg
150 return resources
.imageinfo_list
153 def validate_cloud_account_credentials(self
, loop
):
154 self
._log
.debug("Validating Cloud Account credentials for account %s",
156 self
._status
= RwCloudYang
.YangData_RwProject_Project_Cloud_Account_ConnectionStatus(
158 details
="Cloud account connection validation in progress"
160 rwstatus
, status
= yield from loop
.run_in_executor(
162 self
._cal
.validate_cloud_creds
,
163 self
.cal_account_msg
,
165 if rwstatus
== RwTypes
.RwStatus
.SUCCESS
:
166 self
._status
= RwCloudYang
.YangData_RwProject_Project_Cloud_Account_ConnectionStatus
.from_dict(status
.as_dict())
168 self
._status
= RwCloudYang
.YangData_RwProject_Project_Cloud_Account_ConnectionStatus(
170 details
="Error when calling CAL validate cloud creds"
173 if self
._status
.status
== 'failure':
174 self
._log
.error("Cloud account validation failed. Acct: %s, response: %s",
175 self
.name
, self
._status
)
178 def start_validate_credentials(self
, loop
):
179 if self
._validate
_task
is not None:
180 self
._validate
_task
.cancel()
181 self
._validate
_task
= None
183 self
._validate
_task
= yield from asyncio
.ensure_future(
184 self
.validate_cloud_account_credentials(loop
),