62
60
raise exception.InvalidInstanceIDMalformed(val)
65
def _gen_key(context, user_id, key_name):
68
This is a module level method because it is slow and we need to defer
69
it into a process pool."""
70
# NOTE(vish): generating key pair is slow so check for legal
71
# creation before creating key_pair
73
db.key_pair_get(context, user_id, key_name)
74
raise exception.KeyPairExists(key_name=key_name)
75
except exception.NotFound:
77
private_key, public_key, fingerprint = crypto.generate_key_pair()
79
key['user_id'] = user_id
80
key['name'] = key_name
81
key['public_key'] = public_key
82
key['fingerprint'] = fingerprint
83
db.key_pair_create(context, key)
84
return {'private_key': private_key, 'fingerprint': fingerprint}
87
63
# EC2 API can return the following values as documented in the EC2 API
88
64
# http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/
89
65
# ApiReference-ItemType-InstanceStateType.html
347
324
return self._format_snapshot(context, snapshot)
349
326
def delete_snapshot(self, context, snapshot_id, **kwargs):
350
snapshot_id = ec2utils.ec2_id_to_id(snapshot_id)
327
snapshot_id = ec2utils.ec2_snap_id_to_uuid(snapshot_id)
351
328
snapshot = self.volume_api.get_snapshot(context, snapshot_id)
352
329
self.volume_api.delete_snapshot(context, snapshot)
355
332
def describe_key_pairs(self, context, key_name=None, **kwargs):
356
key_pairs = db.key_pair_get_all_by_user(context, context.user_id)
333
key_pairs = self.keypair_api.get_key_pairs(context, context.user_id)
357
334
if not key_name is None:
358
335
key_pairs = [x for x in key_pairs if x['name'] in key_name]
370
347
return {'keySet': result}
372
349
def create_key_pair(self, context, key_name, **kwargs):
373
if not re.match('^[a-zA-Z0-9_\- ]+$', str(key_name)):
374
err = _("Value (%s) for KeyName is invalid."
375
" Content limited to Alphanumeric character, "
376
"spaces, dashes, and underscore.") % key_name
377
raise exception.EC2APIError(err)
379
if len(str(key_name)) > 255:
380
err = _("Value (%s) for Keyname is invalid."
381
" Length exceeds maximum of 255.") % key_name
382
raise exception.EC2APIError(err)
384
350
LOG.audit(_("Create key pair %s"), key_name, context=context)
385
data = _gen_key(context, context.user_id, key_name)
353
keypair = self.keypair_api.create_key_pair(context,
356
except exception.KeypairLimitExceeded:
357
msg = _("Quota exceeded, too many key pairs.")
358
raise exception.EC2APIError(msg)
359
except exception.InvalidKeypair:
360
msg = _("Keypair data is invalid")
361
raise exception.EC2APIError(msg)
362
except exception.KeyPairExists:
363
msg = _("Key pair '%s' already exists.") % key_name
364
raise exception.KeyPairExists(msg)
386
365
return {'keyName': key_name,
387
'keyFingerprint': data['fingerprint'],
388
'keyMaterial': data['private_key']}
366
'keyFingerprint': keypair['fingerprint'],
367
'keyMaterial': keypair['private_key']}
389
368
# TODO(vish): when context is no longer an object, pass it here
391
370
def import_key_pair(self, context, key_name, public_key_material,
393
372
LOG.audit(_("Import key %s"), key_name, context=context)
395
db.key_pair_get(context, context.user_id, key_name)
396
raise exception.KeyPairExists(key_name=key_name)
397
except exception.NotFound:
399
374
public_key = base64.b64decode(public_key_material)
400
fingerprint = crypto.generate_fingerprint(public_key)
402
key['user_id'] = context.user_id
403
key['name'] = key_name
404
key['public_key'] = public_key
405
key['fingerprint'] = fingerprint
406
db.key_pair_create(context, key)
377
keypair = self.keypair_api.import_key_pair(context,
381
except exception.KeypairLimitExceeded:
382
msg = _("Quota exceeded, too many key pairs.")
383
raise exception.EC2APIError(msg)
384
except exception.InvalidKeypair:
385
msg = _("Keypair data is invalid")
386
raise exception.EC2APIError(msg)
387
except exception.KeyPairExists:
388
msg = _("Key pair '%s' already exists.") % key_name
389
raise exception.EC2APIError(msg)
407
391
return {'keyName': key_name,
408
'keyFingerprint': fingerprint}
392
'keyFingerprint': keypair['fingerprint']}
410
394
def delete_key_pair(self, context, key_name, **kwargs):
411
395
LOG.audit(_("Delete key pair %s"), key_name, context=context)
413
db.key_pair_destroy(context, context.user_id, key_name)
397
self.keypair_api.delete_key_pair(context, context.user_id,
414
399
except exception.NotFound:
415
400
# aws returns true even if the key doesn't exist
865
850
def _format_volume(self, context, volume):
866
851
instance_ec2_id = None
867
852
instance_data = None
868
if volume.get('instance', None):
869
instance_id = volume['instance']['id']
854
if volume.get('instance_uuid', None):
855
instance_uuid = volume['instance_uuid']
856
instance = db.instance_get_by_uuid(context.elevated(),
859
instance_id = instance['id']
870
860
instance_ec2_id = ec2utils.id_to_ec2_id(instance_id)
871
861
instance_data = '%s[%s]' % (instance_ec2_id,
872
volume['instance']['host'])
874
864
v['volumeId'] = ec2utils.id_to_ec2_vol_id(volume['id'])
875
865
v['status'] = volume['status']
1240
1230
return list(reservations.values())
1242
def describe_addresses(self, context, **kwargs):
1243
return self.format_addresses(context)
1245
def format_addresses(self, context):
1247
floaters = self.network_api.get_floating_ips_by_project(context)
1248
for floating_ip_ref in floaters:
1249
if floating_ip_ref['project_id'] is None:
1251
address = floating_ip_ref['address']
1253
if floating_ip_ref['fixed_ip_id']:
1254
fixed_id = floating_ip_ref['fixed_ip_id']
1255
fixed = self.network_api.get_fixed_ip(context, fixed_id)
1256
if fixed['instance_id'] is not None:
1257
ec2_id = ec2utils.id_to_ec2_id(fixed['instance_id'])
1258
address_rv = {'public_ip': address,
1259
'instance_id': ec2_id}
1260
if context.is_admin:
1261
details = "%s (%s)" % (address_rv['instance_id'],
1262
floating_ip_ref['project_id'])
1263
address_rv['instance_id'] = details
1264
addresses.append(address_rv)
1232
def describe_addresses(self, context, public_ip=None, **kwargs):
1235
for address in public_ip:
1236
floating = self.network_api.get_floating_ip_by_address(context,
1238
floatings.append(floating)
1240
floatings = self.network_api.get_floating_ips_by_project(context)
1241
addresses = [self._format_address(context, f) for f in floatings]
1265
1242
return {'addressesSet': addresses}
1244
def _format_address(self, context, floating_ip):
1246
if floating_ip['fixed_ip_id']:
1247
fixed_id = floating_ip['fixed_ip_id']
1248
fixed = self.network_api.get_fixed_ip(context, fixed_id)
1249
if fixed['instance_id'] is not None:
1250
ec2_id = ec2utils.id_to_ec2_id(fixed['instance_id'])
1251
address = {'public_ip': floating_ip['address'],
1252
'instance_id': ec2_id}
1253
if context.is_admin:
1254
details = "%s (%s)" % (address['instance_id'],
1255
floating_ip['project_id'])
1256
address['instance_id'] = details
1267
1259
def allocate_address(self, context, **kwargs):
1268
1260
LOG.audit(_("Allocate address"), context=context)
1270
public_ip = self.network_api.allocate_floating_ip(context)
1271
return {'publicIp': public_ip}
1272
except rpc_common.RemoteError as ex:
1273
# NOTE(tr3buchet) - why does this block exist?
1274
if ex.exc_type == 'NoMoreFloatingIps':
1275
raise exception.NoMoreFloatingIps()
1261
public_ip = self.network_api.allocate_floating_ip(context)
1262
return {'publicIp': public_ip}
1279
1264
def release_address(self, context, public_ip, **kwargs):
1280
1265
LOG.audit(_("Release address %s"), public_ip, context=context)
1281
self.network_api.release_floating_ip(context, address=public_ip)
1282
return {'return': "true"}
1267
self.network_api.release_floating_ip(context, address=public_ip)
1268
return {'return': "true"}
1269
except exception.FloatingIpNotFound:
1270
raise exception.EC2APIError(_('Unable to release IP Address.'))
1284
1272
def associate_address(self, context, instance_id, public_ip, **kwargs):
1285
1273
LOG.audit(_("Associate address %(public_ip)s to"
1286
1274
" instance %(instance_id)s") % locals(), context=context)
1287
1275
instance_id = ec2utils.ec2_id_to_id(instance_id)
1288
1276
instance = self.compute_api.get(context, instance_id)
1289
self.compute_api.associate_floating_ip(context,
1292
return {'return': "true"}
1278
self.compute_api.associate_floating_ip(context,
1281
return {'return': "true"}
1282
except exception.FloatingIpNotFound:
1283
raise exception.EC2APIError(_('Unable to associate IP Address.'))
1294
1285
def disassociate_address(self, context, public_ip, **kwargs):
1295
1286
LOG.audit(_("Disassociate address %s"), public_ip, context=context)