actions
Action is an entity used to describe an operation on an ADCM object. This action is ultimately the launch of an Ansible playbook with certain parameters under certain conditions.
---
- type: cluster
name: control
version: 1
description: "Monitoring and Control Software"
actions:
install:
display_name: "Install Monitor Server"
description: |
By click on this button you install monitoring and controlling server ...
type: job
script_type: ansible
script: ansible/site.yaml
allow_to_terminate: true
params:
ansible_tags: install
jinja2_native: true
states:
available:
- created
on_success: installed
on_fail: created
config:
quorum:
type: integer
Properties that can be used to define actions are listed below.
allow_for_action_host_group
Action may have an optional boolean property allow_for_action_host_group, which controls whether the action can be executed for a host group. The default value is false. If allow_for_action_host_group is set to true, the action can be executed for host groups.
actions:
upgrade:
type: job
script_type: ansible
script: ansible/site.yaml
allow_for_action_host_group: true
Restrictions on using the allow_for_action_host_group property:
-
Actions that are part of an upgrade operation (see Upgrade a cluster to a new ADPG version) cannot be executed for a host group.
-
The simultaneous use of this property and the host_action property is not supported.
allow_in_maintenance_mode
Action may have an optional boolean property allow_in_maintenance_mode that controls whether the action is permitted to run in maintenance mode. The default value is false. When both allow_in_maintenance_mode and allow_maintenance_mode are set to true, the action is allowed to run even if the object or any of its hosts is in maintenance mode.
allow_to_terminate
Action may have an optional boolean property allow_to_terminate that controls whether the action and its jobs can be forcibly stopped. The default value is false. If allow_to_terminate is set to true, the user can interrupt the execution of the action. In this case:
-
When a job is interrupted, the currently running subjob completes its execution by interrupting the Ansible playbook, after which the job is terminated.
-
When a subjob is interrupted (using the
icon), the execution of the Ansible playbook is interrupted and the next subjob is started without terminating the job.
In all other cases, stopping an action is not allowed.
The allow_to_terminate property applies to all subjobs that are part of the action. When one of these subjobs is interrupted, the execution of the action continues with the next subjob. Therefore, specifying the allow_to_terminate property for an action is equivalent to specifying this property for all of its subjobs.
config
Action may have an optional config property. This property defines a list of values for the configuration parameters. When an action is started from the ADCM web interface, the values of the specified configuration parameters are requested from the user before the action starts.
Later, if required, these values can be accessed in the Ansible script:
{{ job.config.quorum }}
The config property is used for static configuration parameters that are displayed in the same way each time the action is executed. If you need to work with dynamic configuration parameters, use the config_jinja property.
config_jinja
Action may have an optional config_jinja property. This property points to a file in the Jinja format (supported in ADCM 2.xx).
|
NOTE
The config_jinja is deprecated and is not supported starting from contract version 2.0 (contract_version: 2). To work with dynamic configuration parameters of actions, it is recommended to use config_template.
|
The config_jinja property is used to work with dynamic configuration parameters. Here, "dynamism" means the ability to show or hide certain parameters based on specific conditions — in other words, depending on the cluster topology (for example, whether a particular service was added to the cluster).
This property cannot be used together with the config property, which is used for static configuration parameters.
---
actions:
- name: Restart and Reboot
type: job
script_type: ansible
script: ansible/restart.yaml
config_jinja: config_jinja/restart.j2
The restart.j2 file:
- reboot_servers:
type: boolean
default: false
display_name: Reboot servers
{% if cluster.state == 'created' %}
- configure_etc:
type: boolean
default: false
display_name: Configure /etc/hosts
{% endif %}
config_template
Action may have an optional config_template property. This is a new mechanism for working with dynamic configuration parameters, which defines stricter rules for handling them when an action runs. It replaces the outdated config_jinja mechanism.
---
actions:
start:
display_name: Start
config_template:
file:
path: scripts_jinja/cluster/restart.j2
engine:
type: jinja2
scripts_template:
file:
path: scripts_jinja/cluster/manage_install.j2
engine:
type: jinja2
states:
available:
- installed
The template description format for the <wizard|scripts>_template properties also applies to the config_template property.
display_name
The display_name property specifies a short name for the action displayed to the user in the ADCM web interface.
hc_acl
Action may have an optional hc_acl property. This property is used when the action is run in the ADCM web interface, requiring the user to provide a new host-component mapping before the action starts.
actions:
expand:
type: job
script_type: ansible
script: ansible/site.yaml
states:
available: all
hc_acl:
-
service: hadoop
component: datanode
action: add
-
service: hadoop
component: server
action: remove
The hc_acl property defines the following list that controls operations for modifying the host-component mapping:
-
service— name of the service. -
component— name of the component. -
action— type of operation. Possible values:add,remove.
host_action
Action may have an optional boolean property host_action that is used to define the scope of an action at the level of an individual host. The default value is false. If host_action is set to true, the action appears in the drop-down list of actions on the Clusters → <Cluster name> → Hosts → <Host name> → Host-Components page. In this case, the action is executed for the selected host and a target group including only that host is automatically created.
It is recommended to declare an action (host_action: true) only in the context of a component as these actions allow managing a specific component on a specific host.
actions:
install:
type: job
script_type: ansible
script: action.yaml
host_action: true
masking
masking is an alternative way to define the availability of an action in the ADCM web interface and via the API. This property allows specifying a set of basic (states) and advanced (multi_state) object states.
Use masking if you want to define action availability using advanced states, which are specified in the multi_state property.
|
IMPORTANT
The masking property is not compatible with the states property which is described below.
|
---
actions:
install:
display_name: "Install Monitor Server"
type: job
masking:
# Action will be shown if both condition under state and multi_state are met.
state:
available:
# If the state equal to any of this, then condition is true
- "state_value1"
- "state_value2"
unavailable:
# If you place unavailable, then no available should be there
- "state_value1"
- "state_value2"
multi_state:
available:
# If we have any of this multistate, then condition is true
- "multi_state_1"
- "multi_state_2"
unavailable:
# If you place unavailable, then no available should be there
- "multi_state_3"
- "multi_state_4"
on_fail:
state: "new_sate_value"
multi_state:
set:
- "multi_state3"
unset:
- "multi_state4"
on_success:
state: "new_sate_value"
multi_state:
set:
- "multi_state3"
unset:
- "multi_state4"
To simplify the description of rules, you can use the any scalar which represents all possible values:
---
masking:
state:
available: "any"
unavailable: "any"
multi_state:
available: "any"
unavailable: "any"
If the masking property is not set, the action is considered available for every value of the state or multi_state properties. Thus, the following options are equivalent:
---
masking:
---
masking:
state:
---
masking:
state:
available: "any"
The options listed below are also considered equivalent:
---
masking:
---
masking:
multi_state:
---
masking:
multi_state:
available: "any"
states
Action may have an optional states property that is used to control the availability of the action and changes of states of an object during its execution. This property specifies the list of the states in which the action is allowed to run, as well as the object state after successful or failed completion of the action.
The states property defines the following states:
-
available— list of object states in which the action is available; -
on_success— object state after successful action completion; -
on_fail— object state after failed action completion.
The on_success and on_fail states are optional. If they are not specified, the object state will remain unchanged after successful or unsuccessful completion action.
The states property also has two reserved values:
-
created— initial state of objects after creation; -
upgrading— state to which the cluster can be moved. In this state, certain actions, such as removing a host or service from the cluster, are not available to the user.
type
The type property defines the type of the action. Possible values:
-
job— action that runs a single script. It uses the following parameters:-
NOTEActions of the
jobtype is deprecated and is not supported starting from contract version2.0(contract_version: 2).
-
task— action that consists of a sequence of jobs. It uses the following parameters:
|
NOTE
The type property is deprecated and is not supported starting from contract version 2.0 (contract_version: 2).
|
ui_options
The ui_options block allows you to configure how the action is displayed and executed in the ADCM web interface. When hovering over the action, a tooltip will appear showing the message specified in the disclaimer field:
actions:
install:
type: job
script_type: ansible
script: ansible/site.yaml
ui_options:
disclaimer: "Enter your disclaimer"
venv
The required venv property specifies which Ansible version will be used to execute the action.
|
NOTE
The venv property is deprecated and is not supported starting from contract version 2.0 (contract_version: 2).
|
Possible values:
-
default— launch action in the Ansible 2.8 environment (contract version1.0only); -
2.9— launch action in the Ansible 2.9 environment; -
2.16— launch action in the Ansible 2.16 environment (starting with ADCM 2.8.0).
|
NOTE
Ansible 2.8 is deprecated and is supported only for contract version 1.0 (contract_version: 1).
|
Changing the default environment for all actions on an object:
---
- type: cluster # service component hostprovider host
name: control
version: 1
contract_version: 2.0
venv: "2.9"
wizard_template
Action might have the optional wizard_template property which is the template of the flow formed as a result of its rendering.
Unlike the config property, the wizard_template property allows you to do the following:
-
divide an action configuration into several logical steps as modal windows;
-
pass the template rendering context between steps;
-
save the states of the steps that are already provided by the user.
The wizard_template property is mutually exclusive with the following properties:
-
config, which is intended to work with static configuration parameters; -
config_jinja, which is intended to work with dynamic configuration parameters;
-
hc_acl, which is intended to work with the host-component mapping.
The specified property is displayed in the ADCM web interface as Wizard which is the preparation phase of an action before its launch.
The flow is a sequence of the following elements:
-
Stages — the containers of logically related steps.
-
Steps — the minimal indivisible elements of a process performed by the user.
NOTEThe process occurs when a user clicks the action in the drop-down list of actions available to work with an object.A step can be one of the three types:
-
Configuration — a configuration filled in by the user. The configuration is dynamically generated during the rendering of the template specified in the
config_templatestatement when receiving information about a specific step. -
Operation — a job representing a set of subjobs that is launched when executing the step. The set of subjobs is dynamically generated during rendering of the template specified in the
scripts_templatestatement when executing the specific step. The example of a step of the operation type is given in the manage_install.j2 file (thecheck_kerberosstep of themanage_kerberos_stagestage). -
Mapping — a rule for a host-component mapping. The rule template and the form with default values are generated dynamically during the rendering of the template specified in the
mapping_templateproperty when receiving step information.IMPORTANTUnlike regular actions, when using Wizard, the host-component mapping is not automatically applied to the target cluster. In this case, the bundle developer should manually save the mapping specified by the user by calling hc_apply out of context Wizard process — in other words, as part of the main job of the corresponding action.
-
Description of the Wizard visual representation in the ADCM web interface is given in the Wizard article.
Steps of the operation type provide the following options:
-
validating the action configuration parameter values entered by the user;
-
saving the action configuration parameter values entered by the user in configuration of the target object (cluster, service, or component) using the
config_applyfunction.
Each stage includes the following parameters:
-
name— unique stage name; -
display_name— name of the stage that is displayed in the ADCM web interface for the user; -
steps— sequence of steps.
The following attributes are used to describe the step:
-
Common attributes:
-
name— step name that is unique to this stage. -
display_name— Wizard step name which is intended to be used as the name of the modal window step.
-
-
Attribute for a step of the configuration type:
config_template— template for working with dynamic configuration parameters. -
Attributes for a step of the operation type:
-
ui_options— attributes specific to UI, in particular,button_name— button name. -
scripts_template— template for dynamic generation of the subjob sequence.
-
-
Attribute for a step of the mapping type:
hc_template— template for defining host-component mapping rule. The template may include:-
componentandservice— names of the component and service of the corresponding object. -
operation— type of operation to be performed. Possible values:-
add— extend the set of hosts. -
remove— reduce the set of hosts.
-
-
Template description format (the <wizard|config|scripts|hc>_template property) includes the following parameters:
-
file— file that is used as a template and contains the following attributes:-
path— path to the file with the .j2 or .py extension. -
entrypoint— name of thecallable()function that should be called (without specifying the package or module). This attribute is used only ifengineis set topython.
-
-
engine— file processing engine. Possible values:jinja2,python.
Based on the received information about an action (if wizard_template is used), a process is created.
actions:
install:
display_name: "Install"
type: task
allow_to_terminate: true
scripts_jinja: scripts_jinja/cluster/manage_install.j2
wizard_template:
file:
path: wizard_jinja/manage_install.j2
engine:
type: jinja2
states:
available:
- created
- faulty_installed
Creating a process, among other things, includes rendering of the file specified in wizard_template. This results in a flow. During the template rendering, the context is formed according to the inventory file, except config group changes, as well as variables and facts that Ansible generates during a playbook execution.
The wizard_jinja/manage_install.j2 file:
- name: manage_ssl_stage
display_name: "Manage SSL"
steps:
- name: configure_ssl
display_name: "Configure SSL"
config_template:
file:
path: configs_jinja/manage_ssl.j2
engine:
type: jinja2
- name: manage_kerberos_stage
display_name: "Manage Kerberos"
stpes:
- name: configure_kerberos
display_name: "Kerberos configuration"
config_template:
file:
path: configs_jinja/manage_kerberos.j2
engine:
type: jinja2
- name: check_kerberos
display_name: "Check configuration"
ui_options:
button_name: Check
scripts_template:
file:
path: scripts_jinja/cluster/save_config.j2
engine:
type: jinja2
{% if services.hdfs is defined and services.hdfs.state == 'created' %}
- name: hdfs_stage
display_name: "Manage HDFS"
steps:
- name: configure_hdfs
display_name: "Configure HDFS"
config_template:
file:
path: configs_jinja/manage_hdfs.j2
engine:
type: jinja2
- name: mapping
display_name: "Fill host-component mapping"
hc_template:
file:
path: hc_jinja/manage_hdfs_hc_step.j2
engine:
type: jinja2
- name: validate
display_name: "Validate host-component mapping"
ui_options:
button_name: Validate
scripts_template:
file:
path: scripts_jinja/validate_mapping.j2
engine:
type: jinja2
{% endif %}
{% if services.hdfs is defined and services.hdfs.state == 'created' %}
- name: hbase_stage
display_name: "Manage Hbase"
steps:
- name: validate
display_name: "Validate host-component mapping"
ui_options:
button_name: Validate
scripts_template:
file:
path: scripts_jinja/validate_mapping.j2
engine:
type: jinja2
{% endif %}
- name: save_stage
display_name: "Save configuration"
steps:
- name: save_configuration
display_name: "Check configuration"
ui_options:
button_name: Check
scripts_template:
file:
path: scripts_python/cluster/check.py
entrypoint: generate_scripts
engine:
type: python
The manage_ssl.j2 file:
- name: ssl_config
display_name: "Enable SSL"
type: group
{% if vars.cluster.config.ssl_config.enable_ssl %}
activatable: true
{% else %}
activatable: false
{% endif %}
subs:
- name: keystore_path
display_name: "Keystore path"
type: string
default: "{{ cluster.config.ssl_default_config.keystore_path }}"
- name: keystore_password
display_name: "Keystore password"
type: password
The manage_kerberos.j2 file:
- name: kerberos_config
display_name: "Enable Kerberos"
type: group
{% if vars.cluster.config.kerberos_config.enable_kerberos %}
activatable: true
{% else %}
activatable: false
{% endif %}
subs:
- name: keystore_password
display_name: "Keystore password"
type: password
default: {{ action.process.stages.manage_ssl_stage.configure_ssl.config.ssl_config.keystore_password }}
The save_config.j2 file:
{% set ssl_key = "ssl_default_config/keystore_password" %}
- name: validate
display_name: "Precheck"
script_type: ansible
script: some/playbook.yaml
params:
ansible_tags:
- check
- name: state_2
display_name: "State 2"
script_type: internal
script: config_apply
params:
changes:
- object:
type: cluster
parameters:
{% if action.process.stages.manage_ssl_stage.configure_ssl.config.ssl_config.enable_ssl %}
- key: "{{ ssl_key }}"
value: "{{ action.process.stages.manage_ssl_stage.configure_ssl.config.ssl_config }}"
{% endif %}
{% if action.process.stages.manage_kerberos_wizard.config.kerberos_config.enable_kerberos %}
- key: "kerberos_default_config/keystore_password}"
value: "{{ action.process.stages.manage_kerberos_stage.configure_kerberos.config.kerberos_config.keystore_password }}"
{% endif %}
The manage_hdfs_hc_step.j2 file:
{% raw %}
- service: hdfs
component: namenode
operation: add
- service: hdfs
component: datanode
operation: add
{% endraw %}
The manage_hdfs.j2 file:
- name: kerberos_config
display_name: "DFS data dir"
type: string
default: {{ vars.services.hdfs.config.data_dir }}
The check.py file:
def create_script_template(display_name, name, params, script, script_type):
"""Template for creating action dictionaries with consistent structure."""
return {
'display_name': display_name,
'name': name,
'params': params,
'script': script,
'script_type': script_type
}
def generate_scripts(context: dict):
cluster = context['cluster']
action = context['action']
script1 = create_script_template(
display_name='Check',
name='validate',
params={'ansible_tags': ['check']},
script='some/playbook.yaml',
script_type='ansible'
)
script2_params = [{
'object': {'type': 'cluster'},
'parameters': [{
'key': 'ssl_config',
'value': action['process']['stages']['manage_ssl_stage']['configure_ssl']['config']['ssl_config']
}]
}]
script2 = create_script_template(
display_name='State 2',
name='state_2',
params=script2_params,
script='config_apply',
script_type='internal'
)
return [script1, script2]
### Return
[{'display_name': 'Check',
'name': 'validate',
'params': {'ansible_tags': ['check']},
'script': 'some/playbook.yaml',
'script_type': 'ansible'},
{'display_name': 'State 2',
'name': 'state_2',
'params': [{'object': {'type': 'cluster'},
'parameters': [{'key': 'ssl_config', 'value': 'some_value'}]}],
'script': 'config_apply',
'script_type': 'internal'}]
The validate_mapping.j2 file:
- name: validate
display_name: "Precheck"
script_type: ansible
script: some/playbook.yaml
params:
process:
current_stage: {{ action.process.current.stage }}
Parameters for actions of the job type
Below are the required parameters that should be defined for an action of the job type (type: job).
|
NOTE
The type is not supported starting from contract version 2.0 (contract_version: 2).
|
params
The params parameter allows you to pass any additional parameters for invoking Ansible. These parameters are used when calling the ansible-playbook command.
One of the supported parameters is ansible_tags. This parameter is a direct equivalent of the --tags argument used when running ansible-playbook.
You can also specify the jinja2_native parameter. This parameter is written to the ansible.cfg file and allows variable types to be preserved during Jinja2 template processing.
script
The script parameter takes a value depending on the script_type parameter value:
-
If the
script_typeparameter is set toansible, thescriptparameter specifies the path to the script file. In the example above for theinstallaction, thescriptparameter specifies the path to the Ansible playbook located in the <bundle_root>/ansible/site.yaml directory. You can use a dot (.) to specify the script file path. In this case, the script file will be searched for in the directory containing the config.yaml file:script: ./site.yaml
-
If the
script_typeparameter is set tointernal, thescriptparameter can take one of three ADCM functions:-
bundle_revert— this function returns the cluster to its state before the upgrade. The cluster state includes its configuration, all services, hosts, and components, as well as the host-component map. -
hc_apply— this function is useful when an action includeshc_acland it becomes necessary to commit the host-component mapping changes regardless of the action execution result or after the certain subjob execution. Thehc_applyfunction commits the host-component mapping changes in accordance with data received from the user. You can use the optionalparamsparameter when it is necessary to commit partial changes. In other words, withparams, you can specify a rule similarly tohc_acl(the service and component names, and also theaddorremoveoperation), that will commit part of the host-component mapping associated with the specified rule.- name: apply hc script_type: internal script: hc_apply params: rules: - service: redis component: server action: add - service: redis component: server action: remove -
config_apply— this function is useful when an action includeswizard_templateand it becomes necessary to save changes in configuration parameter values, for example, according to the data received from a user. You need to specify the rule of committing configuration parameter values and objects using theparamsparameter which describes the object, the service and component names corresponding to the object type, and also the set of key/value pairs.NOTETheconfig_applyfunction is available starting from version 2.8.0.- name: save display_name: "Save configuration on target objects" script_type: internal script: config_apply params: changes: - object: type: cluster parameters: - key: "ssl_default_config/keystore_password" value: "my_secrete_value" - object: type: service service_name: "hive" parameters: - key: "core-site_xml/keystore_password" value: "my_secrete_value" - object: type: component service_name: "hive" component_name: "server" parameters: - key: "core-site_xml/keystore_password" value: "my_value"- name: state_2 display_name: "State 2" script_type: internal script: config_apply params: changes: - object: type: cluster parameters: - key: "{{ ssl_key }}" value: "{{ action.process.stages.manage_ssl_stage.configure_ssl.config.ssl_config }}" - object: type: service service_name: "{{ roles_generic_args.service_name }}" parameters: - key: "{{ ssl_key }}" value: "{{ action.process.stages.manage_ssl_stage.configure_ssl.config.ssl_config }}" - object: type: component service_name: "{{ roles_generic_args.service_name }}" component_name: "{{ roles_generic_args.component_name }}" parameters: - key: "{{ ssl_key }}" value: "{{ action.process.stages.manage_ssl_stage.configure_ssl.config.ssl_config }}" -
bundle_switch— this function upgrades all prototypes to their new versions. The function can be used only forupgrade, it cannot be used in the common actions.
-
Parameters for actions of the task type
Below are the required parameters that should be defined for an action of the task type (type: task).
|
NOTE
The type is not supported starting from contract version 2.0 (contract_version: 2).
|
scripts
The sequence of jobs to execute is determined by the scripts parameter. Jobs are executed in the order in which they are listed in scripts. If any script fails, job execution stops, and the object moves to the state defined by the on_fail parameter.
actions:
install:
type: task
scripts:
-
name: prepare
display_name: Prepare to install
script_type: ansible
script: ansible/prepare.yaml
on_fail: created
-
name: install
display_name: Actual install
script_type: ansible
script: ansible/install.yaml
on_fail: prepare
states:
available:
- created
- prepare
on_success: installed
scripts_jinja
Action may have an optional scripts_jinja parameter. This property points to a file in the Jinja format (supported in ADCM 2.xx).
|
NOTE
The scripts_jinja parameter is deprecated and is not supported starting from contract version 2.0 (contract_version: 2).
|
The scripts_jinja parameter is used to dynamically generate a set of subjobs based on the context, depending on conditions — in other words, based on the cluster topology (for example, whether a particular service is present in the cluster). After the action is started, the Jinja2 template file is rendered to generate the sequence of subjobs. When rendering the template, the context is built based on the inventory file, excluding changes from config groups, as well as the variables and facts generated by Ansible during playbook execution (including additional action details, such as values and selections made by the user during action configuration).
The scripts_jinja parameter is supported only for actions of the task type and is mutually exclusive with the scripts parameter (static subjob generation).
---
actions:
- name: Add/remove components
type: task
scripts_jinja: scripts_jinja/manage_component_scripts.j2
The manage_component_scripts.j2 file:
{%- if (groups['zookeeper.SERVER.add'] | length) > 0 %}
- name: zookeeper
display_name: "Zookeeper"
script_type: ansible
script: ansible/playbooks/cluster/zookeeper_install.yaml
params:
ansible_tags: repo_add, install, configure, configure_main_info, start, bootstrap
{%- endif %}
{%- if (groups['zookeeper.SERVER.remove'] | length) > 0 %}
- name: zookeeper
display_name: "Zookeeper"
script_type: ansible
script: ansible/playbooks/cluster/zookeeper_remove.yaml
params:
ansible_tags: stop, remove
{%- endif %}
- name: zookeeper
display_name: "Zookeeper"
script_type: ansible
script: ansible/playbooks/cluster/zookeeper_install.yaml
params:
ansible_tags: configure
Special actions
There are four special actions that can be executed in the ADCM web interface and via the specified API endpoints:
-
adcm_turn_on_maintenance_mode -
adcm_turn_off_maintenance_mode -
adcm_host_turn_on_maintenance_mode -
adcm_host_turn_off_maintenance_mode
An example of a special action definition:
actions:
adcm_turn_on_maintenance_mode
Special actions should be described in the matching prototypes. The following table lists the special actions available in ADCM, along with their prototype type and description.
| Action name | Type of the prototype | Description |
|---|---|---|
adcm_turn_on_maintenance_mode |
Service/component |
Turns on the maintenance mode on an object via the corresponding element of the ADCM web interface |
adcm_turn_off_maintenance_mode |
Service/component |
Turns off the maintenance mode on an object via the corresponding element of the ADCM web interface |
adcm_host_turn_on_maintenance_mode |
Cluster |
Turns on the maintenance mode on a cluster host via the corresponding element of the ADCM web interface |
adcm_host_turn_off_maintenance_mode |
Cluster |
Turns off the maintenance mode on a cluster host via the corresponding element of the ADCM web interface |
adcm_delete_service |
Service |
Deletes a service via the corresponding element of the ADCM web interface |
Special actions defined in the cluster prototype (adcm_host_turn_on_maintenance_mode and adcm_host_turn_off_maintenance_mode) should also be declared for the host (host_action: true).