mirror of
https://github.com/OpenNebula/one.git
synced 2025-01-10 01:17:40 +03:00
Merge branch 'Semedi-F5189'
This commit is contained in:
commit
a3b21a0a86
@ -42,6 +42,32 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
|
||||
#
|
||||
#-----------------------------------------------------------------------
|
||||
EOT
|
||||
},
|
||||
:az => {
|
||||
:help => <<-EOT.unindent,
|
||||
#-----------------------------------------------------------------------
|
||||
# Supported AZURE AUTH ATTRIBUTTES:
|
||||
#
|
||||
# AZ_ID = <azure classic id>
|
||||
# AZ_CERT = <azure classic certificate>
|
||||
#
|
||||
# REGION_NAME = <the name of the azure region>
|
||||
#
|
||||
# CAPACITY = [
|
||||
# Small = <number of small machines>,
|
||||
# Medium = <number of medium machines>,
|
||||
# Large = <number of large machines
|
||||
# ]
|
||||
#
|
||||
# You can set any machine type supported by azure classic
|
||||
# See your az_driver.conf for more information
|
||||
#
|
||||
# Optionally you can set a endpoint
|
||||
#
|
||||
# AZ_ENDPOINT = <endpoint address>
|
||||
#
|
||||
#-----------------------------------------------------------------------
|
||||
EOT
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -693,6 +693,9 @@ int Host::from_xml(const string& xml)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static void nebula_crypt(const std::string in, std::string& out)
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
@ -715,44 +718,36 @@ static void nebula_crypt(const std::string in, std::string& out)
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static const map<std::string, unsigned int> MAX_HOST_VAR_SIZES = {
|
||||
{"EC2_ACCESS", 21},
|
||||
{"EC2_SECRET", 41},
|
||||
{"AZ_ID", 41},
|
||||
{"AZ_CERT", 3130},
|
||||
{"VCENTER_PASSWORD", 22}
|
||||
};
|
||||
|
||||
int Host::post_update_template(string& error)
|
||||
{
|
||||
string vcenter_password;
|
||||
string new_im_mad;
|
||||
string new_vm_mad;
|
||||
|
||||
string ec2_access;
|
||||
string ec2_secret;
|
||||
map<std::string, unsigned int>::const_iterator it;
|
||||
|
||||
string crypted;
|
||||
|
||||
get_template_attribute("VCENTER_PASSWORD", vcenter_password);
|
||||
|
||||
if (!vcenter_password.empty() && vcenter_password.size() <= 22)
|
||||
for (it = MAX_HOST_VAR_SIZES.begin(); it != MAX_HOST_VAR_SIZES.end() ; ++it)
|
||||
{
|
||||
nebula_crypt(vcenter_password, crypted);
|
||||
string att;
|
||||
string crypted;
|
||||
|
||||
replace_template_attribute("VCENTER_PASSWORD", crypted);
|
||||
}
|
||||
get_template_attribute(it->first.c_str(), att);
|
||||
|
||||
get_template_attribute("EC2_ACCESS", ec2_access);
|
||||
if (!att.empty() && att.size() <= it->second)
|
||||
{
|
||||
nebula_crypt(att, crypted);
|
||||
|
||||
if (!ec2_access.empty() && ec2_access.size() <= 21)
|
||||
{
|
||||
nebula_crypt(ec2_access, crypted);
|
||||
|
||||
replace_template_attribute("EC2_ACCESS", crypted);
|
||||
}
|
||||
|
||||
get_template_attribute("EC2_SECRET", ec2_secret);
|
||||
|
||||
if (!ec2_secret.empty() && ec2_secret.size() <= 41)
|
||||
{
|
||||
nebula_crypt(ec2_secret, crypted);
|
||||
|
||||
replace_template_attribute("EC2_SECRET", crypted);
|
||||
replace_template_attribute(it->first, crypted);
|
||||
}
|
||||
}
|
||||
|
||||
get_template_attribute("IM_MAD", new_im_mad);
|
||||
|
@ -1,98 +1,4 @@
|
||||
proxy_uri:
|
||||
regions:
|
||||
default:
|
||||
region_name: "West Europe"
|
||||
# pem_management_cert --> Absolute path to pem management certificate
|
||||
# Info on creating certificates:
|
||||
# http://azure.microsoft.com/en-us/documentation/articles/linux-use-ssh-key/
|
||||
pem_management_cert:
|
||||
subscription_id:
|
||||
management_endpoint:
|
||||
capacity:
|
||||
Small: 5
|
||||
Medium: 1
|
||||
Large: 0
|
||||
west-europe:
|
||||
region_name: "West Europe"
|
||||
pem_management_cert:
|
||||
subscription_id:
|
||||
management_endpoint:
|
||||
capacity:
|
||||
Small: 5
|
||||
Medium: 1
|
||||
Large: 0
|
||||
north-europe:
|
||||
region_name: "North Europe"
|
||||
pem_management_cert:
|
||||
subscription_id:
|
||||
management_endpoint:
|
||||
capacity:
|
||||
Small:
|
||||
Medium:
|
||||
Large:
|
||||
east-us:
|
||||
region_name: "East US"
|
||||
pem_management_cert:
|
||||
subscription_id:
|
||||
management_endpoint:
|
||||
capacity:
|
||||
Small:
|
||||
Medium:
|
||||
Large:
|
||||
south-central-us:
|
||||
region_name: "South Central US"
|
||||
pem_management_cert:
|
||||
subscription_id:
|
||||
management_endpoint:
|
||||
capacity:
|
||||
Small:
|
||||
Medium:
|
||||
Large:
|
||||
west-us:
|
||||
region_name: "West US"
|
||||
pem_management_cert:
|
||||
subscription_id:
|
||||
management_endpoint:
|
||||
capacity:
|
||||
Small:
|
||||
Medium:
|
||||
Large:
|
||||
east-asia:
|
||||
region_name: "East Asia"
|
||||
pem_management_cert:
|
||||
subscription_id:
|
||||
management_endpoint:
|
||||
capacity:
|
||||
Small:
|
||||
Medium:
|
||||
Large:
|
||||
southeast-asia:
|
||||
region_name: "Southeast Asia"
|
||||
pem_management_cert:
|
||||
subscription_id:
|
||||
management_endpoint:
|
||||
capacity:
|
||||
Small:
|
||||
Medium:
|
||||
Large:
|
||||
japan-west:
|
||||
region_name: "Japan West"
|
||||
pem_management_cert:
|
||||
subscription_id:
|
||||
management_endpoint:
|
||||
capacity:
|
||||
Small:
|
||||
Medium:
|
||||
Large:
|
||||
brazil-south:
|
||||
region_name: "Brazil South"
|
||||
pem_management_cert:
|
||||
subscription_id:
|
||||
management_endpoint:
|
||||
capacity:
|
||||
Small:
|
||||
Medium:
|
||||
Large:
|
||||
instance_types:
|
||||
ExtraSmall:
|
||||
cpu: 1
|
||||
|
@ -33,6 +33,7 @@ require 'yaml'
|
||||
require 'rubygems'
|
||||
require 'azure'
|
||||
require 'uri'
|
||||
require 'tempfile'
|
||||
|
||||
$: << RUBY_LIB_LOCATION
|
||||
|
||||
@ -135,6 +136,7 @@ class AzureDriver
|
||||
# Azure constructor, loads credentials and endpoint
|
||||
def initialize(host)
|
||||
@host = host
|
||||
@to_inst ={}
|
||||
|
||||
@public_cloud_az_conf = YAML::load(File.read(AZ_DRIVER_CONF))
|
||||
|
||||
@ -143,67 +145,115 @@ class AzureDriver
|
||||
end
|
||||
|
||||
@instance_types = @public_cloud_az_conf['instance_types']
|
||||
@instance_types.keys.each{ |key|
|
||||
@to_inst[key.upcase] = key
|
||||
}
|
||||
|
||||
regions = @public_cloud_az_conf['regions']
|
||||
@region = regions[host] || regions["default"]
|
||||
certificate = Tempfile.new("certificate")
|
||||
conn_opts = get_connect_info(host)
|
||||
|
||||
access_id = conn_opts[:id]
|
||||
endpoint_addr = conn_opts[:endpoint]
|
||||
@region_name = conn_opts[:region]
|
||||
certificate << conn_opts[:cert]
|
||||
|
||||
certificate.close
|
||||
|
||||
# Sanitize region data
|
||||
if @region['pem_management_cert'].nil?
|
||||
if certificate.nil?
|
||||
raise "pem_management_cert not defined for #{host}"
|
||||
end
|
||||
|
||||
if @region['subscription_id'].nil?
|
||||
if access_id.nil?
|
||||
raise "subscription_id not defined for #{host}"
|
||||
end
|
||||
|
||||
# Set default endpoint if not declared
|
||||
if @region['management_endpoint'].nil?
|
||||
@region['management_endpoint']="https://management.core.windows.net"
|
||||
if endpoint_addr.nil?
|
||||
endpoint_addr="https://management.core.windows.net"
|
||||
end
|
||||
###################################################################
|
||||
|
||||
Azure.configure do |config|
|
||||
config.management_certificate = @region['pem_management_cert']
|
||||
config.subscription_id = @region['subscription_id']
|
||||
config.management_endpoint = @region['management_endpoint']
|
||||
config.management_certificate = certificate.path
|
||||
config.subscription_id = access_id
|
||||
config.management_endpoint = endpoint_addr
|
||||
end
|
||||
|
||||
certificate.unlink # deletes the temp file
|
||||
|
||||
@azure_vms = Azure::VirtualMachineManagementService.new
|
||||
end
|
||||
|
||||
def get_host_info(client)
|
||||
pool = OpenNebula::HostPool.new(client)
|
||||
pool.info
|
||||
objects=pool.select {|object| object.name==@host }
|
||||
|
||||
objects.first
|
||||
end
|
||||
|
||||
# Check the current template to retrieve
|
||||
# conection info needed for Azure
|
||||
def get_connect_info(host)
|
||||
conn_opts={}
|
||||
client = OpenNebula::Client.new
|
||||
xmlhost = get_host_info(client)
|
||||
|
||||
system = OpenNebula::System.new(client)
|
||||
config = system.get_configuration
|
||||
raise "Error getting oned configuration : #{config.message}" if OpenNebula.is_error?(config)
|
||||
|
||||
token = config["ONE_KEY"]
|
||||
|
||||
conn_opts = {
|
||||
:cert => xmlhost["TEMPLATE/AZ_CERT"],
|
||||
:id => xmlhost["TEMPLATE/AZ_ID"]
|
||||
}
|
||||
#conn_opts = OpenNebula.encrypt(conn_opts, token)
|
||||
conn_opts = OpenNebula.decrypt(conn_opts, token)
|
||||
|
||||
conn_opts[:region] = xmlhost["TEMPLATE/REGION_NAME"]
|
||||
conn_opts[:endpoint] = xmlhost["TEMPLATE/AZ_ENDPOINT"]
|
||||
|
||||
|
||||
return conn_opts
|
||||
end
|
||||
|
||||
# DEPLOY action
|
||||
def deploy(id, host, xml_text, lcm_state, deploy_id)
|
||||
if lcm_state == "BOOT" || lcm_state == "BOOT_FAILURE"
|
||||
load_default_template_values
|
||||
if lcm_state == "BOOT" || lcm_state == "BOOT_FAILURE"
|
||||
load_default_template_values
|
||||
|
||||
az_info = get_deployment_info(host, xml_text)
|
||||
az_info = get_deployment_info(host, xml_text)
|
||||
|
||||
if !az_value(az_info, 'IMAGE')
|
||||
raise "Cannot find IMAGE in deployment file"
|
||||
end
|
||||
if !az_value(az_info, 'IMAGE')
|
||||
raise "Cannot find IMAGE in deployment file"
|
||||
end
|
||||
|
||||
csn = az_value(az_info, 'CLOUD_SERVICE')
|
||||
csn = az_value(az_info, 'CLOUD_SERVICE')
|
||||
|
||||
csn = "csn#{id}" if !csn
|
||||
csn = "csn#{id}" if !csn
|
||||
|
||||
create_params = create_params(id,csn,az_info)
|
||||
create_options = create_options(id,csn,az_info)
|
||||
instance = nil
|
||||
create_params = create_params(id,csn,az_info)
|
||||
create_options = create_options(id,csn,az_info)
|
||||
instance = nil
|
||||
|
||||
in_silence do
|
||||
instance = @azure_vms.create_virtual_machine(create_params,
|
||||
create_options)
|
||||
end
|
||||
in_silence do
|
||||
instance = @azure_vms.create_virtual_machine(create_params,
|
||||
create_options)
|
||||
end
|
||||
|
||||
|
||||
if instance.class == Azure::VirtualMachineManagement::VirtualMachine
|
||||
puts(instance.vm_name)
|
||||
if instance.class == Azure::VirtualMachineManagement::VirtualMachine
|
||||
puts(instance.vm_name)
|
||||
else
|
||||
raise "Deployment failure " + instance
|
||||
end
|
||||
else
|
||||
raise "Deployment failure " + instance
|
||||
restore(deploy_id)
|
||||
deploy_id
|
||||
end
|
||||
else
|
||||
restore(deploy_id)
|
||||
deploy_id
|
||||
end
|
||||
end
|
||||
|
||||
# Shutdown an Azure instance
|
||||
@ -248,12 +298,19 @@ class AzureDriver
|
||||
def monitor_all_vms
|
||||
totalmemory = 0
|
||||
totalcpu = 0
|
||||
@region['capacity'].each { |name, size|
|
||||
cpu, mem = instance_type_capacity(name)
|
||||
|
||||
totalmemory += mem * size.to_i
|
||||
totalcpu += cpu * size.to_i
|
||||
}
|
||||
host_obj=get_host_info(OpenNebula::Client.new)
|
||||
capacity = host_obj.to_hash["HOST"]["TEMPLATE"]["CAPACITY"]
|
||||
if !capacity.nil? && Hash === capacity
|
||||
capacity.each{ |name, value|
|
||||
cpu, mem = instance_type_capacity(name)
|
||||
|
||||
totalmemory += mem * value.to_i
|
||||
totalcpu += cpu * value.to_i
|
||||
}
|
||||
else
|
||||
raise "you must define CAPACITY section properly! check the template"
|
||||
end
|
||||
|
||||
host_info = "HYPERVISOR=AZURE\n"
|
||||
host_info << "PUBLIC_CLOUD=YES\n"
|
||||
@ -314,9 +371,10 @@ private
|
||||
# Get the associated capacity of the instance_type as cpu (in 100 percent
|
||||
# e.g. 800 for 8 cores) and memory (in KB)
|
||||
def instance_type_capacity(name)
|
||||
return 0, 0 if @instance_types[name].nil?
|
||||
return (@instance_types[name]['cpu'].to_f * 100).to_i ,
|
||||
(@instance_types[name]['memory'].to_f * 1024 * 1024).to_i
|
||||
resource = @instance_types[@to_inst[name]] || @instance_types[name]
|
||||
return 0, 0 if resource.nil?
|
||||
return (resource['cpu'].to_f * 100).to_i ,
|
||||
(resource['memory'].to_f * 1024 * 1024).to_i
|
||||
end
|
||||
|
||||
# Get the Azure section of the template. If more than one Azure section
|
||||
@ -331,6 +389,7 @@ private
|
||||
# First, let's see if we have an Azure location that matches
|
||||
# our host name
|
||||
all_az_elements.each { |element|
|
||||
|
||||
cloud_host = element.elements["LOCATION"]
|
||||
type = element.elements["TYPE"].text
|
||||
|
||||
@ -342,87 +401,84 @@ private
|
||||
}
|
||||
|
||||
if !az
|
||||
# If we don't find an Azure location, and ONE just
|
||||
# knows about one Azure location, let's use that
|
||||
if all_az_elements.size == 1 and
|
||||
all_az_elements[0].elements["TYPE"].text.downcase.eql? "azure"
|
||||
az = all_az_elements[0]
|
||||
else
|
||||
STDERR.puts(
|
||||
"Cannot find Azure element in VM template "<<
|
||||
"or couldn't find any Azure location matching "<<
|
||||
"one of the templates.")
|
||||
exit(-1)
|
||||
end
|
||||
end
|
||||
|
||||
# If LOCATION not explicitly defined, try to get default, if not
|
||||
# try to use hostname as datacenter
|
||||
if !az.elements["LOCATION"]
|
||||
location=REXML::Element.new("LOCATION")
|
||||
if @defaults["LOCATION"]
|
||||
location.text=@defaults["LOCATION"]
|
||||
# If we don't find an Azure location, and ONE just
|
||||
# knows about one Azure location, let's use that
|
||||
if all_az_elements.size == 1 and
|
||||
all_az_elements[0].elements["TYPE"].text.downcase.eql? "azure"
|
||||
az = all_az_elements[0]
|
||||
else
|
||||
location.text=host
|
||||
STDERR.puts(
|
||||
"Cannot find Azure element in VM template "<<
|
||||
"or couldn't find any Azure location matching "<<
|
||||
"one of the templates.")
|
||||
exit(-1)
|
||||
end
|
||||
end
|
||||
|
||||
# location can be retrieved from host information...
|
||||
|
||||
# If LOCATION not explicitly defined, try to get default, if not
|
||||
# try to use hostname as datacenter
|
||||
if !az.elements["LOCATION"]
|
||||
location=REXML::Element.new("LOCATION")
|
||||
if @region_name
|
||||
location.text=@region_name
|
||||
else
|
||||
location.text=host
|
||||
end
|
||||
az.elements << location
|
||||
end
|
||||
end
|
||||
|
||||
# Translate region name form keyword to actual value
|
||||
region_keyword = az.elements["LOCATION"].text
|
||||
translated_region = @public_cloud_az_conf["regions"][region_keyword]
|
||||
az.elements["LOCATION"].text=translated_region["region_name"]
|
||||
|
||||
az
|
||||
az
|
||||
end
|
||||
|
||||
# Retrive the vm information from the Azure instance
|
||||
def parse_poll(instance)
|
||||
begin
|
||||
info = "#{POLL_ATTRIBUTE[:memory]}=0 " \
|
||||
"#{POLL_ATTRIBUTE[:cpu]}=0 " \
|
||||
"#{POLL_ATTRIBUTE[:nettx]}=0 " \
|
||||
"#{POLL_ATTRIBUTE[:netrx]}=0 "
|
||||
begin
|
||||
info = "#{POLL_ATTRIBUTE[:memory]}=0 " \
|
||||
"#{POLL_ATTRIBUTE[:cpu]}=0 " \
|
||||
"#{POLL_ATTRIBUTE[:nettx]}=0 " \
|
||||
"#{POLL_ATTRIBUTE[:netrx]}=0 "
|
||||
|
||||
state = ""
|
||||
if !instance
|
||||
state = VM_STATE[:deleted]
|
||||
else
|
||||
state = case instance.deployment_status
|
||||
when "Running", "Starting"
|
||||
VM_STATE[:active]
|
||||
when "Suspended", "Stopping",
|
||||
VM_STATE[:paused]
|
||||
state = ""
|
||||
if !instance
|
||||
state = VM_STATE[:deleted]
|
||||
else
|
||||
VM_STATE[:unknown]
|
||||
end
|
||||
end
|
||||
info << "#{POLL_ATTRIBUTE[:state]}=#{state} "
|
||||
|
||||
AZ_POLL_ATTRS.map { |key|
|
||||
value = instance.send(key)
|
||||
if !value.nil? && !value.empty?
|
||||
if key.to_s.upcase == "TCP_ENDPOINTS" or
|
||||
key.to_s.upcase == "UDP_ENDPOINTS"
|
||||
value_str = format_endpoints(value)
|
||||
elsif value.kind_of?(Hash)
|
||||
value_str = value.inspect
|
||||
state = case instance.deployment_status
|
||||
when "Running", "Starting"
|
||||
VM_STATE[:active]
|
||||
when "Suspended", "Stopping",
|
||||
VM_STATE[:paused]
|
||||
else
|
||||
value_str = value
|
||||
VM_STATE[:unknown]
|
||||
end
|
||||
|
||||
info << "AZ_#{key.to_s.upcase}="
|
||||
info << "\\\"#{value_str.gsub("\"","")}\\\" "
|
||||
|
||||
end
|
||||
}
|
||||
info << "#{POLL_ATTRIBUTE[:state]}=#{state} "
|
||||
|
||||
info
|
||||
rescue
|
||||
# Unknown state if exception occurs retrieving information from
|
||||
# an instance
|
||||
"#{POLL_ATTRIBUTE[:state]}=#{VM_STATE[:unknown]} "
|
||||
end
|
||||
AZ_POLL_ATTRS.map { |key|
|
||||
value = instance.send(key)
|
||||
if !value.nil? && !value.empty?
|
||||
if key.to_s.upcase == "TCP_ENDPOINTS" or
|
||||
key.to_s.upcase == "UDP_ENDPOINTS"
|
||||
value_str = format_endpoints(value)
|
||||
elsif value.kind_of?(Hash)
|
||||
value_str = value.inspect
|
||||
else
|
||||
value_str = value
|
||||
end
|
||||
|
||||
info << "AZ_#{key.to_s.upcase}="
|
||||
info << "\\\"#{value_str.gsub("\"","")}\\\" "
|
||||
|
||||
end
|
||||
}
|
||||
|
||||
info
|
||||
rescue
|
||||
# Unknown state if exception occurs retrieving information from
|
||||
# an instance
|
||||
"#{POLL_ATTRIBUTE[:state]}=#{VM_STATE[:unknown]} "
|
||||
end
|
||||
end
|
||||
|
||||
def format_endpoints(endpoints)
|
||||
|
Loading…
Reference in New Issue
Block a user