diff options
| author | Devin Carlen <devin.carlen@gmail.com> | 2010-09-29 01:53:14 +0000 |
|---|---|---|
| committer | Tarmac <> | 2010-09-29 01:53:14 +0000 |
| commit | 27220e66e20e30304bae8491ebe90fcc968c43ca (patch) | |
| tree | 7329256f146fdfc9357e17bb238749b9b6eb1dc0 | |
| parent | 0945a8869fa64d466527f865ba13b6275f1649c2 (diff) | |
| parent | e3102b6b9be148597a2f502d2b2baf750ecc0a34 (diff) | |
| download | nova-27220e66e20e30304bae8491ebe90fcc968c43ca.tar.gz nova-27220e66e20e30304bae8491ebe90fcc968c43ca.tar.xz nova-27220e66e20e30304bae8491ebe90fcc968c43ca.zip | |
Added random ec2 style id's for volumes and instances.
| -rwxr-xr-x | bin/nova-manage | 2 | ||||
| -rw-r--r-- | nova/api/ec2/cloud.py | 46 | ||||
| -rw-r--r-- | nova/compute/manager.py | 10 | ||||
| -rw-r--r-- | nova/db/api.py | 12 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/api.py | 60 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/models.py | 13 | ||||
| -rw-r--r-- | nova/network/linux_net.py | 2 | ||||
| -rw-r--r-- | nova/network/manager.py | 2 | ||||
| -rw-r--r-- | nova/volume/manager.py | 10 |
9 files changed, 99 insertions, 58 deletions
diff --git a/bin/nova-manage b/bin/nova-manage index baa1cb4db..a5087bfec 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -316,7 +316,7 @@ class FloatingIpCommands(object): for floating_ip in floating_ips: instance = None if floating_ip['fixed_ip']: - instance = floating_ip['fixed_ip']['instance']['str_id'] + instance = floating_ip['fixed_ip']['instance']['ec2_id'] print "%s\t%s\t%s" % (floating_ip['host'], floating_ip['address'], instance) diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 367511e3b..05e8065f3 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -103,7 +103,7 @@ class CloudController(object): result = {} for instance in db.instance_get_by_project(None, project_id): if instance['fixed_ip']: - line = '%s slots=%d' % (instance['fixed_ip']['str_id'], + line = '%s slots=%d' % (instance['fixed_ip']['address'], INSTANCE_TYPES[instance['instance_type']]['vcpus']) key = str(instance['key_name']) if key in result: @@ -143,7 +143,7 @@ class CloudController(object): }, 'hostname': hostname, 'instance-action': 'none', - 'instance-id': instance_ref['str_id'], + 'instance-id': instance_ref['ec2_id'], 'instance-type': instance_ref['instance_type'], 'local-hostname': hostname, 'local-ipv4': address, @@ -245,7 +245,7 @@ class CloudController(object): def get_console_output(self, context, instance_id, **kwargs): # instance_id is passed in as a list of instances - instance_ref = db.instance_get_by_str(context, instance_id[0]) + instance_ref = db.instance_get_by_ec2_id(context, instance_id[0]) return rpc.call('%s.%s' % (FLAGS.compute_topic, instance_ref['host']), {"method": "get_console_output", @@ -264,7 +264,7 @@ class CloudController(object): def _format_volume(self, context, volume): v = {} - v['volumeId'] = volume['str_id'] + v['volumeId'] = volume['ec2_id'] v['status'] = volume['status'] v['size'] = volume['size'] v['availabilityZone'] = volume['availability_zone'] @@ -282,7 +282,7 @@ class CloudController(object): 'device': volume['mountpoint'], 'instanceId': volume['instance_id'], 'status': 'attached', - 'volume_id': volume['str_id']}] + 'volume_id': volume['ec2_id']}] else: v['attachmentSet'] = [{}] return v @@ -314,13 +314,13 @@ class CloudController(object): def attach_volume(self, context, volume_id, instance_id, device, **kwargs): - volume_ref = db.volume_get_by_str(context, volume_id) + volume_ref = db.volume_get_by_ec2_id(context, volume_id) # TODO(vish): abstract status checking? if volume_ref['status'] != "available": raise exception.ApiError("Volume status must be available") if volume_ref['attach_status'] == "attached": raise exception.ApiError("Volume is already attached") - instance_ref = db.instance_get_by_str(context, instance_id) + instance_ref = db.instance_get_by_ec2_id(context, instance_id) host = instance_ref['host'] rpc.cast(db.queue_get_for(context, FLAGS.compute_topic, host), {"method": "attach_volume", @@ -336,7 +336,7 @@ class CloudController(object): 'volumeId': volume_ref['id']} def detach_volume(self, context, volume_id, **kwargs): - volume_ref = db.volume_get_by_str(context, volume_id) + volume_ref = db.volume_get_by_ec2_id(context, volume_id) instance_ref = db.volume_get_instance(context, volume_ref['id']) if not instance_ref: raise exception.ApiError("Volume isn't attached to anything!") @@ -356,7 +356,7 @@ class CloudController(object): db.volume_detached(context) return {'attachTime': volume_ref['attach_time'], 'device': volume_ref['mountpoint'], - 'instanceId': instance_ref['str_id'], + 'instanceId': instance_ref['ec2_id'], 'requestId': context.request_id, 'status': volume_ref['attach_status'], 'volumeId': volume_ref['id']} @@ -395,7 +395,7 @@ class CloudController(object): if instance['image_id'] == FLAGS.vpn_image_id: continue i = {} - i['instanceId'] = instance['str_id'] + i['instanceId'] = instance['ec2_id'] i['imageId'] = instance['image_id'] i['instanceState'] = { 'code': instance['state'], @@ -404,10 +404,10 @@ class CloudController(object): fixed_addr = None floating_addr = None if instance['fixed_ip']: - fixed_addr = instance['fixed_ip']['str_id'] + fixed_addr = instance['fixed_ip']['address'] if instance['fixed_ip']['floating_ips']: fixed = instance['fixed_ip'] - floating_addr = fixed['floating_ips'][0]['str_id'] + floating_addr = fixed['floating_ips'][0]['address'] i['privateDnsName'] = fixed_addr i['publicDnsName'] = floating_addr i['dnsName'] = i['publicDnsName'] or i['privateDnsName'] @@ -442,11 +442,11 @@ class CloudController(object): iterator = db.floating_ip_get_by_project(context, context.project.id) for floating_ip_ref in iterator: - address = floating_ip_ref['str_id'] + address = floating_ip_ref['address'] instance_id = None if (floating_ip_ref['fixed_ip'] and floating_ip_ref['fixed_ip']['instance']): - instance_id = floating_ip_ref['fixed_ip']['instance']['str_id'] + instance_id = floating_ip_ref['fixed_ip']['instance']['ec2_id'] address_rv = {'public_ip': address, 'instance_id': instance_id} if context.user.is_admin(): @@ -477,19 +477,19 @@ class CloudController(object): rpc.cast(network_topic, {"method": "deallocate_floating_ip", "args": {"context": None, - "floating_address": floating_ip_ref['str_id']}}) + "floating_address": floating_ip_ref['address']}}) return {'releaseResponse': ["Address released."]} def associate_address(self, context, instance_id, public_ip, **kwargs): - instance_ref = db.instance_get_by_str(context, instance_id) + instance_ref = db.instance_get_by_ec2_id(context, instance_id) fixed_ip_ref = db.fixed_ip_get_by_instance(context, instance_ref['id']) floating_ip_ref = db.floating_ip_get_by_address(context, public_ip) network_topic = self._get_network_topic(context) rpc.cast(network_topic, {"method": "associate_floating_ip", "args": {"context": None, - "floating_address": floating_ip_ref['str_id'], - "fixed_address": fixed_ip_ref['str_id']}}) + "floating_address": floating_ip_ref['address'], + "fixed_address": fixed_ip_ref['address']}}) return {'associateResponse': ["Address associated."]} def disassociate_address(self, context, public_ip, **kwargs): @@ -498,7 +498,7 @@ class CloudController(object): rpc.cast(network_topic, {"method": "disassociate_floating_ip", "args": {"context": None, - "floating_address": floating_ip_ref['str_id']}}) + "floating_address": floating_ip_ref['address']}}) return {'disassociateResponse': ["Address disassociated."]} def _get_network_topic(self, context): @@ -589,7 +589,7 @@ class CloudController(object): inst = {} inst['mac_address'] = utils.generate_mac() inst['launch_index'] = num - inst['hostname'] = instance_ref['str_id'] + inst['hostname'] = instance_ref['ec2_id'] db.instance_update(context, inst_id, inst) address = self.network_manager.allocate_fixed_ip(context, inst_id, @@ -618,7 +618,7 @@ class CloudController(object): for id_str in instance_id: logging.debug("Going to try and terminate %s" % id_str) try: - instance_ref = db.instance_get_by_str(context, id_str) + instance_ref = db.instance_get_by_ec2_id(context, id_str) except exception.NotFound: logging.warning("Instance %s was not found during terminate" % id_str) @@ -664,7 +664,7 @@ class CloudController(object): def reboot_instances(self, context, instance_id, **kwargs): """instance_id is a list of instance ids""" for id_str in instance_id: - instance_ref = db.instance_get_by_str(context, id_str) + instance_ref = db.instance_get_by_ec2_id(context, id_str) host = instance_ref['host'] rpc.cast(db.queue_get_for(context, FLAGS.compute_topic, host), {"method": "reboot_instance", @@ -674,7 +674,7 @@ class CloudController(object): def delete_volume(self, context, volume_id, **kwargs): # TODO: return error if not authorized - volume_ref = db.volume_get_by_str(context, volume_id) + volume_ref = db.volume_get_by_ec2_id(context, volume_id) if volume_ref['status'] != "available": raise exception.ApiError("Volume status must be available") now = datetime.datetime.utcnow() diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 24538e4f1..f370ede8b 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -67,7 +67,7 @@ class ComputeManager(manager.Manager): def run_instance(self, context, instance_id, **_kwargs): """Launch a new instance with specified options.""" instance_ref = self.db.instance_get(context, instance_id) - if instance_ref['str_id'] in self.driver.list_instances(): + if instance_ref['ec2_id'] in self.driver.list_instances(): raise exception.Error("Instance has already been created") logging.debug("instance %s: starting...", instance_id) project_id = instance_ref['project_id'] @@ -129,7 +129,7 @@ class ComputeManager(manager.Manager): raise exception.Error( 'trying to reboot a non-running' 'instance: %s (state: %s excepted: %s)' % - (instance_ref['str_id'], + (instance_ref['ec2_id'], instance_ref['state'], power_state.RUNNING)) @@ -151,7 +151,7 @@ class ComputeManager(manager.Manager): if FLAGS.connection_type == 'libvirt': fname = os.path.abspath(os.path.join(FLAGS.instances_path, - instance_ref['str_id'], + instance_ref['ec2_id'], 'console.log')) with open(fname, 'r') as f: output = f.read() @@ -174,7 +174,7 @@ class ComputeManager(manager.Manager): instance_ref = self.db.instance_get(context, instance_id) dev_path = yield self.volume_manager.setup_compute_volume(context, volume_id) - yield self.driver.attach_volume(instance_ref['str_id'], + yield self.driver.attach_volume(instance_ref['ec2_id'], dev_path, mountpoint) self.db.volume_attached(context, volume_id, instance_id, mountpoint) @@ -189,7 +189,7 @@ class ComputeManager(manager.Manager): volume_id) instance_ref = self.db.instance_get(context, instance_id) volume_ref = self.db.volume_get(context, volume_id) - yield self.driver.detach_volume(instance_ref['str_id'], + yield self.driver.detach_volume(instance_ref['ec2_id'], volume_ref['mountpoint']) self.db.volume_detached(context, volume_id) defer.returnValue(True) diff --git a/nova/db/api.py b/nova/db/api.py index b0b8f234d..208720ff9 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -275,9 +275,9 @@ def instance_get_floating_address(context, instance_id): return IMPL.instance_get_floating_address(context, instance_id) -def instance_get_by_str(context, str_id): - """Get an instance by string id.""" - return IMPL.instance_get_by_str(context, str_id) +def instance_get_by_ec2_id(context, ec2_id): + """Get an instance by ec2 id.""" + return IMPL.instance_get_by_ec2_id(context, ec2_id) def instance_is_vpn(context, instance_id): @@ -540,9 +540,9 @@ def volume_get_by_project(context, project_id): return IMPL.volume_get_by_project(context, project_id) -def volume_get_by_str(context, str_id): - """Get a volume by string id.""" - return IMPL.volume_get_by_str(context, str_id) +def volume_get_by_ec2_id(context, ec2_id): + """Get a volume by ec2 id.""" + return IMPL.volume_get_by_ec2_id(context, ec2_id) def volume_get_shelf_and_blade(context, volume_id): diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 5c1ceee92..8b9a3e1c6 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -22,11 +22,12 @@ Implementation of SQLAlchemy backend from nova import db from nova import exception from nova import flags +from nova import utils from nova.db.sqlalchemy import models from nova.db.sqlalchemy.session import get_session from sqlalchemy import or_ from sqlalchemy.orm import joinedload_all -from sqlalchemy.sql import func +from sqlalchemy.sql import exists, func FLAGS = flags.FLAGS @@ -356,9 +357,15 @@ def instance_create(_context, values): instance_ref = models.Instance() for (key, value) in values.iteritems(): instance_ref[key] = value - instance_ref.save() - return instance_ref + 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 + instance_ref.save(session=session) + return instance_ref def instance_data_get_for_project(_context, project_id): session = get_session() @@ -415,8 +422,22 @@ def instance_get_by_reservation(_context, reservation_id): ).all() -def instance_get_by_str(context, str_id): - return models.Instance.find_by_str(str_id, deleted=_deleted(context)) +def instance_get_by_ec2_id(context, ec2_id): + session = get_session() + instance_ref = session.query(models.Instance + ).filter_by(ec2_id=ec2_id + ).filter_by(deleted=_deleted(context) + ).first() + if not instance_ref: + raise exception.NotFound('Instance %s not found' % (ec2_id)) + + return instance_ref + + +def instance_ec2_id_exists(context, ec2_id, session=None): + if not session: + session = get_session() + return session.query(exists().where(models.Instance.id==ec2_id)).one()[0] def instance_get_fixed_address(_context, instance_id): @@ -706,7 +727,7 @@ def auth_create_token(_context, token): tk[k] = v tk.save() return tk - + ################### @@ -775,7 +796,14 @@ def volume_create(_context, values): volume_ref = models.Volume() for (key, value) in values.iteritems(): volume_ref[key] = value - volume_ref.save() + + session = get_session() + with session.begin(): + while volume_ref.ec2_id == None: + ec2_id = utils.generate_uid(volume_ref.__prefix__) + if not volume_ec2_id_exists(_context, ec2_id, session=session): + volume_ref.ec2_id = ec2_id + volume_ref.save(session=session) return volume_ref @@ -828,8 +856,22 @@ def volume_get_by_project(context, project_id): ).all() -def volume_get_by_str(context, str_id): - return models.Volume.find_by_str(str_id, deleted=_deleted(context)) +def volume_get_by_ec2_id(context, ec2_id): + session = get_session() + volume_ref = session.query(models.Volume + ).filter_by(ec2_id=ec2_id + ).filter_by(deleted=_deleted(context) + ).first() + if not volume_ref: + raise exception.NotFound('Volume %s not found' % (ec2_id)) + + return volume_ref + + +def volume_ec2_id_exists(context, ec2_id, session=None): + if not session: + session = get_session() + return session.query(exists().where(models.Volume.id==ec2_id)).one()[0] def volume_get_instance(_context, volume_id): diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 63f8c6172..d4e04153a 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -126,6 +126,7 @@ class NovaBase(object): # __tablename__ = 'images' # __prefix__ = 'ami' # id = Column(Integer, primary_key=True) +# ec2_id = Column(String(12), unique=True) # user_id = Column(String(255)) # project_id = Column(String(255)) # image_type = Column(String(255)) @@ -195,6 +196,7 @@ class Instance(BASE, NovaBase): __tablename__ = 'instances' __prefix__ = 'i' id = Column(Integer, primary_key=True) + ec2_id = Column(String(10), unique=True) user_id = Column(String(255)) project_id = Column(String(255)) @@ -209,7 +211,7 @@ class Instance(BASE, NovaBase): @property def name(self): - return self.str_id + return self.ec2_id image_id = Column(String(255)) kernel_id = Column(String(255)) @@ -267,6 +269,7 @@ class Volume(BASE, NovaBase): __tablename__ = 'volumes' __prefix__ = 'vol' id = Column(Integer, primary_key=True) + ec2_id = Column(String(12), unique=True) user_id = Column(String(255)) project_id = Column(String(255)) @@ -400,8 +403,8 @@ class NetworkIndex(BASE, NovaBase): uselist=False)) class AuthToken(BASE, NovaBase): - """Represents an authorization token for all API transactions. Fields - are a string representing the actual token and a user id for mapping + """Represents an authorization token for all API transactions. Fields + are a string representing the actual token and a user id for mapping to the actual user""" __tablename__ = 'auth_tokens' token_hash = Column(String(255), primary_key=True) @@ -456,10 +459,6 @@ class FloatingIp(BASE, NovaBase): project_id = Column(String(255)) host = Column(String(255)) # , ForeignKey('hosts.id')) - @property - def str_id(self): - return self.address - @classmethod def find_by_str(cls, str_id, session=None, deleted=False): if not session: diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 41aeb5da7..25a9456b9 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -133,7 +133,7 @@ def get_dhcp_hosts(context, network_id): """Get a string containing a network's hosts config in dnsmasq format""" hosts = [] for fixed_ip in db.network_get_associated_fixed_ips(context, network_id): - hosts.append(_host_dhcp(fixed_ip['str_id'])) + hosts.append(_host_dhcp(fixed_ip['address'])) return '\n'.join(hosts) diff --git a/nova/network/manager.py b/nova/network/manager.py index 191c1d364..321dac914 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -270,7 +270,7 @@ class VlanManager(NetworkManager): raise exception.Error("IP %s leased to bad mac %s vs %s" % (address, instance_ref['mac_address'], mac)) self.db.fixed_ip_update(context, - fixed_ip_ref['str_id'], + fixed_ip_ref['address'], {'leased': True}) def release_fixed_ip(self, context, mac, address): diff --git a/nova/volume/manager.py b/nova/volume/manager.py index 034763512..8508f27b2 100644 --- a/nova/volume/manager.py +++ b/nova/volume/manager.py @@ -77,7 +77,7 @@ class AOEManager(manager.Manager): size = volume_ref['size'] logging.debug("volume %s: creating lv of size %sG", volume_id, size) - yield self.driver.create_volume(volume_ref['str_id'], size) + yield self.driver.create_volume(volume_ref['ec2_id'], size) logging.debug("volume %s: allocating shelf & blade", volume_id) self._ensure_blades(context) @@ -87,7 +87,7 @@ class AOEManager(manager.Manager): logging.debug("volume %s: exporting shelf %s & blade %s", volume_id, shelf_id, blade_id) - yield self.driver.create_export(volume_ref['str_id'], + yield self.driver.create_export(volume_ref['ec2_id'], shelf_id, blade_id) @@ -111,10 +111,10 @@ class AOEManager(manager.Manager): raise exception.Error("Volume is not local to this node") shelf_id, blade_id = self.db.volume_get_shelf_and_blade(context, volume_id) - yield self.driver.remove_export(volume_ref['str_id'], + yield self.driver.remove_export(volume_ref['ec2_id'], shelf_id, blade_id) - yield self.driver.delete_volume(volume_ref['str_id']) + yield self.driver.delete_volume(volume_ref['ec2_id']) self.db.volume_destroy(context, volume_id) defer.returnValue(True) @@ -125,7 +125,7 @@ class AOEManager(manager.Manager): Returns path to device. """ volume_ref = self.db.volume_get(context, volume_id) - yield self.driver.discover_volume(volume_ref['str_id']) + yield self.driver.discover_volume(volume_ref['ec2_id']) shelf_id, blade_id = self.db.volume_get_shelf_and_blade(context, volume_id) defer.returnValue("/dev/etherd/e%s.%s" % (shelf_id, blade_id)) |
