diff --git a/src/flow/lib/models/service.rb b/src/flow/lib/models/service.rb index 5f6410ad53..253db3af82 100644 --- a/src/flow/lib/models/service.rb +++ b/src/flow/lib/models/service.rb @@ -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 diff --git a/src/flow/oneflow-server.rb b/src/flow/oneflow-server.rb index 2ee67669f8..b2a581c3a5 100644 --- a/src/flow/oneflow-server.rb +++ b/src/flow/oneflow-server.rb @@ -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 diff --git a/src/oca/ruby/opennebula/flow/service_template.rb b/src/oca/ruby/opennebula/flow/service_template.rb index 6f6a18556e..d511b58df6 100644 --- a/src/oca/ruby/opennebula/flow/service_template.rb +++ b/src/oca/ruby/opennebula/flow/service_template.rb @@ -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