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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
|
import os
import logging
from twisted.internet.defer import succeed
from landscape.lib.twisted_util import gather_results
from landscape.manager.plugin import ManagerPlugin
class EucalyptusInfo(object):
"""Provide utility methods to get information about a Eucalyptus cloud."""
def __init__(self, tools):
self._tools = tools
def get_version_info(self):
"""Return information about the version of Eucalyptus in use.
@return: A L{Deferred} firing with the string output of the
C{--version} command.
"""
return succeed(self._tools._runTool("euca_conf", ["--version"]))
def get_walrus_info(self):
"""Return information about the registered walruses (S3).
@return: a L{Deferred} firing with the string output of the
C{--list-walruses} command.
"""
return succeed(self._tools._runTool("euca_conf", ["--list-walruses"]))
def get_cluster_controller_info(self):
"""Return information about the registered cluster controllers..
@return: a L{Deferred} firing with the string output of the
C{--list-clusters} command.
"""
return succeed(self._tools._runTool("euca_conf", ["--list-clusters"]))
def get_storage_controller_info(self):
"""Return information about the registered storage controllers (EBS).
@return: a L{Deferred} firing with the string output of the
C{--list-scs} command.
"""
return succeed(self._tools._runTool("euca_conf", ["--list-scs"]))
def get_node_controller_info(self):
"""Return information about the registered node controller.
@return: a L{Deferred} firing with the string output of the
C{--list-nodes} command.
"""
return succeed(self._tools._runTool("euca_conf", ["--list-nodes"]))
class Eucalyptus(ManagerPlugin):
"""A management plugin for a Eucalyptus cloud."""
plugin_name = "eucalyptus-manager"
message_type = "eucalyptus-info"
error_message_type = "eucalyptus-info-error"
run_interval = 15 * 60
def __init__(self, service_hub_factory=None, eucalyptus_info_factory=None):
super(Eucalyptus, self).__init__()
self._service_hub_factory = service_hub_factory
if self._service_hub_factory is None:
self._service_hub_factory = start_service_hub
self._eucalyptus_info_factory = eucalyptus_info_factory
if self._eucalyptus_info_factory is None:
self._eucalyptus_info_factory = get_eucalyptus_info
self.enabled = True
def run(self):
"""Run the plugin.
A C{ServiceHub} runs services that provide information about
Eucalyptus. If a service hub can't be created the plugin assumes that
Eucalyptus is not installed. In such cases a message is written to
the log and the plugin is disabled.
@return: A C{Deferred} that will fire when the plugin has finished
running, unless it's disabled in which case None is returned.
"""
if not self.enabled:
return
return self.registry.broker.call_if_accepted(
self.message_type, self.send_message)
def send_message(self):
data_path = self.registry.config.data_path
try:
service_hub = self._service_hub_factory(data_path)
except Exception, e:
logging.exception(e)
self.enabled = False
logging.info("Couldn't start service hub. '%s' plugin has been "
"disabled." % self.message_type)
else:
from imagestore.eucaservice import GetEucaInfo
deferred = service_hub.addTask(GetEucaInfo("admin"))
deferred.addCallback(self._get_message)
deferred.addErrback(self._get_error_message)
deferred.addCallback(self.registry.broker.send_message)
deferred.addBoth(lambda ignored: service_hub.stop())
return deferred
def _get_message(self, credentials):
"""Create a message with information about a Eucalyptus cloud.
@param credentials: A C{EucaInfo} instance containing credentials for
the Eucalyptus cloud being managed.
@return: A message with information about Eucalyptus to send to the
server.
"""
deferred_list = []
info = self._eucalyptus_info_factory(credentials)
deferred_list = [
info.get_version_info(),
info.get_walrus_info(),
info.get_cluster_controller_info(),
info.get_storage_controller_info(),
info.get_node_controller_info()]
def create_message(result):
(version_info, walrus_info, cluster_controller_info,
storage_controller_info, node_controller_info) = result
version = version_info.split()[-1]
data = {"access_key": credentials.accessKey,
"secret_key": credentials.secretKey,
"private_key_path": credentials.privateKeyPath,
"certificate_path": credentials.certificatePath,
"cloud_certificate_path": credentials.cloudCertificatePath,
"url_for_s3": credentials.urlForS3,
"url_for_ec2": credentials.urlForEC2,
"eucalyptus_version": version}
return {"type": self.message_type, "basic_info": data,
"walrus_info": walrus_info,
"cluster_controller_info": cluster_controller_info,
"storage_controller_info": storage_controller_info,
"node_controller_info": node_controller_info}
return gather_results(deferred_list).addCallback(create_message)
def _get_error_message(self, failure):
"""Create an error message.
@param failure: A C{Failure} instance containing information about an
error that occurred while trying to retrieve credentials.
@return: An error message to send to the server.
"""
from imagestore.eucaservice import EucaToolsError
if failure.check(EucaToolsError):
self.enabled = False
error = failure.getBriefTraceback()
return {"type": self.error_message_type, "error": error}
def start_service_hub(data_path):
"""Create and start a C{ServiceHub} to use when getting credentials.
@param data_path: The path to Landscape's data directory.
@return: A running C{ServiceHub} with a C{EucaService} service that
can be used to retrieve credentials.
"""
from twisted.internet import reactor
from imagestore.lib.service import ServiceHub
from imagestore.eucaservice import EucaService
base_path = os.path.join(data_path, "eucalyptus")
if not os.path.exists(base_path):
os.makedirs(base_path)
service_hub = ServiceHub()
service_hub.addService(EucaService(reactor, base_path))
service_hub.start()
return service_hub
def get_eucalyptus_info(credentials):
"""Create a L{EucalyptusInfo} instance.
@param credentials: An C{imagestore.eucaservice.EucaInfo} instance.
@return: A L{EucalyptusInfo} instance.
"""
from imagestore.eucaservice import EucaTools
return EucalyptusInfo(EucaTools(credentials))
|