forked from openstack-charmers/zaza
-
Notifications
You must be signed in to change notification settings - Fork 0
/
controller.py
151 lines (122 loc) · 4.64 KB
/
controller.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# Copyright 2018 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Module for interacting with a juju controller."""
import logging
from juju.controller import Controller
import subprocess
import tenacity
from zaza import sync_wrapper
import zaza.utilities.exceptions
async def async_add_model(model_name, config=None, region=None):
"""Add a model to the current controller.
:param model_name: Name to give the new model.
:type model_name: str
:param config: Model configuration.
:type config: dict
:param region: Region in which to create the model.
:type region: str
"""
controller = Controller()
await controller.connect()
logging.debug("Adding model {}".format(model_name))
model = await controller.add_model(
model_name, config=config, region=region)
# issue/135 It is necessary to disconnect the model here or async spews
# tracebacks even during a successful run.
await model.disconnect()
await controller.disconnect()
add_model = sync_wrapper(async_add_model)
async def async_destroy_model(model_name):
"""Remove a model from the current controller.
:param model_name: Name of model to remove
:type model_name: str
"""
controller = Controller()
await controller.connect()
logging.debug("Destroying model {}".format(model_name))
await controller.destroy_model(model_name, force=True, max_wait=600)
# The model ought to be destroyed by now. Let's make sure, and if not,
# raise an error. Even if the model has been destroyed, it's still hangs
# around in the .list_models() for a little while; retry until it goes
# away, or that fails.
for attempt in tenacity.Retrying(
stop=tenacity.stop_after_attempt(20),
wait=tenacity.wait_exponential(
multiplier=1, min=2, max=20),
retry=tenacity.retry_if_exception_type(
zaza.utilities.exceptions.DestroyModelFailed)):
with attempt:
remaining_models = await controller.list_models()
if model_name in remaining_models:
raise zaza.utilities.exceptions.DestroyModelFailed(
"Destroying model {} failed.".format(model_name))
logging.debug("Model {} destroyed.".format(model_name))
await controller.disconnect()
destroy_model = sync_wrapper(async_destroy_model)
async def async_cloud(name=None):
"""Return information about cloud.
:param name: Cloud name. If not specified, the cloud where
the controller lives on is returned.
:type name: Optional[str]
:returns: Information on all clouds in the controller.
:rtype: CloudResult
"""
controller = Controller()
await controller.connect()
cloud = await controller.cloud(name=name)
await controller.disconnect()
return cloud
cloud = sync_wrapper(async_cloud)
def get_cloud_type(name=None):
"""Return type of cloud.
:param name: Cloud name. If not specified, the cloud where
the controller lives on is returned.
:type name: Optional[str]
:returns: Type of cloud
:rtype: str
"""
_cloud = cloud(name=name)
return _cloud.cloud.type_
async def async_get_cloud():
"""Return the name of the current cloud.
:returns: Name of cloud
:rtype: str
"""
controller = Controller()
await controller.connect()
cloud = await controller.get_cloud()
await controller.disconnect()
return cloud
get_cloud = sync_wrapper(async_get_cloud)
async def async_list_models():
"""Return a list of tha available clouds.
:returns: List of clouds
:rtype: list
"""
controller = Controller()
await controller.connect()
models = await controller.list_models()
await controller.disconnect()
return models
list_models = sync_wrapper(async_list_models)
def go_list_models():
"""Execute juju models.
NOTE: Excuting the juju models command updates the local cache of models.
Python-juju currently does not update the local cache on add model.
https://github.com/juju/python-libjuju/issues/267
:returns: None
:rtype: None
"""
cmd = ["juju", "models"]
subprocess.check_call(cmd)