diff options
| author | Jason Koelker <jason@koelker.net> | 2011-06-29 14:42:32 -0500 |
|---|---|---|
| committer | Jason Koelker <jason@koelker.net> | 2011-06-29 14:42:32 -0500 |
| commit | 4f3ef1a568caecb26b57c757316a3cdfda20cc31 (patch) | |
| tree | 39f602af3f7edf199cdee1bc1bbaa0a091bd9f03 /nova/db | |
| parent | 8e09478b8de752909f5937668b44d7f67d7719ed (diff) | |
| parent | 89756b879e7094876697a2380e56c26796d50878 (diff) | |
merge with trey
Diffstat (limited to 'nova/db')
| -rw-r--r-- | nova/db/api.py | 29 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/api.py | 161 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/migrate_repo/versions/028_add_instance_type_extra_specs.py | 67 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/migrate_repo/versions/029_multi_nic.py (renamed from nova/db/sqlalchemy/migrate_repo/versions/028_multi_nic.py) | 0 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/migrate_repo/versions/030_fk_fixed_ips_virtual_interface_id.py (renamed from nova/db/sqlalchemy/migrate_repo/versions/029_fk_fixed_ips_virtual_interface_id.py) | 0 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/migrate_repo/versions/030_sqlite_downgrade.sql (renamed from nova/db/sqlalchemy/migrate_repo/versions/029_sqlite_downgrade.sql) | 0 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/migrate_repo/versions/030_sqlite_upgrade.sql (renamed from nova/db/sqlalchemy/migrate_repo/versions/029_sqlite_update.sql) | 0 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/models.py | 17 |
8 files changed, 255 insertions, 19 deletions
diff --git a/nova/db/api.py b/nova/db/api.py index b372ac6a7..7de91b79e 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -55,11 +55,6 @@ IMPL = utils.LazyPluggable(FLAGS['db_backend'], sqlalchemy='nova.db.sqlalchemy.api') -class NoMoreAddresses(exception.Error): - """No more available addresses.""" - pass - - class NoMoreBlades(exception.Error): """No more available blades.""" pass @@ -223,6 +218,9 @@ def certificate_update(context, certificate_id, values): ################### +def floating_ip_get(context, id): + return IMPL.floating_ip_get(context, id) + def floating_ip_allocate_address(context, project_id): """Allocate free floating ip and return the address. @@ -1398,3 +1396,24 @@ def agent_build_destroy(context, agent_update_id): def agent_build_update(context, agent_build_id, values): """Update agent build entry.""" IMPL.agent_build_update(context, agent_build_id, values) + + +#################### + + +def instance_type_extra_specs_get(context, instance_type_id): + """Get all extra specs for an instance type.""" + return IMPL.instance_type_extra_specs_get(context, instance_type_id) + + +def instance_type_extra_specs_delete(context, instance_type_id, key): + """Delete the given extra specs item.""" + IMPL.instance_type_extra_specs_delete(context, instance_type_id, key) + + +def instance_type_extra_specs_update_or_create(context, instance_type_id, + extra_specs): + """Create or update instance type extra specs. This adds or modifies the + key/value pairs specified in the extra specs dict argument""" + IMPL.instance_type_extra_specs_update_or_create(context, instance_type_id, + extra_specs) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 8f10c4078..37840f911 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -433,6 +433,31 @@ def certificate_update(context, certificate_id, values): @require_context +def floating_ip_get(context, id): + session = get_session() + result = None + if is_admin_context(context): + result = session.query(models.FloatingIp).\ + options(joinedload('fixed_ip')).\ + options(joinedload_all('fixed_ip.instance')).\ + filter_by(id=id).\ + filter_by(deleted=can_read_deleted(context)).\ + first() + elif is_user_context(context): + result = session.query(models.FloatingIp).\ + options(joinedload('fixed_ip')).\ + options(joinedload_all('fixed_ip.instance')).\ + filter_by(project_id=context.project_id).\ + filter_by(id=id).\ + filter_by(deleted=False).\ + first() + if not result: + raise exception.FloatingIpNotFound(id=id) + + return result + + +@require_context def floating_ip_allocate_address(context, project_id): authorize_project_context(context, project_id) session = get_session() @@ -563,7 +588,7 @@ def floating_ip_get_all_by_host(context, host): filter_by(deleted=False).\ all() if not floating_ip_refs: - raise exception.NoFloatingIpsDefinedForHost(host=host) + raise exception.FloatingIpNotFoundForHost(host=host) return floating_ip_refs @@ -579,7 +604,7 @@ def floating_ip_get_all_by_project(context, project_id): filter_by(deleted=False).\ all() if not floating_ip_refs: - raise exception.NoFloatingIpFoundForProject(project_id=project_id) + raise exception.FloatingIpNotFoundForProject(project_id=project_id) return floating_ip_refs @@ -595,7 +620,7 @@ def floating_ip_get_by_address(context, address, session=None): filter_by(deleted=can_read_deleted(context)).\ first() if not result: - raise exception.FloatingIpNotFound(address=address) + raise exception.FloatingIpNotFoundForAddress(address=address) return result @@ -626,7 +651,7 @@ def fixed_ip_associate(context, address, instance_id): # NOTE(vish): if with_lockmode isn't supported, as in sqlite, # then this has concurrency issues if not fixed_ip_ref: - raise db.NoMoreAddresses() + raise exception.NoMoreFixedIps() fixed_ip_ref.instance = instance session.add(fixed_ip_ref) @@ -647,7 +672,7 @@ def fixed_ip_associate_pool(context, network_id, instance_id): # NOTE(vish): if with_lockmode isn't supported, as in sqlite, # then this has concurrency issues if not fixed_ip_ref: - raise db.NoMoreAddresses() + raise exception.NoMoreFixedIps() if not fixed_ip_ref.network: fixed_ip_ref.network = network_get(context, network_id, @@ -721,7 +746,7 @@ def fixed_ip_get_all_by_host(context, host=None): all() if not result: - raise exception.NoFixedIpsDefinedForHost(host=host) + raise exception.FixedIpNotFoundForHost(host=host) return result @@ -738,7 +763,7 @@ def fixed_ip_get_by_address(context, address, session=None): options(joinedload('instance')).\ first() if not result: - raise exception.FixedIpNotFound(address=address) + raise exception.FixedIpNotFoundForAddress(address=address) if is_user_context(context): authorize_project_context(context, result.instance.project_id) @@ -755,7 +780,7 @@ def fixed_ip_get_by_instance(context, instance_id): filter_by(deleted=False).\ all() if not rv: - raise exception.NoFixedIpsFoundForInstance(instance_id=instance_id) + raise exception.FixedIpNotFoundForInstance(instance_id=instance_id) return rv @@ -768,7 +793,7 @@ def fixed_ip_get_by_virtual_interface(context, vif_id): filter_by(deleted=False).\ all() if not rv: - raise exception.NoFixedIpFoundForVirtualInterface(vif_id=vif_id) + raise exception.FixedIpNotFoundForVirtualInterface(vif_id=vif_id) return rv @@ -2841,7 +2866,22 @@ def console_get(context, console_id, instance_id=None): @require_admin_context def instance_type_create(_context, values): + """Create a new instance type. In order to pass in extra specs, + the values dict should contain a 'extra_specs' key/value pair: + + {'extra_specs' : {'k1': 'v1', 'k2': 'v2', ...}} + + """ try: + specs = values.get('extra_specs') + specs_refs = [] + if specs: + for k, v in specs.iteritems(): + specs_ref = models.InstanceTypeExtraSpecs() + specs_ref['key'] = k + specs_ref['value'] = v + specs_refs.append(specs_ref) + values['extra_specs'] = specs_refs instance_type_ref = models.InstanceTypes() instance_type_ref.update(values) instance_type_ref.save() @@ -2850,6 +2890,25 @@ def instance_type_create(_context, values): return instance_type_ref +def _dict_with_extra_specs(inst_type_query): + """Takes an instance type query returned by sqlalchemy + and returns it as a dictionary, converting the extra_specs + entry from a list of dicts: + + 'extra_specs' : [{'key': 'k1', 'value': 'v1', ...}, ...] + + to a single dict: + + 'extra_specs' : {'k1': 'v1'} + + """ + inst_type_dict = dict(inst_type_query) + extra_specs = dict([(x['key'], x['value']) for x in \ + inst_type_query['extra_specs']]) + inst_type_dict['extra_specs'] = extra_specs + return inst_type_dict + + @require_context def instance_type_get_all(context, inactive=False): """ @@ -2858,17 +2917,19 @@ def instance_type_get_all(context, inactive=False): session = get_session() if inactive: inst_types = session.query(models.InstanceTypes).\ + options(joinedload('extra_specs')).\ order_by("name").\ all() else: inst_types = session.query(models.InstanceTypes).\ + options(joinedload('extra_specs')).\ filter_by(deleted=False).\ order_by("name").\ all() if inst_types: inst_dict = {} for i in inst_types: - inst_dict[i['name']] = dict(i) + inst_dict[i['name']] = _dict_with_extra_specs(i) return inst_dict else: raise exception.NoInstanceTypesFound() @@ -2879,12 +2940,14 @@ def instance_type_get_by_id(context, id): """Returns a dict describing specific instance_type""" session = get_session() inst_type = session.query(models.InstanceTypes).\ + options(joinedload('extra_specs')).\ filter_by(id=id).\ first() + if not inst_type: raise exception.InstanceTypeNotFound(instance_type=id) else: - return dict(inst_type) + return _dict_with_extra_specs(inst_type) @require_context @@ -2892,12 +2955,13 @@ def instance_type_get_by_name(context, name): """Returns a dict describing specific instance_type""" session = get_session() inst_type = session.query(models.InstanceTypes).\ + options(joinedload('extra_specs')).\ filter_by(name=name).\ first() if not inst_type: raise exception.InstanceTypeNotFoundByName(instance_type_name=name) else: - return dict(inst_type) + return _dict_with_extra_specs(inst_type) @require_context @@ -2905,12 +2969,13 @@ def instance_type_get_by_flavor_id(context, id): """Returns a dict describing specific flavor_id""" session = get_session() inst_type = session.query(models.InstanceTypes).\ + options(joinedload('extra_specs')).\ filter_by(flavorid=int(id)).\ first() if not inst_type: raise exception.FlavorNotFound(flavor_id=id) else: - return dict(inst_type) + return _dict_with_extra_specs(inst_type) @require_admin_context @@ -3078,6 +3143,9 @@ def instance_metadata_update_or_create(context, instance_id, metadata): return metadata +#################### + + @require_admin_context def agent_build_create(context, values): agent_build_ref = models.AgentBuild() @@ -3127,3 +3195,70 @@ def agent_build_update(context, agent_build_id, values): first() agent_build_ref.update(values) agent_build_ref.save(session=session) + + +#################### + + +@require_context +def instance_type_extra_specs_get(context, instance_type_id): + session = get_session() + + spec_results = session.query(models.InstanceTypeExtraSpecs).\ + filter_by(instance_type_id=instance_type_id).\ + filter_by(deleted=False).\ + all() + + spec_dict = {} + for i in spec_results: + spec_dict[i['key']] = i['value'] + return spec_dict + + +@require_context +def instance_type_extra_specs_delete(context, instance_type_id, key): + session = get_session() + session.query(models.InstanceTypeExtraSpecs).\ + filter_by(instance_type_id=instance_type_id).\ + filter_by(key=key).\ + filter_by(deleted=False).\ + update({'deleted': True, + 'deleted_at': utils.utcnow(), + 'updated_at': literal_column('updated_at')}) + + +@require_context +def instance_type_extra_specs_get_item(context, instance_type_id, key): + session = get_session() + + sppec_result = session.query(models.InstanceTypeExtraSpecs).\ + filter_by(instance_type_id=instance_type_id).\ + filter_by(key=key).\ + filter_by(deleted=False).\ + first() + + if not spec_result: + raise exception.\ + InstanceTypeExtraSpecsNotFound(extra_specs_key=key, + instance_type_id=instance_type_id) + return spec_result + + +@require_context +def instance_type_extra_specs_update_or_create(context, instance_type_id, + specs): + session = get_session() + spec_ref = None + for key, value in specs.iteritems(): + try: + spec_ref = instance_type_extra_specs_get_item(context, + instance_type_id, + key, + session) + except: + spec_ref = models.InstanceTypeExtraSpecs() + spec_ref.update({"key": key, "value": value, + "instance_type_id": instance_type_id, + "deleted": 0}) + spec_ref.save(session=session) + return specs diff --git a/nova/db/sqlalchemy/migrate_repo/versions/028_add_instance_type_extra_specs.py b/nova/db/sqlalchemy/migrate_repo/versions/028_add_instance_type_extra_specs.py new file mode 100644 index 000000000..f26ad6d2c --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/028_add_instance_type_extra_specs.py @@ -0,0 +1,67 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 University of Southern California +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from sqlalchemy import Boolean, Column, DateTime, ForeignKey, Integer +from sqlalchemy import MetaData, String, Table +from nova import log as logging + +meta = MetaData() + +# Just for the ForeignKey and column creation to succeed, these are not the +# actual definitions of instances or services. +instance_types = Table('instance_types', meta, + Column('id', Integer(), primary_key=True, nullable=False), + ) + +# +# New Tables +# + +instance_type_extra_specs_table = Table('instance_type_extra_specs', meta, + Column('created_at', DateTime(timezone=False)), + Column('updated_at', DateTime(timezone=False)), + Column('deleted_at', DateTime(timezone=False)), + Column('deleted', Boolean(create_constraint=True, name=None)), + Column('id', Integer(), primary_key=True, nullable=False), + Column('instance_type_id', + Integer(), + ForeignKey('instance_types.id'), + nullable=False), + Column('key', + String(length=255, convert_unicode=False, assert_unicode=None, + unicode_error=None, _warn_on_bytestring=False)), + Column('value', + String(length=255, convert_unicode=False, assert_unicode=None, + unicode_error=None, _warn_on_bytestring=False))) + + +def upgrade(migrate_engine): + # Upgrade operations go here. Don't create your own engine; + # bind migrate_engine to your metadata + meta.bind = migrate_engine + for table in (instance_type_extra_specs_table, ): + try: + table.create() + except Exception: + logging.info(repr(table)) + logging.exception('Exception while creating table') + raise + + +def downgrade(migrate_engine): + # Operations to reverse the above upgrade go here. + for table in (instance_type_extra_specs_table, ): + table.drop() diff --git a/nova/db/sqlalchemy/migrate_repo/versions/028_multi_nic.py b/nova/db/sqlalchemy/migrate_repo/versions/029_multi_nic.py index 48fb4032f..48fb4032f 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/028_multi_nic.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/029_multi_nic.py diff --git a/nova/db/sqlalchemy/migrate_repo/versions/029_fk_fixed_ips_virtual_interface_id.py b/nova/db/sqlalchemy/migrate_repo/versions/030_fk_fixed_ips_virtual_interface_id.py index 56e927717..56e927717 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/029_fk_fixed_ips_virtual_interface_id.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/030_fk_fixed_ips_virtual_interface_id.py diff --git a/nova/db/sqlalchemy/migrate_repo/versions/029_sqlite_downgrade.sql b/nova/db/sqlalchemy/migrate_repo/versions/030_sqlite_downgrade.sql index c1d26b180..c1d26b180 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/029_sqlite_downgrade.sql +++ b/nova/db/sqlalchemy/migrate_repo/versions/030_sqlite_downgrade.sql diff --git a/nova/db/sqlalchemy/migrate_repo/versions/029_sqlite_update.sql b/nova/db/sqlalchemy/migrate_repo/versions/030_sqlite_upgrade.sql index 2a9362545..2a9362545 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/029_sqlite_update.sql +++ b/nova/db/sqlalchemy/migrate_repo/versions/030_sqlite_upgrade.sql diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 7f02ac532..27cdb96ce 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -735,6 +735,21 @@ class InstanceMetadata(BASE, NovaBase): 'InstanceMetadata.deleted == False)') +class InstanceTypeExtraSpecs(BASE, NovaBase): + """Represents additional specs as key/value pairs for an instance_type""" + __tablename__ = 'instance_type_extra_specs' + id = Column(Integer, primary_key=True) + key = Column(String(255)) + value = Column(String(255)) + instance_type_id = Column(Integer, ForeignKey('instance_types.id'), + nullable=False) + instance_type = relationship(InstanceTypes, backref="extra_specs", + foreign_keys=instance_type_id, + primaryjoin='and_(' + 'InstanceTypeExtraSpecs.instance_type_id == InstanceTypes.id,' + 'InstanceTypeExtraSpecs.deleted == False)') + + class Zone(BASE, NovaBase): """Represents a child zone of this zone.""" __tablename__ = 'zones' @@ -769,7 +784,7 @@ def register_models(): Network, SecurityGroup, SecurityGroupIngressRule, SecurityGroupInstanceAssociation, AuthToken, User, Project, Certificate, ConsolePool, Console, Zone, - AgentBuild, InstanceMetadata, Migration) + AgentBuild, InstanceMetadata, InstanceTypeExtraSpecs, Migration) engine = create_engine(FLAGS.sql_connection, echo=False) for model in models: model.metadata.create_all(engine) |
