IaC and deployment
EVA ICS v3 supports infrastructure-as-code paradigm, providing a way to deploy items and their params from deployment files in YAML format.
Live deployment examples can be found in EVA ICS demos:
Deployment is possible only on SFA servers.
Note
To allow deployment, SFA must have child controllers connected in management mode (connected controllers master keys should be set). Also, cloud manager feature should be enabled in SFA configuration file.
Deployment configuration file
Deployment configurations are stored in YAML files, which have the following format:
Controllers
Section controller contains:
Driver setup for Universal Controller
Commands, executed after configuration deployment
Common variables setup
Here’s an example to set two cvar values:
controller:
uc/controller1:
cvar:
var1: value1
var2: value2
Driver setup
Here is an example, which:
Loads two PHI vrtrelay modules into Universal Controller uc/controller1 as vr1 and vr2. The second module has configuration option state_full=true.
Creates vr1.opener driver using vr1 PHI module and multistep LPI.
controller:
uc/controller1:
phi:
vr1:
module: vrtrelay
# src: path/to/module
vr2:
module: vrtrelay
config:
state_full: true
driver:
vr1.opener:
module: multistep
config:
bose: true
“src” field tells deployment function to get PHI module from file or URL and upload it to the target controller.
API keys and local users
Keys can contain any valid key properties, local user accounts MUST have both “password” and “key” properties set.
controller:
uc/controller1:
key:
tkey1:
key: verysecret1
groups:
- plant1/#
- plant2/#
sysfunc: true
allow:
- lock
- cmd
tkey2:
key: verysecret2
groups: "#"
allow:
- device
user:
test1:
password: "iu4i32j432s"
key: tkey1
test2:
password: "u89132u2183"
key:
- tkey1
- tkey2
Uploading files
Local files can be uploaded into remote controller runtime directory:
controller:
uc/controller1:
upload-runtime:
- localfile:remotefile
- localfile2:path/to/remotefile2
File list: local/remote files, separated with “:”. If remote directory doesn’t exist, it will be created automatically.
It’s possible to use masks for local files, e.g. in the example below, contents of “bundle” directory will be uploaded to remote node “runtime/upload”, directory structure will be duplicated as-is.
controller:
uc/controller1:
upload-runtime:
- bundle/*:upload/
Note
To upload directory contents recursively, set file mask to **
It’s possible to keep content in the deployment file as well. In this case, use “file_put” API function to create the remote file:
controller:
uc/controller1:
before-deploy:
- api: file_put
i: upload/test.yml
m: |
test: true
test2: false
tags:
- valid: true
x: 2
- valid: true
x: 3
File paths:
if the file path starts with http: or https:, it’s processed as URI
if the file path starts with “/”, it’s considered as absolute
if the file path starts with “./” it’s relative to the current directory
otherwise, the file path is relative to the directory where the deployment file is located
Before/After deploy
Remote calls
Note
EVA ICS architecture does not allow Cloud Manager to execute API calls on remote SFAs. Use the remote node UC or LM instance to act as the agent for that.
Controller API calls may be automatically executed after deployment is complete:
controller:
lm/lm1:
before-deploy:
- api: reset
i: timers/timer1
after-deploy:
- { api: clear, i: timers/timer1 }
- { api: reload_controller, i: uc/uc1 }
- { api: reload_controller, i: uc/uc2 }
- api: custom_fn
_pass: true
param1: 123
param2: "x"
API calls are always executed in the specified order, one-by-one, api: field contains API function to execute, others specify function parameters. The special parameter _pass in the last call allows deployment to ignore failed API call (warning will be printed).
Custom API call timeout can be defined with special parameter _timeout.
Note
It is usually recommended to call reload_controller for Logic Manager to let it instantly load newly deployed items from connected UCs for EVA ICS prior to 3.3.2.
Starting from 3.3.2, if units or sensors were deployed, all LM PLCs, listed in “controller” section, are reloaded automatically. If a LM PLC has no deployment configuration, it should be listed as an empty dict:
controller:
lm/lm1: {}
Local calls
Sometimes it’s useful to call local SFA function deployment process. This can be done with directive “cm-api” which has the same format as “api” for remote calls:
controller:
lm/lm1:
before-deploy:
- api: reset
i: timers/timer1
# just for a test
- cm-api: reload_controller
i: lm/lm1
The local calls can be also merged into “local” controller section. The section can contain any before/after deploy commands, which are executed on local SFA:
controller:
local:
after-deploy:
- install-pkg: test.evapkg
o: { x: 2 }
w: 5
The “local” section is always executed after all other controllers’ sections.
Additionally, local SFA resources, allowed to be deployed:
API keys
user accounts
Macro functions
The following functions execute API macros:
reboot_controller
Executes “shutdown_core” method for the selected controller, after - waits until the controller is back online. The function can be used in for both “api” and “cm-api”.
Parameters:
wait wait until the controller should be back online, sec (default: 30)
Installing packages
A package can be installed during any deployment stage.
Syntax:
controller:
uc/uc1:
after-deploy:
- install-pkg: /path/to/package.evapkg
o: { x: 2 }
w: 5
Additional deploy functions
sleep
Delays execution of next before/after deploy commands. E.g. let’s reload remote UC and wait 5 seconds until its core is restarted:
controller:
uc/uc1:
after-deploy:
- api: shutdown_core
- function: sleep
args: [ 5 ]
system
Executes (local) system command:
controller:
uc/uc1:
after-deploy:
- function: system
args: [ 'ls' ]
Loops, conditions and variables
Deployment files are pre-processed as Jinja2 templates and may contain any valid Jinja2 tags and variables.
The pre-set variable “time_ns” contains current UNIX timestamp (in nanoseconds), which can be used e.g. as “no-cache” value for bypassing cache of proxied external resources.
It’s also possible to import any external Python module with “import_module” function:
{%- set io=import_module('io') %}
{%- set units=io.open('units.list').readlines() %}
unit:
{%- for u in units %}
{{ u.strip() }}:
controller: uc/uc1
{%- endfor %}
Items
Control and monitoring items can be deployed with unit, sensor and lvar sections. All sections are similar, the format is:
unit:
group1/u1:
controller: uc/uc1
action_enabled: true
update_interval: 0
status: 0 # initial status, optional
driver:
id: vr1.default
config:
port: 1
All child fields specify item properties, except:
Field controller specifies controller, where item should be deployed
For units and sensors, driver field may be used to assign driver to the item.
Note
It is not necessary to list the target controller in “controller” section, unless it needs to be additionally configured (e.g. load drivers/PHIs)
If action_exec or update_exec values are started with ^ symbol, it tells deployment tool to upload local file on the controller.
Setting “status” field to “update” asks the controller to trigger item update after deployment:
unit:
group1/u1:
controller: uc/uc1
# ....
status: update
The second example shows how to deploy a sensor and logical variable:
sensor:
group1/s1:
controller: uc/uc1
driver:
id: somedriver.default
config:
port: 1
value: 77 # initial value, optional, initial status for sensor
# is not required (automatically set to 1 - enabled)
lvar:
group1/timer1:
controller: lm/lm1
expires: 30
status: 0 # initial status, optional
value: 77 # initial value, optional
Macros
Logic control macros are deployed in lmacro section:
lmacro:
group1/macro1:
controller: lm/lm1
action_exec: ^macro1.py
All child fields specify item properties, except:
Field controller specifies Logic Manager, where macro should be deployed
If field action_exec value is started with ^ symbol, it tells deployment tool to upload local file on the controller.
Note
To make deployment process more easy, it is recommended to start it in directory, where macro files are located.
Logical rules
Decision-making matrix can be configured with dmatrix_rule section.
Rule example:
dmatrix-rule:
5ef9b8fd-d527-44ce-ae89-9629afd40d76:
controller: lm/farm-scada
description: light normal
enabled: true
oid: "sensor:#/ldr.value"
condition: x = 1
break_after_exec: true
macro: stop_lamp
macro_kwargs:
lamp_id: 1
All child fields specify item properties, except:
Field controller specifies Logic Manager, where rule should be configured
Rule UUID should be pre-generated with any UUID generator, e.g. with uuidgen Linux console command.
Scheduled jobs
Jobs can be deployed the similar way as rules:
job:
e407f61c-a251-455b-92bc-9eee9adcb93b:
controller: lm/lab-ws2
description: "scheduled job 1"
enabled: true
macro: do_scheduled_task
macro_args: [ 'task1' ]
every: "wednesday at 12:00"
Cycles
lcycle:
test:
controller: lm/lab-ws2
description: "scheduled job 1"
interval: 1
macro: do_cycle1
macro_args: [ 'task1' ]
How to deploy configuration
Currently there is no API functions for deploy EVA ICS configuration. The item configuration can be deployed either via CLI or during installation.
Deployment via CLI
Deploying
Deployment configuration can be applied using eva sfa cloud deploy command. When deployed with CLI, deployment file may contain variables.
Example:
unit:
light/room1:
controller: uc/{{ srv }}
Here is srv variable defined. To set its value, e.g. to “uc1”, use -c srv=uc1 command line argument. If multiple variable values are set, they should be comma separated, e.g.: -c srv1=uc1,srv2=uc2 etc.
There’s also command line argument -u which tells CLI to try undeploying target configuration before doing deployment of it. Undeployment process ignores missing items and deletes only existing.
Undeploying
Deployment configuration can be removed with eva sfa cloud undeploy command. Custom variable values can be set in the same way as during deployment.
Deployment during installation
Configuration also can be deployed with easy-setup during SFA installation. Use –deploy FILE command line argument to specify path to the deployment file.
Complex deployments
Bare-metal
Sometimes deployment is more complex than just creating items. In this case deployment scripts are used to prepare environment, call eva sfa cloud deploy command and finish deployment.
Containers
There is no problems when the regular bare-metal or virtual machine installation is performed, but if EVA ICS is being installed into Docker machine or Kubernetes cluster, there is a special environment variable after_install, which tells EVA ICS Docker image to apply the deployment script after the initial setup process is finished. Here is an example part of a docker-compose file:
eva-scada:
environment:
- DEPLOY=/path/or/url/to/yaml
Devices
Starting from EVA ICS 3.3.2, device template format is equal to IaC files.
For cvar deployment, a proper “controller” property should be present in the device template. In “unit” and “sensor” sections, “controller” property is not required and ignored if present.