diff options
| author | Vishvananda Ishaya <vishvananda@yahoo.com> | 2010-10-12 19:00:34 -0700 |
|---|---|---|
| committer | Vishvananda Ishaya <vishvananda@yahoo.com> | 2010-10-12 19:00:34 -0700 |
| commit | dbbdebbcd13b08ec2afb6d0d58144eeee6ecce84 (patch) | |
| tree | 2e458dec12a89fcf5497367486f4288f87a06883 /nova/db | |
| parent | 6cc81214b58972c0d0e815ad340c32862be834dc (diff) | |
| parent | d0a55238fdf64a8da51ea1fe328a1a3dc3d17dc7 (diff) | |
| download | nova-dbbdebbcd13b08ec2afb6d0d58144eeee6ecce84.tar.gz nova-dbbdebbcd13b08ec2afb6d0d58144eeee6ecce84.tar.xz nova-dbbdebbcd13b08ec2afb6d0d58144eeee6ecce84.zip | |
merged trunk
Diffstat (limited to 'nova/db')
| -rw-r--r-- | nova/db/api.py | 199 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/api.py | 439 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/models.py | 139 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/session.py | 9 |
4 files changed, 757 insertions, 29 deletions
diff --git a/nova/db/api.py b/nova/db/api.py index a9f34ef04..a655e6a8a 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -280,9 +280,9 @@ def instance_get_floating_address(context, instance_id): return IMPL.instance_get_floating_address(context, instance_id) -def instance_get_by_ec2_id(context, ec2_id): +def instance_get_by_internal_id(context, internal_id): """Get an instance by ec2 id.""" - return IMPL.instance_get_by_ec2_id(context, ec2_id) + return IMPL.instance_get_by_internal_id(context, internal_id) def instance_is_vpn(context, instance_id): @@ -304,6 +304,11 @@ def instance_update(context, instance_id, values): return IMPL.instance_update(context, instance_id, values) +def instance_add_security_group(context, instance_id, security_group_id): + """Associate the given security group with the given instance""" + return IMPL.instance_add_security_group(context, instance_id, security_group_id) + + ################### @@ -437,7 +442,11 @@ def network_update(context, network_id, values): def project_get_network(context, project_id): - """Return the network associated with the project.""" + """Return the network associated with the project. + + Raises NotFound if no such network can be found. + + """ return IMPL.project_get_network(context, project_id) @@ -570,3 +579,187 @@ def volume_update(context, volume_id, values): """ return IMPL.volume_update(context, volume_id, values) + + +#################### + + +def security_group_get_all(context): + """Get all security groups""" + return IMPL.security_group_get_all(context) + + +def security_group_get(context, security_group_id): + """Get security group by its internal id""" + return IMPL.security_group_get(context, security_group_id) + + +def security_group_get_by_name(context, project_id, group_name): + """Returns a security group with the specified name from a project""" + return IMPL.security_group_get_by_name(context, project_id, group_name) + + +def security_group_get_by_project(context, project_id): + """Get all security groups belonging to a project""" + return IMPL.security_group_get_by_project(context, project_id) + + +def security_group_get_by_instance(context, instance_id): + """Get security groups to which the instance is assigned""" + return IMPL.security_group_get_by_instance(context, instance_id) + + +def security_group_exists(context, project_id, group_name): + """Indicates if a group name exists in a project""" + return IMPL.security_group_exists(context, project_id, group_name) + + +def security_group_create(context, values): + """Create a new security group""" + return IMPL.security_group_create(context, values) + + +def security_group_destroy(context, security_group_id): + """Deletes a security group""" + return IMPL.security_group_destroy(context, security_group_id) + + +def security_group_destroy_all(context): + """Deletes a security group""" + return IMPL.security_group_destroy_all(context) + + +#################### + + +def security_group_rule_create(context, values): + """Create a new security group""" + return IMPL.security_group_rule_create(context, values) + + +def security_group_rule_get_by_security_group(context, security_group_id): + """Get all rules for a a given security group""" + return IMPL.security_group_rule_get_by_security_group(context, security_group_id) + +def security_group_rule_destroy(context, security_group_rule_id): + """Deletes a security group rule""" + return IMPL.security_group_rule_destroy(context, security_group_rule_id) + + +################### + + +def user_get(context, id): + """Get user by id""" + return IMPL.user_get(context, id) + + +def user_get_by_uid(context, uid): + """Get user by uid""" + return IMPL.user_get_by_uid(context, uid) + + +def user_get_by_access_key(context, access_key): + """Get user by access key""" + return IMPL.user_get_by_access_key(context, access_key) + + +def user_create(context, values): + """Create a new user""" + return IMPL.user_create(context, values) + + +def user_delete(context, id): + """Delete a user""" + return IMPL.user_delete(context, id) + + +def user_get_all(context): + """Create a new user""" + return IMPL.user_get_all(context) + + +def user_add_role(context, user_id, role): + """Add another global role for user""" + return IMPL.user_add_role(context, user_id, role) + + +def user_remove_role(context, user_id, role): + """Remove global role from user""" + return IMPL.user_remove_role(context, user_id, role) + + +def user_get_roles(context, user_id): + """Get global roles for user""" + return IMPL.user_get_roles(context, user_id) + + +def user_add_project_role(context, user_id, project_id, role): + """Add project role for user""" + return IMPL.user_add_project_role(context, user_id, project_id, role) + + +def user_remove_project_role(context, user_id, project_id, role): + """Remove project role from user""" + return IMPL.user_remove_project_role(context, user_id, project_id, role) + + +def user_get_roles_for_project(context, user_id, project_id): + """Return list of roles a user holds on project""" + return IMPL.user_get_roles_for_project(context, user_id, project_id) + + +def user_update(context, user_id, values): + """Update user""" + return IMPL.user_update(context, user_id, values) + + +def project_get(context, id): + """Get project by id""" + return IMPL.project_get(context, id) + + +def project_create(context, values): + """Create a new project""" + return IMPL.project_create(context, values) + + +def project_add_member(context, project_id, user_id): + """Add user to project""" + return IMPL.project_add_member(context, project_id, user_id) + + +def project_get_all(context): + """Get all projects""" + return IMPL.project_get_all(context) + + +def project_get_by_user(context, user_id): + """Get all projects of which the given user is a member""" + return IMPL.project_get_by_user(context, user_id) + + +def project_remove_member(context, project_id, user_id): + """Remove the given user from the given project""" + return IMPL.project_remove_member(context, project_id, user_id) + + +def project_update(context, project_id, values): + """Update Remove the given user from the given project""" + return IMPL.project_update(context, project_id, values) + + +def project_delete(context, project_id): + """Delete project""" + return IMPL.project_delete(context, project_id) + + +################### + + +def host_get_networks(context, host): + """Return all networks for which the given host is the designated + network host + """ + return IMPL.host_get_networks(context, host) + diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 6868eb176..14714d4b1 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -29,8 +29,11 @@ from nova.db.sqlalchemy import models from nova.db.sqlalchemy.session import get_session from sqlalchemy import or_ from sqlalchemy.exc import IntegrityError -from sqlalchemy.orm import joinedload, joinedload_all -from sqlalchemy.sql import exists, func +from sqlalchemy.orm import joinedload +from sqlalchemy.orm import joinedload_all +from sqlalchemy.sql import exists +from sqlalchemy.sql import func +from sqlalchemy.orm.exc import NoResultFound FLAGS = flags.FLAGS @@ -240,7 +243,7 @@ def service_create(context, values): def service_update(context, service_id, values): session = get_session() with session.begin(): - service_ref = session_get(context, service_id, session=session) + service_ref = service_get(context, service_id, session=session) for (key, value) in values.iteritems(): service_ref[key] = value service_ref.save(session=session) @@ -450,7 +453,6 @@ def fixed_ip_create(_context, values): fixed_ip_ref.save() return fixed_ip_ref['address'] - @require_context def fixed_ip_disassociate(context, address): session = get_session() @@ -461,7 +463,6 @@ def fixed_ip_disassociate(context, address): fixed_ip_ref.instance = None fixed_ip_ref.save(session=session) - @require_admin_context def fixed_ip_disassociate_all_by_timeout(_context, host, time): session = get_session() @@ -525,6 +526,9 @@ def fixed_ip_update(context, address, values): ################### +#TODO(gundlach): instance_create and volume_create are nearly identical +#and should be refactored. I expect there are other copy-and-paste +#functions between the two of them as well. @require_context def instance_create(context, values): instance_ref = models.Instance() @@ -533,10 +537,11 @@ def instance_create(context, values): session = get_session() with session.begin(): - while instance_ref.ec2_id == None: - ec2_id = utils.generate_uid(instance_ref.__prefix__) - if not instance_ec2_id_exists(context, ec2_id, session=session): - instance_ref.ec2_id = ec2_id + while instance_ref.internal_id == None: + internal_id = utils.generate_uid(instance_ref.__prefix__) + if not instance_internal_id_exists(context, internal_id, + session=session): + instance_ref.internal_id = internal_id instance_ref.save(session=session) return instance_ref @@ -569,11 +574,13 @@ def instance_get(context, instance_id, session=None): if is_admin_context(context): result = session.query(models.Instance + ).options(joinedload('security_groups') ).filter_by(id=instance_id ).filter_by(deleted=can_read_deleted(context) ).first() elif is_user_context(context): result = session.query(models.Instance + ).options(joinedload('security_groups') ).filter_by(project_id=context.project.id ).filter_by(id=instance_id ).filter_by(deleted=False @@ -589,6 +596,7 @@ def instance_get_all(context): session = get_session() return session.query(models.Instance ).options(joinedload_all('fixed_ip.floating_ips') + ).options(joinedload('security_groups') ).filter_by(deleted=can_read_deleted(context) ).all() @@ -598,6 +606,7 @@ def instance_get_all_by_user(context, user_id): session = get_session() return session.query(models.Instance ).options(joinedload_all('fixed_ip.floating_ips') + ).options(joinedload('security_groups') ).filter_by(deleted=can_read_deleted(context) ).filter_by(user_id=user_id ).all() @@ -610,6 +619,7 @@ def instance_get_all_by_project(context, project_id): session = get_session() return session.query(models.Instance ).options(joinedload_all('fixed_ip.floating_ips') + ).options(joinedload('security_groups') ).filter_by(project_id=project_id ).filter_by(deleted=can_read_deleted(context) ).all() @@ -622,12 +632,14 @@ def instance_get_all_by_reservation(context, reservation_id): if is_admin_context(context): return session.query(models.Instance ).options(joinedload_all('fixed_ip.floating_ips') + ).options(joinedload('security_groups') ).filter_by(reservation_id=reservation_id ).filter_by(deleted=can_read_deleted(context) ).all() elif is_user_context(context): return session.query(models.Instance ).options(joinedload_all('fixed_ip.floating_ips') + ).options(joinedload('security_groups') ).filter_by(project_id=context.project.id ).filter_by(reservation_id=reservation_id ).filter_by(deleted=False @@ -635,31 +647,35 @@ def instance_get_all_by_reservation(context, reservation_id): @require_context -def instance_get_by_ec2_id(context, ec2_id): +def instance_get_by_internal_id(context, internal_id): session = get_session() if is_admin_context(context): result = session.query(models.Instance - ).filter_by(ec2_id=ec2_id + ).options(joinedload('security_groups') + ).filter_by(internal_id=internal_id ).filter_by(deleted=can_read_deleted(context) ).first() elif is_user_context(context): result = session.query(models.Instance + ).options(joinedload('security_groups') ).filter_by(project_id=context.project.id - ).filter_by(ec2_id=ec2_id + ).filter_by(internal_id=internal_id ).filter_by(deleted=False ).first() if not result: - raise exception.NotFound('Instance %s not found' % (ec2_id)) + raise exception.NotFound('Instance %s not found' % (internal_id)) return result @require_context -def instance_ec2_id_exists(context, ec2_id, session=None): +def instance_internal_id_exists(context, internal_id, session=None): if not session: session = get_session() - return session.query(exists().where(models.Instance.id==ec2_id)).one()[0] + return session.query( + exists().where(models.Instance.internal_id==internal_id) + ).one()[0] @require_context @@ -714,6 +730,18 @@ def instance_update(context, instance_id, values): instance_ref.save(session=session) +def instance_add_security_group(context, instance_id, security_group_id): + """Associate the given security group with the given instance""" + session = get_session() + with session.begin(): + instance_ref = instance_get(context, instance_id, session=session) + security_group_ref = security_group_get(context, + security_group_id, + session=session) + instance_ref.security_groups += [security_group_ref] + instance_ref.save(session=session) + + ################### @@ -1181,6 +1209,7 @@ def volume_get(context, volume_id, session=None): @require_admin_context def volume_get_all(context): + session = get_session() return session.query(models.Volume ).filter_by(deleted=can_read_deleted(context) ).all() @@ -1266,3 +1295,383 @@ def volume_update(context, volume_id, values): for (key, value) in values.iteritems(): volume_ref[key] = value volume_ref.save(session=session) + + +################### + + +@require_context +def security_group_get_all(context): + session = get_session() + return session.query(models.SecurityGroup + ).filter_by(deleted=can_read_deleted(context) + ).options(joinedload_all('rules') + ).all() + + +@require_context +def security_group_get(context, security_group_id, session=None): + if not session: + session = get_session() + if is_admin_context(context): + result = session.query(models.SecurityGroup + ).filter_by(deleted=can_read_deleted(context), + ).filter_by(id=security_group_id + ).options(joinedload_all('rules') + ).first() + else: + result = session.query(models.SecurityGroup + ).filter_by(deleted=False + ).filter_by(id=security_group_id + ).filter_by(project_id=context.project_id + ).options(joinedload_all('rules') + ).first() + if not result: + raise exception.NotFound("No secuity group with id %s" % + security_group_id) + return result + + +@require_context +def security_group_get_by_name(context, project_id, group_name): + session = get_session() + result = session.query(models.SecurityGroup + ).filter_by(project_id=project_id + ).filter_by(name=group_name + ).filter_by(deleted=False + ).options(joinedload_all('rules') + ).options(joinedload_all('instances') + ).first() + if not result: + raise exception.NotFound( + 'No security group named %s for project: %s' \ + % (group_name, project_id)) + return result + + +@require_context +def security_group_get_by_project(context, project_id): + session = get_session() + return session.query(models.SecurityGroup + ).filter_by(project_id=project_id + ).filter_by(deleted=False + ).options(joinedload_all('rules') + ).all() + + +@require_context +def security_group_get_by_instance(context, instance_id): + session = get_session() + return session.query(models.SecurityGroup + ).filter_by(deleted=False + ).options(joinedload_all('rules') + ).join(models.SecurityGroup.instances + ).filter_by(id=instance_id + ).filter_by(deleted=False + ).all() + + +@require_context +def security_group_exists(context, project_id, group_name): + try: + group = security_group_get_by_name(context, project_id, group_name) + return group != None + except exception.NotFound: + return False + + +@require_context +def security_group_create(context, values): + security_group_ref = models.SecurityGroup() + # FIXME(devcamcar): Unless I do this, rules fails with lazy load exception + # once save() is called. This will get cleaned up in next orm pass. + security_group_ref.rules + for (key, value) in values.iteritems(): + security_group_ref[key] = value + security_group_ref.save() + return security_group_ref + + +@require_context +def security_group_destroy(context, security_group_id): + session = get_session() + with session.begin(): + # TODO(vish): do we have to use sql here? + session.execute('update security_groups set deleted=1 where id=:id', + {'id': security_group_id}) + session.execute('update security_group_rules set deleted=1 ' + 'where group_id=:id', + {'id': security_group_id}) + +@require_context +def security_group_destroy_all(context, session=None): + if not session: + session = get_session() + with session.begin(): + # TODO(vish): do we have to use sql here? + session.execute('update security_groups set deleted=1') + session.execute('update security_group_rules set deleted=1') + + +################### + + +@require_context +def security_group_rule_get(context, security_group_rule_id, session=None): + if not session: + session = get_session() + if is_admin_context(context): + result = session.query(models.SecurityGroupIngressRule + ).filter_by(deleted=can_read_deleted(context) + ).filter_by(id=security_group_rule_id + ).first() + else: + # TODO(vish): Join to group and check for project_id + result = session.query(models.SecurityGroupIngressRule + ).filter_by(deleted=False + ).filter_by(id=security_group_rule_id + ).first() + if not result: + raise exception.NotFound("No secuity group rule with id %s" % + security_group_rule_id) + return result + + +@require_context +def security_group_rule_create(context, values): + security_group_rule_ref = models.SecurityGroupIngressRule() + for (key, value) in values.iteritems(): + security_group_rule_ref[key] = value + security_group_rule_ref.save() + return security_group_rule_ref + +@require_context +def security_group_rule_destroy(context, security_group_rule_id): + session = get_session() + with session.begin(): + security_group_rule = security_group_rule_get(context, + security_group_rule_id, + session=session) + security_group_rule.delete(session=session) + + +################### + +@require_admin_context +def user_get(context, id, session=None): + if not session: + session = get_session() + + result = session.query(models.User + ).filter_by(id=id + ).filter_by(deleted=can_read_deleted(context) + ).first() + + if not result: + raise exception.NotFound('No user for id %s' % id) + + return result + + +@require_admin_context +def user_get_by_access_key(context, access_key, session=None): + if not session: + session = get_session() + + result = session.query(models.User + ).filter_by(access_key=access_key + ).filter_by(deleted=can_read_deleted(context) + ).first() + + if not result: + raise exception.NotFound('No user for id %s' % id) + + return result + + +@require_admin_context +def user_create(_context, values): + user_ref = models.User() + for (key, value) in values.iteritems(): + user_ref[key] = value + user_ref.save() + return user_ref + + +@require_admin_context +def user_delete(context, id): + session = get_session() + with session.begin(): + session.execute('delete from user_project_association where user_id=:id', + {'id': id}) + session.execute('delete from user_role_association where user_id=:id', + {'id': id}) + session.execute('delete from user_project_role_association where user_id=:id', + {'id': id}) + user_ref = user_get(context, id, session=session) + session.delete(user_ref) + + +def user_get_all(context): + session = get_session() + return session.query(models.User + ).filter_by(deleted=can_read_deleted(context) + ).all() + + +def project_create(_context, values): + project_ref = models.Project() + for (key, value) in values.iteritems(): + project_ref[key] = value + project_ref.save() + return project_ref + + +def project_add_member(context, project_id, user_id): + session = get_session() + with session.begin(): + project_ref = project_get(context, project_id, session=session) + user_ref = user_get(context, user_id, session=session) + + project_ref.members += [user_ref] + project_ref.save(session=session) + + +def project_get(context, id, session=None): + if not session: + session = get_session() + + result = session.query(models.Project + ).filter_by(deleted=False + ).filter_by(id=id + ).options(joinedload_all('members') + ).first() + + if not result: + raise exception.NotFound("No project with id %s" % id) + + return result + + +def project_get_all(context): + session = get_session() + return session.query(models.Project + ).filter_by(deleted=can_read_deleted(context) + ).options(joinedload_all('members') + ).all() + + +def project_get_by_user(context, user_id): + session = get_session() + user = session.query(models.User + ).filter_by(deleted=can_read_deleted(context) + ).options(joinedload_all('projects') + ).first() + return user.projects + + +def project_remove_member(context, project_id, user_id): + session = get_session() + project = project_get(context, project_id, session=session) + user = user_get(context, user_id, session=session) + + if user in project.members: + project.members.remove(user) + project.save(session=session) + + +def user_update(context, user_id, values): + session = get_session() + with session.begin(): + user_ref = user_get(context, user_id, session=session) + for (key, value) in values.iteritems(): + user_ref[key] = value + user_ref.save(session=session) + + +def project_update(context, project_id, values): + session = get_session() + with session.begin(): + project_ref = project_get(context, project_id, session=session) + for (key, value) in values.iteritems(): + project_ref[key] = value + project_ref.save(session=session) + + +def project_delete(context, id): + session = get_session() + with session.begin(): + session.execute('delete from user_project_association where project_id=:id', + {'id': id}) + session.execute('delete from user_project_role_association where project_id=:id', + {'id': id}) + project_ref = project_get(context, id, session=session) + session.delete(project_ref) + + +def user_get_roles(context, user_id): + session = get_session() + with session.begin(): + user_ref = user_get(context, user_id, session=session) + return [role.role for role in user_ref['roles']] + + +def user_get_roles_for_project(context, user_id, project_id): + session = get_session() + with session.begin(): + res = session.query(models.UserProjectRoleAssociation + ).filter_by(user_id=user_id + ).filter_by(project_id=project_id + ).all() + return [association.role for association in res] + +def user_remove_project_role(context, user_id, project_id, role): + session = get_session() + with session.begin(): + session.execute('delete from user_project_role_association where ' + \ + 'user_id=:user_id and project_id=:project_id and ' + \ + 'role=:role', { 'user_id' : user_id, + 'project_id' : project_id, + 'role' : role }) + + +def user_remove_role(context, user_id, role): + session = get_session() + with session.begin(): + res = session.query(models.UserRoleAssociation + ).filter_by(user_id=user_id + ).filter_by(role=role + ).all() + for role in res: + session.delete(role) + + +def user_add_role(context, user_id, role): + session = get_session() + with session.begin(): + user_ref = user_get(context, user_id, session=session) + models.UserRoleAssociation(user=user_ref, role=role).save(session=session) + + +def user_add_project_role(context, user_id, project_id, role): + session = get_session() + with session.begin(): + user_ref = user_get(context, user_id, session=session) + project_ref = project_get(context, project_id, session=session) + models.UserProjectRoleAssociation(user_id=user_ref['id'], + project_id=project_ref['id'], + role=role).save(session=session) + + +################### + + + +@require_admin_context +def host_get_networks(context, host): + session = get_session() + with session.begin(): + return session.query(models.Network + ).filter_by(deleted=False + ).filter_by(host=host + ).all() diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 6c64d553d..eed8f0578 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -27,7 +27,9 @@ import datetime from sqlalchemy.orm import relationship, backref, exc, object_mapper from sqlalchemy import Column, Integer, String, schema from sqlalchemy import ForeignKey, DateTime, Boolean, Text +from sqlalchemy.exc import IntegrityError from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.schema import ForeignKeyConstraint from nova.db.sqlalchemy.session import get_session @@ -60,7 +62,13 @@ class NovaBase(object): if not session: session = get_session() session.add(self) - session.flush() + try: + session.flush() + except IntegrityError, e: + if str(e).endswith('is not unique'): + raise exception.Duplicate(str(e)) + else: + raise def delete(self, session=None): """Delete this object""" @@ -144,7 +152,7 @@ class Instance(BASE, NovaBase): __tablename__ = 'instances' __prefix__ = 'i' id = Column(Integer, primary_key=True) - ec2_id = Column(String(10), unique=True) + internal_id = Column(Integer, unique=True) admin_pass = Column(String(255)) @@ -161,7 +169,7 @@ class Instance(BASE, NovaBase): @property def name(self): - return self.ec2_id + return "instance-%d" % self.internal_id image_id = Column(String(255)) kernel_id = Column(String(255)) @@ -179,7 +187,6 @@ class Instance(BASE, NovaBase): launch_index = Column(Integer) key_name = Column(String(255)) key_data = Column(Text) - security_group = Column(String(255)) state = Column(Integer) state_description = Column(String(255)) @@ -281,10 +288,66 @@ class ExportDevice(BASE, NovaBase): 'ExportDevice.deleted==False)') +class SecurityGroupInstanceAssociation(BASE, NovaBase): + __tablename__ = 'security_group_instance_association' + id = Column(Integer, primary_key=True) + security_group_id = Column(Integer, ForeignKey('security_groups.id')) + instance_id = Column(Integer, ForeignKey('instances.id')) + + +class SecurityGroup(BASE, NovaBase): + """Represents a security group""" + __tablename__ = 'security_groups' + id = Column(Integer, primary_key=True) + + name = Column(String(255)) + description = Column(String(255)) + user_id = Column(String(255)) + project_id = Column(String(255)) + + instances = relationship(Instance, + secondary="security_group_instance_association", + primaryjoin="and_(SecurityGroup.id == SecurityGroupInstanceAssociation.security_group_id," + "SecurityGroup.deleted == False)", + secondaryjoin="and_(SecurityGroupInstanceAssociation.instance_id == Instance.id," + "Instance.deleted == False)", + backref='security_groups') + + @property + def user(self): + return auth.manager.AuthManager().get_user(self.user_id) + + @property + def project(self): + return auth.manager.AuthManager().get_project(self.project_id) + + +class SecurityGroupIngressRule(BASE, NovaBase): + """Represents a rule in a security group""" + __tablename__ = 'security_group_rules' + id = Column(Integer, primary_key=True) + + parent_group_id = Column(Integer, ForeignKey('security_groups.id')) + parent_group = relationship("SecurityGroup", backref="rules", + foreign_keys=parent_group_id, + primaryjoin="and_(SecurityGroupIngressRule.parent_group_id == SecurityGroup.id," + "SecurityGroupIngressRule.deleted == False)") + + protocol = Column(String(5)) # "tcp", "udp", or "icmp" + from_port = Column(Integer) + to_port = Column(Integer) + cidr = Column(String(255)) + + # Note: This is not the parent SecurityGroup. It's SecurityGroup we're + # granting access for. + group_id = Column(Integer, ForeignKey('security_groups.id')) + + class KeyPair(BASE, NovaBase): """Represents a public key pair for ssh""" __tablename__ = 'key_pairs' id = Column(Integer, primary_key=True) + name = Column(String(255)) user_id = Column(String(255)) @@ -361,6 +424,67 @@ class FixedIp(BASE, NovaBase): return self.address +class User(BASE, NovaBase): + """Represents a user""" + __tablename__ = 'users' + id = Column(String(255), primary_key=True) + + name = Column(String(255)) + access_key = Column(String(255)) + secret_key = Column(String(255)) + + is_admin = Column(Boolean) + + +class Project(BASE, NovaBase): + """Represents a project""" + __tablename__ = 'projects' + id = Column(String(255), primary_key=True) + name = Column(String(255)) + description = Column(String(255)) + + project_manager = Column(String(255), ForeignKey(User.id)) + + members = relationship(User, + secondary='user_project_association', + backref='projects') + + +class UserProjectRoleAssociation(BASE, NovaBase): + __tablename__ = 'user_project_role_association' + user_id = Column(String(255), primary_key=True) + user = relationship(User, + primaryjoin=user_id==User.id, + foreign_keys=[User.id], + uselist=False) + + project_id = Column(String(255), primary_key=True) + project = relationship(Project, + primaryjoin=project_id==Project.id, + foreign_keys=[Project.id], + uselist=False) + + role = Column(String(255), primary_key=True) + ForeignKeyConstraint(['user_id', + 'project_id'], + ['user_project_association.user_id', + 'user_project_association.project_id']) + + +class UserRoleAssociation(BASE, NovaBase): + __tablename__ = 'user_role_association' + user_id = Column(String(255), ForeignKey('users.id'), primary_key=True) + user = relationship(User, backref='roles') + role = Column(String(255), primary_key=True) + + +class UserProjectAssociation(BASE, NovaBase): + __tablename__ = 'user_project_association' + user_id = Column(String(255), ForeignKey(User.id), primary_key=True) + project_id = Column(String(255), ForeignKey(Project.id), primary_key=True) + + + class FloatingIp(BASE, NovaBase): """Represents a floating ip that dynamically forwards to a fixed ip""" __tablename__ = 'floating_ips' @@ -379,9 +503,10 @@ class FloatingIp(BASE, NovaBase): def register_models(): """Register Models and create metadata""" from sqlalchemy import create_engine - models = (Service, Instance, Volume, ExportDevice, - FixedIp, FloatingIp, Network, - AuthToken) # , Image, Host) + models = (Service, Instance, Volume, ExportDevice, FixedIp, + FloatingIp, Network, SecurityGroup, + SecurityGroupIngressRule, SecurityGroupInstanceAssociation, + AuthToken, User, Project) # , Image, Host engine = create_engine(FLAGS.sql_connection, echo=False) for model in models: model.metadata.create_all(engine) diff --git a/nova/db/sqlalchemy/session.py b/nova/db/sqlalchemy/session.py index 69a205378..826754f6a 100644 --- a/nova/db/sqlalchemy/session.py +++ b/nova/db/sqlalchemy/session.py @@ -36,7 +36,8 @@ def get_session(autocommit=True, expire_on_commit=False): if not _MAKER: if not _ENGINE: _ENGINE = create_engine(FLAGS.sql_connection, echo=False) - _MAKER = sessionmaker(bind=_ENGINE, - autocommit=autocommit, - expire_on_commit=expire_on_commit) - return _MAKER() + _MAKER = (sessionmaker(bind=_ENGINE, + autocommit=autocommit, + expire_on_commit=expire_on_commit)) + session = _MAKER() + return session |
