Skip to content

Commit

Permalink
run_instanceもほぼ実装
Browse files Browse the repository at this point in the history
  • Loading branch information
sakama committed Jul 11, 2013
1 parent c10dfac commit b4d2597
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 90 deletions.
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Vagrant.configure("2") do |config|
niftycloud.secret_access_key = ENV["NIFTY_CLOUD_SECRET_KEY"] || "<Your Secret Access Key>"
niftycloud.image_id = "26"
niftycloud.key_name = "<YOUR SSH KEY NAME>"
override.ssh.username = "root"
override.ssh.private_key_path = "PATH TO YOUR PRIVATE KEY"
end
Expand Down Expand Up @@ -97,7 +97,8 @@ boxフォーマットには`metadata.json`が必要です。


* `access_key_id` - ニフティクラウドのAccessKey。[コントロールパネルから取得した値](http://cloud.nifty.com/help/status/api_key.htm)を指定して下さい。
* `image_id` - サーバ立ち上げ時に指定するimage_id。(後述)
* `image_id` - サーバ立ち上げ時に指定するimage_id。([後述](https://github.com/sakama/vagrant-niftycloud#image_id))
* `key_name` - サーバ接続時に使用するSSHキー名。[コントロールパネルで設定した値](http://cloud.nifty.com/help/netsec/ssh_key.htm)を指定して下さい。
* `availability_zone` - ニフティクラウドのゾーン。例)"east-12"
* `instance_ready_timeout` - インスタンス起動実行からタイムアウトとなるまでの秒数。デフォルトは120秒です。
* `instance_type` - サーバタイプ。例)"small2"。指定がない場合のデフォルト値は"mini"です。
Expand Down Expand Up @@ -131,6 +132,7 @@ Vagrant.configure("2") do |config|
niftycloud.access_key_id = "foo"
niftycloud.secret_access_key = "bar"
niftycloud.region = "east-12"
niftycloud.key_name = "vagrantkey"
# シンプルな書き方
niftycloud.region_config "east-12", :image_id => 26
Expand All @@ -139,6 +141,7 @@ Vagrant.configure("2") do |config|
niftycloud.region_config "east-13" do |region|
region.image_id = 21
region.instance_type = small
region.key_name = "vagrantkey2"
end
end
end
Expand All @@ -152,11 +155,11 @@ end

以下にニフティから提供されている公式イメージとそのIDを記載します。

全てのOS・ディストリビューションでのテストは行なっていません。
`全てのOS・ディストリビューションでの動作確認は行なっていません。`

自分で作成したサーバイメージを使用する場合等でimage_idを確認したい時には[ニフティクラウドAPI](http://cloud.nifty.com/api/rest/reference.htm)[DescribeImages](http://cloud.nifty.com/api/rest/DescribeImages.htm)を使用すると確認できます。

[ニフティクラウドSDK for Ruby](http://cloud.nifty.com/api/sdk/#ruby)[knife-nc](https://github.com/tily/ruby-knife-nc)等を使うとより簡単です。
[ニフティクラウドSDK for Ruby](http://cloud.nifty.com/api/sdk/#ruby)[ニフティクラウド CLI](http://cloud.nifty.com/api/cli/)[knife-nc](https://github.com/tily/ruby-knife-nc)等を使うとより簡単です。

image_id | OS・ディストリビューション |
------------|------------------------------------|
Expand Down Expand Up @@ -194,9 +197,11 @@ Vagrantの`config.vm.network`で設定可能なネットワーク機能につい

[vagrant-aws](https://github.com/mitchellh/vagrant-aws)には起動したインスタンスに任意のTagsを付与するためのオプションが存在しますが、ニフティクラウド自体がTags機能に対応していないため未対応となります。

### User data
### サーバ起動時スクリプト

以下のようにニフティクラウドの[サーバ起動時スクリプト](http://cloud.nifty.com/service/svscript.htm)を使用したインスタンスの立ち上げが可能です。

以下のようにUser dataを使用したインスタンスの立ち上げが可能です
ChefやFabricを使って立ち上げる場合、一般的には指定しないことが多いと思います

```
Vagrant.configure("2") do |config|
Expand Down
2 changes: 1 addition & 1 deletion example_box/Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@

Vagrant.configure("2") do |config|
config.vm.provider :niftycloud do |niftycloud|
niftycloud.ami = "21"
niftycloud.image_id = 26
end
end
21 changes: 7 additions & 14 deletions lib/vagrant-niftycloud/action/read_ssh_info.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,19 @@ def read_ssh_info(niftycloud, machine)
return nil if machine.id.nil?

# Find the machine
instances = env[:niftycloud_compute].describe_instances(:instance_id => machine.id)
if instances.nil?
server = env[:niftycloud_compute].describe_instances(:instance_id => machine.id)).reservationSet.item.first.instancesSet.item.first
if server.nil?
# The machine can't be found
@logger.info("Machine couldn't be found, assuming it got destroyed.")
machine.id = nil
return nil
end

reservationSet.item.each do |set|
set.instancesSet.item.each do |instance|
server = instance.instancesSet.item.first
if server.instanceId == machine.id
# Read the DNS info
return {
:host => server.ipAddress
:port => 22
}
end
end
end
# Read the DNS info
return {
:host => server.ipAddress
:port => 22
}
end
end
end
Expand Down
28 changes: 10 additions & 18 deletions lib/vagrant-niftycloud/action/read_state.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,23 @@ def read_state(niftycloud, machine)
return :not_created if machine.id.nil?

# Find the machine
instances = env[:niftycloud_compute].describe_instances(:instance_id => machine.id)
if instances.nil?
server = env[:niftycloud_compute].describe_instances(:instance_id => machine.id)).reservationSet.item.first.instancesSet.item.first
if server.nil?
# The machine can't be found
@logger.info("Machine not found or terminated, assuming it got destroyed.")
machine.id = nil
return :not_created
end

reservationSet.item.each do |set|
set.instancesSet.item.each do |instance|
server = instance.instancesSet.item.first
if server.instanceId == machine.id
state = server.instanceState.name
case state
when 'stopped', 'warning', 'waiting', 'creating', 'suspending', 'uploading', 'import_error', 'pending'
@logger.info("Machine not found or terminated, assuming it got destroyed.")
machine.id = nil
return :not_created
else
return state.to_sym
end
end
end
state = server.instanceState.name
case state
when 'stopped', 'warning', 'waiting', 'creating', 'suspending', 'uploading', 'import_error', 'pending'
@logger.info("Machine not found or terminated, assuming it got destroyed.")
machine.id = nil
return :not_created
else
return state.to_sym
end
return :not_created
end
end
end
Expand Down
61 changes: 29 additions & 32 deletions lib/vagrant-niftycloud/action/run_instance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,57 +22,55 @@ def call(env)
region = env[:machine].provider_config.region

# Get the configs
region_config = env[:machine].provider_config.get_region_config(region)
image_id = region_config.image_id
availability_zone = region_config.availability_zone
instance_type = region_config.instance_type
security_groups = region_config.security_groups
user_data = region_config.user_data

# If there is no keypair then warn the user
if !keypair
env[:ui].warn(I18n.t("vagrant_niftycloud.launch_no_keypair"))
end
region_config = env[:machine].provider_config.get_region_config(region)
image_id = region_config.image_id
availability_zone = region_config.availability_zone
instance_type = region_config.instance_type
key_name = region_config.key_name,
security_groups = [region_config.security_groups]
user_data = region_config.user_data

# Launch!
env[:ui].info(I18n.t("vagrant_niftycloud.launching_instance"))
env[:ui].info(" -- Type: #{instance_type}")
env[:ui].info(" -- ImageId: #{image_id}")
env[:ui].info(" -- Availability Zone: #{availability_zone}") if availability_zone
env[:ui].info(" -- Availability Zone: #{availability_zone}") if availability_zone
env[:ui].info(" -- Key Name: #{key_name}") if key_name
env[:ui].info(" -- User Data: yes") if user_data
env[:ui].info(" -- Security Groups: #{security_groups.inspect}") if !security_groups.empty?
env[:ui].info(" -- User Data: #{user_data}") if user_data

begin
options = {
:availability_zone => availability_zone,
:flavor_id => instance_type,
:image_id => image_id,
:user_data => user_data
:availability_zone => availability_zone,
:instance_type => instance_type,
:image_id => image_id,
:key_name => key_name,
:user_data => user_data
:accounting_type => 2 #従量課金
:disable_api_termination => false #APIから即terminate可
}

if !security_groups.empty?
security_group_key = :groups
options[security_group_key] = security_groups
end

server = env[:niftycloud_compute].servers.create(options)
rescue Fog::Compute::NiftyCloud::NotFound => e
# Invalid subnet doesn't have its own error so we catch and
# check the error message here.
if e.message =~ /subnet ID/
raise Errors::FogError,
:message => "Subnet ID not found: #{subnet_id}"
end
# インスタンス立ち上げ開始
server = env[:niftycloud_compute].run_instances(options).instancesSet.item.first

raise
rescue Fog::Compute::NiftyCloud::Error => e
raise Errors::FogError, :message => e.message
# wait for it to be ready to do stuff
while server.instanceState.name != 'running'
server = env[:niftycloud_compute].describe_instances(:instance_id => server.instanceId).reservationSet.item.first.instancesSet.item.first
sleep 5
end
rescue
raise Errors::VagrantNiftyCloudError, :message => e.message
end

# Immediately save the ID since it is created at this point.
env[:machine].id = server.id

env[:machine].id = server.instanceId
# Wait for the instance to be ready first
env[:metrics]["instance_ready_time"] = Util::Timer.time do
tries = region_config.instance_ready_timeout / 2
Expand All @@ -86,13 +84,12 @@ def call(env)
# Wait for the server to be ready
server.wait_for(2) { ready? }
end
rescue Fog::Errors::TimeoutError
rescue
# Delete the instance
terminate(env)

# Notify the user
raise Errors::InstanceReadyTimeout,
timeout: region_config.instance_ready_timeout
raise Errors::InstanceReadyTimeout, timeout: region_config.instance_ready_timeout
end
end

Expand Down
12 changes: 8 additions & 4 deletions lib/vagrant-niftycloud/action/terminate_instance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,15 @@ def initialize(app, env)
end

def call(env)
env[:ui].info(I18n.t("vagrant_niftycloud.terminating"))
response = env[:niftycloud_compute].terminate_instances(:instance_id => env[:machine].id)
env[:machine].id = nil
begin
env[:ui].info(I18n.t("vagrant_niftycloud.terminating"))
response = env[:niftycloud_compute].terminate_instances(:instance_id => env[:machine].id)
env[:machine].id = nil

@app.call(env)
@app.call(env)
rescue NoMethodError
ui.error("Could not locate server '#{env[:machine].id}'. Please verify it was provisioned in the current region.")
end
end
end
end
Expand Down
94 changes: 82 additions & 12 deletions lib/vagrant-niftycloud/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,10 @@ class Config < Vagrant.plugin("2", :config)
# @return [String]
attr_accessor :instance_type

# The NiftyCloud endpoint to connect to
# The name of the keypair to use.
#
# @return [String]
attr_accessor :endpoint

# The version of the NiftyCloud api to use
#
# @return [String]
attr_accessor :version
attr_accessor :key_name

# The secret access key for accessing NiftyCloud.
#
Expand All @@ -61,8 +56,7 @@ def initialize(region_specific=false)
@availability_zone = UNSET_VALUE
@instance_ready_timeout = UNSET_VALUE
@instance_type = UNSET_VALUE
@endpoint = UNSET_VALUE
@version = UNSET_VALUE
@key_name = UNSET_VALUE
@secret_access_key = UNSET_VALUE
@security_groups = UNSET_VALUE
@user_data = UNSET_VALUE
Expand All @@ -75,6 +69,62 @@ def initialize(region_specific=false)
@__region_specific = region_specific
end

# Allows region-specific overrides of any of the settings on this
# configuration object. This allows the user to override things like
# image_id and key name for regions. Example:
#
# niftycloud.region_config "east-12" do |region|
# region.image_id = 21
# region.key_name = "company-east12"
# end
#
# @param [String] region The region name to configure.
# @param [Hash] attributes Direct attributes to set on the configuration
# as a shortcut instead of specifying a full block.
# @yield [config] Yields a new Nifty Cloud configuration.
def region_config(region, attributes=nil, &block)
# Append the block to the list of region configs for that region.
# We'll evaluate these upon finalization.
@__region_config[region] ||= []

# Append a block that sets attributes if we got one
if attributes
attr_block = lambda do |config|
config.set_options(attributes)
end

@__region_config[region] << attr_block
end

# Append a block if we got one
@__region_config[region] << block if block_given?
end

#-------------------------------------------------------------------
# Internal methods.
#-------------------------------------------------------------------

def merge(other)
super.tap do |result|
# Copy over the region specific flag. "True" is retained if either
# has it.
new_region_specific = other.instance_variable_get(:@__region_specific)
result.instance_variable_set(
:@__region_specific, new_region_specific || @__region_specific)

# Go through all the region configs and prepend ours onto
# theirs.
new_region_config = other.instance_variable_get(:@__region_config)
@__region_config.each do |key, value|
new_region_config[key] ||= []
new_region_config[key] = value + new_region_config[key]
end

# Set it
result.instance_variable_set(:@__region_config, new_region_config)
end
end

def finalize!
# Try to get access keys from standard NiftyCloud environment variables; they
# will default to nil if the environment variables are not present.
Expand All @@ -90,16 +140,36 @@ def finalize!
# Default instance type is an mini
@instance_type = "mini" if @instance_type == UNSET_VALUE

@availability_zone = nil if @availability_zone == UNSET_VALUE
@endpoint = nil if @endpoint == UNSET_VALUE
@version = nil if @version == UNSET_VALUE
# Keypair defaults to nil
@key_name = nil if @key_name == UNSET_VALUE

@availability_zone = nil if @availability_zone == UNSET_VALUE

# The security groups are empty by default.
@security_groups = [] if @security_groups == UNSET_VALUE

# User Data is nil by default
@user_data = nil if @user_data == UNSET_VALUE

if !@__region_specific
@__region_config.each do |region, blocks|
config = self.class.new(true).merge(self)

# Execute the configuration for each block
blocks.each { |b| b.call(config) }

# The region name of the configuration always equals the
# region config name:
config.region = region

# Finalize the configuration
config.finalize!

# Store it for retrieval
@__compiled_region_configs[region] = config
end
end

# Mark that we finalized
@__finalized = true
end
Expand Down
Loading

0 comments on commit b4d2597

Please sign in to comment.