-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
F #553: Scale service roles at cardinality changes
- Loading branch information
Showing
7 changed files
with
837 additions
and
98 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,218 @@ | ||
commit 7a9a6f87b61b6f8a212ee7b87f846f69002210b5 | ||
Author: Victor Palma <[email protected]> | ||
Date: Fri May 12 13:49:51 2023 +0200 | ||
|
||
F #5591: Add API support for custom role attrs (#2578) | ||
|
||
diff --git a/src/flow/lib/models/service.rb b/usr/lib/one/oneflow/lib/models/service.rb | ||
index 5f6410ad53..253db3af82 100644 | ||
--- a/src/flow/lib/models/service.rb | ||
+++ b/usr/lib/one/oneflow/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/usr/lib/one/oneflow/oneflow-server.rb | ||
index 2ee67669f8..b2a581c3a5 100644 | ||
--- a/src/flow/oneflow-server.rb | ||
+++ b/usr/lib/one/oneflow/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 !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'] | ||
|
||
- 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) | ||
+ 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/usr/lib/one/ruby/opennebula/flow/service_template.rb | ||
index 6f6a18556e..d511b58df6 100644 | ||
--- a/src/oca/ruby/opennebula/flow/service_template.rb | ||
+++ b/usr/lib/one/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 |
Oops, something went wrong.