Skip to content

Commit

Permalink
F #553: Scale service roles at cardinality changes
Browse files Browse the repository at this point in the history
  • Loading branch information
sk4zuzu committed Jun 1, 2024
1 parent 2c33564 commit 216107f
Show file tree
Hide file tree
Showing 7 changed files with 837 additions and 98 deletions.
218 changes: 218 additions & 0 deletions .github/patches/5.12/f-5591.patch
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
Loading

0 comments on commit 216107f

Please sign in to comment.