Skip to content

Commit

Permalink
Add Function FLAVOURS to VM instances (#39)
Browse files Browse the repository at this point in the history
* More robust SCHEDULING and FLAVOUR saved on VM.USER_TEMPLATE

* Fix tuple handling and Improved UT mapping

* Fixed scheduling tests
  • Loading branch information
dann1 authored Feb 7, 2024
1 parent e01736a commit 061a554
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 70 deletions.
2 changes: 1 addition & 1 deletion share/api.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
openapi: "3.0.0"
info:
version: "1.1.0"
version: "1.2.0"
title: "Provisioning Engine REST API"
description: Provides FaaS capabilities by leveraging features from OpenNebula. Allows to manage Serverless Runtime instances based on a group of Functions defined on request.

Expand Down
70 changes: 35 additions & 35 deletions src/server/function.rb
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def self.get(client, id)
#
# @return [String] vm_template contents for a oneflow service template
#
def self.vm_template_contents(specification, vm_template, conf_capacity)
def self.map_vm_template(specification, vm_template, conf_capacity)
disk_size = specification['DISK_SIZE']
disk_size ||= conf_capacity[:disk][:default]

Expand Down Expand Up @@ -184,6 +184,40 @@ def self.vm_template_contents(specification, vm_template, conf_capacity)
xaas.join("\n")
end

#
# Translates specification parameters to Function VM USER_TEMPLATE
#
# @param [Hash] specification Serverless Runtime definition
#
# @return [String] User Template string compatible with opennebula VM Template
#
def self.map_user_template(specification)
user_template = ''

if specification.key?('SCHEDULING')
specification['SCHEDULING'].each do |property, value|
user_template << "#{Function::SCHED_MAP[property]}=\"#{value.upcase}\"\n" if value
end
end

if specification.key?('DEVICE_INFO')
i_template = ''

specification['DEVICE_INFO'].each do |property, value|
i_template << "#{property}=\"#{value}\",\n" if value
end

if !i_template.empty?
i_template.reverse!.sub!("\n", '').reverse!
i_template.reverse!.sub!(',', '').reverse!
end

user_template << "DEVICE_INFO=[#{i_template}]\n"
end

user_template
end

#
# Creates a runtime function hash for the Serverless Runtime document
#
Expand Down Expand Up @@ -315,40 +349,6 @@ def state_function
return STATES[:updating]
end

#
# Translates specification parameters to Function VM USER_TEMPLATE
#
# @param [Hash] specification Serverless Runtime definition
#
# @return [String] User Template string compatible with opennebula VM Template
#
def self.map_user_template(specification)
schevice=''

if specification.key?('SCHEDULING')
specification['SCHEDULING'].each do |property, value|
schevice << "#{Function::SCHED_MAP[property]}=\"#{value}\"\n" if value
end
end

if specification.key?('DEVICE_INFO')
i_template = ''

specification['DEVICE_INFO'].each do |property, value|
i_template << "#{property}=\"#{value}\",\n" if value
end

if !i_template.empty?
i_template.reverse!.sub!("\n", '').reverse!
i_template.reverse!.sub!(',', '').reverse!
end

schevice << "DEVICE_INFO=[#{i_template}]\n"
end

schevice
end

end

end
21 changes: 12 additions & 9 deletions src/server/runtime.rb
Original file line number Diff line number Diff line change
Expand Up @@ -212,13 +212,12 @@ def update_sr(specification)

end

schevice = Function.map_user_template(specification)

response = vm.update(schevice, true) unless schevice.empty?
user_template = Function.map_user_template(specification)
response = vm.update(user_template, true) unless user_template.empty?

if OpenNebula.is_error?(response)
rc = ProvisionEngine::Error.map_error_oned(response.errno)
error = "Failed to update #{SRF} #{schevice}"
error = "Failed to update #{SRF} #{user_template}"
return ProvisionEngine::Error.new(rc, error, response.message)
end

Expand Down Expand Up @@ -390,10 +389,12 @@ def self.to_service(client, specification)
service_templates.each do |service_template|
next unless service_template['NAME'] == tuple

client.logger.info("Found matching flow template for tuple: #{tuple}")

merge_template = {
'roles' => []
}
schevice = Function.map_user_template(specification)
user_template = Function.map_user_template(specification) + "FLAVOURS=\"#{tuple}\""

ProvisionEngine::Function::FUNCTIONS.each do |role|
next unless specification[role] && !specification[role]['FLAVOUR'].empty?
Expand All @@ -418,15 +419,17 @@ def self.to_service(client, specification)
return ProvisionEngine::Error.new(500, error)
end

override = ProvisionEngine::Function.vm_template_contents(specification[role], vm_template,
vm_template = ProvisionEngine::Function.map_vm_template(specification[role], vm_template,
client.conf[:capacity])

vm_template_contents = "#{vm_template}\n#{user_template}"

client.logger.info("Applying \"vm_template_contents\" to role #{role}")
client.logger.debug(override)
client.logger.debug(vm_template_contents)

merge_template['roles'] << {
'name' => role,
'vm_template_contents' => "#{override}\n#{schevice}"
'vm_template_contents' => vm_template_contents
}
end
end
Expand Down Expand Up @@ -597,7 +600,7 @@ def service_id
# @return [String] FaasName possibly + -DaasName if DaaS flavour is specified
#
def self.tuple(specification)
tuple = specification['FAAS']['FLAVOUR']
tuple = specification['FAAS']['FLAVOUR'].dup

if specification['DAAS'] && !specification['DAAS']['FLAVOUR'].empty?
tuple << "-#{specification['DAAS']['FLAVOUR']}"
Expand Down
3 changes: 2 additions & 1 deletion src/server/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@
require 'runtime'
require 'function'

VERSION = '1.2.0'

############################################################################
# API configuration
############################################################################

VERSION = '1.1.0'
conf = ProvisionEngine::Configuration.new

configure do
Expand Down
8 changes: 4 additions & 4 deletions tests/conf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
:delete: 30
:examples: # What group of examples should be tested
'crud': true
'auth': true
'crud_invalid': true
'server_info': true
'logs': true
'auth': false
'crud_invalid': false
'server_info': false
'logs': false
:purge: true # delete services owned by the user running the tests. DO NOT RUN AS ONEADMIN !!!
22 changes: 12 additions & 10 deletions tests/lib/common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,19 +88,21 @@ def verify_sr_spec(specification, runtime)
expect(runtime[role]['ERROR']).to eq(vm["#{T}ERROR"])
end

['DEVICE_INFO', 'SCHEDULING'].each do |schevice|
next unless specification.key?(schevice)
# Verify VM.USER_TEMPLATE

if schevice == 'SCHEDULING'
specification[schevice].each do |k, v|
expect(vm["#{UT}#{ProvisionEngine::Function::SCHED_MAP[k]}"]).to eq(v.to_s)
end
else
specification[schevice].each do |k, v|
expect(vm["#{UT}#{schevice}/#{k}"]).to eq(v.to_s)
end
expect(vm["#{UT}FLAVOURS"]).to eq(ProvisionEngine::ServerlessRuntime.tuple(specification))

if specification.key?('SCHEDULING')
specification['SCHEDULING'].each do |k, v|
expect(vm["#{UT}#{ProvisionEngine::Function::SCHED_MAP[k]}"]).to eq(v.to_s.upcase)
end
end

next unless specification.key?('DEVICE_INFO')

specification['DEVICE_INFO'].each do |k, v|
expect(vm["#{UT}DEVICE_INFO/#{k}"]).to eq(v.to_s)
end
end
end

Expand Down
5 changes: 0 additions & 5 deletions tests/lib/crud.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@

case rc
when 200
pp runtime

verify_sr_spec(@conf[:runtime], runtime)
break
when 423
Expand All @@ -65,7 +63,6 @@
sleep 1
next
else
pp runtime
verify_error(runtime)

raise "Unexpected error code #{rc}"
Expand All @@ -81,8 +78,6 @@

runtime = JSON.parse(response.body)

pp runtime

verify_sr_spec(@conf[:runtime], runtime)
end

Expand Down
7 changes: 2 additions & 5 deletions tests/templates/_sr_sched.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
{
"SERVERLESS_RUNTIME": {
"NAME": "Example Serverless Runtime with defined SCHEDULING",
"FAAS": {
"FLAVOUR": "Function"
},
"SCHEDULING": {
"POLICY": "energy",
"REQUIREMENTS": "FREECPU > 10"
},
"DEVICE_INFO": {
"LATENCY_TO_PE": 100,
"GEOGRAPHIC_LOCATION": "Madrid"
"REQUIREMENTS": "energy=50"
}
}
}

0 comments on commit 061a554

Please sign in to comment.