1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-23 22:50:09 +03:00

feature : Moved OCAInteration to VDC class. Update method still needs to be moved

This commit is contained in:
Ruben S. Montero 2011-09-25 03:31:53 +02:00
parent 2787cd8fb4
commit fc6303a14c
3 changed files with 314 additions and 144 deletions
src/ozones/Server

@ -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
@ -46,52 +47,6 @@ module OZones
return vdc_attributes
end
#######################################################################
# Methods to handle the ACL list
#######################################################################
# 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)
rule_str = Array.new
# Grant permissions to the group
rule_str << "@#{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"
###############################################################
#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))
end
def get_host_acls_str(group_id, host_list = nil)
rule_str = Array.new
if host_list == nil
host_list = self.hosts
end
# Grant permissions to use the vdc hosts
host_list.split(',').each{|hostid|
rule_str << "@#{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}
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)
@ -111,4 +66,246 @@ module OZones
return acl_ids
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
#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 "Error: VDC with id #{vdcid} not found"
end
zone = OZones::Zones.get(@vdc.zones_id)
end
@client = OpenNebula::Client.new(
"#{zone.onename}:#{zone.onepass}",
zone.endpoint,
false)
end
#######################################################################
#
#######################################################################
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
@vdc.raise_on_save_failure = true
vdcpass = Digest::SHA1.hexdigest(vdc_data.delete(:vdcadminpass))
@vdc.attributes = vdc_data
puts 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
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(group, user, acls_str, rc)
end
acls_str << acl.id.to_s << ","
}
@vdc.acls = acls_str.chop
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
rc = OpenNebula::Group.new_with_id(@vdc.group_id, @client).delete
if OpenNebula.is_error?(rc)
return rc
else
return @vdc.destroy
end
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_acls
rule_str = Array.new
# Grant permissions to the group
rule_str << "@#{@vdc.group_id} VM+NET+IMAGE+TEMPLATE/* " \
"CREATE+INFO_POOL_MINE"
# Grant permissions to the vdc admin
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(get_host_acls)
end
def get_host_acls(host_list = nil)
rule_str = Array.new
if host_list == nil
host_list = @vdc.hosts
end
# Grant permissions to use the vdc hosts
host_list.split(',').each{|hostid|
rule_str << "@#{@vdc.group_id} HOST/##{hostid} USE"
}
return rule_str
end
#######################################################################
# Functions to delete resources associated to the VDC
#######################################################################
# Deletes ACLs for the hosts
def delete_host_acls
@vdc.acls.split(',')[HOST_ACL_FIRST_ID..-1].each{|acl|
OpenNebula::Acl.new_with_id(acl.to_i, @client).delete
}
end
# Delete ACLs
def delete_acls
@vdc.acls.split(",").each{|acl|
OpenNebula::Acl.new_with_id(acl.to_i, @client).delete
}
end
# Deletes images
def delete_images
ip = OpenNebula::ImagePool.new(@client)
ip.info
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
end
end

@ -109,7 +109,7 @@ module OZones
end
###########################################################################
# This class represents a Zone with able to interact with its supporting
# This class represents a Zone able to interact with its supporting
# OpenNebula installation through OCA. Data persistence is provided by a
# Zones class
##########################################################################
@ -118,7 +118,7 @@ module OZones
@zone = Zones.get(zoneid)
if !@zone
raise "Error: Resource zone with id #{zoneid} not found"
raise "Error: Zone with id #{zoneid} not found"
end
@client = OpenNebula::Client.new(

@ -80,13 +80,18 @@ class OzonesServer
# 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]
else
return [200, resource.to_json]
rc = 200
res = case kind
when "vdc" then
OZones::Vdc.get(id)
when "zone" then
OZones::Zones.get(id)
else
rc = 404
OZones::Error.new("Error: #{kind} resource not supported")
end
return [rc, res.to_json]
end
############################################################################
@ -106,78 +111,53 @@ class OzonesServer
data.each{|key,value|
vdc_data[key.downcase.to_sym]=value if key!="pool"
}
#Get the Zone that will host the VDC. And check resouces
zoneid = vdc_data.delete(:zoneid)
force = vdc_data.delete(:force)
mandatory_params = [:vdcadminname, :vdcadminpass,
:zoneid, :name, :hosts]
if !zoneid
return [400, OZones::Error.new("Error: Couldn't create " \
"vdc. Mandatory attribute zoneid missing.").to_json]
end
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
}
# Check if the referenced zone exists
zone=OZones::Zones.get(vdc_data[:zoneid])
zone = OZones::Zones.get(zoneid)
if !zone
error = OZones::Error.new("Error: Zone " +
"#{vdc_data[:zoneid]} not found, cannot create Vdc.")
return [404, error.to_json]
return [404, OZones::Error.new("Error: Couldn't create " \
"vdc. Zone #{zoneid} not found.").to_json]
end
if (!vdc_data[:force] or vdc_data[:force].upcase!="YES") and
if (!force or force.upcase!="YES") and
!host_uniqueness?(zone, vdc_data[:hosts])
return [403, OZones::Error.new(
"Error: Couldn't create resource #{kind}. " +
"Hosts are not unique, and no force option" +
" was given.").to_json]
return [403, OZones::Error.new( "Error: Couldn't create " \
"Hosts are not unique, use force to override").to_json]
end
vdcadminname = vdc_data[:vdcadminname]
vdcadminpass = vdc_data[:vdcadminpass]
vdc_data.delete(:zoneid)
vdc_data.delete(:vdcadminpass)
vdc_data.delete(:force)
# Create de VDC
vdc = OZones::OpenNebulaVdc.new(-1,zone)
rc = vdc.create(vdc_data)
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]
if OpenNebula.is_error?(rc)
return [400, OZones::Error.new("Error: Couldn't create " \
"vdc. Reason: #{rc.message}").to_json]
end
zone.vdcs << vdc
zone.save
#Update the zone and save the vdc
zone.raise_on_save_failure = true
zone.vdcs << vdc.vdc
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
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]
begin
zone.save
rescue => e
#TODO Rollback VDC creation?
return [400, OZones::Error.new("Error: Couldn't create " \
"vdc. Zone could not be saved: #{e.message}").to_json]
end
pr.update # Rewrite proxy conf file
return [200, vdc.to_json]
when "zone" then
zone = OZones::Zones.create(data)
@ -279,21 +259,30 @@ class OzonesServer
############################################################################
# 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]
case kind
when "vdc" then
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
when "zone" then
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
else
return [404, OZones::Error.new("Error: #{kind} resource " \
"not supported").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
if !rc
return [500, OZones::Error.new(
"Error: Couldn't delete resource #{kind} with id #{id}").to_json]
else
@ -303,6 +292,9 @@ class OzonesServer
end
end
############################################################################
# Misc Helper Functions
############################################################################
private
# Check if hosts are already include in any Vdc of the zone
@ -322,23 +314,4 @@ class OzonesServer
return true
end
# Get hold of a object of a particular kind
def retrieve_resource(kind, id)
rc = case kind
when "vdc" then
OZones::Vdc.get(id)
when "zone" then
OZones::Zones.get(id)
else
OZones::Error.new("Error: #{kind} resource not supported")
end
if rc
return rc
else
return OZones::Error.new("Error: #{kind} with id #{id} not found")
end
end
end