summaryrefslogtreecommitdiff
path: root/src/action/unit_start.c
blob: b06ac4d3da8c13db06b06718fa8caa40a6c02196 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
 * This file is part of activationd.
 *
 * Copyright © 2019 Samsung Electronics
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "action.h"
#include "action_executor.h"
#include "decision_made_event.h"
#include "log.h"
#include "systemd_dbus.h"
#include "common.h"

static int unit_action_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error)
{
	struct action_executed_event *exe_info = userdata;
	int ret;

	if (!exe_info)
		return -EINVAL;

	exe_info->result = 0;
	ret = event_processor_report_event(&exe_info->event);
	epc_event_unref(&exe_info->event);

	return ret;
}

static int start_unit(struct epc_action *action,
		struct action_executed_event *exe_info)
{
	struct epc_event *ev = pop_epc_event(&action->execution_queue);
	struct decision_made_event *dm_ev = to_decision_made_event(ev);
	char *unit_name = NULL;
	char *unit_action = NULL;
	int ret;

	/*
	 * We are passing an event to exe_info, so there is no need to unref it
	 * in this function
	 */
	exe_info->reason = ev;

	ret = epc_object_get_string(dm_ev->action_data,
			EPC_AD_UNIT_NAME, &unit_name);
	if (!unit_name) {
		epc_object_append_string(exe_info->action_log, "error",
				"Unit name not specified");
		exe_info->result = -EINVAL;
		return 0;
	}

	epc_object_get_string(dm_ev->action_data,
			EPC_AD_UNIT_ACTION, &unit_action);
	if (!unit_action) {
		epc_object_append_string(exe_info->action_log, "error",
				"Unit action not specified");
		exe_info->result = -EINVAL;
		return 0;
	}

	if (strcmp(unit_action, "StartUnit") &&
			strcmp(unit_action, "StopUnit") &&
			strcmp(unit_action, "RestartUnit")) {
		epc_object_append_string(exe_info->action_log, "error",
				"Unit action is not one of \"StartUnit\", "
				"\"StopUnit\" or \"RestartUnit\"");
		exe_info->result = -EINVAL;
		return 0;
	}

	ret = epc_dbus_call_systemd_simple_async(SYSTEMD_OBJ,
			SYSTEMD_MANAGER_INTERFACE,
			unit_action,
			unit_action_handler,
			exe_info,
			"ss",
			unit_name,
			"replace");
	if (ret < 0)
		epc_object_append_string(exe_info->action_log, "error",
				"Failed to call systemd");
	else
		log_kmsg("Starting unit: %s", unit_name);

	exe_info->result = -EPROBE_DEFER;
	epc_event_ref(&exe_info->event);
	return 0;
}

static struct epc_action unit_start_action = {
	.action_id = EPC_ACTION_UNIT_START_ID,
	.impl_name = EPC_DEFAULT_ACTION_IMPL,
	.execute = start_unit,
	.node = LIST_HEAD_INIT(unit_start_action.node),
};

EPC_ACTION_REGISTER_SIMPLE(unit_start_action);