1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-19 06:50:07 +03:00

Merge branch 'feature-2259'

This commit is contained in:
Ruben S. Montero 2013-10-25 22:17:50 +02:00
commit aed6b9d8bc
20 changed files with 884 additions and 103 deletions

View File

@ -1320,6 +1320,7 @@ ECO_LIB_FILES="src/cloud/ec2/lib/EC2QueryClient.rb \
src/cloud/ec2/lib/ImageEC2.rb \
src/cloud/ec2/lib/elastic_ip.rb \
src/cloud/ec2/lib/ebs.rb \
src/cloud/ec2/lib/tags.rb \
src/cloud/ec2/lib/instance.rb \
src/cloud/ec2/lib/keypair.rb \
src/cloud/ec2/lib/net_ssh_replacement.rb \
@ -1332,7 +1333,14 @@ 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_tags.erb \
src/cloud/ec2/lib/views/delete_tags.erb \
src/cloud/ec2/lib/views/describe_tags.erb \
src/cloud/ec2/lib/views/create_volume.erb \
src/cloud/ec2/lib/views/create_snapshot.erb \
src/cloud/ec2/lib/views/delete_snapshot.erb \
src/cloud/ec2/lib/views/describe_snapshots.erb \
src/cloud/ec2/lib/views/create_image.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 \

View File

@ -64,6 +64,20 @@
# default 1
#:datastore_id:
# Include terminated instances in the describe_instances xml
:describe_with_terminated_instances: = true
# Terminated VMs will be included in the list
# till the termination date + TERMINATED_INSTANCES_EXPIRATION_TIME is reached
:terminated_instances_expiration_time: 900
#############################################################
# [DEPRECATED] File based templates
#############################################################
# Use former file based templates for instance types instead
# of OpenNebula templates
:use_file_templates: false
# VM types allowed and its template file (inside templates directory)
:instance_types:

View File

@ -28,6 +28,7 @@ require 'ebs'
require 'elastic_ip'
require 'instance'
require 'keypair'
require 'tags'
################################################################################
# Extends the OpenNebula::Error class to include an EC2 render of error
@ -126,20 +127,30 @@ class EC2QueryServer < CloudServer
return response.result(binding), 200
end
# TODO Kernel, Ramdisk, Arch, BlockDeviceMapping
def register_image(params)
# Get the Image ID
tmp, img=params['ImageLocation'].split('-')
image_id = params['ImageLocation']
image = ImageEC2.new(Image.build_xml(image_id.to_i), @client)
image = Image.new(Image.build_xml(img.to_i), @client)
# Enable the new Image
rc = image.info
if OpenNebula.is_error?(rc)
rc.ec2_code = "InvalidAMIID.NotFound"
return rc
end
image.enable
if image["EBS_VOLUME"] == "YES"
return OpenNebula::Error.new("The image you are trying to register"\
" is already a volume")
elsif image["EBS_SNAPSHOT"] == "YES"
return OpenNebula::Error.new("The image you are trying to register"\
" is already an snapshot")
end
image.add_element('TEMPLATE', {"EC2_AMI" => "YES"})
rc = image.update
if OpenNebula.is_error?(rc)
return rc
end
erb_version = params['Version']
@ -148,11 +159,34 @@ class EC2QueryServer < CloudServer
end
def describe_images(params)
user_flag = OpenNebula::Pool::INFO_ALL
impool = ImageEC2Pool.new(@client, user_flag)
impool = []
params.each { |key, value|
if key =~ /ImageId\./
if value =~ /ami\-(.+)/
image = ImageEC2.new(Image.build_xml($1), @client)
rc = image.info
if OpenNebula.is_error?(rc) || !image.ec2_ami?
rc ||= OpenNebula::Error.new()
rc.ec2_code = "InvalidAMIID.NotFound"
return rc
else
impool << image
end
else
rc = OpenNebula::Error.new("InvalidAMIID.Malformed #{value}")
rc.ec2_code = "InvalidAMIID.Malformed"
return rc
end
end
}
rc = impool.info
return rc if OpenNebula::is_error?(rc)
if impool.empty?
user_flag = OpenNebula::Pool::INFO_ALL
impool = ImageEC2Pool.new(@client, user_flag)
rc = impool.info
return rc if OpenNebula::is_error?(rc)
end
erb_version = params['Version']
@ -160,6 +194,43 @@ class EC2QueryServer < CloudServer
return response.result(binding), 200
end
# TODO: NoReboot = false, cleanly shut down the instance before image
# creation and then reboots the instance.
# TODO: If you customized your instance with instance store volumes
# or EBS volumes in addition to the root device volume, the
# new AMI contains block device mapping information for those volumes
def create_image(params)
instance_id = params['InstanceId']
instance_id = instance_id.split('-')[1]
vm = VirtualMachine.new(
VirtualMachine.build_xml(instance_id),
@client)
rc = vm.info
if OpenNebula::is_error?(rc)
rc.ec2_code = "InvalidInstanceID.NotFound"
return rc
end
image_id = vm.disk_snapshot(1,
params["Name"],
OpenNebula::Image::IMAGE_TYPES[0],
true)
# TODO Add AMI Tags
# TODO A new persistent image should be created for each instance
if OpenNebula::is_error?(image_id)
return image_id
end
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/create_image.erb"))
return response.result(binding), 200
end
###########################################################################
# Helper functions
###########################################################################

View File

@ -44,7 +44,7 @@ class ImageEC2 < Image
}
ONE_IMAGE = %q{
NAME = "ec2-<%= uuid %>"
NAME = "<%= ImageEC2.generate_uuid %>"
TYPE = <%= @image_info[:type] %>
<% if @image_info[:size] != nil %>
SIZE = "<%= @image_info[:size] %>"
@ -55,7 +55,7 @@ class ImageEC2 < Image
<% if @image_info[:persistent] != nil %>
PERSISTENT = "YES"
<% end %>
<% if @image_info[:ebs] != nil %>
<% if @image_info[:ebs_volume] != nil %>
EBS_VOLUME = "YES"
<% end %>
<% if @image_file != nil %>
@ -74,8 +74,6 @@ class ImageEC2 < Image
end
def to_one_template()
uuid = UUIDTools::UUID.random_create.to_s
one = ERB.new(ONE_IMAGE)
return one.result(binding)
end
@ -91,4 +89,40 @@ class ImageEC2 < Image
def render_create_time
Time.at(self["REGTIME"].to_i).xmlschema
end
def self.generate_uuid
"ec2-" + UUIDTools::UUID.random_create.to_s
end
def ebs_volume?
self["TEMPLATE/EBS_VOLUME"] == "YES"
end
def ec2_ami?
self["TEMPLATE/EC2_AMI"] == "YES"
end
def ebs_snapshot?
self["TEMPLATE/EBS_SNAPSHOT"] == "YES"
end
def ec2_id
if self.ebs_snapshot?
"snap-" + sprintf('%08i', self.id)
elsif self.ec2_ami?
"ami-" + sprintf('%08i', self.id)
elsif self.ebs_volume?
"vol-" + sprintf('%08i', self.id)
end
end
def resource_type
if self.ebs_snapshot?
"snapshot"
elsif self.ec2_ami?
"image"
elsif self.ebs_volume?
"volume"
end
end
end

View File

@ -168,34 +168,65 @@ module EBS
# the new volume (unsupported).
# @option params [String] AvailabilityZone The Availability Zone in which
# to create the new volume (unsupported)
# TODO: Availability zone
def create_volume(params)
size = params['Size'].to_i # in GiBs
size *= 1024
snapshot_id = params['SnapshotId']
if snapshot_id
snapshot_id = snapshot_id.split('-')[1]
opts = {
:type => "DATABLOCK",
:size => size,
:fstype => @config[:ebs_fstype]||DEFAULT_FSTYPE,
:persistent => "YES",
:ebs => "YES"
}
snapshot = ImageEC2.new(Image.build_xml(snapshot_id.to_i), @client)
rc = snapshot.info
if OpenNebula::is_error?(rc) || !snapshot.ebs_snapshot?
rc ||= OpenNebula::Error.new()
rc.ec2_code = "InvalidSnapshot.NotFound"
return rc
end
image = ImageEC2.new(Image.build_xml, @client, nil, opts)
template = image.to_one_template
# Clone
volume_id = snapshot.clone(ImageEC2.generate_uuid)
if OpenNebula::is_error?(volume_id)
return volume_id
end
if OpenNebula.is_error?(template)
return template
volume = ImageEC2.new(Image.build_xml(volume_id.to_i), @client)
rc = volume.info
if OpenNebula::is_error?(rc)
return rc
end
volume.delete_element("TEMPLATE/EBS_SNAPSHOT")
volume.add_element('TEMPLATE', {
"EBS_VOLUME" => "YES",
"EBS_FROM_SNAPSHOT_ID" => snapshot.ec2_id})
volume.update
else
size = params['Size'].to_i # in GiBs
size *= 1024
opts = {
:type => "DATABLOCK",
:size => size,
:fstype => @config[:ebs_fstype]||DEFAULT_FSTYPE,
:persistent => "YES",
:ebs_volume => "YES"
}
volume = ImageEC2.new(Image.build_xml, @client, nil, opts)
template = volume.to_one_template
if OpenNebula.is_error?(template)
return template
end
rc = volume.allocate(template, @config[:datastore_id]||1)
if OpenNebula.is_error?(rc)
return rc
end
volume.info
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"))
@ -237,4 +268,134 @@ module EBS
return response.result(binding), 200
end
# Creates a snapshot of an Amazon EBS volume
#
# @param [Hash] params
# @option params [String] VolumeId The ID of the Amazon EBS volume.
# @option params [String] Description A description for the snapshot.
def create_snapshot(params)
image_id = params['VolumeId']
image_id = image_id.split('-')[1]
image = ImageEC2.new(Image.build_xml(image_id.to_i), @client)
rc = image.info
if OpenNebula::is_error?(rc) || !image.ebs_volume?
rc ||= OpenNebula::Error.new()
rc.ec2_code = "InvalidVolume.NotFound"
return rc
end
instance_id = image["TEMPLATE/EBS/INSTANCE_ID"]
if instance_id
# Disk snapshot
instance_id = instance_id.split('-')[1]
vm = VirtualMachine.new(
VirtualMachine.build_xml(instance_id),
@client)
rc = vm.info
if OpenNebula::is_error?(rc)
rc.ec2_code = "InvalidInstanceID.NotFound"
return rc
end
disk_id = vm["TEMPLATE/DISK[IMAGE_ID=#{image_id}]/DISK_ID"]
if !disk_id.nil?
snapshot_id = vm.disk_snapshot(disk_id.to_i,
params["Description"]||ImageEC2.generate_uuid,
OpenNebula::Image::IMAGE_TYPES[image["TYPE"].to_i],
true)
if OpenNebula::is_error?(snapshot_id)
return snapshot_id
end
end
end
if snapshot_id.nil?
# Clone
snapshot_id = image.clone(params["Description"]||ImageEC2.generate_uuid)
if OpenNebula::is_error?(snapshot_id)
return snapshot_id
end
end
snapshot = ImageEC2.new(Image.build_xml(snapshot_id.to_i), @client)
rc = snapshot.info
if OpenNebula::is_error?(rc)
return rc
end
snapshot.delete_element("TEMPLATE/EBS_VOLUME")
snapshot.add_element('TEMPLATE', {"EBS_SNAPSHOT" => "YES"})
snapshot.update
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/create_snapshot.erb"))
return response.result(binding), 200
end
# Deletes the specified snapshot.
#
# @param [Hash] params
# @option params [String] SnapshotId The ID of the Amazon EBS snapshot.
def delete_snapshot(params)
snapshot_id = params['SnapshotId']
snapshot_id = snapshot_id.split('-')[1]
snapshot = ImageEC2.new(Image.build_xml(snapshot_id.to_i), @client)
rc = snapshot.info
if OpenNebula::is_error?(rc) || !snapshot.ebs_snapshot?
rc ||= OpenNebula::Error.new()
rc.ec2_code = "InvalidSnapshot.NotFound"
return rc
end
rc = snapshot.delete
if OpenNebula::is_error?(rc)
return rc
end
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/delete_snapshot.erb"))
return response.result(binding), 200
end
def describe_snapshots(params)
impool = []
params.each { |key, value|
if key =~ /SnapshotId\./
if value =~ /snap\-(.+)/
image = ImageEC2.new(Image.build_xml($1), @client)
rc = image.info
if OpenNebula.is_error?(rc) || !image.ebs_snapshot?
rc.ec2_code = "InvalidSnapshot.NotFound"
return rc
else
impool << image
end
else
rc = OpenNebula::Error.new("InvalidSnapshot.Malformed #{value}")
rc.ec2_code = "InvalidSnapshot.Malformed"
return rc
end
end
}
if impool.empty?
user_flag = OpenNebula::Pool::INFO_ALL
impool = ImageEC2Pool.new(@client, user_flag)
rc = impool.info
return rc if OpenNebula::is_error?(rc)
end
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/describe_snapshots.erb"))
return response.result(binding), 200
end
end

View File

@ -134,6 +134,20 @@ class EC2Application
result,rc = econe_server.describe_regions(params)
when 'DescribeAvailabilityZones'
result,rc = econe_server.describe_availability_zones(params)
when 'CreateSnapshot'
result,rc = econe_server.create_snapshot(params)
when 'DeleteSnapshot'
result,rc = econe_server.delete_snapshot(params)
when 'DescribeSnapshots'
result,rc = econe_server.describe_snapshots(params)
when 'CreateTags'
result,rc = econe_server.create_tags(params)
when 'DeleteTags'
result,rc = econe_server.delete_tags(params)
when 'DescribeTags'
result,rc = econe_server.describe_tags(params)
#when 'CreateImage'
# result,rc = econe_server.create_image(params)
when 'CreateVolume'
result,rc = econe_server.create_volume(params)
when 'DescribeVolumes'

View File

@ -47,58 +47,147 @@ module Instance
'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]
EC2_ACTIONS = {
:start => :resume,
:stop => :poweroff,
:terminate => :shutdown,
:reboot => :reboot
}
if instance_type != nil
path = @config[:template_location] + "/#{instance_type[:template]}"
end
# Include terminated instances in the describe_instances xml
DESCRIBE_WITH_TERMINATED_INSTANCES = true
# Terminated VMs will be included in the list
# till the termination date + TERMINATED_INSTANCES_EXPIRATION_TIME is reached
TERMINATED_INSTANCES_EXPIRATION_TIME = 900
def run_instances(params)
# Get the image
img = nil
if params['ImageId'] =~ /ami\-(.+)/
img = $1
else
rc = OpenNebula::Error.new("InvalidAMIID.Malformed #{params['ImageId']}")
rc.ec2_code = "InvalidAMIID.Malformed"
return rc
end
# Get the image
tmp, img = params['ImageId'].split('-')
if @config[:use_file_templates]
# 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]
# 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']
erb_vm_info[:public_key] = fetch_publickey(params)
erb_vm_info[:key_name] = params['KeyName']
template = ERB.new(File.read(erb_vm_info[:template]))
template_text = template.result(binding)
erb_vms = Array.new
min_count = params['MinCount'] || 1
max_count = params['MaxCount'] || min_count
max_count.to_i.times {
# Start the VM.
instance = VirtualMachine.new(VirtualMachine.build_xml, @client)
rc = instance.allocate(template_text)
if OpenNebula::is_error?(rc)
if erb_vms.size < min_count.to_i
erb_vms.each { |vm|
vm.finalize
}
return rc
if instance_type != nil
path = @config[:template_location] + "/#{instance_type[:template]}"
end
else
instance.info
erb_vms << instance
end
}
# 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']
erb_vm_info[:public_key] = fetch_publickey(params)
erb_vm_info[:key_name] = params['KeyName']
template = ERB.new(File.read(erb_vm_info[:template]))
template_text = template.result(binding)
erb_vms = Array.new
min_count = params['MinCount'] || 1
max_count = params['MaxCount'] || min_count
max_count.to_i.times {
# Start the VM.
instance = VirtualMachine.new(VirtualMachine.build_xml, @client)
rc = instance.allocate(template_text)
if OpenNebula::is_error?(rc)
if erb_vms.size < min_count.to_i
erb_vms.each { |vm|
vm.finalize
}
return rc
end
else
instance.info
erb_vms << instance
end
}
else
template_pool = TemplatePool.new(@client)
rc = template_pool.info
if OpenNebula::is_error?(rc)
return rc
end
template_id = template_pool["VMTEMPLATE/TEMPLATE[EC2_INSTANCE_TYPE=\'#{params['InstanceType']}\']/../ID"]
if template_id.nil?
rc.ec2_code = "InvalidInstanceID.NotFound"
return rc
end
template = Template.new(Template.build_xml(template_id), @client)
rc = template.info
if OpenNebula.is_error?(rc)
rc.ec2_code = "InvalidInstanceID.NotFound"
return rc
end
merge_info = {}
merge_info["DISK"] = []
merge_info["DISK"] << {"IMAGE_ID" => img.to_i}
template.each("TEMPLATE/DISK") { |e|
merge_info["DISK"] << e.to_hash["DISK"]
}
merge_info["CONTEXT"] = {}
template.each("TEMPLATE/CONTEXT") { |e|
merge_info["CONTEXT"] = e.to_hash["CONTEXT"]
}
context = merge_info["CONTEXT"]
public_key = fetch_publickey(params)
context["EC2_PUBLIC_KEY"] = public_key if public_key
context["EC2_KEYNAME"] = params['KeyName'] if params['KeyName']
context["EC2_USER_DATA"] = params['UserData'] if params['UserData']
template_str = template_to_str(merge_info)
vm_id =
erb_vms = Array.new
min_count = params['MinCount'] || 1
max_count = params['MaxCount'] || min_count
max_count.to_i.times {
# Start the VM.
rc = template.instantiate("", false, template_str)
if OpenNebula::is_error?(rc)
if erb_vms.size < min_count.to_i
erb_vms.each { |vm|
vm.finalize
}
return rc
end
else
instance = VirtualMachine.new(VirtualMachine.build_xml(rc), @client)
instance.info
erb_vms << instance
end
}
end
erb_user_name = params['AWSAccessKeyId']
erb_version = params['Version']
@ -108,11 +197,39 @@ module Instance
end
def describe_instances(params)
user_flag = OpenNebula::Pool::INFO_ALL
vmpool = VirtualMachinePool.new(@client, user_flag)
vmpool = []
params.each { |key, value|
if key =~ /InstanceId\./
if value =~ /i\-(.+)/
vm = VirtualMachine.new(VirtualMachine.build_xml($1), @client)
rc = vm.info
if OpenNebula.is_error?(rc)
rc.ec2_code = "InvalidInstanceID.NotFound"
return rc
else
vmpool << vm
end
else
rc = OpenNebula::Error.new("InvalidInstanceID.Malformed #{value}")
rc.ec2_code = "InvalidInstanceID.Malformed"
return rc
end
end
}
rc = vmpool.info
return rc if OpenNebula::is_error?(rc)
if vmpool.empty?
user_flag = OpenNebula::Pool::INFO_ALL
vmpool = VirtualMachinePool.new(@client, user_flag)
if include_terminated_instances?
rc = vmpool.info(user_flag, -1, -1,
OpenNebula::VirtualMachinePool::INFO_ALL_VM)
else
rc = vmpool.info
end
return rc if OpenNebula::is_error?(rc)
end
erb_version = params['Version']
erb_user_name = params['AWSAccessKeyId']
@ -124,7 +241,7 @@ module Instance
def terminate_instances(params)
perform_action(params, "terminate_instances.erb") { |vm|
if vm.status == 'runn'
vm.shutdown
vm.send(EC2_ACTIONS[:terminate])
else
vm.finalize
end
@ -133,19 +250,19 @@ module Instance
def start_instances(params)
perform_action(params, "start_instances.erb") { |vm|
vm.resume
vm.send(EC2_ACTIONS[:start])
}
end
def stop_instances(params)
perform_action(params, "stop_instances.erb") { |vm|
vm.stop
vm.send(EC2_ACTIONS[:stop])
}
end
def reboot_instances(params)
perform_action(params, "reboot_instances.erb") { |vm|
vm.reboot
vm.send(EC2_ACTIONS[:reboot])
}
end
@ -171,6 +288,7 @@ module Instance
rc = vm.info
if OpenNebula::is_error?(rc)
rc.ec2_code = "InvalidInstanceID.NotFound"
return rc
end
@ -208,4 +326,68 @@ module Instance
instance_id = "i-" + sprintf('%08i', vm.id)
return "<instanceId>#{instance_id}</instanceId>"
end
def include_terminated_instances?
@config[:describe_with_terminated_instances] || DESCRIBE_WITH_TERMINATED_INSTANCES
end
def include_terminated_instance?(vm)
if include_terminated_instances?
if EC2_STATES[ONE_STATES[vm.status]||:pending][:name] == "terminated"
if (Time.now.getutc.to_i - vm["ETIME"].to_i) <= TERMINATED_INSTANCES_EXPIRATION_TIME
return true
else
return false
end
end
end
return true
end
def template_to_str(attributes, indent=true)
if indent
ind_enter="\n"
ind_tab=' '
else
ind_enter=''
ind_tab=' '
end
str=attributes.collect do |key, value|
if value
str_line=""
if value.class==Array && !value.empty?
value.each do |value2|
str_line << key.to_s.upcase << "=[" << ind_enter
if value2 && value2.class==Hash
str_line << value2.collect do |key3, value3|
str = ind_tab + key3.to_s.upcase + "="
str += "\"#{value3.to_s}\"" if value3
str
end.compact.join(",\n")
end
str_line << "\n]\n"
end
elsif value.class==Hash && !value.empty?
str_line << key.to_s.upcase << "=[" << ind_enter
str_line << value.collect do |key3, value3|
str = ind_tab + key3.to_s.upcase + "="
str += "\"#{value3.to_s}\"" if value3
str
end.compact.join(",\n")
str_line << "\n]\n"
else
str_line<<key.to_s.upcase << "=" << "\"#{value.to_s}\""
end
str_line
end
end.compact.join("\n")
str
end
end

214
src/cloud/ec2/lib/tags.rb Normal file
View File

@ -0,0 +1,214 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs #
# #
# 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 Tags
# Adds or overwrites one or more tags for the specified EC2 resource or
# resources. Each resource can have a maximum of 10 tags. Each tag
# consists of a key and optional value. Tag keys must be unique per resource.
#
# @param [Hash] params
# @option params [String] ResourceId.n The IDs of one or more resources
# to tag. For example, ami-1a2b3c4d.
# @option params [String] Tag.n.Key The key for a tag.
# @option params [String] Tag.n.Value The value for a tag. If you don't
# want the tag to have a value, specify the parameter with no value,
# and we set the value to an empty string.
#
# TODO: return if error or continue
def create_tags(params)
resources = []
tags = {}
params.each { |key, value|
case key
when /ResourceId\./
resources << case value
when /ami\-(.+)/
image = ImageEC2.new(Image.build_xml($1), @client)
rc = image.info
if OpenNebula.is_error?(rc) || !image.ec2_ami?
rc ||= OpenNebula::Error.new()
rc.ec2_code = "InvalidAMIID.NotFound"
return rc
else
image
end
when /vol\-(.+)/
image = ImageEC2.new(Image.build_xml($1), @client)
rc = image.info
if OpenNebula.is_error?(rc) || !image.ebs_volume?
rc ||= OpenNebula::Error.new()
rc.ec2_code = "InvalidVolume.NotFound"
return rc
else
image
end
when /snap\-(.+)/
image = ImageEC2.new(Image.build_xml($1), @client)
rc = image.info
if OpenNebula.is_error?(rc) || !image.ebs_snapshot?
rc ||= OpenNebula::Error.new()
rc.ec2_code = "InvalidSnapshot.NotFound"
return rc
else
image
end
when /i\-(.+)/
vm = VirtualMachine.new(VirtualMachine.build_xml($1), @client)
rc = vm.info
if OpenNebula.is_error?(rc)
rc.ec2_code = "InvalidInstanceID.NotFound"
return rc
else
vm
end
end
when /Tag\.(\d+)\.Key/
tags[value] = params["Tag.#{$1}.Value"] || ""
end
}
resources.each {|resource|
if resource.is_a?(VirtualMachine)
template_key = "USER_TEMPLATE"
elsif resource.is_a?(Image)
template_key = "TEMPLATE"
end
former_tags = resource.to_hash.first[1][template_key]["EC2_TAGS"] || {}
resource.delete_element("#{template_key}/EC2_TAGS")
resource.add_element(template_key, {"EC2_TAGS" => former_tags.merge(tags)})
rc = resource.update(resource.template_like_str(template_key))
return rc if OpenNebula::is_error?(rc)
}
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/create_tags.erb"))
return response.result(binding), 200
end
# Deletes the specified set of tags from the specified set of resources.
#
# @param [Hash] params
# @option params [String] ResourceId.n The IDs of one or more resources
# to tag. For example, ami-1a2b3c4d.
# @option params [String] Tag.n.Key The key for a tag.
# @option params [String] Tag.n.Value The value for a tag. If you don't
# want the tag to have a value, specify the parameter with no value,
# and we set the value to an empty string.
#
# TODO: return if error or continue
def delete_tags(params)
resources = []
tags = {}
params.each { |key, value|
case key
when /ResourceId\./
resources << case value
when /ami\-(.+)/
image = ImageEC2.new(Image.build_xml($1), @client)
rc = image.info
if OpenNebula.is_error?(rc) || !image.ec2_ami?
rc ||= OpenNebula::Error.new()
rc.ec2_code = "InvalidAMIID.NotFound"
return rc
else
image
end
when /vol\-(.+)/
image = ImageEC2.new(Image.build_xml($1), @client)
rc = image.info
if OpenNebula.is_error?(rc) || !image.ebs_volume?
rc ||= OpenNebula::Error.new()
rc.ec2_code = "InvalidVolume.NotFound"
return rc
else
image
end
when /snap\-(.+)/
image = ImageEC2.new(Image.build_xml($1), @client)
rc = image.info
if OpenNebula.is_error?(rc) || !image.ebs_snapshot?
rc ||= OpenNebula::Error.new()
rc.ec2_code = "InvalidSnapshot.NotFound"
return rc
else
image
end
when /i\-(.+)/
vm = VirtualMachine.new(VirtualMachine.build_xml($1), @client)
rc = vm.info
if OpenNebula.is_error?(rc)
rc.ec2_code = "InvalidInstanceID.NotFound"
return rc
else
vm
end
end
when /Tag\.(\d+)\.Key/
tags[value] = params["Tag.#{$1}.Value"] || ""
end
}
resources.each {|resource|
if resource.is_a?(VirtualMachine)
template_key = "USER_TEMPLATE"
elsif resource.is_a?(Image)
template_key = "TEMPLATE"
end
tags.each { |key,value|
resource.delete_element("#{template_key}/EC2_TAGS/#{key}")
}
rc = resource.update(resource.template_like_str(template_key))
return rc if OpenNebula::is_error?(rc)
}
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/delete_tags.erb"))
return response.result(binding), 200
end
def describe_tags(params)
user_flag = OpenNebula::Pool::INFO_ALL
impool = ImageEC2Pool.new(@client, user_flag)
rc = impool.info
return rc if OpenNebula::is_error?(rc)
user_flag = OpenNebula::Pool::INFO_ALL
vmpool = VirtualMachinePool.new(@client, user_flag)
if include_terminated_instances?
rc = vmpool.info(user_flag, -1, -1,
OpenNebula::VirtualMachinePool::INFO_ALL_VM)
else
rc = vmpool.info
end
return rc if OpenNebula::is_error?(rc)
erb_version = params['Version']
response = ERB.new(File.read(@config[:views]+"/describe_tags.erb"))
return response.result(binding), 200
end
end

View File

@ -0,0 +1,4 @@
<CreateImageResponse xmlns="http://ec2.amazonaws.com/doc/2013-06-15/">
<requestId><%= @request_id %></requestId>
<imageId>ami-<%= sprintf('%08i', image_id) %></imageId>
</CreateImageResponse>

View File

@ -0,0 +1,11 @@
<CreateSnapshotResponse xmlns="http://ec2.amazonaws.com/doc/2013-06-15/">
<requestId><%= @request_id %></requestId>
<snapshotId>snap-<%= sprintf('%08i', snapshot["ID"]) %></snapshotId>
<volumeId><%= params["VolumeId"] %></volumeId>
<status><%= snapshot.render_state %></status>
<startTime><%= snapshot.render_create_time %></startTime>
<progress>100%</progress>
<ownerId><%= snapshot["UNAME"] %></ownerId>
<volumeSize><%= snapshot.render_size %></volumeSize>
<description><%= snapshot["NAME"] %></description>
</CreateSnapshotResponse>

View File

@ -0,0 +1,4 @@
<CreateTagsResponse xmlns="http://ec2.amazonaws.com/doc/2013-06-15/">
<requestId><%= @request_id %></requestId>
<return>true</return>
</CreateTagsResponse>

View File

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

View File

@ -0,0 +1,4 @@
<DeleteSnapshotResponse xmlns="http://ec2.amazonaws.com/doc/2013-06-15/">
<requestId><%= @request_id %></requestId>
<return>true</return>
</DeleteSnapshotResponse>

View File

@ -0,0 +1,4 @@
<DeleteTagsResponse xmlns="http://ec2.amazonaws.com/doc/2013-06-15/">
<requestId><%= @request_id %></requestId>
<return>true</return>
</DeleteTagsResponse>

View File

@ -3,7 +3,7 @@
<requestId><%= @request_id %></requestId>
<imagesSet>
<% impool.each do |im| %>
<% if (state_image = im.render_state) && (im['TEMPLATE/EBS_VOLUME'] != 'YES') %>
<% if (state_image = im.render_state) && im.ec2_ami? %>
<item>
<name><%= im['NAME'] %></name>
<% if im['TEMPLATE/DESCRIPTION'] %>
@ -12,7 +12,7 @@
<% if im['TEMPLATE/PLATFORM'] %>
<platform><%= im['TEMPLATE/PLATFORM'] %></platform>
<% end %>
<imageId>ami-<%= sprintf('%08i', im.id) %></imageId>
<imageId><%= im.ec2_id %></imageId>
<imageLocation><%= im['SOURCE'].split('/').last %></imageLocation>
<imageState><%= state_image %></imageState>
<imageOwnerId><%= im['UNAME'] %></imageOwnerId>

View File

@ -12,6 +12,7 @@
</groupSet>
<instancesSet>
<% vmpool.each do |vm| %>
<% if include_terminated_instance?(vm) %>
<item>
<%= render_instance_id(vm) %>
<imageId><%= vm['USER_TEMPLATE/IMAGE_ID'] %></imageId>
@ -45,6 +46,7 @@
</item>
<% end %>
<% end %>
</instancesSet>
</item>
</reservationSet>

View File

@ -0,0 +1,23 @@
<DescribeSnapshotsResponse xmlns="http://ec2.amazonaws.com/doc/2013-06-15/">
<requestId><%= @request_id %></requestId>
<snapshotSet>
<% impool.each do |im| %>
<% logger.debug(im.id) %>
<% if (state_image = im.render_state) && im.ebs_snapshot? %>
<item>
<snapshotId>snap-<%= sprintf('%08i', im.id) %></snapshotId>
<volumeId></volumeId>
<status><%= state_image %></status>
<startTime><%= im.render_create_time %></startTime>
<progress>100%</progress>
<ownerId><%= im["UNAME"] %></ownerId>
<volumeSize><%= im.render_size %></volumeSize>
<description><%= im["NAME"] %></description>
<tagSet></tagSet>
</item>
<% else
next
end
end %>
</snapshotSet>
</DescribeSnapshotsResponse>

View File

@ -0,0 +1,31 @@
<DescribeTagsResponse xmlns="http://ec2.amazonaws.com/doc/2013-06-15/">
<requestId><%= @request_id %></requestId>
<tagSet>
<% impool.each do |im| %>
<% if (state_image = im.render_state) && im.has_elements?("TEMPLATE/EC2_TAGS") %>
<% image_hash = im.to_hash %>
<% image_hash["IMAGE"]["TEMPLATE"]["EC2_TAGS"].each do |key, value| %>
<item>
<resourceId><%= im.ec2_id %></resourceId>
<resourceType>image</resourceType>
<key><%= key %></key>
<value><%= value %></value>
</item>
<% end
end
end %>
<% vmpool.each do |vm| %>
<% if include_terminated_instance?(vm) && vm.has_elements?("USER_TEMPLATE/EC2_TAGS") %>
<% vm_hash = vm.to_hash %>
<% vm_hash["VM"]["USER_TEMPLATE"]["EC2_TAGS"].each do |key, value| %>
<item>
<resourceId>i-<%= sprintf('%08i', vm.id) %></resourceId>
<resourceType>instance</resourceType>
<key><%= key %></key>
<value><%= value %></value>
</item>
<% end
end
end %>
</tagSet>
</DescribeTagsResponse>

View File

@ -3,11 +3,11 @@
<requestId><%= @request_id %></requestId>
<volumeSet>
<% impool.each do |im| %>
<% if (state_image = im.render_state) && (im['TEMPLATE/EBS_VOLUME'] == 'YES') %>
<% if (state_image = im.render_state) && im.ebs_volume? %>
<item>
<volumeId>vol-<%= sprintf('%08i', im.id) %></volumeId>
<size><%= im.render_size %></size>
<snapshotId/>
<snapshotId><%= im["TEMPLATE/EBS_FROM_SNAPSHOT_ID"] %></snapshotId>
<availabilityZone/>
<status><%= state_image %></status>
<createTime><%= im.render_create_time %></createTime>
@ -30,4 +30,4 @@
end
end %>
</volumeSet>
</DescribeVolumesResponse>
</DescribeVolumesResponse>

View File

@ -11,7 +11,7 @@
<% erb_vms.each { |vm| %>
<item>
<%= render_instance_id(vm) %>
<imageId><%= erb_vm_info[:ec2_img_id] %></imageId>
<imageId><%= params['ImageId'] %></imageId>
<instanceState><%= render_state(vm) %></instanceState>
<% if vm.has_elements?("TEMPLATE/NIC/IP") %>
<% ips_str = vm.retrieve_elements("TEMPLATE/NIC/IP").join(', ') %>
@ -25,7 +25,7 @@
<keyName><%= vm['TEMPLATE/CONTEXT/EC2_KEYNAME'] %></keyName>
<% end %>
<amiLaunchIndex><%= vm.id %></amiLaunchIndex>
<instanceType><%= erb_vm_info[:instance_type] %></instanceType>
<instanceType><%= params['InstanceType'] %></instanceType>
<%= render_launch_time(vm) %>
<placement>
<availabilityZone>default</availabilityZone>