From: Jan Provaznik <[email protected]>

Key per instance setup should work this way:
- create instance key for each provider account
- when creating an instance we use this cloud account key (it's passed to 
condor)
- when instance is started, we generate unique instance key and update it in 
instance (from instance observer)
---
 src/app/models/cloud_account.rb                    |   13 +++--------
 src/app/models/cloud_account_observer.rb           |    9 ++++++++
 src/app/models/instance.rb                         |    3 +-
 src/app/models/instance_key.rb                     |    3 +-
 src/app/models/instance_observer.rb                |    9 ++++++++
 src/config/environment.rb                          |    2 +-
 src/db/migrate/20090804142049_create_instances.rb  |    1 -
 .../migrate/20100902081651_create_instance_keys.rb |    3 +-
 src/spec/models/cloud_account_observer_spec.rb     |   22 ++++++++++++++++++++
 src/spec/models/instance_observer_spec.rb          |   13 +++++++++++
 10 files changed, 63 insertions(+), 15 deletions(-)
 create mode 100644 src/app/models/cloud_account_observer.rb
 create mode 100644 src/spec/models/cloud_account_observer_spec.rb

diff --git a/src/app/models/cloud_account.rb b/src/app/models/cloud_account.rb
index e4fe6c6..4371a1a 100644
--- a/src/app/models/cloud_account.rb
+++ b/src/app/models/cloud_account.rb
@@ -33,7 +33,7 @@ class CloudAccount < ActiveRecord::Base
            :include => [:role],
            :order => "permissions.id ASC"
 
-  has_one :instance_key, :dependent => :destroy
+  has_one :instance_key, :as => :instance_key_owner, :dependent => :destroy
 
   # Helpers
   attr_accessor :x509_cert_priv_file, :x509_cert_pub_file
@@ -62,7 +62,6 @@ class CloudAccount < ActiveRecord::Base
   end
 
   # Hooks
-  after_create :generate_cloud_account_key
   before_destroy :destroyable?
   before_validation :read_x509_files
 
@@ -170,13 +169,9 @@ EOT
     return xml.to_s
   end
 
-  private
-  def generate_cloud_account_key
+  def generate_auth_key
     client = connect
-    if client && client.feature?(:instances, :authentication_key)
-      key = client.create_key(:name => "#{self.name}_#{Time.now.to_i}_key")
-      InstanceKey.create(:cloud_account => self, :pem => key.pem, :name => 
key.id) if key
-    end
+    return nil unless client && client.feature?(:instances, 
:authentication_key)
+    client.create_key(:name => 
"#{self.name}_#{Time.now.to_i}_key_#{self.object_id}")
   end
-
 end
diff --git a/src/app/models/cloud_account_observer.rb 
b/src/app/models/cloud_account_observer.rb
new file mode 100644
index 0000000..a0826ea
--- /dev/null
+++ b/src/app/models/cloud_account_observer.rb
@@ -0,0 +1,9 @@
+class CloudAccountObserver < ActiveRecord::Observer
+  def after_create(account)
+    if key = account.generate_auth_key
+      account.update_attribute(:instance_key, InstanceKey.create!(:pem => 
key.pem, :name => key.id, :instance_key_owner => account))
+    end
+  end
+end
+
+CloudAccountObserver.instance
diff --git a/src/app/models/instance.rb b/src/app/models/instance.rb
index 8573c5a..e7757e3 100644
--- a/src/app/models/instance.rb
+++ b/src/app/models/instance.rb
@@ -33,9 +33,10 @@ class Instance < ActiveRecord::Base
   belongs_to :template
   belongs_to :realm
   belongs_to :owner, :class_name => "User", :foreign_key => "owner_id"
-  belongs_to :instance_key
   belongs_to :instance_hwp
 
+  has_one :instance_key, :as => :instance_key_owner, :dependent => :destroy
+
   validates_presence_of :pool_id
   validates_presence_of :hardware_profile_id
   validates_presence_of :template_id
diff --git a/src/app/models/instance_key.rb b/src/app/models/instance_key.rb
index b3b7513..9c941fe 100644
--- a/src/app/models/instance_key.rb
+++ b/src/app/models/instance_key.rb
@@ -21,7 +21,6 @@
 #
 class InstanceKey < ActiveRecord::Base
 
-  belongs_to :cloud_account
-  has_many :instances
+  belongs_to :instance_key_owner, :polymorphic => true
 
 end
diff --git a/src/app/models/instance_observer.rb 
b/src/app/models/instance_observer.rb
index 3b9af13..80b39c5 100644
--- a/src/app/models/instance_observer.rb
+++ b/src/app/models/instance_observer.rb
@@ -61,6 +61,15 @@ class InstanceObserver < ActiveRecord::Observer
     end
   end
 
+  def before_update(instance)
+    # we try to generate key only when instance is running
+    # and instance_key is not generated yet
+    return if instance.state != Instance::STATE_RUNNING or 
instance.instance_key
+    if key = instance.cloud_account.generate_auth_key
+      instance.instance_key = InstanceKey.create!(:pem => key.pem, :name => 
key.id, :instance_key_owner => instance)
+    end
+  end
+
 end
 
 InstanceObserver.instance
diff --git a/src/config/environment.rb b/src/config/environment.rb
index 09ec85b..d00ae2f 100644
--- a/src/config/environment.rb
+++ b/src/config/environment.rb
@@ -56,7 +56,7 @@ Rails::Initializer.run do |config|
 
   config.middleware.swap Rack::MethodOverride, 'Rack::RestfulSubmit'
 
-  config.active_record.observers = :instance_observer, :task_observer
+  config.active_record.observers = :instance_observer, :task_observer, 
:cloud_account_observer
   # Only load the plugins named here, in the order given. By default, all 
plugins
   # in vendor/plugins are loaded in alphabetical order.
   # :all can be used as a placeholder for all plugins not explicitly named
diff --git a/src/db/migrate/20090804142049_create_instances.rb 
b/src/db/migrate/20090804142049_create_instances.rb
index 5c84456..de5533d 100644
--- a/src/db/migrate/20090804142049_create_instances.rb
+++ b/src/db/migrate/20090804142049_create_instances.rb
@@ -36,7 +36,6 @@ class CreateInstances < ActiveRecord::Migration
       t.string    :state
       t.string    :condor_job_id
       t.string    :last_error
-      t.integer   :instance_key_id
       t.integer   :lock_version, :default => 0
       t.integer   :acc_pending_time, :default => 0
       t.integer   :acc_running_time, :default => 0
diff --git a/src/db/migrate/20100902081651_create_instance_keys.rb 
b/src/db/migrate/20100902081651_create_instance_keys.rb
index 841d7ff..8ee23fb 100644
--- a/src/db/migrate/20100902081651_create_instance_keys.rb
+++ b/src/db/migrate/20100902081651_create_instance_keys.rb
@@ -1,7 +1,8 @@
 class CreateInstanceKeys < ActiveRecord::Migration
   def self.up
     create_table :instance_keys do |t|
-      t.integer :cloud_account_id, :null => false
+      t.integer :instance_key_owner_id, :null => false
+      t.string  :instance_key_owner_type, :null => false
       t.string  :name, :null => false
       t.text    :pem
       t.timestamps
diff --git a/src/spec/models/cloud_account_observer_spec.rb 
b/src/spec/models/cloud_account_observer_spec.rb
new file mode 100644
index 0000000..48491c0
--- /dev/null
+++ b/src/spec/models/cloud_account_observer_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe CloudAccountObserver do
+  fixtures :all
+
+  it "should create an instance_key if provider is EC2" do
+    @client = mock('DeltaCloud', :null_object => true)
+    @provider = Factory.build :ec2_provider
+    @key = mock('Key', :null_object => true)
+    @key.stub!(:pem).and_return("PEM")
+    @key.stub!(:id).and_return("1_user")
+    @client.stub!(:"feature?").and_return(true)
+    @client.stub!(:"create_key").and_return(@key)
+
+    cloud_account = Factory.build :ec2_cloud_account
+    cloud_account.stub!(:connect).and_return(@client)
+    cloud_account.save
+    cloud_account.instance_key.should_not == nil
+    cloud_account.instance_key.pem == "PEM"
+    cloud_account.instance_key.id == "1_user"
+  end
+end
diff --git a/src/spec/models/instance_observer_spec.rb 
b/src/spec/models/instance_observer_spec.rb
index a696319..96eac6d 100644
--- a/src/spec/models/instance_observer_spec.rb
+++ b/src/spec/models/instance_observer_spec.rb
@@ -154,4 +154,17 @@ describe InstanceObserver do
     end
   end
 
+  it "should generate instance key when instance is running" do
+    client = mock('DeltaCloud', :null_object => true)
+    key = mock('Key', :null_object => true)
+    key.stub!(:pem).and_return("PEM")
+    key.stub!(:id).and_return("1_user")
+    client.stub!(:"feature?").and_return(true)
+    client.stub!(:"create_key").and_return(key)
+    @cloud_account.stub!(:connect).and_return(client)
+
+    @instance.state = Instance::STATE_RUNNING
+    @instance.save!
+    @instance.instance_key.should_not == nil
+  end
 end
-- 
1.7.3.4

_______________________________________________
deltacloud-devel mailing list
[email protected]
https://fedorahosted.org/mailman/listinfo/deltacloud-devel

Reply via email to