1
from osv import fields, osv
2
from keystoneclient.v2_0 import client as ksclient
3
from ceilometerclient import exc
4
from ceilometerclient import client as ceilometerclient
5
import openerp.exceptions
8
class ceilometer_subscription(osv.osv):
9
_description = 'Ceilometer subscription configuration'
10
_name = 'ceilometer.subscription'
11
_endpoint_type = 'metering'
12
_endpoint_url = 'publicURL'
15
def _get_total_users(self, cr, uid, ids, field_name, field_value, arg, context=None):
16
records = self.browse(cr, uid, ids)
19
for record in records:
20
# count the number of users
21
result[record.id] = len(record.user_ids)
24
def _get_total_projects(self, cr, uid, ids, field_name, field_value, arg, context=None):
25
records = self.browse(cr, uid, ids)
28
for record in records:
29
# count the number of projects
30
result[record.id] = len(record.project_ids)
33
def _get_total_resources(self, cr, uid, ids, field_name, field_value, arg, context=None):
34
records = self.browse(cr, uid, ids)
37
for record in records:
38
# count the number of users
39
result[record.id] = len(record.resource_ids)
42
def _get_total_meters(self, cr, uid, ids, field_name, field_value, arg, context=None):
43
records = self.browse(cr, uid, ids)
46
for record in records:
47
# count the number of users
48
result[record.id] = len(record.meter_ids)
52
'name': fields.char('Subscription name', size=64, required=True),
53
'url': fields.char('Server URL', size=255, required=True),
54
'username': fields.char('Username', size=64, required=True),
55
'password': fields.char('Password', size=64, required=True),
56
'tenant': fields.char('Tenant name', size=64, required=True),
57
'active': fields.boolean('Active'),
58
'user_ids': fields.one2many('ceilometer.user', 'subscription_id', 'Associated users'),
59
'project_ids': fields.one2many('ceilometer.project', 'subscription_id', 'Associated projects'),
60
'resource_ids': fields.one2many('ceilometer.resource', 'subscription_id', 'Associated resources'),
61
'meter_ids': fields.one2many('ceilometer.meter', 'subscription_id', 'Associated meters'),
62
'total_users': fields.function(_get_total_users, type='integer', method=True, store=False, string='# users'),
63
'total_projects': fields.function(_get_total_projects, type='integer', method=True, store=False, string='# projects'),
64
'total_meters': fields.function(_get_total_meters, type='integer', method=True, store=False, string='# meters'),
65
'total_resources': fields.function(_get_total_resources, type='integer', method=True, store=False, string='# resources')
74
# establish a connection to ceilometer client and returns it
75
def _get_ceilometer_client(self, account):
77
ks_client = ksclient.Client(username=account["username"], password=account["password"], tenant_name=account["tenant"], auth_url=account["url"])
79
if ks_client and ks_client.auth_token:
81
endpoint = ks_client.service_catalog.url_for(service_type=self._endpoint_type, endpoint_type=self._endpoint_url)
83
ceilometer_client = ceilometerclient.Client(self._api_version, endpoint=endpoint, token=ks_client.auth_token)
84
return ceilometer_client
91
def action_test_connection(self, cursor, user, ids, context=None):
93
checks Ceilometer credentials and confirms if outgoing connection works
98
account = self.browse(cursor, user, ids, context)
101
raise openerp.exceptions.Warning("Subscription for the given ID does not exist")
103
# test ceilometer client
104
ceil_client = self._get_ceilometer_client(account)
106
raise openerp.exceptions.Warning("Ceilometer connection not properly configured. Please check your credentials")
108
raise openerp.exceptions.Warning("Ceilomer account successfully configured")
111
def sync_users(self, cr, uid, ceil_client, subscription_details, context=None):
113
obj_user = self.pool.get("ceilometer.user")
117
users = ceil_client.users.list()
119
api_users.append(user.user_id)
122
for existing_user in subscription_details.user_ids:
124
if (existing_user.name not in api_users):
126
obj_user.unlink(cr, uid, existing_user.id)
128
model_users.append(existing_user.name)
130
# check api user against db user
131
for api_user in api_users:
132
if (api_user not in model_users):
136
'subscription_id': subscription_details.id,
138
user_id = obj_user.create(cr, uid, new_user, context=context)
146
def sync_projects(self, cr, uid, ceil_client, subscription_details, context=None):
148
obj_project = self.pool.get("ceilometer.project")
150
# get projects from api
152
projects = ceil_client.projects.list()
153
for project in projects:
154
api_projects.append(project.project_id)
157
for existing_project in subscription_details.project_ids:
159
if (existing_project.name not in api_projects):
160
# remove that project
161
obj_project.unlink(cr, uid, existing_project.id)
163
model_projects.append(existing_project.name)
165
# check api project against db project
166
for api_project in api_projects:
167
if (api_project not in model_projects):
171
'subscription_id': subscription_details.id,
173
project_id = obj_project.create(cr, uid, new_project, context=context)
181
def sync_resources(self, cr, uid, ceil_client, subscription_details, context=None):
183
obj_resource = self.pool.get("ceilometer.resource")
185
# get resources from api
187
resources = ceil_client.resources.list()
188
for resource in resources:
189
api_resources.append(resource.resource_id)
192
for existing_resource in subscription_details.resource_ids:
194
if (existing_resource.name not in api_resources):
195
# remove that resource
196
obj_resource.unlink(cr, uid, existing_resource.id)
198
model_resources.append(existing_resource.name)
200
# check api resource against db resource
201
for api_resource in api_resources:
202
if (api_resource not in model_resources):
203
# create new resource
205
'name': api_resource,
206
'subscription_id': subscription_details.id,
208
resource_id = obj_resource.create(cr, uid, new_resource, context=context)
216
def search_project(self, cr, uid, project_id, context=None):
217
existing_project = None
220
project_model = self.pool.get("ceilometer.project")
221
existing_project_ids = project_model.search(cr, uid, [('name', '=', project_id)])
222
if existing_project_ids:
223
project_data = project_model.browse(cr, uid, existing_project_ids)
224
if project_data and len(project_data)>0:
225
existing_project = project_data[0].id
227
return existing_project
229
def search_user(self, cr, uid, user_id, context=None):
233
user_model = self.pool.get("ceilometer.user")
234
existing_user_ids = user_model.search(cr, uid, [('name', '=', user_id)])
235
if existing_user_ids:
236
user_data = user_model.browse(cr, uid, existing_user_ids)
237
if user_data and len(user_data)>0:
238
existing_user = user_data[0].id
242
def search_resource(self, cr, uid, resource_id, context=None):
243
existing_resource = None
246
resource_model = self.pool.get("ceilometer.resource")
247
existing_resource_ids = resource_model.search(cr, uid, [('name', '=', resource_id)])
248
if existing_resource_ids:
249
resource_data = resource_model.browse(cr, uid, existing_resource_ids)
250
if resource_data and len(resource_data)>0:
251
existing_resource = resource_data[0].id
253
return existing_resource
255
def sync_meters(self, cr, uid, ceil_client, subscription_details, context=None):
257
obj_meter = self.pool.get("ceilometer.meter")
259
# get meters from api
261
api_meter_details = []
263
meters = ceil_client.meters.list()
265
content_signature = str(meter.type)+"|"+str(meter.project_id)+"|"+str(meter.user_id)+"|"+str(meter.name)+"|"+str(meter.resource_id)
266
content_hash = md5.new(content_signature).digest()
267
api_meters.append(content_hash)
269
new_api_meter = {"type": meter.type, "project_id": meter.project_id, "user_id": meter.user_id, "name": meter.name, "resource_id": meter.resource_id,
270
"signature": content_hash}
271
api_meter_details.append(new_api_meter)
274
for existing_meter in subscription_details.meter_ids:
275
if (existing_meter.signature not in api_meters):
277
obj_meter.unlink(cr, uid, existing_meter.id)
279
model_meters.append(existing_meter.signature)
281
# check api meter against db meter
282
for api_meter in api_meter_details:
283
if (api_meter["signature"] not in model_meters):
284
# search relationships
285
existing_project = self.search_project(cr, uid, api_meter["project_id"], context=context)
286
existing_user = self.search_user(cr, uid, api_meter["user_id"], context=context)
287
existing_resource = self.search_resource(cr, uid, api_meter["resource_id"], context=context)
291
'name': api_meter["name"],
292
'type': api_meter["type"],
293
'project_id': existing_project,
294
'user_id': existing_user,
295
'resource_id': existing_resource,
296
'subscription_id': subscription_details.id,
297
'signature': api_meter["signature"]
299
meter_id = obj_meter.create(cr, uid, new_meter, context=context)
307
def sync_subscription(self, cr, uid, id, context=None):
308
subscription_details = self.browse(cr, uid, id)
309
if subscription_details:
310
# test ceilometer client
311
ceil_client = self._get_ceilometer_client(subscription_details)
313
self.sync_users(cr, uid, ceil_client, subscription_details, context)
314
self.sync_projects(cr, uid, ceil_client, subscription_details, context)
315
self.sync_resources(cr, uid, ceil_client, subscription_details, context)
316
self.sync_sources(cr, uid, ceil_client, subscription_details, context)
317
self.sync_meters(cr, uid, ceil_client, subscription_details, context)
319
def sync_subscriptions(self, cr, uid, ids, context=None):
320
# if no ids are passed, read all
322
ids = self.search(cr, uid, [('active','=',True)])
324
for subscription_id in ids:
325
print "sync "+subscription_id
326
self.sync_subscription(cr, uid, subscription_id, context)
328
raise openerp.exceptions.Warning("Ceilometer sync finished")
330
ceilometer_subscription()