From: Jan Provaznik <jprovazn(a)redhat.com>
Instance SSH key name is now unique (had same name as cloud account key till
now)
---
src/app/models/instance.rb | 16 ++++++++++++----
src/app/models/instance_key.rb | 17 ++++++++---------
src/app/models/instance_observer.rb | 8 ++++----
src/dbomatic/dbomatic | 8 --------
4 files changed, 24 insertions(+), 25 deletions(-)
diff --git a/src/app/models/instance.rb b/src/app/models/instance.rb
index 1172998..96e5d39 100644
--- a/src/app/models/instance.rb
+++ b/src/app/models/instance.rb
@@ -171,19 +171,27 @@ class Instance < ActiveRecord::Base
end
def create_unique_key
- client = self.cloud_account.connect
- # TODO: what if dcloud driver is not running
- return unless client && client.feature?(:instances, :authentication_key)
+ return unless self.cloud_account and self.cloud_account.instance_key
# deltacloud/ec2 api's create_key method returns only private part of
# key -> we don't know public part, so we generate new ssh key
# and replace whole authorized_keys file
+ key_name = "#{self.name}_rsa_#{Time.now.to_f}"
+ self.instance_key =
InstanceKey.new(self.cloud_account.instance_key.attributes.merge({
+ :instance_key_owner => self,
+ :name => key_name
+ }))
begin
- self.instance_key.replace_key(self.public_addresses)
+ self.instance_key.replace_key(self.public_addresses,
self.cloud_account.instance_key.pem)
self.events.create!(:summary => "successfully updated ssh key",
:event_time => Time.now)
rescue
msg = "failed to upload ssh key: #{$!}"
self.last_error = msg
self.events.create!(:summary => msg, :event_time => Time.now)
+ ensure
+ # if replace_key fails, we still save instance_key - should be copy of
+ # cloud_account key which was used when launching instance
+ self.instance_key.save!
+ self.save!
end
end
diff --git a/src/app/models/instance_key.rb b/src/app/models/instance_key.rb
index 3ec3e51..2f9e540 100644
--- a/src/app/models/instance_key.rb
+++ b/src/app/models/instance_key.rb
@@ -27,22 +27,21 @@ class InstanceKey < ActiveRecord::Base
belongs_to :instance_key_owner, :polymorphic => true
+ # TODO: this is ec2 specific, create more general ProviderType model,
+ # this will have type, ssh_user, and optionally homedir fields.
REMOTE_USER = 'ec2-user'
REMOTE_HOME = '/home/ec2-user'
- def replace_key(addr)
- transaction do
- key = generate_ssh_key
- replace_on_server(addr, key[:public])
- self.pem = key[:private]
- save!
- end
+ def replace_key(addr, old_pem)
+ key = generate_ssh_key
+ replace_on_server(addr, old_pem, key[:public])
+ self.pem = key[:private]
end
private
- def replace_on_server(addr, new_pub)
- Net::SCP::start(addr, REMOTE_USER, :key_data => [self.pem], :keys => []) do
|scp|
+ def replace_on_server(addr, old_pem, new_pub)
+ Net::SCP::start(addr, REMOTE_USER, :key_data => [old_pem], :keys => []) do
|scp|
scp.upload! StringIO.new(new_pub), File.join(REMOTE_HOME,
'/.ssh/authorized_keys')
end
end
diff --git a/src/app/models/instance_observer.rb b/src/app/models/instance_observer.rb
index a0c5cb1..a2b1dfd 100644
--- a/src/app/models/instance_observer.rb
+++ b/src/app/models/instance_observer.rb
@@ -62,11 +62,11 @@ class InstanceObserver < ActiveRecord::Observer
end
def after_update(instance)
- # we try to generate key only when instance is running
- # and instance_key is same is cloud account key (same names - in dbomatic we
- # copy cloud account key to instance key)
+ # we try to generate unique key only when instance is running
+ # and cloud_account for this instance has instance_key (cloud account
+ # instance_key is used as default ssh key when instance is launched)
if instance.state_changed? and instance.state == Instance::STATE_RUNNING and
- instance.instance_key and instance.instance_key.name ==
instance.cloud_account.instance_key.name
+ not instance.instance_key and instance.cloud_account and
instance.cloud_account.instance_key
instance.delay.create_unique_key
end
end
diff --git a/src/dbomatic/dbomatic b/src/dbomatic/dbomatic
index e021ff6..7067bb0 100755
--- a/src/dbomatic/dbomatic
+++ b/src/dbomatic/dbomatic
@@ -209,14 +209,6 @@ class CondorEventLog < Nokogiri::XML::SAX::Document
inst.cloud_account_id = cloud_account.id
- # FIXME: we are updating the instance_key_id here, but this is really not
- # the right way or place to do this. This will have to be revisited when
- # we come up with a real key management architecture
- new_key = InstanceKey.new(cloud_account.instance_key.attributes)
- new_key.instance_key_owner = inst
- new_key.save!
- inst.instance_key = new_key
-
inst.save!
end
--
1.7.3.5