From: Jan Provaznik jprovazn@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