blob: dd128978ccc09d09b77bec9812fffd0f79e4e1ac [file] [log] [blame]
Kevin Wolff3534152020-02-24 15:29:49 +01001/*
2 * QEMU storage daemon
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 * Copyright (c) 2019 Kevin Wolf <kwolf@redhat.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26#include "qemu/osdep.h"
27
28#include <getopt.h>
29
30#include "block/block.h"
Kevin Wolfeed8b692020-02-24 15:29:57 +010031#include "block/nbd.h"
Kevin Wolf5e6911c2020-02-24 15:30:01 +010032#include "chardev/char.h"
Kevin Wolff3534152020-02-24 15:29:49 +010033#include "crypto/init.h"
Kevin Wolf2af282e2020-02-24 15:30:08 +010034#include "monitor/monitor.h"
35#include "monitor/monitor-internal.h"
Kevin Wolff3534152020-02-24 15:29:49 +010036
37#include "qapi/error.h"
Kevin Wolfeed8b692020-02-24 15:29:57 +010038#include "qapi/qapi-visit-block.h"
39#include "qapi/qapi-visit-block-core.h"
Kevin Wolf2af282e2020-02-24 15:30:08 +010040#include "qapi/qapi-visit-control.h"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010041#include "qapi/qmp/qdict.h"
Kevin Wolf2af282e2020-02-24 15:30:08 +010042#include "qapi/qmp/qstring.h"
Kevin Wolf14837c62020-02-24 15:29:54 +010043#include "qapi/qobject-input-visitor.h"
44
Kevin Wolff3534152020-02-24 15:29:49 +010045#include "qemu-common.h"
46#include "qemu-version.h"
47#include "qemu/config-file.h"
48#include "qemu/error-report.h"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010049#include "qemu/help_option.h"
Kevin Wolff3534152020-02-24 15:29:49 +010050#include "qemu/log.h"
51#include "qemu/main-loop.h"
52#include "qemu/module.h"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010053#include "qemu/option.h"
54#include "qom/object_interfaces.h"
Kevin Wolff3534152020-02-24 15:29:49 +010055
Kevin Wolf2af282e2020-02-24 15:30:08 +010056#include "storage-daemon/qapi/qapi-commands.h"
57#include "storage-daemon/qapi/qapi-init-commands.h"
58
Kevin Wolfaa706832020-02-24 15:30:00 +010059#include "sysemu/runstate.h"
Kevin Wolff3534152020-02-24 15:29:49 +010060#include "trace/control.h"
61
Kevin Wolfaa706832020-02-24 15:30:00 +010062static volatile bool exit_requested = false;
63
64void qemu_system_killed(int signal, pid_t pid)
65{
66 exit_requested = true;
67}
68
Kevin Wolf2af282e2020-02-24 15:30:08 +010069void qmp_quit(Error **errp)
70{
71 exit_requested = true;
72}
73
Kevin Wolff3534152020-02-24 15:29:49 +010074static void help(void)
75{
76 printf(
77"Usage: %s [options]\n"
78"QEMU storage daemon\n"
79"\n"
80" -h, --help display this help and exit\n"
81" -T, --trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
82" specify tracing options\n"
83" -V, --version output version information and exit\n"
84"\n"
Kevin Wolf14837c62020-02-24 15:29:54 +010085" --blockdev [driver=]<driver>[,node-name=<N>][,discard=ignore|unmap]\n"
86" [,cache.direct=on|off][,cache.no-flush=on|off]\n"
87" [,read-only=on|off][,auto-read-only=on|off]\n"
88" [,force-share=on|off][,detect-zeroes=on|off|unmap]\n"
89" [,driver specific parameters...]\n"
90" configure a block backend\n"
91"\n"
Kevin Wolf5e6911c2020-02-24 15:30:01 +010092" --chardev <options> configure a character device backend\n"
93" (see the qemu(1) man page for possible options)\n"
94"\n"
Kevin Wolf39411122020-02-24 15:29:59 +010095" --export [type=]nbd,device=<node-name>[,name=<export-name>]\n"
96" [,writable=on|off][,bitmap=<name>]\n"
97" export the specified block node over NBD\n"
98" (requires --nbd-server)\n"
99"\n"
Kevin Wolf2af282e2020-02-24 15:30:08 +0100100" --monitor [chardev=]name[,mode=control][,pretty[=on|off]]\n"
101" configure a QMP monitor\n"
102"\n"
Kevin Wolfeed8b692020-02-24 15:29:57 +0100103" --nbd-server addr.type=inet,addr.host=<host>,addr.port=<port>\n"
104" [,tls-creds=<id>][,tls-authz=<id>]\n"
105" --nbd-server addr.type=unix,addr.path=<path>\n"
106" [,tls-creds=<id>][,tls-authz=<id>]\n"
107" start an NBD server for exporting block nodes\n"
108"\n"
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100109" --object help list object types that can be added\n"
110" --object <type>,help list properties for the given object type\n"
111" --object <type>[,<property>=<value>...]\n"
112" create a new object of type <type>, setting\n"
113" properties in the order they are specified. Note\n"
114" that the 'id' property must be set.\n"
115" See the qemu(1) man page for documentation of the\n"
116" objects that can be added.\n"
117"\n"
Kevin Wolff3534152020-02-24 15:29:49 +0100118QEMU_HELP_BOTTOM "\n",
119 error_get_progname());
120}
121
Kevin Wolf14837c62020-02-24 15:29:54 +0100122enum {
123 OPTION_BLOCKDEV = 256,
Kevin Wolf5e6911c2020-02-24 15:30:01 +0100124 OPTION_CHARDEV,
Kevin Wolf39411122020-02-24 15:29:59 +0100125 OPTION_EXPORT,
Kevin Wolf2af282e2020-02-24 15:30:08 +0100126 OPTION_MONITOR,
Kevin Wolfeed8b692020-02-24 15:29:57 +0100127 OPTION_NBD_SERVER,
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100128 OPTION_OBJECT,
129};
130
Kevin Wolf5e6911c2020-02-24 15:30:01 +0100131extern QemuOptsList qemu_chardev_opts;
132
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100133static QemuOptsList qemu_object_opts = {
134 .name = "object",
135 .implied_opt_name = "qom-type",
136 .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head),
137 .desc = {
138 { }
139 },
Kevin Wolf14837c62020-02-24 15:29:54 +0100140};
141
Kevin Wolf2af282e2020-02-24 15:30:08 +0100142static void init_qmp_commands(void)
143{
144 qmp_init_marshal(&qmp_commands);
145 qmp_register_command(&qmp_commands, "query-qmp-schema",
146 qmp_query_qmp_schema, QCO_ALLOW_PRECONFIG);
147
148 QTAILQ_INIT(&qmp_cap_negotiation_commands);
149 qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
150 qmp_marshal_qmp_capabilities, QCO_ALLOW_PRECONFIG);
151}
152
Kevin Wolf39411122020-02-24 15:29:59 +0100153static void init_export(BlockExport *export, Error **errp)
154{
155 switch (export->type) {
156 case BLOCK_EXPORT_TYPE_NBD:
157 qmp_nbd_server_add(&export->u.nbd, errp);
158 break;
159 default:
160 g_assert_not_reached();
161 }
162}
163
Kevin Wolff3534152020-02-24 15:29:49 +0100164static void process_options(int argc, char *argv[])
165{
166 int c;
167
168 static const struct option long_options[] = {
Kevin Wolf14837c62020-02-24 15:29:54 +0100169 {"blockdev", required_argument, NULL, OPTION_BLOCKDEV},
Kevin Wolf5e6911c2020-02-24 15:30:01 +0100170 {"chardev", required_argument, NULL, OPTION_CHARDEV},
Kevin Wolf39411122020-02-24 15:29:59 +0100171 {"export", required_argument, NULL, OPTION_EXPORT},
Kevin Wolff3534152020-02-24 15:29:49 +0100172 {"help", no_argument, NULL, 'h'},
Kevin Wolf2af282e2020-02-24 15:30:08 +0100173 {"monitor", required_argument, NULL, OPTION_MONITOR},
Kevin Wolfeed8b692020-02-24 15:29:57 +0100174 {"nbd-server", required_argument, NULL, OPTION_NBD_SERVER},
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100175 {"object", required_argument, NULL, OPTION_OBJECT},
Kevin Wolff3534152020-02-24 15:29:49 +0100176 {"trace", required_argument, NULL, 'T'},
177 {"version", no_argument, NULL, 'V'},
178 {0, 0, 0, 0}
179 };
180
181 /*
182 * In contrast to the system emulator, options are processed in the order
183 * they are given on the command lines. This means that things must be
184 * defined first before they can be referenced in another option.
185 */
186 while ((c = getopt_long(argc, argv, "hT:V", long_options, NULL)) != -1) {
187 switch (c) {
188 case '?':
189 exit(EXIT_FAILURE);
190 case 'h':
191 help();
192 exit(EXIT_SUCCESS);
193 case 'T':
194 {
195 char *trace_file = trace_opt_parse(optarg);
196 trace_init_file(trace_file);
197 g_free(trace_file);
198 break;
199 }
200 case 'V':
201 printf("qemu-storage-daemon version "
202 QEMU_FULL_VERSION "\n" QEMU_COPYRIGHT "\n");
203 exit(EXIT_SUCCESS);
Kevin Wolf14837c62020-02-24 15:29:54 +0100204 case OPTION_BLOCKDEV:
205 {
206 Visitor *v;
207 BlockdevOptions *options;
208
209 v = qobject_input_visitor_new_str(optarg, "driver",
210 &error_fatal);
211
212 visit_type_BlockdevOptions(v, NULL, &options, &error_fatal);
213 visit_free(v);
214
215 qmp_blockdev_add(options, &error_fatal);
216 qapi_free_BlockdevOptions(options);
217 break;
218 }
Kevin Wolf5e6911c2020-02-24 15:30:01 +0100219 case OPTION_CHARDEV:
220 {
221 /* TODO This interface is not stable until we QAPIfy it */
222 QemuOpts *opts = qemu_opts_parse_noisily(&qemu_chardev_opts,
223 optarg, true);
224 if (opts == NULL) {
225 exit(EXIT_FAILURE);
226 }
227
228 if (!qemu_chr_new_from_opts(opts, NULL, &error_fatal)) {
229 /* No error, but NULL returned means help was printed */
230 exit(EXIT_SUCCESS);
231 }
232 qemu_opts_del(opts);
233 break;
234 }
Kevin Wolf39411122020-02-24 15:29:59 +0100235 case OPTION_EXPORT:
236 {
237 Visitor *v;
238 BlockExport *export;
239
240 v = qobject_input_visitor_new_str(optarg, "type", &error_fatal);
241 visit_type_BlockExport(v, NULL, &export, &error_fatal);
242 visit_free(v);
243
244 init_export(export, &error_fatal);
245 qapi_free_BlockExport(export);
246 break;
247 }
Kevin Wolf2af282e2020-02-24 15:30:08 +0100248 case OPTION_MONITOR:
249 {
250 Visitor *v;
251 MonitorOptions *monitor;
252
253 v = qobject_input_visitor_new_str(optarg, "chardev",
254 &error_fatal);
255 visit_type_MonitorOptions(v, NULL, &monitor, &error_fatal);
256 visit_free(v);
257
258 /* TODO Catch duplicate monitor IDs */
259 monitor_init(monitor, false, &error_fatal);
260 qapi_free_MonitorOptions(monitor);
261 break;
262 }
Kevin Wolfeed8b692020-02-24 15:29:57 +0100263 case OPTION_NBD_SERVER:
264 {
265 Visitor *v;
266 NbdServerOptions *options;
267
268 v = qobject_input_visitor_new_str(optarg, NULL, &error_fatal);
269 visit_type_NbdServerOptions(v, NULL, &options, &error_fatal);
270 visit_free(v);
271
272 nbd_server_start_options(options, &error_fatal);
273 qapi_free_NbdServerOptions(options);
274 break;
275 }
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100276 case OPTION_OBJECT:
277 {
278 QemuOpts *opts;
279 const char *type;
280 QDict *args;
281 QObject *ret_data = NULL;
282
283 /* FIXME The keyval parser rejects 'help' arguments, so we must
284 * unconditionall try QemuOpts first. */
285 opts = qemu_opts_parse(&qemu_object_opts,
286 optarg, true, &error_fatal);
287 type = qemu_opt_get(opts, "qom-type");
288 if (type && user_creatable_print_help(type, opts)) {
289 exit(EXIT_SUCCESS);
290 }
291 qemu_opts_del(opts);
292
293 args = keyval_parse(optarg, "qom-type", &error_fatal);
294 qmp_object_add(args, &ret_data, &error_fatal);
295 qobject_unref(args);
296 qobject_unref(ret_data);
297 break;
298 }
Kevin Wolff3534152020-02-24 15:29:49 +0100299 default:
300 g_assert_not_reached();
301 }
302 }
303 if (optind != argc) {
304 error_report("Unexpected argument: %s", argv[optind]);
305 exit(EXIT_FAILURE);
306 }
307}
308
309int main(int argc, char *argv[])
310{
311#ifdef CONFIG_POSIX
312 signal(SIGPIPE, SIG_IGN);
313#endif
314
315 error_init(argv[0]);
316 qemu_init_exec_dir(argv[0]);
Kevin Wolfaa706832020-02-24 15:30:00 +0100317 os_setup_signal_handling();
Kevin Wolff3534152020-02-24 15:29:49 +0100318
319 module_call_init(MODULE_INIT_QOM);
320 module_call_init(MODULE_INIT_TRACE);
321 qemu_add_opts(&qemu_trace_opts);
322 qcrypto_init(&error_fatal);
323 bdrv_init();
Kevin Wolf2af282e2020-02-24 15:30:08 +0100324 monitor_init_globals_core();
325 init_qmp_commands();
Kevin Wolff3534152020-02-24 15:29:49 +0100326
327 if (!trace_init_backends()) {
328 return EXIT_FAILURE;
329 }
330 qemu_set_log(LOG_TRACE);
331
332 qemu_init_main_loop(&error_fatal);
333 process_options(argc, argv);
334
Kevin Wolfaa706832020-02-24 15:30:00 +0100335 while (!exit_requested) {
336 main_loop_wait(false);
337 }
338
Kevin Wolff3534152020-02-24 15:29:49 +0100339 return EXIT_SUCCESS;
340}