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

F #5591: Add API support for custom role attrs (#2578)

(cherry picked from commit 7a9a6f87b61b6f8a212ee7b87f846f69002210b5)
This commit is contained in:
Victor Palma 2023-05-12 13:49:51 +02:00 committed by Ruben S. Montero
parent 8b7d7029db
commit 33420561f7
No known key found for this signature in database
GPG Key ID: A0CEA6FA880A1D87
3 changed files with 91 additions and 36 deletions

View File

@ -323,6 +323,9 @@ module OpenNebula
template['start_time'] = Integer(Time.now)
# Replace $attibute by the corresponding value
resolve_attributes(template)
super(template.to_json, template['name'])
end
@ -660,7 +663,7 @@ module OpenNebula
end if deploy
# Replace $attibute by the corresponding value
resolve_attributes(body)
resolve_networks(body)
# @body = template.to_hash
@ -784,31 +787,49 @@ module OpenNebula
end
# rubocop:disable Layout/LineLength
def resolve_networks(template)
template['roles'].each do |role|
next unless role['vm_template_contents']
# $CUSTOM1_VAR Any word character
# (letter, number, underscore)
role['vm_template_contents'].scan(/\$(\w+)/).each do |key|
net = template['networks_values'].find {|att| att.key? key[0] }
next if net.nil?
role['vm_template_contents'].gsub!(
'$'+key[0],
net[net.keys[0]]['id'].to_s
)
end
end
end
def resolve_attributes(template)
template['roles'].each do |role|
if role['vm_template_contents']
# $CUSTOM1_VAR Any word character
# (letter, number, underscore)
role['vm_template_contents'].scan(/\$(\w+)/).each do |key|
# Check if $ var value is in custom_attrs_values
if !template['custom_attrs_values'].nil? &&
template['custom_attrs_values'].key?(key[0])
# Check if $ var value is in custom_attrs_values within the role
if !role['custom_attrs_values'].nil? && \
role['custom_attrs_values'].key?(key[0])
role['vm_template_contents'].gsub!(
'$'+key[0],
template['custom_attrs_values'][key[0]]
role['custom_attrs_values'][key[0]]
)
next
end
# Check if $ var value is in networks
net = template['networks_values']
.find {|att| att.key? key[0] }
# Check if $ var value is in custom_attrs_values
next if net.nil?
next unless !template['custom_attrs_values'].nil? && \
template['custom_attrs_values'].key?(key[0])
role['vm_template_contents'].gsub!(
'$'+key[0],
net[net.keys[0]]['id'].to_s
template['custom_attrs_values'][key[0]]
)
end
end

View File

@ -186,6 +186,26 @@ def one_error_to_http(error)
end
end
# Check if the custom_attrs and their respective values are correct
#
# @param custom_attrs [Hash] Custom attrs of the service/role
# @param custom_attrs_values [Hash] Custom attrs values to check
def check_custom_attrs(custom_attrs, custom_attrs_values)
return if custom_attrs.nil? || custom_attrs.empty?
if custom_attrs_values.nil?
raise 'The Service template specifies custom attributes but no values have been found'
end
if !custom_attrs.is_a?(Hash) || !custom_attrs_values.is_a?(Hash)
raise 'Wrong custom_attrs or custom_attrs_values format'
end
return if (custom_attrs.keys - custom_attrs_values.keys).empty?
raise 'Verify that every custom attribute have its corresponding value defined'
end
##############################################################################
# Defaults
##############################################################################
@ -626,39 +646,43 @@ post '/service_template/:id/action' do
return internal_error(rc.message, one_error_to_http(rc.errno))
end
merge_template = opts['merge_template']
merge_template = opts['merge_template'] || {}
service_json = JSON.parse(service_template.to_json)
# Check custom_attrs
body = service_json['DOCUMENT']['TEMPLATE']['BODY']
custom_attrs = body['custom_attrs']
body = service_json['DOCUMENT']['TEMPLATE']['BODY']
if merge_template
begin
# Check service custom_attrs
custom_attrs = body['custom_attrs']
custom_attrs_values = merge_template['custom_attrs_values']
end
check_custom_attrs(custom_attrs, custom_attrs_values)
if custom_attrs && !(custom_attrs.is_a? Hash)
return internal_error('Wrong custom_attrs format',
VALIDATION_EC)
end
# Check custom attrs in each role
body['roles'].each do |role|
next if role['custom_attrs'].nil?
if custom_attrs_values && !(custom_attrs_values.is_a? Hash)
return internal_error('Wrong custom_attrs_values format',
VALIDATION_EC)
end
roles_merge_template = merge_template['roles']
if custom_attrs && !custom_attrs.empty? && !custom_attrs_values
return internal_error('No custom_attrs_values found',
VALIDATION_EC)
end
# merge_template must have 'role' key if role has custom attributes
if roles_merge_template.nil?
raise 'The Service template specifies custom attributes for the role ' \
"#{role['name']} but no values have been found"
end
if custom_attrs &&
!custom_attrs.empty? &&
custom_attrs_values &&
!(custom_attrs.keys - custom_attrs_values.keys).empty?
return internal_error('Every custom_attrs key must have its ' \
'value defined at custom_attrs_value',
VALIDATION_EC)
if !roles_merge_template.is_a?(Array) || roles_merge_template.empty?
raise 'The role custom attributes are empty or do not have a valid format'
end
# Select role from merge_template by role name
merge_role = roles_merge_template.find {|item| item['name'] == role['name'] }
role_custom_attrs = role['custom_attrs']
role_custom_attrs_values = merge_role['custom_attrs_values']
check_custom_attrs(role_custom_attrs, role_custom_attrs_values)
end
rescue StandardError => e
return internal_error(e.message, VALIDATION_EC)
end
# Check networks

View File

@ -42,6 +42,16 @@ module OpenNebula
:type => :string,
:required => false
},
'custom_attrs' => {
:type => :object,
:properties => {},
:required => false
},
'custom_attrs_values' => {
:type => :object,
:properties => {},
:required => false
},
'parents' => {
:type => :array,
:items => {
@ -487,7 +497,7 @@ module OpenNebula
instantiate_template = JSON.parse(@body.to_json)
else
instantiate_template = JSON.parse(@body.to_json)
.merge(merge_template)
.deep_merge(merge_template)
end
begin