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('RwcalYang', '1.0')
22 require_version('RwTypes', '1.0')
23 require_version('RwCloudYang', '1.0')
25 from gi
.repository
import (
32 if sys
.version_info
< (3, 4, 4):
33 asyncio
.ensure_future
= asyncio
.async
36 class PluginLoadingError(Exception):
40 class CloudAccountCalError(Exception):
44 class CloudAccount(object):
45 def __init__(self
, log
, rwlog_hdl
, account_msg
):
47 self
._account
_msg
= account_msg
.deep_copy()
49 self
._cal
_plugin
= None
52 self
._cal
= self
.plugin
.get_interface("Cloud")
53 self
._cal
.init(rwlog_hdl
)
55 self
._status
= RwCloudYang
.CloudAccount_ConnectionStatus(
57 details
="Connection status lookup not started"
60 self
._validate
_task
= None
64 if self
._cal
_plugin
is None:
66 self
._cal
_plugin
= rw_peas
.PeasPlugin(
67 getattr(self
._account
_msg
, self
.account_type
).plugin_name
,
71 except AttributeError as e
:
72 raise PluginLoadingError(str(e
))
74 self
._engine
, _
, _
= self
._cal
_plugin
()
76 return self
._cal
_plugin
78 def _wrap_status_fn(self
, fn
, *args
, **kwargs
):
79 ret
= fn(*args
, **kwargs
)
81 if rw_status
!= RwTypes
.RwStatus
.SUCCESS
:
82 msg
= "%s returned %s" % (fn
.__name
__, str(rw_status
))
84 raise CloudAccountCalError(msg
)
86 # If there was only one other return value besides rw_status, then just
87 # return that element. Otherwise return the rest of the return values
89 return ret
[1] if len(ret
) == 2 else ret
[1:]
97 return self
._account
_msg
.name
100 def account_msg(self
):
101 return self
._account
_msg
104 def cal_account_msg(self
):
105 return RwcalYang
.CloudAccount
.from_dict(
106 self
.account_msg
.as_dict(),
107 ignore_missing_keys
=True,
110 def cloud_account_msg(self
, account_dict
):
111 self
._account
_msg
= RwCloudYang
.CloudAccount
.from_dict(account_dict
)
114 def account_type(self
):
115 return self
._account
_msg
.account_type
118 def connection_status(self
):
121 def update_from_cfg(self
, cfg
):
122 self
._log
.debug("Updating parent CloudAccount to %s", cfg
)
124 # Hack to catch updates triggered from apply_callback when a sdn-account is removed
125 # from a cloud-account. To be fixed properly when updates are handled
126 if (self
.account_msg
.name
== cfg
.name
127 and self
.account_msg
.account_type
== cfg
.account_type
):
130 if cfg
.has_field("sdn_account"):
131 self
.account_msg
.sdn_account
= cfg
.sdn_account
133 raise NotImplementedError("Update cloud account not yet supported")
135 def create_image(self
, image_info_msg
):
136 image_id
= self
._wrap
_status
_fn
(
137 self
.cal
.create_image
, self
.cal_account_msg
, image_info_msg
142 def get_image_list(self
):
143 self
._log
.debug("Getting image list from account: %s", self
.name
)
144 resources
= self
._wrap
_status
_fn
(
145 self
.cal
.get_image_list
, self
.cal_account_msg
148 return resources
.imageinfo_list
151 def validate_cloud_account_credentials(self
, loop
):
152 self
._log
.debug("Validating Cloud Account credentials %s", self
._account
_msg
)
153 self
._status
= RwCloudYang
.CloudAccount_ConnectionStatus(
155 details
="Cloud account connection validation in progress"
157 rwstatus
, status
= yield from loop
.run_in_executor(
159 self
._cal
.validate_cloud_creds
,
160 self
.cal_account_msg
,
162 if rwstatus
== RwTypes
.RwStatus
.SUCCESS
:
163 self
._status
= RwCloudYang
.CloudAccount_ConnectionStatus
.from_dict(status
.as_dict())
165 self
._status
= RwCloudYang
.CloudAccount_ConnectionStatus(
167 details
="Error when calling CAL validate cloud creds"
170 self
._log
.info("Got cloud account validation response: %s", self
._status
)
172 def start_validate_credentials(self
, loop
):
173 if self
._validate
_task
is not None:
174 self
._validate
_task
.cancel()
175 self
._validate
_task
= None
177 self
._validate
_task
= asyncio
.ensure_future(
178 self
.validate_cloud_account_credentials(loop
),