1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-27 14:03:40 +03:00

Merge branch 'feature-378'

This commit is contained in:
Ruben S. Montero 2012-08-31 23:19:17 +02:00
commit f645213add
38 changed files with 2150 additions and 333 deletions

View File

@ -1080,12 +1080,21 @@ ECO_LIB_FILES="src/cloud/ec2/lib/EC2QueryClient.rb \
src/cloud/ec2/lib/EC2QueryServer.rb \
src/cloud/ec2/lib/ImageEC2.rb \
src/cloud/ec2/lib/elastic_ip.rb \
src/cloud/ec2/lib/ebs.rb \
src/cloud/ec2/lib/instance.rb \
src/cloud/ec2/lib/econe-server.rb"
ECO_LIB_CLIENT_FILES="src/cloud/ec2/lib/EC2QueryClient.rb"
ECO_LIB_VIEW_FILES="src/cloud/ec2/lib/views/describe_images.erb \
src/cloud/ec2/lib/views/describe_instances.erb \
src/cloud/ec2/lib/views/describe_regions.erb \
src/cloud/ec2/lib/views/describe_availability_zones.erb \
src/cloud/ec2/lib/views/create_volume.erb \
src/cloud/ec2/lib/views/describe_volumes.erb \
src/cloud/ec2/lib/views/attach_volume.erb \
src/cloud/ec2/lib/views/detach_volume.erb \
src/cloud/ec2/lib/views/delete_volume.erb \
src/cloud/ec2/lib/views/register_image.erb \
src/cloud/ec2/lib/views/run_instances.erb \
src/cloud/ec2/lib/views/allocate_address.erb \
@ -1093,14 +1102,25 @@ ECO_LIB_VIEW_FILES="src/cloud/ec2/lib/views/describe_images.erb \
src/cloud/ec2/lib/views/disassociate_address.erb \
src/cloud/ec2/lib/views/describe_addresses.erb \
src/cloud/ec2/lib/views/release_address.erb \
src/cloud/ec2/lib/views/terminate_instances.erb"
src/cloud/ec2/lib/views/terminate_instances.erb \
src/cloud/ec2/lib/views/stop_instances.erb \
src/cloud/ec2/lib/views/reboot_instances.erb \
src/cloud/ec2/lib/views/start_instances.erb"
ECO_BIN_FILES="src/cloud/ec2/bin/econe-server \
src/cloud/ec2/bin/econe-describe-images \
src/cloud/ec2/bin/econe-describe-volumes \
src/cloud/ec2/bin/econe-describe-instances \
src/cloud/ec2/bin/econe-register \
src/cloud/ec2/bin/econe-attach-volume \
src/cloud/ec2/bin/econe-detach-volume \
src/cloud/ec2/bin/econe-delete-volume \
src/cloud/ec2/bin/econe-create-volume \
src/cloud/ec2/bin/econe-run-instances \
src/cloud/ec2/bin/econe-terminate-instances \
src/cloud/ec2/bin/econe-start-instances \
src/cloud/ec2/bin/econe-stop-instances \
src/cloud/ec2/bin/econe-reboot-instances \
src/cloud/ec2/bin/econe-describe-addresses \
src/cloud/ec2/bin/econe-allocate-address \
src/cloud/ec2/bin/econe-release-address \
@ -1110,9 +1130,17 @@ ECO_BIN_FILES="src/cloud/ec2/bin/econe-server \
ECO_BIN_CLIENT_FILES="src/cloud/ec2/bin/econe-describe-images \
src/cloud/ec2/bin/econe-describe-instances \
src/cloud/ec2/bin/econe-describe-volumes \
src/cloud/ec2/bin/econe-register \
src/cloud/ec2/bin/econe-attach-volume \
src/cloud/ec2/bin/econe-detach-volume \
src/cloud/ec2/bin/econe-delete-volume \
src/cloud/ec2/bin/econe-create-volume \
src/cloud/ec2/bin/econe-run-instances \
src/cloud/ec2/bin/econe-terminate-instances \
src/cloud/ec2/bin/econe-start-instances \
src/cloud/ec2/bin/econe-stop-instances \
src/cloud/ec2/bin/econe-reboot-instances \
src/cloud/ec2/bin/econe-describe-addresses \
src/cloud/ec2/bin/econe-allocate-address \
src/cloud/ec2/bin/econe-release-address \

View File

@ -115,11 +115,11 @@ if CloudClient::is_error?(addr)
end
if headers
puts "publicIP"
puts "publicIp"
puts "------------------------------------------------------------------------------"
end
puts addr['publicIP']
puts addr['publicIp']
exit 0

View File

@ -0,0 +1,150 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
end
$: << RUBY_LIB_LOCATION
$: << RUBY_LIB_LOCATION+"/cloud"
COMMANDS_HELP=<<-EOT
econe-attach-volume
Attaches a DATABLOCK to a running instance and exposes it as the specified device.
Usage:
econe-attach-volume [OPTIONS] VOLUME-ID
Options:
--help, -h
Show help
--access-key <id>, -K <id>
The username of the user
--secret-key <key>, -S <key>
The password of the user
--url <url>, -U <url>
Set url as the web service url to use
--instance <instance_id>, -i <instance_id>
The ID of the instance to attach the volume to
--device <device>, -d <device
Specifies the device name to expose to the instance.
Example: -d /dev/sdf
--headers, -H
Display column headers
VOLUME-ID: The ID of the DATABLOCK
EOT
require 'econe/EC2QueryClient'
require 'CloudClient'
require 'getoptlong'
include CloudCLI
opts = GetoptLong.new(
['--help', '-h',GetoptLong::NO_ARGUMENT],
['--version', '-v',GetoptLong::NO_ARGUMENT],
['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT],
['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT],
['--url', '-U',GetoptLong::REQUIRED_ARGUMENT],
['--instance', '-i',GetoptLong::REQUIRED_ARGUMENT],
['--device', '-d',GetoptLong::REQUIRED_ARGUMENT],
['--headers', '-H',GetoptLong::NO_ARGUMENT]
)
headers = false
url = nil
access = nil
secret = nil
auth = nil
instance = nil
device = nil
begin
opts.each do |opt, arg|
case opt
when '--help'
puts COMMANDS_HELP
return
when '--version'
puts CloudCLI.version_text
exit 0
when '--access-key'
access = arg
when '--secret-key'
secret = arg
when '--url'
url = arg
when '--instance'
instance = arg
when '--headers'
headers = true
when '--device'
device = arg
end
end
rescue Exception => e
exit -1
end
volume_id = ARGV.shift
if !volume_id
puts "#{cmd_name}: missing VOLUME-ID parameter"
exit -1
end
auth = "#{access}:#{secret}" if secret && access
begin
ec2_client = EC2QueryClient::Client.new(auth,url)
rescue Exception => e
puts "#{cmd_name}: #{e.message}"
exit -1
end
rc = ec2_client.attach_volume(volume_id, instance, device)
if CloudClient::is_error?(rc)
puts "#{cmd_name}: #{rc.message}"
exit -1
end
fmt = "%-15s %-15s %-10s %s"
if headers
puts fmt % ["volumeId", "instanceId", "status", "device"]
puts "------------------------------------------------------------------------------"
end
puts fmt % [rc['volumeId'], rc['instanceId'], rc['status'], rc['device']]
exit 0

View File

@ -0,0 +1,138 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
end
$: << RUBY_LIB_LOCATION
$: << RUBY_LIB_LOCATION+"/cloud"
COMMANDS_HELP=<<-EOT
econe-create-volume
Create a new DATABLOCK
Usage:
econe-create-volume [OPTIONS]
Options:
--help, -h
Show help
--access-key <id>, -K <id>
The username of the user
--secret-key <key>, -S <key>
The password of the user
--url <url>, -U <url>
Set url as the web service url to use
--size <size>, -s <size>
The ID of the instance to attach the volume to
--headers, -H
Display column headers
EOT
require 'econe/EC2QueryClient'
require 'CloudClient'
require 'getoptlong'
include CloudCLI
opts = GetoptLong.new(
['--help', '-h',GetoptLong::NO_ARGUMENT],
['--version', '-v',GetoptLong::NO_ARGUMENT],
['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT],
['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT],
['--url', '-U',GetoptLong::REQUIRED_ARGUMENT],
['--size', '-s',GetoptLong::REQUIRED_ARGUMENT],
['--headers', '-H',GetoptLong::NO_ARGUMENT]
)
headers = false
url = nil
access = nil
secret = nil
auth = nil
size = nil
begin
opts.each do |opt, arg|
case opt
when '--help'
puts COMMANDS_HELP
return
when '--version'
puts CloudCLI.version_text
exit 0
when '--access-key'
access = arg
when '--secret-key'
secret = arg
when '--url'
url = arg
when '--size'
size = arg
when '--headers'
headers = true
end
end
rescue Exception => e
exit -1
end
if !size
puts "#{cmd_name}: missing --size option"
exit -1
end
auth = "#{access}:#{secret}" if secret && access
begin
ec2_client = EC2QueryClient::Client.new(auth,url)
rescue Exception => e
puts "#{cmd_name}: #{e.message}"
exit -1
end
rc = ec2_client.create_volume(size)
if CloudClient::is_error?(rc)
puts "#{cmd_name}: #{rc.message}"
exit -1
end
fmt = "%-15s %-10s %s"
if headers
puts fmt % ["volumeId", "size", "createTime"]
puts "------------------------------------------------------------------------------"
end
puts fmt % [rc['volumeId'], rc['size'], rc['createTime']]
exit 0

View File

@ -0,0 +1,126 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
end
$: << RUBY_LIB_LOCATION
$: << RUBY_LIB_LOCATION+"/cloud"
COMMANDS_HELP=<<-EOT
econe-delete-volume
Deletes a DATABLOCK
Usage:
econe-delete-volume [OPTIONS] VOLUME-ID
Options:
--help, -h
Show help
--access-key <id>, -K <id>
The username of the user
--secret-key <key>, -S <key>
The password of the user
--url <url>, -U <url>
Set url as the web service url to use
--headers, -H
Display column headers
VOLUME-ID: The ID of the DATABLOCK
EOT
require 'econe/EC2QueryClient'
require 'CloudClient'
require 'getoptlong'
include CloudCLI
opts = GetoptLong.new(
['--help', '-h',GetoptLong::NO_ARGUMENT],
['--version', '-v',GetoptLong::NO_ARGUMENT],
['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT],
['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT],
['--url', '-U',GetoptLong::REQUIRED_ARGUMENT],
['--headers', '-H',GetoptLong::NO_ARGUMENT]
)
headers = false
url = nil
access = nil
secret = nil
auth = nil
begin
opts.each do |opt, arg|
case opt
when '--help'
puts COMMANDS_HELP
return
when '--version'
puts CloudCLI.version_text
exit 0
when '--access-key'
access = arg
when '--secret-key'
secret = arg
when '--url'
url = arg
when '--headers'
headers = true
end
end
rescue Exception => e
exit -1
end
volume_id = ARGV.shift
if !volume_id
puts "#{cmd_name}: missing VOLUME-ID parameter"
exit -1
end
auth = "#{access}:#{secret}" if secret && access
begin
ec2_client = EC2QueryClient::Client.new(auth,url)
rescue Exception => e
puts "#{cmd_name}: #{e.message}"
exit -1
end
rc = ec2_client.delete_volume(volume_id)
if CloudClient::is_error?(rc)
puts "#{cmd_name}: #{rc.message}"
exit -1
end
exit 0

View File

@ -114,7 +114,10 @@ if CloudClient::is_error?(rc)
exit -1
end
addresses = []
if rc['addressesSet']
addresses = rc['addressesSet']['item']
end
fmt = "%-12s %s"
@ -123,11 +126,9 @@ if headers
puts "------------------------------------------------------------------------------"
end
if addresses
addresses.each { |addr|
puts fmt % [addr['publicIP'],addr['instanceID']]
puts fmt % [addr['publicIp'],addr['instanceId']]
}
end
exit 0

View File

@ -115,7 +115,10 @@ if CloudClient::is_error?(rc)
exit -1
end
images = []
if rc['imagesSet']
images = rc['imagesSet']['item']
end
fmt = "%-12s %-13s %-14s %-12s %s"
@ -124,7 +127,6 @@ if headers
puts "------------------------------------------------------------------------------"
end
if images
images.each { |img|
if img['isPublic'] == 'true'
visibility = "public"
@ -133,7 +135,6 @@ if images
end
puts fmt % [img['imageOwnerId'],img['imageId'], img['imageState'], visibility,img['imageLocation']]
}
end
exit 0

View File

@ -113,7 +113,11 @@ if CloudClient::is_error?(rc)
exit -1
end
instances = []
if rc['reservationSet']['item'][0]['instancesSet']
instances = rc['reservationSet']['item'][0]['instancesSet']['item']
end
owner = rc['reservationSet']['item'][0]['ownerId']
fmt = "%-10s %-11s %-13s %-11s %-15s %-10s"
@ -123,9 +127,9 @@ if headers
puts "-----------------------------------------------------------------------------------"
end
if instances
instances.each { |img|
puts fmt % [owner, img['instanceId'],img['imageId'],img['instanceState']['name'],img['dnsName'],img['instanceType']]
}
end
exit 0

View File

@ -0,0 +1,141 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
end
$: << RUBY_LIB_LOCATION
$: << RUBY_LIB_LOCATION+"/cloud"
COMMANDS_HELP=<<-EOT
econe-describe-volumes
Describes your Amazon EBS volumes
Usage:
econe-describe-volumes [OPTIONS]
Options:
--help, -h
Show help
--access-key <id>, -K <id>
The username of the user
--secret-key <key>, -S <key>
The password of the user
--url <url>, -U <url>
Set url as the web service url to use
--headers, -H
Display column headers
EOT
require 'econe/EC2QueryClient'
require 'CloudClient'
require 'getoptlong'
include CloudCLI
opts = GetoptLong.new(
['--help', '-h',GetoptLong::NO_ARGUMENT],
['--version', '-v',GetoptLong::NO_ARGUMENT],
['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT],
['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT],
['--url', '-U',GetoptLong::REQUIRED_ARGUMENT],
['--headers', '-H',GetoptLong::NO_ARGUMENT]
)
headers = false
url = nil
access = nil
secret = nil
auth = nil
begin
opts.each do |opt, arg|
case opt
when '--help'
puts COMMANDS_HELP
return
when '--version'
puts CloudCLI.version_text
exit 0
when '--access-key'
access = arg
when '--secret-key'
secret = arg
when '--url'
url = arg
when '--headers'
headers = true
end
end
rescue Exception => e
exit -1
end
auth = "#{access}:#{secret}" if secret && access
begin
ec2_client = EC2QueryClient::Client.new(auth,url)
rescue Exception => e
puts "#{cmd_name}: #{e.message}"
exit -1
end
rc = ec2_client.describe_volumes
if CloudClient::is_error?(rc)
puts "#{cmd_name}: #{rc.message}"
exit -1
end
volumes = []
if rc['volumeSet']
volumes = rc['volumeSet']['item']
end
fmt = "%-15s %-10s %s"
if headers
puts fmt % ["volumeId", "size", "instanceId"]
puts "------------------------------------------------------------------------------"
end
volumes.each { |vol|
instances = ""
if vol['attachmentSet'] && vol['attachmentSet']['item']
instances = vol['attachmentSet']['item'].collect{ |item|
item['instanceId']
}.join(',')
end
puts fmt % [vol['volumeId'], vol['size'], instances]
}
exit 0

View File

@ -0,0 +1,151 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
end
$: << RUBY_LIB_LOCATION
$: << RUBY_LIB_LOCATION+"/cloud"
COMMANDS_HELP=<<-EOT
econe-detach-volume
Detaches an Amazon EBS volume from an instance. Make sure to unmount any
file systems on the device within your operating system before detaching the volume
Usage:
econe-detach-volume [OPTIONS] VOLUME-ID
Options:
--help, -h
Show help
--access-key <id>, -K <id>
The username of the user
--secret-key <key>, -S <key>
The password of the user
--url <url>, -U <url>
Set url as the web service url to use
--instance <instance_id>, -i <instance_id>
The ID of the instance to attach the volume to
--device <device>, -d <device
Specifies the device name to expose to the instance.
Example: -d /dev/sdf
--headers, -H
Display column headers
VOLUME-ID: The ID of the DATABLOCK
EOT
require 'econe/EC2QueryClient'
require 'CloudClient'
require 'getoptlong'
include CloudCLI
opts = GetoptLong.new(
['--help', '-h',GetoptLong::NO_ARGUMENT],
['--version', '-v',GetoptLong::NO_ARGUMENT],
['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT],
['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT],
['--url', '-U',GetoptLong::REQUIRED_ARGUMENT],
['--instance', '-i',GetoptLong::REQUIRED_ARGUMENT],
['--device', '-d',GetoptLong::REQUIRED_ARGUMENT],
['--headers', '-H',GetoptLong::NO_ARGUMENT]
)
headers = false
url = nil
access = nil
secret = nil
auth = nil
instance = nil
device = nil
begin
opts.each do |opt, arg|
case opt
when '--help'
puts COMMANDS_HELP
return
when '--version'
puts CloudCLI.version_text
exit 0
when '--access-key'
access = arg
when '--secret-key'
secret = arg
when '--url'
url = arg
when '--instance'
instance = arg
when '--headers'
headers = true
when '--device'
device = arg
end
end
rescue Exception => e
exit -1
end
volume_id = ARGV.shift
if !volume_id
puts "#{cmd_name}: missing VOLUME-ID parameter"
exit -1
end
auth = "#{access}:#{secret}" if secret && access
begin
ec2_client = EC2QueryClient::Client.new(auth,url)
rescue Exception => e
puts "#{cmd_name}: #{e.message}"
exit -1
end
rc = ec2_client.detach_volume(volume_id, instance, device)
if CloudClient::is_error?(rc)
puts "#{cmd_name}: #{rc.message}"
exit -1
end
fmt = "%-15s %-15s %-10s %s"
if headers
puts fmt % ["volumeId", "instanceId", "status", "device"]
puts "------------------------------------------------------------------------------"
end
puts fmt % [rc['volumeId'], rc['instanceId'], rc['status'], rc['device']]
exit 0

View File

@ -0,0 +1,125 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
end
$: << RUBY_LIB_LOCATION
$: << RUBY_LIB_LOCATION+"/cloud"
COMMANDS_HELP=<<-EOT
econe-reboot-instances
reboot the selected running instance
Usage:
econe-register [OPTIONS] INSTANCE-ID
Options:
--help, -h
Show help
--access-key <id>, -K <id>
The username of the user
--secret-key <key>, -S <key>
The password of the user
--url <url>, -U <url>
Set url as the web service url to use
INSTANCE-ID: The instance identification as returned by
the econe-run-instances command
EOT
require 'econe/EC2QueryClient'
require 'CloudClient'
require 'getoptlong'
include CloudCLI
opts = GetoptLong.new(
['--help', '-h',GetoptLong::NO_ARGUMENT],
['--version', '-v',GetoptLong::NO_ARGUMENT],
['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT],
['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT],
['--url', '-U',GetoptLong::REQUIRED_ARGUMENT]
)
url = nil
access = nil
secret = nil
auth = nil
begin
opts.each do |opt, arg|
case opt
when '--help'
puts COMMANDS_HELP
return
when '--version'
puts CloudCLI.version_text
exit 0
when '--access-key'
access = arg
when '--secret-key'
secret = arg
when '--url'
url = arg
when '--headers'
headers = true
end
end
rescue Exception => e
exit -1
end
instance = ARGV.shift
if !instance
puts "#{cmd_name}: missing INSTANCE-ID parameter"
exit -1
end
auth = "#{access}:#{secret}" if secret && access
begin
ec2_client = EC2QueryClient::Client.new(auth,url)
rescue Exception => e
puts "#{cmd_name}: #{e.message}"
exit -1
end
rc = ec2_client.reboot_instances(instance)
if CloudClient::is_error?(rc)
puts "#{cmd_name}: #{rc.message}"
exit -1
end
puts "Success: Reboting"
exit 0

View File

@ -0,0 +1,126 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
end
$: << RUBY_LIB_LOCATION
$: << RUBY_LIB_LOCATION+"/cloud"
COMMANDS_HELP=<<-EOT
econe-start-instances
Start the selected running instance
Usage:
econe-register [OPTIONS] INSTANCE-ID
Options:
--help, -h
Show help
--access-key <id>, -K <id>
The username of the user
--secret-key <key>, -S <key>
The password of the user
--url <url>, -U <url>
Set url as the web service url to use
INSTANCE-ID: The instance identification as returned by
the econe-run-instances command
EOT
require 'econe/EC2QueryClient'
require 'CloudClient'
require 'getoptlong'
include CloudCLI
opts = GetoptLong.new(
['--help', '-h',GetoptLong::NO_ARGUMENT],
['--version', '-v',GetoptLong::NO_ARGUMENT],
['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT],
['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT],
['--url', '-U',GetoptLong::REQUIRED_ARGUMENT]
)
url = nil
access = nil
secret = nil
auth = nil
begin
opts.each do |opt, arg|
case opt
when '--help'
puts COMMANDS_HELP
return
when '--version'
puts CloudCLI.version_text
exit 0
when '--access-key'
access = arg
when '--secret-key'
secret = arg
when '--url'
url = arg
when '--headers'
headers = true
end
end
rescue Exception => e
exit -1
end
instance = ARGV.shift
if !instance
puts "#{cmd_name}: missing INSTANCE-ID parameter"
exit -1
end
auth = "#{access}:#{secret}" if secret && access
begin
ec2_client = EC2QueryClient::Client.new(auth,url)
rescue Exception => e
puts "#{cmd_name}: #{e.message}"
exit -1
end
rc = ec2_client.start_instances(instance)
if CloudClient::is_error?(rc)
puts "#{cmd_name}: #{rc.message}"
exit -1
end
result = rc['instancesSet']['item'][0]
puts "Success: Starting #{result['instanceId']} in #{result['previousState']['name']} state"
exit 0

View File

@ -0,0 +1,126 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"]
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
end
$: << RUBY_LIB_LOCATION
$: << RUBY_LIB_LOCATION+"/cloud"
COMMANDS_HELP=<<-EOT
econe-stop-instances
Stop the selected running instance
Usage:
econe-register [OPTIONS] INSTANCE-ID
Options:
--help, -h
Show help
--access-key <id>, -K <id>
The username of the user
--secret-key <key>, -S <key>
The password of the user
--url <url>, -U <url>
Set url as the web service url to use
INSTANCE-ID: The instance identification as returned by
the econe-run-instances command
EOT
require 'econe/EC2QueryClient'
require 'CloudClient'
require 'getoptlong'
include CloudCLI
opts = GetoptLong.new(
['--help', '-h',GetoptLong::NO_ARGUMENT],
['--version', '-v',GetoptLong::NO_ARGUMENT],
['--access-key', '-K',GetoptLong::REQUIRED_ARGUMENT],
['--secret-key', '-S',GetoptLong::REQUIRED_ARGUMENT],
['--url', '-U',GetoptLong::REQUIRED_ARGUMENT]
)
url = nil
access = nil
secret = nil
auth = nil
begin
opts.each do |opt, arg|
case opt
when '--help'
puts COMMANDS_HELP
return
when '--version'
puts CloudCLI.version_text
exit 0
when '--access-key'
access = arg
when '--secret-key'
secret = arg
when '--url'
url = arg
when '--headers'
headers = true
end
end
rescue Exception => e
exit -1
end
instance = ARGV.shift
if !instance
puts "#{cmd_name}: missing INSTANCE-ID parameter"
exit -1
end
auth = "#{access}:#{secret}" if secret && access
begin
ec2_client = EC2QueryClient::Client.new(auth,url)
rescue Exception => e
puts "#{cmd_name}: #{e.message}"
exit -1
end
rc = ec2_client.stop_instances(instance)
if CloudClient::is_error?(rc)
puts "#{cmd_name}: #{rc.message}"
exit -1
end
result = rc['instancesSet']['item'][0]
puts "Success: Stopping #{result['instanceId']} in #{result['previousState']['name']} state"
exit 0

View File

@ -85,3 +85,10 @@
# Script to disassociate a public IP
# - arguments: elastic_ip
:disassociate_script: /usr/bin/false
#############################################################
# EBS
#############################################################
# FSTYPE that will be used when creating new volumes (DATABLOCKs)
:ebs_fstype: ext3

View File

@ -135,6 +135,57 @@ module EC2QueryClient
return response
end
######################################################################
#
#
######################################################################
def stop_instances(instance_id)
begin
response = @ec2_connection.stop_instances(
:instance_id => instance_id
)
rescue Exception => e
error = CloudClient::Error.new(e.message)
return error
end
return response
end
######################################################################
#
#
######################################################################
def start_instances(instance_id)
begin
response = @ec2_connection.start_instances(
:instance_id => instance_id
)
rescue Exception => e
error = CloudClient::Error.new(e.message)
return error
end
return response
end
######################################################################
#
#
######################################################################
def reboot_instances(instance_id)
begin
response = @ec2_connection.reboot_instances(
:instance_id => instance_id
)
rescue Exception => e
error = CloudClient::Error.new(e.message)
return error
end
return response
end
######################################################################
#
# Returns true if HTTP code is 200,
@ -305,5 +356,93 @@ module EC2QueryClient
return response
end
######################################################################
#
#
######################################################################
def describe_volumes
begin
response = @ec2_connection.describe_volumes
rescue Exception => e
error = CloudClient::Error.new(e.message)
return error
end
return response
end
######################################################################
#
#
######################################################################
def attach_volume(volume, instance, device)
begin
response = @ec2_connection.attach_volume(
:volume_id => volume,
:instance_id => instance,
:device => device
)
rescue Exception => e
error = CloudClient::Error.new(e.message)
return error
end
return response
end
######################################################################
#
#
######################################################################
def delete_volume(volume)
begin
response = @ec2_connection.delete_volume(
:volume_id => volume
)
rescue Exception => e
error = CloudClient::Error.new(e.message)
return error
end
return response
end
######################################################################
#
#
######################################################################
def detach_volume(volume, instance, device)
begin
response = @ec2_connection.detach_volume(
:volume_id => volume,
:instance_id => instance,
:device => device
)
rescue Exception => e
error = CloudClient::Error.new(e.message)
return error
end
return response
end
######################################################################
#
#
######################################################################
def create_volume(size)
begin
response = @ec2_connection.create_volume(
:size => size,
:availability_zone => 'default'
)
rescue Exception => e
error = CloudClient::Error.new(e.message)
return error
end
return response
end
end
end

View File

@ -22,6 +22,31 @@ require 'base64'
require 'CloudServer'
require 'ImageEC2'
require 'ebs'
require 'elastic_ip'
require 'instance'
module OpenNebula
EC2_ERROR = %q{
<Response>
<RequestId/>
<Errors>
<Error>
<Code><%= (@ec2_code||'UnsupportedOperation') %></Code>
<Message><%= @message %></Message>
</Error>
</Errors>
</Response>
}
class Error
attr_accessor :ec2_code
def to_ec2
ERB.new(EC2_ERROR).result(binding)
end
end
end
###############################################################################
# The EC2Query Server implements a EC2 compatible server based on the
@ -29,48 +54,6 @@ require 'ImageEC2'
###############################################################################
class EC2QueryServer < CloudServer
###########################################################################
# Class Constants. Defined the EC2 and OpenNebula State mapping
###########################################################################
EC2_STATES={
:pending => {:code => 0, :name => 'pending'},
:running => {:code => 16,:name => 'running'},
:shutdown => {:code => 32,:name => 'shutting-down'},
:terminated => {:code => 48,:name => 'terminated'}
}
ONE_STATES={
'init' => :pending,
'pend' => :pending,
'hold' => :pending,
'stop' => :pending,
'susp' => :pending,
'done' => :terminated,
'fail' => :terminated,
'prol' => :pending,
'boot' => :running,
'runn' => :running,
'migr' => :running,
'save' => :pending,
'epil' => :shutdown,
'shut' => :shutdown,
'clea' => :shutdown,
'fail' => :terminated,
'unkn' => :terminated
}
EC2_IMAGE_STATES={
"INIT" => "pending",
"READY" => "available",
"USED" => "available",
"DISABLED" => nil,
"LOCKED" => "pending",
"ERROR" => "failed",
"CLONE" => "available",
"DELETE" => nil,
"USED_PERS" => "available"
}
###########################################################################
def initialize(client, oneadmin_client, config, logger)
@ -79,12 +62,35 @@ class EC2QueryServer < CloudServer
@client = client
@oneadmin_client = oneadmin_client
if config[:ssl_server]
@base_url=config[:ssl_server]
else
@base_url="http://#{config[:server]}:#{config[:port]}"
end
if @config[:elasticips_vnet_id].nil?
logger.error { 'ElasticIP module not loaded' }
else
require 'elastic_ip'
extend ElasticIP
end
extend EBS
extend Instance
end
###########################################################################
# Regions and Availability Zones
###########################################################################
def describe_availability_zones(params)
response = ERB.new(
File.read(@config[:views]+"/describe_availability_zones.erb"))
return response.result(binding), 200
end
def describe_regions(params)
response = ERB.new(File.read(@config[:views]+"/describe_regions.erb"))
return response.result(binding), 200
end
###########################################################################
@ -92,16 +98,19 @@ class EC2QueryServer < CloudServer
###########################################################################
def upload_image(params)
image = ImageEC2.new(Image.build_xml, @client, params['file'])
image = ImageEC2.new(Image.build_xml,
@client,
params['file'],
{:type => "OS"})
template = image.to_one_template
if OpenNebula.is_error?(template)
return OpenNebula::Error.new('Unsupported'), 400
return template
end
rc = image.allocate(template, @config[:datastore_id]||1)
if OpenNebula.is_error?(rc)
return OpenNebula::Error.new('Unsupported'), 400
return rc
end
erb_version = params['Version']
@ -119,7 +128,8 @@ class EC2QueryServer < CloudServer
# Enable the new Image
rc = image.info
if OpenNebula.is_error?(rc)
return OpenNebula::Error.new('InvalidAMIID.NotFound'), 400
rc.ec2_code = "InvalidAMIID.NotFound"
return rc
end
image.enable
@ -132,8 +142,10 @@ class EC2QueryServer < CloudServer
def describe_images(params)
user_flag = OpenNebula::Pool::INFO_ALL
impool = ImagePool.new(@client, user_flag)
impool.info
impool = ImageEC2Pool.new(@client, user_flag)
rc = impool.info
return rc if OpenNebula::is_error?(rc)
erb_version = params['Version']
@ -141,113 +153,28 @@ class EC2QueryServer < CloudServer
return response.result(binding), 200
end
###########################################################################
# Instance Interface
###########################################################################
def run_instances(params)
# Get the instance type and path
if params['InstanceType'] != nil
instance_type_name = params['InstanceType']
instance_type = @config[:instance_types][instance_type_name.to_sym]
if instance_type != nil
path = @config[:template_location] + "/#{instance_type[:template]}"
end
end
# Get the image
tmp, img=params['ImageId'].split('-')
# Build the VM
erb_vm_info=Hash.new
erb_vm_info[:img_id] = img.to_i
erb_vm_info[:ec2_img_id] = params['ImageId']
erb_vm_info[:instance_type] = instance_type_name
erb_vm_info[:template] = path
erb_vm_info[:user_data] = params['UserData']
template = ERB.new(File.read(erb_vm_info[:template]))
template_text = template.result(binding)
# Start the VM.
vm = VirtualMachine.new(VirtualMachine.build_xml, @client)
rc = vm.allocate(template_text)
if OpenNebula::is_error?(rc)
return OpenNebula::Error.new('Unsupported'),400
end
vm.info
erb_vm_info[:vm_id]=vm.id
erb_vm_info[:vm]=vm
erb_user_name = params['AWSAccessKeyId']
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/run_instances.erb"))
return response.result(binding), 200
end
def describe_instances(params)
user_flag = OpenNebula::Pool::INFO_ALL
vmpool = VirtualMachinePool.new(@client, user_flag)
vmpool.info
erb_version = params['Version']
erb_user_name = params['AWSAccessKeyId']
response = ERB.new(File.read(@config[:views]+"/describe_instances.erb"))
return response.result(binding), 200
end
def terminate_instances(params)
# Get the VM ID
vmid=params['InstanceId.1']
vmid=params['InstanceId.01'] if !vmid
tmp, vmid=vmid.split('-') if vmid[0]==?i
vm = VirtualMachine.new(VirtualMachine.build_xml(vmid),@client)
rc = vm.info
return OpenNebula::Error.new('Unsupported'),400 if OpenNebula::is_error?(rc)
if vm.status == 'runn'
rc = vm.shutdown
else
rc = vm.finalize
end
return OpenNebula::Error.new('Unsupported'),400 if OpenNebula::is_error?(rc)
erb_version = params['Version']
response =ERB.new(File.read(@config[:views]+"/terminate_instances.erb"))
return response.result(binding), 200
end
###########################################################################
# Elastic IP
###########################################################################
def allocate_address(params)
return OpenNebula::Error.new('Unsupported'),400
return OpenNebula::Error.new('Unsupported')
end
def release_address(params)
return OpenNebula::Error.new('Unsupported'),400
return OpenNebula::Error.new('Unsupported')
end
def describe_addresses(params)
return OpenNebula::Error.new('Unsupported'),400
return OpenNebula::Error.new('Unsupported')
end
def associate_address(params)
return OpenNebula::Error.new('Unsupported'),400
return OpenNebula::Error.new('Unsupported')
end
def disassociate_address(params)
return OpenNebula::Error.new('Unsupported'),400
return OpenNebula::Error.new('Unsupported')
end
###########################################################################
@ -255,17 +182,6 @@ class EC2QueryServer < CloudServer
###########################################################################
private
def render_state(vm)
one_state = ONE_STATES[vm.status]
ec2_state = EC2_STATES[one_state||:pending]
return "<code>#{ec2_state[:code]}</code>
<name>#{ec2_state[:name]}</name>"
end
def render_image_state(image)
EC2_IMAGE_STATES[image.state_str]
end
def render_launch_time(vm)
return "<launchTime>#{Time.at(vm["STIME"].to_i).xmlschema}</launchTime>"

View File

@ -19,19 +19,53 @@ require 'OpenNebula'
include OpenNebula
class ImageEC2Pool < ImagePool
def initialize(client, user_id=-1)
super(client, user_id)
end
def factory(element_xml)
ImageEC2.new(element_xml,@client)
end
end
class ImageEC2 < Image
EC2_IMAGE_STATES={
"INIT" => "pending",
"READY" => "available",
"USED" => "available",
"DISABLED" => nil,
"LOCKED" => "pending",
"ERROR" => "failed",
"CLONE" => "available",
"DELETE" => nil,
"USED_PERS" => "in-use"
}
ONE_IMAGE = %q{
NAME = "ec2-<%= uuid %>"
TYPE = OS
TYPE = <%= @image_info[:type] %>
<% if @image_info[:size] != nil %>
SIZE = "<%= @image_info[:size] %>"
<% end %>
<% if @image_info[:fstype] != nil %>
FSTYPE = "<%= @image_info[:fstype] %>"
<% end %>
<% if @image_info[:persistent] != nil %>
PERSISTENT = "YES"
<% end %>
<% if @image_info[:ebs] != "nil" %>
EBS_VOLUME = "YES"
<% end %>
<% if @image_file != nil %>
PATH = "<%= @image_file %>"
<% end %>
}.gsub(/^ /, '')
def initialize(xml, client, file=nil)
def initialize(xml, client, file=nil, opts={})
super(xml, client)
@image_info = nil
@image_info = opts
@image_file = file
if file && file[:tempfile]
@ -45,4 +79,16 @@ class ImageEC2 < Image
one = ERB.new(ONE_IMAGE)
return one.result(binding)
end
def render_state
EC2_IMAGE_STATES[self.state_str]
end
def render_size
self['SIZE'].to_i/1024
end
def render_create_time
Time.at(self["REGTIME"].to_i).xmlschema
end
end

240
src/cloud/ec2/lib/ebs.rb Normal file
View File

@ -0,0 +1,240 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
module EBS
# Default FSTYPE when creating new volumes
DEFAULT_FSTYPE = "ext3"
# Detaches a DATABLOCK from a VM
#
# @param [Hash] params
# @option params [String] VolumeId The ID of the DATABLOCK
# @option params [String] InstanceId The ID of the VM
# @option params [String] Device The TARGET (unsupported)
# @option params [String] Force The TARGET (unsupported)
def detach_volume(params)
target = params['Device']
image_id = params['VolumeId']
vm_id_ec2 = params['InstanceId']
image_id = image_id.split('-')[1] if image_id[0] == "v"
image = Image.new(Image.build_xml(image_id), @client)
rc = image.info
return rc if OpenNebula::is_error?(rc)
if !vm_id_ec2
vm_id_ec2 = image["TEMPLATE/EBS/INSTANCE_ID"]
end
if vm_id_ec2.nil?
rc = OpenNebula::Error.new("The volume #{params['VolumeId']} is\
not attached to any instance")
logger.error {rc.message}
return rc
end
vm_id = vm_id_ec2.split('-')[1] if vm_id_ec2[0] == "i"
# Detach
vm = VirtualMachine.new(VirtualMachine.build_xml(vm_id), @client)
rc = vm.info
return rc if OpenNebula::is_error?(rc)
disk_id = vm["TEMPLATE/DISK[IMAGE_ID=#{image_id.to_i}]/DISK_ID"]
logger.debug { "Detaching DISK: #{disk_id} VM: #{vm_id} IMAGE: #{image_id}" }
if disk_id.nil?
rc = OpenNebula::Error.new("There is no disk to be detached")
logger.error {rc.message}
return rc
end
rc = vm.detachdisk(disk_id.to_i)
return rc if OpenNebula::is_error?(rc)
# Update IMAGE metadata
image.delete_element("TEMPLATE/EBS")
rc = image.update
if OpenNebula::is_error?(rc)
logger.error {rc.message}
return rc
end
# Response
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/detach_volume.erb"))
return response.result(binding), 200
end
# Attaches a DATABLOCK to a running VM and exposes it as the specified
# device.
#
# @param [Hash] params
# @option params [String] VolumeId The ID of the DATABLOCK
# @option params [String] InstanceId The ID of the VM to which the
# volume attaches
# @option params [String] Device How the device is exposed to the
# instance (e.g., /dev/sdh, or xvdh)
def attach_volume(params)
image_id = params['VolumeId']
image_id = image_id.split('-')[1] if image_id[0] == "v"
vm_id = params['InstanceId']
vm_id = vm_id.split('-')[1] if vm_id[0] == "i"
target = params['Device']
if m = target.match(/^\/dev\/(\w+)$/)
target = m[1]
end
# Check if the volume is already attached to another instance
image = Image.new(Image.build_xml(image_id), @client)
rc = image.info
return rc if OpenNebula::is_error?(rc)
if image['TEMPLATE/EBS/INSTANCE_ID']
return OpenNebula::Error.new("Volume #{params['VolumeId']} " <<
"already attached to another instance " <<
"(#{image['TEMPLATE/EBS/INSTANCE_ID']})")
end
# Attach
vm = VirtualMachine.new(VirtualMachine.build_xml(vm_id), @client)
rc = vm.info
return rc if OpenNebula::is_error?(rc)
template = "DISK = [ IMAGE_ID = #{image_id}, TARGET = #{target} ]"
rc = vm.attachdisk(template)
return rc if OpenNebula::is_error?(rc)
# Update IMAGE metadata
attach_time = Time.now.to_i
xml_hash = {'EBS' => {
'INSTANCE_ID' => params['InstanceId'],
"DEVICE" => params['Device'],
"ATTACH_TIME" => attach_time
}
}
image.add_element('TEMPLATE', xml_hash)
rc = image.update
if OpenNebula::is_error?(rc)
logger.error rc.message
return rc
end
# Response
vm.info
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/attach_volume.erb"))
return response.result(binding), 200
end
# Creates a new DATABLOCK that any VM can attach to
#
# @param [Hash] params
# @option params [String] Size The size of the volume, in GiBs.
# @option params [String] SnapshotId The snapshot from which to create
# the new volume (unsupported).
# @option params [String] AvailabilityZone The Availability Zone in which
# to create the new volume (unsupported)
def create_volume(params)
size = params['Size'].to_i # in GiBs
size *= 1024
opts = {
:type => "DATABLOCK",
:size => size,
:fstype => @config[:ebs_fstype]||DEFAULT_FSTYPE,
:persistent => "YES",
:ebs => "YES"
}
image = ImageEC2.new(Image.build_xml, @client, nil, opts)
template = image.to_one_template
if OpenNebula.is_error?(template)
return template
end
rc = image.allocate(template, @config[:datastore_id]||1)
if OpenNebula.is_error?(rc)
return rc
end
# Response
image.info
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/create_volume.erb"))
return response.result(binding), 200
end
# Deletes a DATABLOCK
#
# @param [Hash] params
# @option params [String] VolumeId The ID of the DATABLOCK
def delete_volume(params)
image_id = params['VolumeId']
image_id = image_id.split('-')[1] if image_id[0]==?v
image = ImageEC2.new(Image.build_xml(image_id), @client)
rc = image.delete
return rc if OpenNebula::is_error?(rc)
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/delete_volume.erb"))
return response.result(binding), 200
end
# Describes your Amazon EBS volumes
def describe_volumes(params)
user_flag = OpenNebula::Pool::INFO_ALL
impool = ImageEC2Pool.new(@client, user_flag)
rc = impool.info
return rc if OpenNebula::is_error?(rc)
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/describe_volumes.erb"))
return response.result(binding), 200
end
end

View File

@ -136,42 +136,23 @@ before do
username = settings.cloud_auth.auth(request.env, params)
rescue Exception => e
logger.error {e.message}
error 500, error_xml("AuthFailure", 0)
rc = OpenNebula::Error.new(e.message)
rc.ec2_code = "AuthFailure"
error 401, rc.to_ec2
end
if username.nil?
error 401, error_xml("AuthFailure", 0)
rc = OpenNebula::Error.new("The username or password is not correct")
rc.ec2_code = "AuthFailure"
error 401, rc.to_ec2
else
client = settings.cloud_auth.client(username)
oneadmin_client = settings.cloud_auth.client
@econe_server = EC2QueryServer.new(client, oneadmin_client, settings.config, settings.logger)
end
end
helpers do
def error_xml(code,id)
message = ''
case code
when 'AuthFailure'
message = 'User not authorized'
when 'InvalidAMIID.NotFound'
message = 'Specified AMI ID does not exist'
when 'Unsupported'
message = 'The instance type or feature is not supported in your requested Availability Zone.'
else
message = code
end
xml = "<Response><Errors><Error><Code>"+
code +
"</Code><Message>" +
message +
"</Message></Error></Errors><RequestID>" +
id.to_s +
"</RequestID></Response>"
return xml
@econe_server = EC2QueryServer.new(
client,
oneadmin_client,
settings.config,
settings.logger)
end
end
@ -197,6 +178,12 @@ def do_http_request(params)
result,rc = @econe_server.describe_instances(params)
when 'TerminateInstances'
result,rc = @econe_server.terminate_instances(params)
when 'StartInstances'
result,rc = @econe_server.start_instances(params)
when 'StopInstances'
result,rc = @econe_server.stop_instances(params)
when 'RebootInstances'
result,rc = @econe_server.reboot_instances(params)
when 'AllocateAddress'
result,rc = @econe_server.allocate_address(params)
when 'AssociateAddress'
@ -207,14 +194,38 @@ def do_http_request(params)
result,rc = @econe_server.release_address(params)
when 'DescribeAddresses'
result,rc = @econe_server.describe_addresses(params)
when 'DescribeRegions'
result,rc = @econe_server.describe_regions(params)
when 'DescribeAvailabilityZones'
result,rc = @econe_server.describe_availability_zones(params)
when 'CreateVolume'
result,rc = @econe_server.create_volume(params)
when 'DescribeVolumes'
result,rc = @econe_server.describe_volumes(params)
when 'AttachVolume'
result,rc = @econe_server.attach_volume(params)
when 'DetachVolume'
result,rc = @econe_server.detach_volume(params)
when 'DeleteVolume'
result,rc = @econe_server.delete_volume(params)
else
result = OpenNebula::Error.new(
"#{params['Action']} feature is not supported",
OpenNebula::Error::ENO_EXISTS)
end
if OpenNebula::is_error?(result)
logger.error(result.message)
error rc, error_xml(result.message, 0)
error CloudServer::HTTP_ERROR_CODE[result.errno], result.to_ec2.gsub(/\n\s*/,'')
end
headers['Content-Type'] = 'application/xml'
result
if rc
status rc
end
logger.error { params['Action'] }
result.gsub(/\n\s*/,'')
end

View File

@ -1,13 +1,33 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
module ElasticIP
def allocate_address(params)
# Get public IP
vnet = retrieve_eip_vnet
return vnet, 400 if OpenNebula::is_error?(vnet)
if OpenNebula::is_error?(vnet)
return vnet
end
ips = vnet.retrieve_elements('LEASES/LEASE[USED=0]/IP')
if ips.nil?
logger.error { "There is no lease available to be allocated" }
return OpenNebula::Error.new('AddressLimitExceeded'), 400
rc = OpenNebula::Error.new("There is no lease available to be allocated")
rc.ec2_code = "AddressLimitExceeded"
logger.error { rc.message }
return rc
end
eip = ips.first
@ -16,7 +36,7 @@ module ElasticIP
rc = vnet.hold(eip)
if OpenNebula::is_error?(rc)
logger.error rc.message
return OpenNebula::Error.new('Unsupported'),400
return rc
end
# Update EC2_ADDRESSES list
@ -25,7 +45,7 @@ module ElasticIP
rc = vnet.update
if OpenNebula::is_error?(rc)
logger.error rc.message
return OpenNebula::Error.new('Unsupported'),400
return rc
end
response = ERB.new(File.read(@config[:views]+"/allocate_address.erb"))
@ -35,20 +55,24 @@ module ElasticIP
def release_address(params)
# Check public IP
vnet = retrieve_eip_vnet
return vnet, 400 if OpenNebula::is_error?(vnet)
if OpenNebula::is_error?(vnet)
return vnet
end
eip = params["PublicIp"]
unless vnet["TEMPLATE/EC2_ADDRESSES[IP=\"#{eip}\" and UID=\"#{retrieve_uid}\"]/IP"]
logger.error { "address:#{eip} does not exist" }
return OpenNebula::Error.new('Unsupported'),400
rc = OpenNebula::Error.new("address:#{eip} does not exist")
logger.error { rc.message }
return rc
end
# Disassociate address if needed
if vnet["TEMPLATE/EC2_ADDRESSES[IP=\"#{eip}\"]/VMID"]
cmd_output = `#{@config[:disassociate_script]} #{eip}`
if $?.to_i != 0
logger.error { cmd_output }
return OpenNebula::Error.new('Unsupported'),400
rc = OpenNebula::Error.new(cmd_output)
logger.error { rc.message }
return rc
end
vnet.delete_element("TEMPLATE/EC2_ADDRESSES[IP=\"#{eip}\"]/VMID")
@ -58,7 +82,7 @@ module ElasticIP
rc = vnet.release(eip)
if OpenNebula::is_error?(rc)
logger.error {rc.message}
return OpenNebula::Error.new('Unsupported'),400
return rc
end
# Update EC2_ADDRESSES list
@ -66,7 +90,7 @@ module ElasticIP
rc = vnet.update
if OpenNebula::is_error?(rc)
logger.error {rc.message}
return OpenNebula::Error.new('Unsupported'),400
return rc
end
response = ERB.new(File.read(@config[:views]+"/release_address.erb"))
@ -75,7 +99,9 @@ module ElasticIP
def describe_addresses(params)
vnet = retrieve_eip_vnet
return vnet, 400 if OpenNebula::is_error?(vnet)
if OpenNebula::is_error?(vnet)
return vnet
end
erb_version = params['Version']
user_id = retrieve_uid
@ -87,7 +113,9 @@ module ElasticIP
def associate_address(params)
# Check public IP
vnet = retrieve_eip_vnet
return vnet, 400 if OpenNebula::is_error?(vnet)
if OpenNebula::is_error?(vnet)
return vnet
end
user_id = retrieve_uid
eip = params["PublicIp"]
@ -95,8 +123,9 @@ module ElasticIP
vmid = vmid.split('-')[1] if vmid[0]==?i
unless vnet["TEMPLATE/EC2_ADDRESSES[IP=\"#{eip}\" and UID=\"#{retrieve_uid}\"]/IP"]
logger.error { "address:#{eip} does not exist" }
return OpenNebula::Error.new('Unsupported'),400
rc = OpenNebula::Error.new("address:#{eip} does not exist")
logger.error { rc.message }
return rc
end
# Get private IP of the Instance
@ -104,13 +133,14 @@ module ElasticIP
rc = vm.info
if OpenNebula::is_error?(rc)
logger.error {rc.message}
return OpenNebula::Error.new('Unsupported'),400
return rc
end
ips = vm.retrieve_elements('TEMPLATE/NIC/IP')
if ips.nil?
logger.error { "The instance does not have any NIC" }
return OpenNebula::Error.new('Unsupported'),400
rc = OpenNebula::Error.new("The instance does not have any NIC")
logger.error { rc.message }
return rc
end
private_ip = ips.first
@ -119,8 +149,9 @@ module ElasticIP
if vnet["TEMPLATE/EC2_ADDRESSES[IP=\"#{eip}\"]/VMID"]
cmd_output = `#{@config[:disassociate_script]} #{eip}`
if $?.to_i != 0
logger.error { cmd_output }
return OpenNebula::Error.new('Unsupported'),400
rc = OpenNebula::Error.new(cmd_output)
logger.error { rc.message }
return rc
end
vnet.delete_element("TEMPLATE/EC2_ADDRESSES[IP=\"#{eip}\"]/VMID")
@ -130,8 +161,9 @@ module ElasticIP
vnet_base64 = Base64.encode64(vnet.to_xml).delete("\n")
cmd_output = `#{@config[:associate_script]} #{eip} #{private_ip} \"#{vnet_base64}\"`
if $?.to_i != 0
logger.error { "associate_script" << cmd_output }
return OpenNebula::Error.new('Unsupported'),400
rc = OpenNebula::Error.new(cmd_output)
logger.error { rc.message }
return rc
end
# Update EC2_ADDRESSES list
@ -139,7 +171,7 @@ module ElasticIP
rc = vnet.update
if OpenNebula::is_error?(rc)
logger.error {rc.message}
return OpenNebula::Error.new('Unsupported'),400
return rc
end
response = ERB.new(File.read(@config[:views]+"/associate_address.erb"))
@ -149,19 +181,23 @@ module ElasticIP
def disassociate_address(params)
# Check public IP
vnet = retrieve_eip_vnet
return vnet, 400 if OpenNebula::is_error?(vnet)
if OpenNebula::is_error?(vnet)
return vnet
end
eip = params["PublicIp"]
unless vnet["TEMPLATE/EC2_ADDRESSES[IP=\"#{eip}\" and UID=\"#{retrieve_uid}\"]/VMID"]
logger.error { "address:#{eip} does not exist or is not associated with any instance" }
return OpenNebula::Error.new('Unsupported'),400
rc = OpenNebula::Error.new("address:#{eip} does not exist or is not associated with any instance")
logger.error { rc.message }
return rc
end
# Run external script
cmd_output = `#{@config[:disassociate_script]} #{eip}`
if $?.to_i != 0
logger.error { cmd_output }
return OpenNebula::Error.new('Unsupported'),400
rc = OpenNebula::Error.new(cmd_output)
logger.error { rc.message }
return rc
end
# Update EC2_ADDRESSES list
@ -169,7 +205,7 @@ module ElasticIP
rc = vnet.update
if OpenNebula::is_error?(rc)
logger.error {rc.message}
return OpenNebula::Error.new('Unsupported'),400
return rc
end
response = ERB.new(File.read(@config[:views]+"/disassociate_address.erb"))
@ -183,8 +219,7 @@ module ElasticIP
rc = vnet.info
if OpenNebula::is_error?(rc)
logger.error {rc.message}
return OpenNebula::Error.new('Unsupported')
return rc
end
vnet

View File

@ -0,0 +1,187 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
module Instance
###########################################################################
# Class Constants. Defined the EC2 and OpenNebula State mapping
###########################################################################
EC2_STATES={
:pending => {:code => 0, :name => 'pending'},
:running => {:code => 16,:name => 'running'},
:shutdown => {:code => 32,:name => 'shutting-down'},
:terminated => {:code => 48,:name => 'terminated'},
:stopping => {:code => 64,:name => 'stopping'},
:stopped => {:code => 80,:name => 'stopped'}
}
ONE_STATES={
'init' => :pending,
'pend' => :pending,
'hold' => :pending,
'stop' => :stopped,
'susp' => :stopped,
'done' => :terminated,
'fail' => :terminated,
'prol' => :pending,
'boot' => :running,
'runn' => :running,
'migr' => :running,
'save' => :stopping,
'epil' => :shutdown,
'shut' => :shutdown,
'clea' => :shutdown,
'fail' => :terminated,
'unkn' => :terminated
}
def run_instances(params)
# Get the instance type and path
if params['InstanceType'] != nil
instance_type_name = params['InstanceType']
instance_type = @config[:instance_types][instance_type_name.to_sym]
if instance_type != nil
path = @config[:template_location] + "/#{instance_type[:template]}"
end
end
# Get the image
tmp, img=params['ImageId'].split('-')
# Build the VM
erb_vm_info=Hash.new
erb_vm_info[:img_id] = img.to_i
erb_vm_info[:ec2_img_id] = params['ImageId']
erb_vm_info[:instance_type] = instance_type_name
erb_vm_info[:template] = path
erb_vm_info[:user_data] = params['UserData']
template = ERB.new(File.read(erb_vm_info[:template]))
template_text = template.result(binding)
# Start the VM.
vm = VirtualMachine.new(VirtualMachine.build_xml, @client)
rc = vm.allocate(template_text)
if OpenNebula::is_error?(rc)
return rc
end
vm.info
erb_current_state = render_state(vm)
erb_instance_id = render_instance_id(vm)
erb_user_name = params['AWSAccessKeyId']
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/run_instances.erb"))
return response.result(binding), 200
end
def describe_instances(params)
user_flag = OpenNebula::Pool::INFO_ALL
vmpool = VirtualMachinePool.new(@client, user_flag)
rc = vmpool.info
return rc if OpenNebula::is_error?(rc)
erb_version = params['Version']
erb_user_name = params['AWSAccessKeyId']
response = ERB.new(File.read(@config[:views]+"/describe_instances.erb"))
return response.result(binding), 200
end
def terminate_instances(params)
perform_action(params, "terminate_instances.erb") { |vm|
if vm.status == 'runn'
vm.shutdown
else
vm.finalize
end
}
end
def start_instances(params)
perform_action(params, "start_instances.erb") { |vm|
vm.resume
}
end
def stop_instances(params)
perform_action(params, "stop_instances.erb") { |vm|
vm.stop
}
end
def reboot_instances(params)
perform_action(params, "reboot_instances.erb") { |vm|
vm.reboot
}
end
private
# Perform an action on a given vm
# @param [Hash] params
# @option params [String] InstanceId The ID of the VM
# @param [String] erb_name name of the file, inside the views folder,
# to generate the response
# @yieldparam [OpenNebula::VirtualMachine] vm the VM
# @yieldreturn [OpenNebula::Error, nil]
# @return [OpenNebula::Error, nil]
def perform_action(params, erb_name, &block)
# Get the VM ID
vmid=params['InstanceId.1']
vmid=params['InstanceId.01'] if !vmid
tmp, vmid=vmid.split('-') if vmid[0] == "i"
vm = VirtualMachine.new(VirtualMachine.build_xml(vmid),@client)
rc = vm.info
if OpenNebula::is_error?(rc)
return rc
end
erb_previous_state = render_state(vm)
rc = block.call(vm)
vm.info
erb_current_state = render_state(vm)
erb_instance_id = render_instance_id(vm)
erb_version = params['Version']
response =ERB.new(File.read(@config[:views]+'/'+erb_name))
return response.result(binding), 200
end
def render_state(vm)
one_state = ONE_STATES[vm.status]
ec2_state = EC2_STATES[one_state||:pending]
return "<code>#{ec2_state[:code]}</code><name>#{ec2_state[:name]}</name>"
end
def render_instance_id(vm)
instance_id = "i-" + sprintf('%08i', vm.id)
return "<instanceId>#{instance_id}</instanceId>"
end
end

View File

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<AttachVolumeResponse xmlns="http://ec2.amazonaws.com/doc/<%=erb_version%>/">
<requestId/>
<volumeId>vol-<%= sprintf('%08i', image_id) %></volumeId>
<%= render_instance_id(vm) %>
<device>/dev/<%= vm["TEMPLATE/DISK[IMAGE_ID=#{image_id.to_i}]/TARGET"] %></device>
<status>attaching</status>
<attachTime><%= Time.at(attach_time).xmlschema %></attachTime>
</AttachVolumeResponse>

View File

@ -0,0 +1,10 @@
<?xml version="1.0"?>
<CreateVolumeResponse xmlns="http://ec2.amazonaws.com/doc/<%=erb_version%>/">
<requestId/>
<volumeId>vol-<%= sprintf('%08i', image.id) %></volumeId>
<size><%= image.render_size %></size>
<snapshotId/>
<availabilityZone/>
<status><%= image.render_state %></status>
<createTime><%= image.render_create_time %></createTime>
</CreateVolumeResponse>

View File

@ -0,0 +1,5 @@
<?xml version="1.0"?>
<DeleteVolumeResponse xmlns="http://ec2.amazonaws.com/doc/<%=erb_version%>/">
<requestId/>
<return>true</return>
</DeleteVolumeResponse>

View File

@ -8,7 +8,7 @@
<publicIp><%= eip["IP"] %></publicIp>
<domain>standard</domain>
<% if vm_id = vnet["TEMPLATE/EC2_ADDRESSES[IP=\"#{eip["IP"]}\"]/VMID"] %>
<instanceId><%= vm_id %></instanceId>
<instanceId>i-<%= sprintf('%08i', vm_id) %></instanceId>
<% else %>
<instanceId/>
<% end %>

View File

@ -0,0 +1,12 @@
<?xml version="1.0"?>
<DescribeAvailabilityZonesResponse xmlns="http://ec2.amazonaws.com/doc/<%=params['Version']%>">
<requestId></requestId>
<availabilityZoneInfo>
<item>
<zoneName>opennebula</zoneName>
<zoneState>available</zoneState>
<regionName>opennebula</regionName>
<messageSet/>
</item>
</availabilityZoneInfo>
</DescribeAvailabilityZonesResponse>

View File

@ -2,7 +2,7 @@
<DescribeImagesResponse xmlns="http://ec2.amazonaws.com/doc/<%=erb_version%>/">
<imagesSet>
<% impool.each do |im| %>
<% if state_image = render_image_state(im) %>
<% if (state_image = im.render_state) && (im['TEMPLATE/EBS_VOLUME'] != 'YES') %>
<item>
<imageId>ami-<%= sprintf('%08i', im.id) %></imageId>
<imageLocation><%= im['SOURCE'].split('/').last %></imageLocation>

View File

@ -13,7 +13,7 @@
<instancesSet>
<% vmpool.each do |vm| %>
<item>
<instanceId>i-<%= vm.id %></instanceId>
<%= render_instance_id(vm) %>
<imageId><%= vm['TEMPLATE/IMAGE_ID'] %></imageId>
<instanceState>
<%= render_state(vm) %>

View File

@ -0,0 +1,10 @@
<?xml version="1.0"?>
<DescribeRegionsResponse xmlns="http://ec2.amazonaws.com/doc/<%=params['Version']%>">
<requestId></requestId>
<regionInfo>
<item>
<regionName>opennebula</regionName>
<regionEndpoint><%= @base_url %></regionEndpoint>
</item>
</regionInfo>
</DescribeRegionsResponse>

View File

@ -0,0 +1,33 @@
<?xml version="1.0"?>
<DescribeVolumesResponse xmlns="http://ec2.amazonaws.com/doc/<%=erb_version%>/">
<requestId/>
<volumeSet>
<% impool.each do |im| %>
<% if (state_image = im.render_state) && (im['TEMPLATE/EBS_VOLUME'] == 'YES') %>
<item>
<volumeId>vol-<%= sprintf('%08i', im.id) %></volumeId>
<size><%= im.render_size %></size>
<snapshotId/>
<availabilityZone/>
<status><%= state_image %></status>
<createTime><%= im.render_create_time %></createTime>
<attachmentSet>
<% im.each("TEMPLATE/EBS") do |ebs| %>
<item>
<volumeId>vol-<%= sprintf('%08i', im.id) %></volumeId>
<instanceId><%= ebs['INSTANCE_ID'] %></instanceId>
<device><%= ebs['DEVICE'] %></device>
<status>attached</status>
<attachTime><%= Time.at(ebs['ATTACH_TIME'].to_i).xmlschema %></attachTime>
<deleteOnTermination>false</deleteOnTermination>
</item>
<% end %>
</attachmentSet>
<tagSet/>
</item>
<% else
next
end
end %>
</volumeSet>
</DescribeVolumesResponse>

View File

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<DetachVolumeResponse xmlns="http://ec2.amazonaws.com/doc/<%=erb_version%>/">
<requestId/>
<volumeId>vol-<%= sprintf('%08i', image_id) %></volumeId>
<%= render_instance_id(vm) %>
<device><%= target %></device>
<status>detaching</status>
<attachTime/>
</DetachVolumeResponse>

View File

@ -0,0 +1,5 @@
<?xml version="1.0"?>
<RebootInstancesResponse xmlns="http://ec2.amazonaws.com/doc/<%= params['Version'] %>/">
<requestId></requestId>
<return>true</return>
</RebootInstancesResponse>

View File

@ -8,18 +8,17 @@
</groupSet>
<instancesSet>
<item>
<instanceId>i-<%= erb_vm_info[:vm_id] %></instanceId>
<%= erb_instance_id %>
<imageId><%= erb_vm_info[:ec2_img_id] %></imageId>
<instanceState>
<code>0</code>
<name>pending</name>
<%= render_state(vm) %>
</instanceState>
<privateDnsName><%= erb_vm_info[:vm]["TEMPLATE/NIC/IP"]%></privateDnsName>
<dnsName><%= erb_vm_info[:vm]["TEMPLATE/NIC/IP"]%></dnsName>
<privateDnsName><%= vm["TEMPLATE/NIC/IP"]%></privateDnsName>
<dnsName><%= vm["TEMPLATE/NIC/IP"]%></dnsName>
<keyName>default</keyName>
<amiLaunchIndex>0</amiLaunchIndex>
<instanceType><%= erb_vm_info[:instance_type] %></instanceType>
<%= render_launch_time(erb_vm_info[:vm]) %>
<%= render_launch_time(vm) %>
<placement>
<availabilityZone>default</availabilityZone>
</placement>

View File

@ -0,0 +1,13 @@
<StartInstancesResponse xmlns="http://ec2.amazonaws.com/doc/<%= erb_version %>/">
<instancesSet>
<item>
<%= erb_instance_id %>
<currentState>
<%= erb_current_state %>
</currentState>
<previousState>
<%= erb_previous_state %>
</previousState>
</item>
</instancesSet>
</StartInstancesResponse>

View File

@ -0,0 +1,13 @@
<StopInstancesResponse xmlns="http://ec2.amazonaws.com/doc/<%= erb_version %>/">
<instancesSet>
<item>
<%= erb_instance_id %>
<currentState>
<%= erb_current_state %>
</currentState>
<previousState>
<%= erb_previous_state %>
</previousState>
</item>
</instancesSet>
</StopInstancesResponse>

View File

@ -1,13 +1,12 @@
<TerminateInstancesResponse xmlns="http://ec2.amazonaws.com/doc/<%= erb_version %>/">
<instancesSet>
<item>
<instanceId>i-<%= vm.id %></instanceId>
<shutdownState>
<code>32</code>
<name>shutting-down</name>
</shutdownState>
<%= erb_instance_id %>
<currentState>
<%= erb_current_state %>
</currentState>
<previousState>
<%= render_state(vm) %>
<%= erb_previous_state %>
</previousState>
</item>
</instancesSet>

View File

@ -106,8 +106,9 @@ module OpenNebula
# Replaces the template contents
#
# +new_template+ New template contents
def update(new_template)
# +new_template+ New template contents. If no argument is provided
# the object will be updated using the @xml variable
def update(new_template=nil)
super(IMAGE_METHODS[:update], new_template)
end

View File

@ -88,7 +88,8 @@ module OpenNebula
# Replaces the template contents
#
# +new_template+ New template contents
# +new_template+ New template contents. If no argument is provided
# the object will be updated using the @xml variable
def update(new_template=nil)
super(VN_METHODS[:update], new_template)
end