~yolanda.robla/+junk/ceilometer_openerp

« back to all changes in this revision

Viewing changes to ceilometer_configuration.py.save

  • Committer: yolanda.robla at canonical
  • Date: 2013-01-08 13:51:06 UTC
  • Revision ID: yolanda.robla@canonical.com-20130108135106-5q9wf1nopjwf50uy
first beta version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
6
import md5
 
7
 
 
8
class ceilometer_subscription(osv.osv):
 
9
    _description = 'Ceilometer subscription configuration'
 
10
    _name = 'ceilometer.subscription'
 
11
    _endpoint_type = 'metering'
 
12
    _endpoint_url = 'publicURL'
 
13
    _api_version = '1'
 
14
 
 
15
    def _get_total_users(self, cr, uid, ids, field_name, field_value, arg, context=None):
 
16
        records = self.browse(cr, uid, ids)
 
17
        result = {}
 
18
 
 
19
        for record in records:
 
20
            # count the number of users
 
21
            result[record.id] = len(record.user_ids)
 
22
        return result
 
23
 
 
24
    def _get_total_projects(self, cr, uid, ids, field_name, field_value, arg, context=None):
 
25
        records = self.browse(cr, uid, ids)
 
26
        result = {}
 
27
 
 
28
        for record in records:
 
29
            # count the number of projects
 
30
            result[record.id] = len(record.project_ids)
 
31
        return result
 
32
 
 
33
    def _get_total_resources(self, cr, uid, ids, field_name, field_value, arg, context=None):
 
34
        records = self.browse(cr, uid, ids)
 
35
        result = {}
 
36
 
 
37
        for record in records:
 
38
            # count the number of users
 
39
            result[record.id] = len(record.resource_ids)
 
40
        return result
 
41
 
 
42
    def _get_total_meters(self, cr, uid, ids, field_name, field_value, arg, context=None):
 
43
        records = self.browse(cr, uid, ids)
 
44
        result = {}
 
45
 
 
46
        for record in records:
 
47
            # count the number of users
 
48
            result[record.id] = len(record.meter_ids)
 
49
        return result
 
50
    
 
51
    _columns = {
 
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')
 
66
    }
 
67
 
 
68
    _defaults = {
 
69
        'active':True
 
70
    }
 
71
    
 
72
    _order = "name asc"
 
73
 
 
74
    # establish a connection to ceilometer client and returns it
 
75
    def _get_ceilometer_client(self, account):
 
76
        try:
 
77
            ks_client = ksclient.Client(username=account["username"], password=account["password"], tenant_name=account["tenant"], auth_url=account["url"])
 
78
 
 
79
            if ks_client and ks_client.auth_token:
 
80
                # api client
 
81
                endpoint = ks_client.service_catalog.url_for(service_type=self._endpoint_type, endpoint_type=self._endpoint_url)
 
82
 
 
83
                ceilometer_client = ceilometerclient.Client(self._api_version, endpoint=endpoint, token=ks_client.auth_token)
 
84
                return ceilometer_client
 
85
 
 
86
            return False
 
87
        except Exception, e:
 
88
            return False
 
89
 
 
90
 
 
91
    def action_test_connection(self, cursor, user, ids, context=None):
 
92
        """
 
93
        checks Ceilometer credentials and confirms if outgoing connection works
 
94
        """
 
95
        if type(ids)==list:
 
96
            ids = ids[0]
 
97
 
 
98
        account = self.browse(cursor, user, ids, context)
 
99
 
 
100
        if not account:
 
101
            raise openerp.exceptions.Warning("Subscription for the given ID does not exist")
 
102
 
 
103
        # test ceilometer client
 
104
        ceil_client = self._get_ceilometer_client(account)
 
105
        if not ceil_client:
 
106
            raise openerp.exceptions.Warning("Ceilometer connection not properly configured. Please check your credentials")
 
107
 
 
108
        raise openerp.exceptions.Warning("Ceilomer account successfully configured")            
 
109
        return True
 
110
 
 
111
    def sync_users(self, cr, uid, ceil_client, subscription_details, context=None):
 
112
        try:
 
113
            obj_user = self.pool.get("ceilometer.user")
 
114
 
 
115
            # get users from api
 
116
            api_users = []
 
117
            users = ceil_client.users.list()
 
118
            for user in users:
 
119
                api_users.append(user.user_id)
 
120
 
 
121
            model_users = []
 
122
            for existing_user in subscription_details.user_ids:
 
123
 
 
124
                if (existing_user.name not in api_users): 
 
125
                    # remove that user
 
126
                    obj_user.unlink(cr, uid, existing_user.id)
 
127
                else:
 
128
                    model_users.append(existing_user.name)
 
129
 
 
130
            # check api user against db user
 
131
            for api_user in api_users:
 
132
                if (api_user not in model_users):
 
133
                    # create new user
 
134
                    new_user = {
 
135
                        'name': api_user,
 
136
                        'subscription_id': subscription_details.id,
 
137
                    }
 
138
                    user_id = obj_user.create(cr, uid, new_user, context=context)
 
139
 
 
140
            cr.commit()
 
141
            return True
 
142
        except Exception, e:
 
143
            print e
 
144
            return False
 
145
 
 
146
    def sync_projects(self, cr, uid, ceil_client, subscription_details, context=None):
 
147
        try:
 
148
            obj_project = self.pool.get("ceilometer.project")
 
149
 
 
150
            # get projects from api
 
151
            api_projects = []
 
152
            projects = ceil_client.projects.list()
 
153
            for project in projects:
 
154
                api_projects.append(project.project_id)
 
155
 
 
156
            model_projects = []
 
157
            for existing_project in subscription_details.project_ids:
 
158
 
 
159
                if (existing_project.name not in api_projects): 
 
160
                    # remove that project
 
161
                    obj_project.unlink(cr, uid, existing_project.id)
 
162
                else:
 
163
                    model_projects.append(existing_project.name)
 
164
 
 
165
            # check api project against db project
 
166
            for api_project in api_projects:
 
167
                if (api_project not in model_projects):
 
168
                    # create new project
 
169
                    new_project = {
 
170
                        'name': api_project,
 
171
                        'subscription_id': subscription_details.id,
 
172
                    }
 
173
                    project_id = obj_project.create(cr, uid, new_project, context=context)
 
174
 
 
175
            cr.commit()
 
176
            return True
 
177
        except Exception, e:
 
178
            print e
 
179
            return False
 
180
 
 
181
    def sync_resources(self, cr, uid, ceil_client, subscription_details, context=None):
 
182
        try:
 
183
            obj_resource = self.pool.get("ceilometer.resource")
 
184
 
 
185
            # get resources from api
 
186
            api_resources = []
 
187
            resources = ceil_client.resources.list()
 
188
            for resource in resources:
 
189
                api_resources.append(resource.resource_id)
 
190
 
 
191
            model_resources = []
 
192
            for existing_resource in subscription_details.resource_ids:
 
193
 
 
194
                if (existing_resource.name not in api_resources): 
 
195
                    # remove that resource
 
196
                    obj_resource.unlink(cr, uid, existing_resource.id)
 
197
                else:
 
198
                    model_resources.append(existing_resource.name)
 
199
 
 
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
 
204
                    new_resource = {
 
205
                        'name': api_resource,
 
206
                        'subscription_id': subscription_details.id,
 
207
                    }
 
208
                    resource_id = obj_resource.create(cr, uid, new_resource, context=context)
 
209
 
 
210
            cr.commit()
 
211
            return True
 
212
        except Exception, e:
 
213
            print e
 
214
            return False
 
215
 
 
216
    def search_project(self, cr, uid, project_id, context=None):
 
217
        existing_project = None
 
218
 
 
219
        if project_id:
 
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 
 
226
 
 
227
        return existing_project
 
228
 
 
229
    def search_user(self, cr, uid, user_id, context=None):
 
230
        existing_user = None
 
231
 
 
232
        if user_id:
 
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 
 
239
 
 
240
        return existing_user
 
241
 
 
242
    def search_resource(self, cr, uid, resource_id, context=None):
 
243
        existing_resource = None
 
244
 
 
245
        if resource_id:
 
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 
 
252
 
 
253
        return existing_resource
 
254
 
 
255
    def sync_meters(self, cr, uid, ceil_client, subscription_details, context=None):
 
256
        try:
 
257
            obj_meter = self.pool.get("ceilometer.meter")
 
258
 
 
259
            # get meters from api
 
260
            api_meters = []
 
261
            api_meter_details = []
 
262
 
 
263
            meters = ceil_client.meters.list()
 
264
            for meter in meters:
 
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)
 
268
 
 
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)
 
272
 
 
273
            model_meters = []
 
274
            for existing_meter in subscription_details.meter_ids:
 
275
                if (existing_meter.signature not in api_meters): 
 
276
                    # remove that meter
 
277
                    obj_meter.unlink(cr, uid, existing_meter.id)
 
278
                else:
 
279
                    model_meters.append(existing_meter.signature)
 
280
 
 
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)
 
288
 
 
289
                    # create new meter
 
290
                    new_meter = {
 
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"]
 
298
                    }
 
299
                    meter_id = obj_meter.create(cr, uid, new_meter, context=context)
 
300
 
 
301
            cr.commit()
 
302
            return True
 
303
        except Exception, e:
 
304
            print e
 
305
            return False
 
306
 
 
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)
 
312
            if ceil_client:
 
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)
 
318
 
 
319
    def sync_subscriptions(self, cr, uid, ids, context=None):
 
320
        # if no ids are passed, read all
 
321
        if not ids:
 
322
            ids = self.search(cr, uid, [('active','=',True)])
 
323
 
 
324
        for subscription_id in ids:
 
325
            print "sync "+subscription_id
 
326
            self.sync_subscription(cr, uid, subscription_id, context)
 
327
 
 
328
        raise openerp.exceptions.Warning("Ceilometer sync finished")
 
329
 
 
330
ceilometer_subscription()
 
331
 
 
332