~soren/nova/lp658257

« back to all changes in this revision

Viewing changes to nova/db/sqlalchemy/models.py

  • Committer: Tarmac
  • Author(s): Devin Carlen
  • Date: 2010-10-01 15:08:19 UTC
  • mfrom: (306.2.15 contextual-authorization)
  • Revision ID: hudson@openstack.org-20101001150819-l0z698ahfd1srmcf
Refactor sqlalchemy api to perform contextual authorization.

All database calls now examine the context object for information about what kind of user is accessing the data.  If an administrator is accessing, full privileges are granted.  If a normal user is accessing, then checks are made to ensure that the user does indeed have the rights to the data.

Also refactored NovaBase and removed several methods since they would have to be changed when we move away from sqlalchemy models and begin using sqlalchemy table definitions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
50
50
    deleted_at = Column(DateTime)
51
51
    deleted = Column(Boolean, default=False)
52
52
 
53
 
    @classmethod
54
 
    def all(cls, session=None, deleted=False):
55
 
        """Get all objects of this type"""
56
 
        if not session:
57
 
            session = get_session()
58
 
        return session.query(cls
59
 
                     ).filter_by(deleted=deleted
60
 
                     ).all()
61
 
 
62
 
    @classmethod
63
 
    def count(cls, session=None, deleted=False):
64
 
        """Count objects of this type"""
65
 
        if not session:
66
 
            session = get_session()
67
 
        return session.query(cls
68
 
                     ).filter_by(deleted=deleted
69
 
                     ).count()
70
 
 
71
 
    @classmethod
72
 
    def find(cls, obj_id, session=None, deleted=False):
73
 
        """Find object by id"""
74
 
        if not session:
75
 
            session = get_session()
76
 
        try:
77
 
            return session.query(cls
78
 
                         ).filter_by(id=obj_id
79
 
                         ).filter_by(deleted=deleted
80
 
                         ).one()
81
 
        except exc.NoResultFound:
82
 
            new_exc = exception.NotFound("No model for id %s" % obj_id)
83
 
            raise new_exc.__class__, new_exc, sys.exc_info()[2]
84
 
 
85
 
    @classmethod
86
 
    def find_by_str(cls, str_id, session=None, deleted=False):
87
 
        """Find object by str_id"""
88
 
        int_id = int(str_id.rpartition('-')[2])
89
 
        return cls.find(int_id, session=session, deleted=deleted)
90
 
 
91
53
    @property
92
54
    def str_id(self):
93
55
        """Get string id of object (generally prefix + '-' + id)"""
176
138
    report_count = Column(Integer, nullable=False, default=0)
177
139
    disabled = Column(Boolean, default=False)
178
140
 
179
 
    @classmethod
180
 
    def find_by_args(cls, host, binary, session=None, deleted=False):
181
 
        if not session:
182
 
            session = get_session()
183
 
        try:
184
 
            return session.query(cls
185
 
                         ).filter_by(host=host
186
 
                         ).filter_by(binary=binary
187
 
                         ).filter_by(deleted=deleted
188
 
                         ).one()
189
 
        except exc.NoResultFound:
190
 
            new_exc = exception.NotFound("No model for %s, %s" % (host,
191
 
                                                              binary))
192
 
            raise new_exc.__class__, new_exc, sys.exc_info()[2]
193
 
 
194
141
 
195
142
class Instance(BASE, NovaBase):
196
143
    """Represents a guest vm"""
284
231
    size = Column(Integer)
285
232
    availability_zone = Column(String(255))  # TODO(vish): foreign key?
286
233
    instance_id = Column(Integer, ForeignKey('instances.id'), nullable=True)
287
 
    instance = relationship(Instance, backref=backref('volumes'))
 
234
    instance = relationship(Instance,
 
235
                            backref=backref('volumes'),
 
236
                            foreign_keys=instance_id,
 
237
                            primaryjoin='and_(Volume.instance_id==Instance.id,'
 
238
                                             'Volume.deleted==False)')
288
239
    mountpoint = Column(String(255))
289
240
    attach_time = Column(String(255))  # TODO(vish): datetime
290
241
    status = Column(String(255))  # TODO(vish): enum?
315
266
    def str_id(self):
316
267
        return self.project_id
317
268
 
318
 
    @classmethod
319
 
    def find_by_str(cls, str_id, session=None, deleted=False):
320
 
        if not session:
321
 
            session = get_session()
322
 
        try:
323
 
            return session.query(cls
324
 
                         ).filter_by(project_id=str_id
325
 
                         ).filter_by(deleted=deleted
326
 
                         ).one()
327
 
        except exc.NoResultFound:
328
 
            new_exc = exception.NotFound("No model for project_id %s" % str_id)
329
 
            raise new_exc.__class__, new_exc, sys.exc_info()[2]
330
269
 
331
270
class ExportDevice(BASE, NovaBase):
332
271
    """Represates a shelf and blade that a volume can be exported on"""
335
274
    shelf_id = Column(Integer)
336
275
    blade_id = Column(Integer)
337
276
    volume_id = Column(Integer, ForeignKey('volumes.id'), nullable=True)
338
 
    volume = relationship(Volume, backref=backref('export_device',
339
 
                                                  uselist=False))
 
277
    volume = relationship(Volume,
 
278
                          backref=backref('export_device', uselist=False),
 
279
                          foreign_keys=volume_id,
 
280
                          primaryjoin='and_(ExportDevice.volume_id==Volume.id,'
 
281
                                           'ExportDevice.deleted==False)')
340
282
 
341
283
 
342
284
class KeyPair(BASE, NovaBase):
354
296
    def str_id(self):
355
297
        return '%s.%s' % (self.user_id, self.name)
356
298
 
357
 
    @classmethod
358
 
    def find_by_str(cls, str_id, session=None, deleted=False):
359
 
        user_id, _sep, name = str_id.partition('.')
360
 
        return cls.find_by_str(user_id, name, session, deleted)
361
 
 
362
 
    @classmethod
363
 
    def find_by_args(cls, user_id, name, session=None, deleted=False):
364
 
        if not session:
365
 
            session = get_session()
366
 
        try:
367
 
            return session.query(cls
368
 
                         ).filter_by(user_id=user_id
369
 
                         ).filter_by(name=name
370
 
                         ).filter_by(deleted=deleted
371
 
                         ).one()
372
 
        except exc.NoResultFound:
373
 
            new_exc = exception.NotFound("No model for user %s, name %s" %
374
 
                                         (user_id, name))
375
 
            raise new_exc.__class__, new_exc, sys.exc_info()[2]
376
 
 
377
299
 
378
300
class Network(BASE, NovaBase):
379
301
    """Represents a network"""
409
331
    id = Column(Integer, primary_key=True)
410
332
    index = Column(Integer, unique=True)
411
333
    network_id = Column(Integer, ForeignKey('networks.id'), nullable=True)
412
 
    network = relationship(Network, backref=backref('network_index',
413
 
                                                    uselist=False))
 
334
    network = relationship(Network,
 
335
                           backref=backref('network_index', uselist=False),
 
336
                           foreign_keys=network_id,
 
337
                           primaryjoin='and_(NetworkIndex.network_id==Network.id,'
 
338
                                            'NetworkIndex.deleted==False)')
 
339
 
414
340
 
415
341
class AuthToken(BASE, NovaBase):
416
342
    """Represents an authorization token for all API transactions. Fields
434
360
    network_id = Column(Integer, ForeignKey('networks.id'), nullable=True)
435
361
    network = relationship(Network, backref=backref('fixed_ips'))
436
362
    instance_id = Column(Integer, ForeignKey('instances.id'), nullable=True)
437
 
    instance = relationship(Instance, backref=backref('fixed_ip',
438
 
                                                      uselist=False))
 
363
    instance = relationship(Instance,
 
364
                            backref=backref('fixed_ip', uselist=False),
 
365
                            foreign_keys=instance_id,
 
366
                            primaryjoin='and_(FixedIp.instance_id==Instance.id,'
 
367
                                             'FixedIp.deleted==False)')
439
368
    allocated = Column(Boolean, default=False)
440
369
    leased = Column(Boolean, default=False)
441
370
    reserved = Column(Boolean, default=False)
444
373
    def str_id(self):
445
374
        return self.address
446
375
 
447
 
    @classmethod
448
 
    def find_by_str(cls, str_id, session=None, deleted=False):
449
 
        if not session:
450
 
            session = get_session()
451
 
        try:
452
 
            return session.query(cls
453
 
                         ).filter_by(address=str_id
454
 
                         ).filter_by(deleted=deleted
455
 
                         ).one()
456
 
        except exc.NoResultFound:
457
 
            new_exc = exception.NotFound("No model for address %s" % str_id)
458
 
            raise new_exc.__class__, new_exc, sys.exc_info()[2]
459
 
 
460
376
 
461
377
class FloatingIp(BASE, NovaBase):
462
378
    """Represents a floating ip that dynamically forwards to a fixed ip"""
464
380
    id = Column(Integer, primary_key=True)
465
381
    address = Column(String(255))
466
382
    fixed_ip_id = Column(Integer, ForeignKey('fixed_ips.id'), nullable=True)
467
 
    fixed_ip = relationship(FixedIp, backref=backref('floating_ips'))
468
 
 
 
383
    fixed_ip = relationship(FixedIp,
 
384
                            backref=backref('floating_ips'),
 
385
                            foreign_keys=fixed_ip_id,
 
386
                            primaryjoin='and_(FloatingIp.fixed_ip_id==FixedIp.id,'
 
387
                                             'FloatingIp.deleted==False)')
469
388
    project_id = Column(String(255))
470
389
    host = Column(String(255))  # , ForeignKey('hosts.id'))
471
390
 
472
 
    @classmethod
473
 
    def find_by_str(cls, str_id, session=None, deleted=False):
474
 
        if not session:
475
 
            session = get_session()
476
 
        try:
477
 
            return session.query(cls
478
 
                         ).filter_by(address=str_id
479
 
                         ).filter_by(deleted=deleted
480
 
                         ).one()
481
 
        except exc.NoResultFound:
482
 
            new_exc = exception.NotFound("No model for address %s" % str_id)
483
 
            raise new_exc.__class__, new_exc, sys.exc_info()[2]
484
 
 
485
391
 
486
392
def register_models():
487
393
    """Register Models and create metadata"""