1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-21 14:50:08 +03:00

Merge branch 'feature-789'

This commit is contained in:
Ruben S. Montero 2011-10-07 13:52:16 +02:00
commit e8a19ee45c
7 changed files with 622 additions and 568 deletions

View File

@ -1036,7 +1036,6 @@ OZONES_ETC_FILES="src/ozones/Server/etc/ozones-server.conf"
OZONES_MODELS_FILES="src/ozones/Server/models/OzonesServer.rb \
src/ozones/Server/models/Auth.rb \
src/ozones/Server/models/OCAInteraction.rb \
src/sunstone/models/OpenNebulaJSON/JSONUtils.rb"
OZONES_TEMPLATE_FILES="src/ozones/Server/templates/index.html \

View File

@ -95,7 +95,7 @@ EOT
end
def post_resource_str(kind, tmpl_str)
body_str = OZonesClient::to_body(tmpl_str)
body_str = OZonesClient::to_body(kind, tmpl_str)
url = URI.parse("#{@endpoint}/#{kind}")
@ -112,7 +112,7 @@ EOT
end
def put_resource(kind, id, tmpl_str)
body_str = OZonesClient::to_body(tmpl_str)
body_str = OZonesClient::to_body(kind, tmpl_str)
url = URI.parse("#{@endpoint}/#{kind}/#{id}")
@ -248,16 +248,19 @@ EOT
# JSON & Template utils
##########################################################################
def self.to_body(tmpl_str)
body_str = ""
def self.to_body(kind, tmpl_str)
body_str = "{\n"
body_str << " \"#{kind}\": {"
tmpl_str.strip.each_line{|line|
line.strip!
key,value = line.split("=")
body_str = body_str + key + "=" + URI.escape(value) + "&"
body_str << "\n \"#{key}\": \"#{value}\","
}
body_str.chop!
body_str = body_str[0..-1]
body_str << "\n }\n"
body_str << "}\n"
end
def self.parse_json(json_str, root_element)

View File

@ -25,6 +25,7 @@ module OZones
property :name, String, :required => true, :unique => true
property :group_id, Integer
property :vdcadminname, String, :required => true
property :vdcadmin_id, Integer
property :acls, String
property :hosts, String
@ -45,70 +46,305 @@ module OZones
vdc_attributes["VDC"] = attributes
return vdc_attributes
end
end
###########################################################################
# This class represents a VDC able to interact with its supporting
# OpenNebula installation through OCA. Data persistence is provided by a
# Vdc class
###########################################################################
class OpenNebulaVdc
#######################################################################
# Constants
#######################################################################
VDC_ATTRS = [:vdcadminname, :vdcadminpass, :name, :hosts]
attr_reader :vdc
attr_reader :zone
#Creates an OpenNebula VDC, using its ID, vdcid and the associated zone
def initialize(vdcid, zone = nil)
if vdcid != -1
@vdc = Vdc.get(vdcid)
if !@vdc
raise "VDC with id #{vdcid} not found."
end
@zone = OZones::Zones.get(@vdc.zones_id)
else
@zone = zone
end
@client = OpenNebula::Client.new(
"#{@zone.onename}:#{@zone.onepass}",
@zone.endpoint,
false)
end
def to_json
@vdc.to_json
end
#######################################################################
# Methods to handle the ACL list
#
#######################################################################
def create(vdc_data)
#Check and prepare VDC data
VDC_ATTRS.each { |param|
if !vdc_data[param]
return OZones::Error.new("Error: Couldn't create vdc." \
"Mandatory attribute '#{param}' is missing.")
end
}
#Create a vdc record
@vdc = Vdc.new
vdcpass = Digest::SHA1.hexdigest(vdc_data.delete(:vdcadminpass))
@vdc.attributes = vdc_data
# Create a group in the zone with the VDC name
group = OpenNebula::Group.new(OpenNebula::Group.build_xml, @client)
rc = group.allocate(@vdc.name)
return rc if OpenNebula.is_error?(rc)
@vdc.group_id = group.id
# Create the VDC admin user in the Zone
user = OpenNebula::User.new(OpenNebula::User.build_xml, @client)
rc = user.allocate(@vdc.vdcadminname, vdcpass)
return rollback(group, nil, nil, rc) if OpenNebula.is_error?(rc)
@vdc.vdcadmin_id = user.id
# Change primary group of the admin user to the VDC group
rc = user.chgrp(group.id)
return rollback(group, user, nil, rc) if OpenNebula.is_error?(rc)
# Add ACLs
aclp = OpenNebula::AclPool.new(@client)
rules = get_acls
rc, acls_str = create_acls(rules)
return rollback(group, user,acls_str,rc) if OpenNebula.is_error?(rc)
@vdc.acls = acls_str
return true
end
def destroy
# Delete the resources from the VDC
delete_images
delete_templates
delete_vms
delete_vns
delete_acls
# Delete users from a group
up = OpenNebula::UserPool.new(@client)
up.info
up.each{|user|
if user['GID'].to_i == @vdc.group_id
user.delete
end
}
# Delete the group
OpenNebula::Group.new_with_id(@vdc.group_id, @client).delete
return @vdc.destroy
end
#Cleans bootstrap operations in a zone
def clean_bootstrap
delete_acls
OpenNebula::User.new_with_id(@vdc.vdcadmin_id, @client).delete
OpenNebula::Group.new_with_id(@vdc.group_id, @client).delete
end
def update(host_list)
# Delete existing host ACLs
delete_host_acls
if @vdc.acls =~ /((\d+,){#{HOST_ACL_FIRST_ID}}).*/
newacls = $1.chop
else
newacls = @vdc.acls.clone
end
# Create new ACLs. TODO Rollback ACL creation
if !host_list.empty?
host_acls = get_host_acls(host_list)
rc, acls_str = create_acls(host_acls)
return rc if OpenNebula.is_error?(rc)
#Create the new acl string.
newacls << "," << acls_str
end
#Update the VDC Record
begin
@vdc.raise_on_save_failure = true
@vdc.hosts = host_list
@vdc.acls = newacls
@vdc.save
rescue => e
return OpenNebula::Error.new(e.message)
end
return @vdc.to_json
end
private
#######################################################################
# Functions to generate ACL Strings
#######################################################################
# The ID of the first host ACL
HOST_ACL_FIRST_ID = 3
# This method returns an Array of ACL strings to create them
# in the target zone
def get_vdc_acls_str(user_id, group_id)
def get_acls
rule_str = Array.new
# Grant permissions to the group
rule_str << "@#{group_id} VM+NET+IMAGE+TEMPLATE/* " \
rule_str << "@#{@vdc.group_id} VM+NET+IMAGE+TEMPLATE/* " \
"CREATE+INFO_POOL_MINE"
# Grant permissions to the vdc admin
rule_str << "##{user_id} USER/* CREATE"
rule_str << "##{user_id} USER/@#{group_id} MANAGE+DELETE+INFO"
rule_str << "##{@vdc.vdcadmin_id} USER/* CREATE"
rule_str << "##{@vdc.vdcadmin_id} USER/@#{@vdc.group_id} " \
"MANAGE+DELETE+INFO"
###############################################################
#When more rules are added the class constant HOST_ACL_FIRST_ID
#must be modified
###############################################################
rule_str.concat(self.get_host_acls_str(group_id))
rule_str.concat(get_host_acls)
end
def get_host_acls_str(group_id, host_list = nil)
def get_host_acls(host_list = nil)
rule_str = Array.new
if host_list == nil
host_list = self.hosts
host_list = @vdc.hosts
end
# Grant permissions to use the vdc hosts
host_list.split(',').each{|hostid|
rule_str << "@#{group_id} HOST/##{hostid} USE"
rule_str << "@#{@vdc.group_id} HOST/##{hostid} USE"
}
return rule_str
end
def get_host_acls
self.acls.split(',')[HOST_ACL_FIRST_ID..-1].collect!{|x| x.to_i}
#######################################################################
# Functions to delete resources associated to the VDC
#######################################################################
# Deletes ACLs for the hosts
def delete_host_acls
host_acls = @vdc.acls.split(',')[HOST_ACL_FIRST_ID..-1]
if host_acls
host_acls.each{|acl|
OpenNebula::Acl.new_with_id(acl.to_i, @client).delete
}
end
end
# Returns the host acls as an array of strings.
# The acls of the VDC are updated and the host acl ids removed
def get_host_acls!(new_host_acls = nil)
acl_ids = self.acls.split(',')
vdc_acl = acl_ids.slice!(0,HOST_ACL_FIRST_ID)
newacl = ""
vdc_acl.each{|id|
newacl << id << ','
# Delete ACLs
def delete_acls
@vdc.acls.split(",").each{|acl|
OpenNebula::Acl.new_with_id(acl.to_i, @client).delete
}
newacl.chomp
newacl << new_host_acls if new_host_acls
end
self.acls = newacl
# Deletes images
def delete_images
ip = OpenNebula::ImagePool.new(@client)
ip.info
return acl_ids
ip.each{|image|
image.delete if image['GID'].to_i == @vdc.group_id
}
end
# Deletes templates
def delete_templates
tp = OpenNebula::TemplatePool.new(@client)
tp.info
tp.each{|template|
template.delete if template['GID'].to_i == @vdc.group_id
}
end
# Deletes VMs
def delete_vms
vmp = OpenNebula::VirtualMachinePool.new(@client)
vmp.info
vmp.each{|vm|
vm.delete if vm['GID'].to_i == @vdc.group_id
}
end
# Deletes VNs
def delete_vns
vnp = OpenNebula::VirtualNetworkPool.new(@client)
vnp.info
vnp.each{|vn|
vnp.delete if vn['GID'].to_i == @vdc.group_id
}
end
#######################################################################
# Misc helper functions for the class
#######################################################################
# Deletes resources from failed created VDC
def rollback(group, user, acls, rc)
group.delete
user.delete if user
if acls
acls.chop
acls.split(",").each{|acl|
OpenNebula::Acl.new_with_id(acl.to_i, @client).delete
}
end
return rc
end
# Creates an acl array of acl strings. Returns true or error and
# a comma-separated list with the new acl ids
def create_acls(acls)
acls_str = ""
rc = true
acls.each{|rule|
acl = OpenNebula::Acl.new(OpenNebula::Acl.build_xml,@client)
rc = acl.allocate(*OpenNebula::Acl.parse_rule(rule))
break if OpenNebula.is_error?(rc)
acls_str << acl.id.to_s << ","
}
return rc, acls_str.chop
end
end
end

View File

@ -19,25 +19,38 @@ module OZones
class Zones
include DataMapper::Resource
include OpenNebulaJSON::JSONUtils
extend OpenNebulaJSON::JSONUtils
property :id, Serial
property :name, String, :required => true, :unique => true
property :onename, String, :required => true
property :onepass, String, :required => true
property :endpoint, String, :required => true
property :sunsendpoint, String
extend OpenNebulaJSON::JSONUtils
#######################################################################
# Data Model for the Zone
#######################################################################
property :id, Serial
property :name, String, :required => true, :unique => true
property :onename, String, :required => true
property :onepass, String, :required => true
property :endpoint, String, :required => true
property :sunsendpoint, String
has n, :vdcs
#######################################################################
# Constants
#######################################################################
ZONE_ATTRS = [:onename, :onepass, :endpoint, :name]
#######################################################################
# JSON Functions
#######################################################################
def self.to_hash
zonePoolHash = Hash.new
zonePoolHash["ZONE_POOL"] = Hash.new
zonePoolHash["ZONE_POOL"]["ZONE"] = Array.new unless self.all.empty?
self.all.each{|zone|
zonePoolHash["ZONE_POOL"]["ZONE"] <<
zone.attributes.merge({:numbervdcs => zone.vdcs.all.size})
}
return zonePoolHash
end
@ -45,11 +58,132 @@ module OZones
zone_attributes = Hash.new
zone_attributes["ZONE"] = attributes
zone_attributes["ZONE"][:vdcs] = Array.new
self.vdcs.all.each{|vdc|
zone_attributes["ZONE"][:vdcs]<<vdc.attributes
}
return zone_attributes
end
#######################################################################
# Zone Data Management
#######################################################################
def self.create(data)
zone_data = Hash.new
data.each{|key,value|
zone_data[key.downcase.to_sym] = value
}
ZONE_ATTRS.each { |param|
if !zone_data[param]
return OZones::Error.new("Error: Couldn't create zone. " \
"Mandatory attribute '#{param}' is missing.")
end
}
# Digest and check credentials
zone_data[:onepass] = Digest::SHA1.hexdigest(zone_data[:onepass])
rc = OpenNebulaZone::check_oneadmin(zone_data[:onename],
zone_data[:onepass],
zone_data[:endpoint])
if OpenNebula.is_error?(rc)
return OZones::Error.new("Error: Couldn't create zone. "\
"Reason: #{rc.message}")
end
# Create the zone
begin
zone = Zones.new
zone.raise_on_save_failure = true
zone.attributes = zone_data
zone.save
rescue => e
return OZones::Error.new(e.message)
end
return zone
end
end
###########################################################################
# This class represents a Zone able to interact with its supporting
# OpenNebula installation through OCA. Data persistence is provided by a
# Zones class
##########################################################################
class OpenNebulaZone
def initialize(zoneid)
@zone = Zones.get(zoneid)
if !@zone
raise "Error: Zone with id #{zoneid} not found"
end
@client = OpenNebula::Client.new(
"#{@zone.onename}:#{@zone.onepass}",
@zone.endpoint,
false)
end
def pool_to_json(pool_kind)
pool = case pool_kind
when "host" then
OpenNebulaJSON::HostPoolJSON.new(@client)
when "image" then
OpenNebulaJSON::ImagePoolJSON.new(@client)
when "user" then
OpenNebulaJSON::UserPoolJSON.new(@client)
when "vm" then
OpenNebulaJSON::VirtualMachinePoolJSON.new(@client)
when "vn","vnet" then
OpenNebulaJSON::VirtualNetworkPoolJSON.new(@client)
when "template","vmtemplate" then
OpenNebulaJSON::TemplatePoolJSON.new(@client)
else
error = OZones::Error.new("Error: Pool #{pool_kind} not " \
"supported for zone view")
return [404, error.to_json]
end
pool.info
return [200, pool.to_json]
end
def self.all_pools_to_json(pool_kind)
pool = case pool_kind
when "host" then
OZones::AggregatedHosts.new
when "image" then
OZones::AggregatedImages.new
when "user" then
OZones::AggregatedUsers.new
when "vm" then
OZones::AggregatedVirtualMachines.new
when "vn","vnet" then
OZones::AggregatedVirtualNetworks.new
when "template","vmtemplate" then
OZones::AggregatedTemplates.new
else
error = OZones::Error.new("Error: Pool #{pool_kind} not" \
" supported for aggregated zone view")
return [404, error.to_json]
end
return [200, pool.to_json]
end
def self.check_oneadmin(name, pass, endpoint)
# Create a new client to interact with the zone
client = OpenNebula::Client.new("#{name}:#{pass}",endpoint,false)
hostpool = OpenNebula::HostPool.new(client)
return hostpool.info
end
end
end

View File

@ -1,206 +0,0 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2011, 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. #
#--------------------------------------------------------------------------- #
require 'OpenNebula'
class OCAInteraction
# Creates a VDC (user, group, hosts)
def create_vdc_in_zone(zone, vdc, adminname, adminpass)
# Create a new client to interact with the zone
client = OpenNebula::Client.new(zone.onename + ":" + zone.onepass,
zone.endpoint,
false)
# Create a group in the zone with the VDC name
group = OpenNebula::Group.new(OpenNebula::Group.build_xml, client)
result = group.allocate(vdc.name)
return result if OpenNebula.is_error?(result)
# Create the VDC admin user in the Zone
user = OpenNebula::User.new(OpenNebula::User.build_xml, client)
result = user.allocate(adminname, adminpass)
return rollback(client, group,
result, user) if OpenNebula.is_error?(result)
# Change primary group of the admin user to the VDC group
result = user.chgrp(group.id)
return rollback(client, group,
result, user) if OpenNebula.is_error?(result)
# Add ACLs
aclp = OpenNebula::AclPool.new client
rules = vdc.get_vdc_acls_str(user.id, group.id)
acls_str = ""
rules.each{ |rule_str|
acl = OpenNebula::Acl.new(OpenNebula::Acl.build_xml,client)
rc = acl.allocate(*OpenNebula::Acl.parse_rule(rule_str))
if OpenNebula.is_error?(rc)
return rollback(client, group, rc, user, acls_str)
end
acls_str << acl.id.to_s << ","
}
return acls_str.chop, group.id
end
def delete_vdc_in_zone(id)
vdc = OZones::Vdc.get(id)
zone= OZones::Zones.get(vdc.zones_id)
# Create a new client to interact with the zone
client = OpenNebula::Client.new(zone.onename + ":" + zone.onepass,
zone.endpoint,
false)
# Delete the resources from the VDC
delete_images(vdc.group_id, client)
delete_templates(vdc.group_id, client)
delete_vms(vdc.group_id, client)
delete_vns(vdc.group_id, client)
# Delete ACLs
delete_acls(vdc.acls, client)
# Delete users from a group
up = OpenNebula::UserPool.new(client)
up.info
up.each{|user|
if user['GID'].to_i == vdc.group_id
OpenNebula::User.new_with_id(user['ID'], client).delete
end
}
# Delete the group
rc = OpenNebula::Group.new_with_id(vdc.group_id, client).delete
if OpenNebula.is_error?(rc)
return rc
else
return nil
end
end
def update_vdc_hosts(zone, vdc, host_list)
# Create a new client to interact with the zone
client = OpenNebula::Client.new(zone.onename + ":" + zone.onepass,
zone.endpoint,
false)
# Delete existing host ACLs
vdc.get_host_acls.each{|acl_id|
OpenNebula::Acl.new_with_id(acl_id, client).delete
}
# Create new ACLs
acls_str = ""
host_acls = vdc.get_host_acls_str(vdc.group_id, host_list)
host_acls.each{|rule|
acl = OpenNebula::Acl.new(OpenNebula::Acl.build_xml,client)
rc = acl.allocate(*OpenNebula::Acl.parse_rule(rule))
if OpenNebula.is_error?(rc)
return rc
end
acls_str += acl.id.to_s + ","
}
return acls_str.chop
end
# Creates a VDC (user, group, hosts)
def check_oneadmin(oneadminname, oneadminpass, endpoint)
# Create a new client to interact with the zone
client = OpenNebula::Client.new(oneadminname + ":" + oneadminpass,
endpoint,
false)
hostpool=OpenNebula::HostPool.new(client)
result = hostpool.info
return result
end
# Deletes resources from failed created VDC
def rollback(client, group, result, user=nil, acls_str=nil)
user.delete if user
group.delete
delete_acls(acls_str, client)
return result
end
# Deletes images from a group
def delete_images(groupid, client)
ip = OpenNebula::ImagePool.new(client)
ip.info
ip.each{|image|
if image['GID'].to_i == groupid
OpenNebula::Image.new_with_id(image['ID'], client).delete
end
}
end
# Deletes templates from a group
def delete_templates(groupid, client)
tp = OpenNebula::TemplatePool.new(client)
tp.info
tp.each{|template|
if template['GID'].to_i == groupid
OpenNebula::Image.new_with_id(template['ID'], client).delete
end
}
end
# Deletes VMs from a group
def delete_vms(groupid, client)
vmp = OpenNebula::VirtualMachinePool.new(client)
vmp.info
vmp.each{|vm|
if vm['GID'].to_i == groupid
OpenNebula::VirtualMachine.new_with_id(vm['ID'], client).delete
end
}
end
# Deletes VNs from a group
def delete_vns(groupid, client)
vnp = OpenNebula::VirtualNetworkPool.new(client)
vnp.info
vnp.each{|vn|
if vn['GID'].to_i == groupid
OpenNebula::VirtualNetwork.new_with_id(vn['ID'], client).delete
end
}
end
# Delete ACLs from a group
def delete_acls(acls_str, client)
if acls_str != nil && !acls_str.empty?
acls_str.split(",").each{|acl_id|
OpenNebula::Acl.new_with_id(acl_id.to_i, client).delete
}
end
end
end

View File

@ -14,372 +14,250 @@
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'OCAInteraction'
require 'JSONUtils'
class OzonesServer
include OpenNebulaJSON::JSONUtils
def initialize
@ocaInt = OCAInteraction.new
end
############################################################################
# Retrieve resources
# Get methods for the Zones and VDC interface
############################################################################
def get_pool(kind)
pool = case kind
when "vdc" then OZones::Vdc
when "zone" then OZones::Zones
else
error = OZones::Error.new(
"Error: #{kind} resource not supported")
return [404, error.to_json]
end
return [200, pool.to_json]
# Gets all VDCs
def get_vdcs
return 200, OZones::Vdc.to_json
end
# Gets an aggreageted pool for a zone or vdc
# ie All the hosts in all the Zones
def get_aggregated_pool(kind, aggkind)
aggpool = case kind
when "zone" then
case aggkind
when "host" then OZones::AggregatedHosts.new
when "image" then OZones::AggregatedImages.new
when "user" then OZones::AggregatedUsers.new
when "vm" then OZones::AggregatedVirtualMachines.new
when "vn","vnet" then OZones::AggregatedVirtualNetworks.new
when "template","vmtemplate" then OZones::AggregatedTemplates.new
end
else
error = OZones::Error.new(
"Error: #{aggkind} aggregated pool for #{kind} not supported")
return [404, error.to_json]
end
# Gets a VDC
def get_vdc(id)
vdc = OZones::Vdc.get(id)
return [200, aggpool.to_json]
end
# Gets an aggreageted pool for a zone or vdc in json
# ie All the hosts in all the Zones
def get_full_resource(kind, id, aggkind)
resource = retrieve_resource(kind, id)
if OZones.is_error?(resource)
return [404, resource.to_json]
end
# TODO build the vdc retrieval
if kind == "zone"
client = OpenNebula::Client.new(
resource.onename + ":" + resource.onepass,
resource.endpoint,
false)
simple_pool = case aggkind
when "host" then OpenNebulaJSON::HostPoolJSON.new(client)
when "image" then OpenNebulaJSON::ImagePoolJSON.new(client)
when "user" then OpenNebulaJSON::UserPoolJSON.new(client)
when "vm" then OpenNebulaJSON::VirtualMachinePoolJSON.new(client)
when "vn","vnet" then OpenNebulaJSON::VirtualNetworkPoolJSON.new(client)
when "template","vmtemplate" then OpenNebulaJSON::TemplatePoolJSON.new(client)
else
error = OZones::Error.new(
"Error: #{aggkind} aggregated pool for #{kind} #{id} not supported")
return [404, error.to_json]
end
simple_pool.info
return [200, simple_pool.to_json]
end
end
# Get a json representation resource with local (DB) info
def get_resource(kind, id)
resource = retrieve_resource(kind, id)
if OZones.is_error?(resource)
return [404, resource.to_json]
if vdc
return [200, vdc.to_json]
else
return [200, resource.to_json]
return [404,
OZones::Error.new("Error:VDC with id #{id} not found").to_json]
end
end
#Gets all Zones
def get_zones
return 200, OZones::Zones.to_json
end
# Get hold of a object of a particular kind
def retrieve_resource(kind, id)
resource = case kind
when "vdc" then OZones::Vdc.get(id)
when "zone" then OZones::Zones.get(id)
else
return OZones::Error.new(
"Error: #{kind} resource not supported")
end
#Gets a zone
def get_zone(id)
zone = OZones::Zones.get(id)
if resource
return resource
if zone
return [200, zone.to_json]
else
return OZones::Error.new(
"Error: Resource #{kind} with id #{id} not found")
return [404,
OZones::Error.new("Error:Zone with id #{id} not found").to_json]
end
end
# Gets an aggreageted view of a pool for all zones
def get_zones_pool(pool)
OZones::OpenNebulaZone::all_pools_to_json(pool)
end
# Gets a pool view of a given zone
def get_zone_pool(id, pool)
begin
zone = OZones::OpenNebulaZone.new(id)
return zone.pool_to_json(pool)
rescue => e
return [404, OZones::Error.new(e.message).to_json]
end
end
############################################################################
# Create resources
############################################################################
# Creates a resource of a kind, and updates the Proxy Rules
def create_resource(kind, data, body, pr)
def create_vdc (body,pr)
#Setup POST data
data = parse_json(body,"vdc")
if body.size > 0
result = parse_json(body,kind)
data = result if !OpenNebula.is_error?(result)
if OpenNebula.is_error?(data)
return [400, OZones::Error.new("Error: Couldn't update vdc. " \
"Reason: #{data.message}.").to_json]
end
resource = case kind
when "vdc" then
vdc_data = Hash.new
data.each{|key,value|
vdc_data[key.downcase.to_sym]=value if key!="pool"
}
vdc_data = Hash.new
mandatory_params = [:vdcadminname, :vdcadminpass,
:zoneid, :name, :hosts]
data.each{|key,value|
vdc_data[key.downcase.to_sym] = value
}
#Get the Zone that will host the VDC. And check resouces
zoneid = vdc_data.delete(:zoneid)
force = vdc_data.delete(:force)
mandatory_params.each { |param|
if !vdc_data[param]
return [400, OZones::Error.new(
"Error: Couldn't create resource #{kind}. " +
"Mandatory attribute '#{param}' is missing.").to_json]
end
}
if !zoneid
return [400, OZones::Error.new("Error: Couldn't create vdc. " \
"Mandatory attribute zoneid missing.").to_json]
end
# Check if the referenced zone exists
zone=OZones::Zones.get(vdc_data[:zoneid])
if !zone
error = OZones::Error.new("Error: Zone " +
"#{vdc_data[:zoneid]} not found, cannot create Vdc.")
return [404, error.to_json]
end
zone = OZones::Zones.get(zoneid)
if !zone
return [404, OZones::Error.new("Error: Couldn't create vdc. " \
"Zone #{zoneid} not found.").to_json]
end
if (!defined? vdc_data[:force] or
(defined? vdc_data[:force] and vdc_data[:force]!="yes")) and
!host_uniqueness?(zone, vdc_data[:hosts])
return [403, OZones::Error.new(
"Error: Couldn't create resource #{kind}. " +
"One or several hosts belong to a different VDC "+
"and no force option was provided.").to_json]
end
if (!force or force.upcase!="YES") and
!host_uniqueness?(zone, vdc_data[:hosts])
vdcadminname = vdc_data[:vdcadminname]
vdcadminpass = vdc_data[:vdcadminpass]
vdc_data.delete(:zoneid)
vdc_data.delete(:vdcadminpass)
vdc_data.delete(:force)
return [403, OZones::Error.new("Error: Couldn't create vdc. " \
"Hosts are not unique, use force to override").to_json]
end
begin
vdc = OZones::Vdc.create(vdc_data)
rescue Exception => e
msg = e.message
msg["accessible in OZones::Vdc"] = "supported."
return [400, OZones::Error.new(
"Error: Couldn't create resource #{kind}." +
" #{msg}").to_json]
end
# Create de VDC
vdc = OZones::OpenNebulaVdc.new(-1,zone)
rc = vdc.create(vdc_data)
zone.vdcs << vdc
zone.save
if OpenNebula.is_error?(rc)
return [400, OZones::Error.new("Error: Couldn't create vdc. " \
"Reason: #{rc.message}").to_json]
end
if zone.saved? and vdc.saved?
vdcadminpass = Digest::SHA1.hexdigest(vdcadminpass)
rc = @ocaInt.create_vdc_in_zone(zone,
vdc,
vdcadminname,
vdcadminpass)
if OpenNebula.is_error?(rc)
vdc.destroy
return [400, OZones::Error.new(
"Error: Couldn't create #{kind}. Reason: " +
rc.message).to_json]
else
vdc.acls = rc[0]
vdc.group_id = rc[1]
vdc.save
#Update the zone and save the vdc
zone.raise_on_save_failure = true
zone.vdcs << vdc.vdc
pr.update # Rewrite proxy conf file
return [200, vdc.to_json]
end
else
return [400, OZones::Error.new(
"Error: Couldn't create resource #{kind}." +
" Maybe duplicated name?").to_json]
end
begin
zone.save
rescue => e
vdc.clean_bootstrap
when "zone" then
zone_data=Hash.new
data.each{|key,value|
zone_data[key.downcase.to_sym]=value if key!="pool"
}
return [400, OZones::Error.new("Error: Couldn't create " \
"vdc. Zone could not be saved: #{e.message}").to_json]
end
mandatory_params = [:onename, :onepass, :endpoint, :name]
pr.update # Rewrite proxy conf file
return [200, vdc.to_json]
end
mandatory_params.each { |param|
if !zone_data[param]
return [400, OZones::Error.new(
"Error: Couldn't create resource #{kind}. " +
"Mandatory attribute '#{param}' is missing.").to_json]
end
}
def create_zone(body, pr)
#Setup POST data
data = parse_json(body,"zone")
# Digest and check credentials
zone_data[:onepass] =
Digest::SHA1.hexdigest(zone_data[:onepass])
if OpenNebula.is_error?(data)
return [400, OZones::Error.new("Error: Couldn't update vdc. " \
"Reason: #{data.message}.").to_json]
end
rc = @ocaInt.check_oneadmin(zone_data[:onename],
zone_data[:onepass],
zone_data[:endpoint])
zone = OZones::Zones.create(data)
if OpenNebula.is_error?(rc)
return [400, OZones::Error.new(
"Error: Couldn't create resource #{kind}. Reason: "+
rc.message).to_json]
end
if OZones.is_error?(zone)
return [400, zone.to_json]
end
# Create the zone
zone = OZones::Zones.create(zone_data)
rc = zone.save
if rc
pr.update # Rewrite proxy conf file
return [200, zone.to_json]
else
return [400, OZones::Error.new(
"Error: Couldn't create resource #{kind.upcase}." +
" Maybe duplicated name?").to_json]
end
else
error = OZones::Error.new(
"Error: #{kind.upcase} resource not supported")
return [404, error.to_json]
end
pr.update
return [200, zone.to_json]
end
############################################################################
# Update resources
############################################################################
# Updates a resource of a kind, and updates the Proxy Rules if needed
def update_resource(kind, data, body, pr)
def update_vdc(vdc_id, body)
#Setup PUT data
data = parse_json(body,"vdc")
if body.size > 0
result = parse_json(body,kind)
data = result if !OpenNebula.is_error?(result)
if OpenNebula.is_error?(data)
return [400, OZones::Error.new("Error: Couldn't update vdc. " \
"Reason: #{data.message}.").to_json]
end
resource = case kind
when "vdc" then
vdc_data=Hash.new
vdc_id = nil
data.each{|key,value|
vdc_data[key.downcase.to_sym]=value if key!="id"
vdc_id = value if key=="id"
}
vdc_data = Hash.new
# Check parameters
if !vdc_data[:hosts] || !vdc_id
return [400, OZones::Error.new(
"Error: Couldn't update resource #{kind}. " +
"Need ID and HOSTS to update.").to_json]
end
data.each{|key,value|
vdc_data[key.downcase.to_sym]=value
}
# Check if the referenced Vdc exists
vdc=OZones::Vdc.get(vdc_id)
if !vdc
error = OZones::Error.new("Error: Vdc " +
"#{vdc_id} not found, cannot update Vdc.")
return [404, error.to_json]
end
hosts = vdc_data.delete(:hosts)
force = vdc_data.delete(:force)
# Get the zone where the Vdc belongs
zone=OZones::Zones.get(vdc.zones.id)
if !zone
error = OZones::Error.new("Error: Zone " +
"#{vdc.zones.id} not found, cannot update Vdc.")
return [404, error.to_json]
end
if (!vdc_data[:force] or vdc_data[:force].upcase!="YES") and
!host_uniqueness?(zone, vdc_data[:hosts], vdc_id.to_i)
return [403, OZones::Error.new(
"Error: Couldn't update resource #{kind}. " +
"One or several hosts belong to a different VDC "+
"and no force option was provided.").to_json]
end
# Check parameters
if !hosts
return [400, OZones::Error.new("Error: Couldn't update vdc. " \
"Missing HOSTS.").to_json]
end
rc = @ocaInt.update_vdc_hosts(zone, vdc, vdc_data[:hosts])
# Check if the referenced Vdc exists
begin
vdc = OZones::OpenNebulaVdc.new(vdc_id)
rescue => e
return [404, OZones::Error.new("Error: Couldn't update vdc. " \
"#{e.message}").to_json]
end
if (!force or force.upcase != "YES") and
!host_uniqueness?(vdc.zone, hosts, vdc_id.to_i)
if !OpenNebula.is_error?(rc)
vdc.hosts = vdc_data[:hosts]
vdc.get_host_acls!(rc)
vdc.save
if vdc.saved?
return [200, vdc.to_json]
else
return [500, OZones::Error.new(
"Error: Couldn't update resource #{kind}.").to_json]
end
else
return [500, OZones::Error.new(
"Error: Couldn't update resource #{kind.upcase}." +
" Failed to update ACLs").to_json]
end
else
error = OZones::Error.new(
"Error: #{kind.upcase} resource update not supported")
return [404, error.to_json]
end
end
return [403, OZones::Error.new("Error: Couldn't update vdc. " \
"Hosts are not unique, use force to override").to_json]
end
rc = vdc.update(hosts)
if !OpenNebula.is_error?(rc)
return [200, rc]
else
return [500, OZones::Error.new("Error: Couldn't update vdc. " \
" Reason: #{rc.message}").to_json]
end
end
############################################################################
# Delete resources
############################################################################
# Deletes a resource of a kind, and updates the Proxy Rules
def delete_resource(kind, id, pr)
resource = retrieve_resource(kind, id)
if OZones.is_error?(resource)
return [404, resource.to_json]
def delete_vdc(id, pr)
begin
vdc = OZones::OpenNebulaVdc.new(id)
rc = vdc.destroy
rescue => e
return [404, OZones::Error.new("Error: Can not delete vdc. " \
"Reason: #{e.message}").to_json]
end
if kind == "vdc"
rc = @ocaInt.delete_vdc_in_zone(id)
if OpenNebula.is_error?(rc)
return [500, OZones::Error.new(
"Error: Couldn't delete resources from VDC with id #{id}, " +
"aborting VDC deletion. Reason:" + rc.message).to_json]
end
end
if !resource.destroy
return [500, OZones::Error.new(
"Error: Couldn't delete resource #{kind} with id #{id}").to_json]
if !rc
return [500, OZones::Error.new("Error: Couldn't delete " \
"vdc #{id}").to_json]
else
pr.update # Rewrite proxy conf file
return [200, OZones.str_to_json(
"Resource #{kind} with id #{id} successfully deleted")]
return [200, OZones.str_to_json("Vdc #{id} successfully deleted")]
end
end
def delete_zone(id, pr)
zone = OZones::Zones.get(id)
if zone
rc = zone.destroy
else
return [404, OZones::Error.new("Error: Can not delete " \
"zone. Reason: zone #{id} not found").to_json]
end
if !rc
return [500, OZones::Error.new("Error: Couldn't delete " \
"zone #{id}").to_json]
else
pr.update # Rewrite proxy conf file
return [200, OZones.str_to_json("Zone #{id} successfully deleted")]
end
end
############################################################################
# Helper functions
# Misc Helper Functions
############################################################################
private
# Check if hosts are already include in any Vdc of the zone
def host_uniqueness?(zone, host_list, vdc_id = -1)
return true if host_list.empty?
all_hosts = ""
zone.vdcs.all.each{|vdc|
if vdc.hosts != nil and !vdc.hosts.empty? and vdc.id != vdc_id
@ -395,6 +273,4 @@ class OzonesServer
return true
end
end

View File

@ -226,48 +226,60 @@ get '/config' do
end
##############################################################################
# GET Pool information
# GET information
##############################################################################
get '/:pool' do
@OzonesServer.get_pool(params[:pool])
get '/vdc' do
@OzonesServer.get_vdcs
end
get '/vdc/:id' do
@OzonesServer.get_vdc(params[:id])
end
get '/zone' do
@OzonesServer.get_zones
end
get %r{/zone/([\d]+)/([\w]+)} do
@OzonesServer.get_zone_pool(params[:captures][0], params[:captures][1])
end
get %r{/zone/([\d]+)} do
@OzonesServer.get_zone(params[:captures].first)
end
get %r{/zone/([\w]+)} do
@OzonesServer.get_zones_pool(params[:captures].first)
end
##############################################################################
# GET Resource information
# POSTs information
##############################################################################
get %r{/(zone|vdc)/(\d+)/(\w+)} do |kind, id, aggpool|
@OzonesServer.get_full_resource(kind,id,aggpool)
post '/vdc' do
@OzonesServer.create_vdc(request.body.read, @pr)
end
get %r{/(zone|vdc)/(\d+)} do |kind, id|
@OzonesServer.get_resource(kind,id)
end
get '/:pool/:aggpool' do
@OzonesServer.get_aggregated_pool(params[:pool], params[:aggpool])
end
##############################################################################
# Create a new Resource
##############################################################################
post '/:pool' do
@OzonesServer.create_resource(params[:pool], params, request.body.read, @pr)
post '/zone' do
@OzonesServer.create_zone(request.body.read, @pr)
end
##############################################################################
# Update Resource
##############################################################################
put '/:resource/:id' do
@OzonesServer.update_resource(params[:resource], params,
request.body.read, @pr)
put '/vdc/:id' do
@OzonesServer.update_vdc(params[:id], request.body.read)
end
##############################################################################
# Delete Resource
##############################################################################
delete '/:resource/:id' do
@OzonesServer.delete_resource(params[:resource], params[:id], @pr)
delete '/vdc/:id' do
@OzonesServer.delete_vdc(params[:id], @pr)
end
delete '/zone/:id' do
@OzonesServer.delete_zone(params[:id], @pr)
end