mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-23 22:50:09 +03:00
feature #789: Moved OCAInteration to VDC class. Update method still needs to be moved
This commit is contained in:
parent
2787cd8fb4
commit
fc6303a14c
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user