blob: 276a412915c8b158df7d15d74351bbfbe9e3d576 [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 Wolff3534152020-02-24 15:29:49 +010032#include "crypto/init.h"
33
34#include "qapi/error.h"
Kevin Wolfeed8b692020-02-24 15:29:57 +010035#include "qapi/qapi-commands-block.h"
Kevin Wolf14837c62020-02-24 15:29:54 +010036#include "qapi/qapi-commands-block-core.h"
Kevin Wolfeed8b692020-02-24 15:29:57 +010037#include "qapi/qapi-visit-block.h"
38#include "qapi/qapi-visit-block-core.h"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010039#include "qapi/qmp/qdict.h"
Kevin Wolf14837c62020-02-24 15:29:54 +010040#include "qapi/qobject-input-visitor.h"
41
Kevin Wolff3534152020-02-24 15:29:49 +010042#include "qemu-common.h"
43#include "qemu-version.h"
44#include "qemu/config-file.h"
45#include "qemu/error-report.h"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010046#include "qemu/help_option.h"
Kevin Wolff3534152020-02-24 15:29:49 +010047#include "qemu/log.h"
48#include "qemu/main-loop.h"
49#include "qemu/module.h"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010050#include "qemu/option.h"
51#include "qom/object_interfaces.h"
Kevin Wolff3534152020-02-24 15:29:49 +010052
53#include "trace/control.h"
54
55static void help(void)
56{
57 printf(
58"Usage: %s [options]\n"
59"QEMU storage daemon\n"
60"\n"
61" -h, --help display this help and exit\n"
62" -T, --trace [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
63" specify tracing options\n"
64" -V, --version output version information and exit\n"
65"\n"
Kevin Wolf14837c62020-02-24 15:29:54 +010066" --blockdev [driver=]<driver>[,node-name=<N>][,discard=ignore|unmap]\n"
67" [,cache.direct=on|off][,cache.no-flush=on|off]\n"
68" [,read-only=on|off][,auto-read-only=on|off]\n"
69" [,force-share=on|off][,detect-zeroes=on|off|unmap]\n"
70" [,driver specific parameters...]\n"
71" configure a block backend\n"
72"\n"
Kevin Wolfeed8b692020-02-24 15:29:57 +010073" --nbd-server addr.type=inet,addr.host=<host>,addr.port=<port>\n"
74" [,tls-creds=<id>][,tls-authz=<id>]\n"
75" --nbd-server addr.type=unix,addr.path=<path>\n"
76" [,tls-creds=<id>][,tls-authz=<id>]\n"
77" start an NBD server for exporting block nodes\n"
78"\n"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010079" --object help list object types that can be added\n"
80" --object <type>,help list properties for the given object type\n"
81" --object <type>[,<property>=<value>...]\n"
82" create a new object of type <type>, setting\n"
83" properties in the order they are specified. Note\n"
84" that the 'id' property must be set.\n"
85" See the qemu(1) man page for documentation of the\n"
86" objects that can be added.\n"
87"\n"
Kevin Wolff3534152020-02-24 15:29:49 +010088QEMU_HELP_BOTTOM "\n",
89 error_get_progname());
90}
91
Kevin Wolf14837c62020-02-24 15:29:54 +010092enum {
93 OPTION_BLOCKDEV = 256,
Kevin Wolfeed8b692020-02-24 15:29:57 +010094 OPTION_NBD_SERVER,
Kevin Wolfd6da78b2020-02-24 15:29:56 +010095 OPTION_OBJECT,
96};
97
98static QemuOptsList qemu_object_opts = {
99 .name = "object",
100 .implied_opt_name = "qom-type",
101 .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head),
102 .desc = {
103 { }
104 },
Kevin Wolf14837c62020-02-24 15:29:54 +0100105};
106
Kevin Wolff3534152020-02-24 15:29:49 +0100107static void process_options(int argc, char *argv[])
108{
109 int c;
110
111 static const struct option long_options[] = {
Kevin Wolf14837c62020-02-24 15:29:54 +0100112 {"blockdev", required_argument, NULL, OPTION_BLOCKDEV},
Kevin Wolff3534152020-02-24 15:29:49 +0100113 {"help", no_argument, NULL, 'h'},
Kevin Wolfeed8b692020-02-24 15:29:57 +0100114 {"nbd-server", required_argument, NULL, OPTION_NBD_SERVER},
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100115 {"object", required_argument, NULL, OPTION_OBJECT},
Kevin Wolff3534152020-02-24 15:29:49 +0100116 {"trace", required_argument, NULL, 'T'},
117 {"version", no_argument, NULL, 'V'},
118 {0, 0, 0, 0}
119 };
120
121 /*
122 * In contrast to the system emulator, options are processed in the order
123 * they are given on the command lines. This means that things must be
124 * defined first before they can be referenced in another option.
125 */
126 while ((c = getopt_long(argc, argv, "hT:V", long_options, NULL)) != -1) {
127 switch (c) {
128 case '?':
129 exit(EXIT_FAILURE);
130 case 'h':
131 help();
132 exit(EXIT_SUCCESS);
133 case 'T':
134 {
135 char *trace_file = trace_opt_parse(optarg);
136 trace_init_file(trace_file);
137 g_free(trace_file);
138 break;
139 }
140 case 'V':
141 printf("qemu-storage-daemon version "
142 QEMU_FULL_VERSION "\n" QEMU_COPYRIGHT "\n");
143 exit(EXIT_SUCCESS);
Kevin Wolf14837c62020-02-24 15:29:54 +0100144 case OPTION_BLOCKDEV:
145 {
146 Visitor *v;
147 BlockdevOptions *options;
148
149 v = qobject_input_visitor_new_str(optarg, "driver",
150 &error_fatal);
151
152 visit_type_BlockdevOptions(v, NULL, &options, &error_fatal);
153 visit_free(v);
154
155 qmp_blockdev_add(options, &error_fatal);
156 qapi_free_BlockdevOptions(options);
157 break;
158 }
Kevin Wolfeed8b692020-02-24 15:29:57 +0100159 case OPTION_NBD_SERVER:
160 {
161 Visitor *v;
162 NbdServerOptions *options;
163
164 v = qobject_input_visitor_new_str(optarg, NULL, &error_fatal);
165 visit_type_NbdServerOptions(v, NULL, &options, &error_fatal);
166 visit_free(v);
167
168 nbd_server_start_options(options, &error_fatal);
169 qapi_free_NbdServerOptions(options);
170 break;
171 }
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100172 case OPTION_OBJECT:
173 {
174 QemuOpts *opts;
175 const char *type;
176 QDict *args;
177 QObject *ret_data = NULL;
178
179 /* FIXME The keyval parser rejects 'help' arguments, so we must
180 * unconditionall try QemuOpts first. */
181 opts = qemu_opts_parse(&qemu_object_opts,
182 optarg, true, &error_fatal);
183 type = qemu_opt_get(opts, "qom-type");
184 if (type && user_creatable_print_help(type, opts)) {
185 exit(EXIT_SUCCESS);
186 }
187 qemu_opts_del(opts);
188
189 args = keyval_parse(optarg, "qom-type", &error_fatal);
190 qmp_object_add(args, &ret_data, &error_fatal);
191 qobject_unref(args);
192 qobject_unref(ret_data);
193 break;
194 }
Kevin Wolff3534152020-02-24 15:29:49 +0100195 default:
196 g_assert_not_reached();
197 }
198 }
199 if (optind != argc) {
200 error_report("Unexpected argument: %s", argv[optind]);
201 exit(EXIT_FAILURE);
202 }
203}
204
205int main(int argc, char *argv[])
206{
207#ifdef CONFIG_POSIX
208 signal(SIGPIPE, SIG_IGN);
209#endif
210
211 error_init(argv[0]);
212 qemu_init_exec_dir(argv[0]);
213
214 module_call_init(MODULE_INIT_QOM);
215 module_call_init(MODULE_INIT_TRACE);
216 qemu_add_opts(&qemu_trace_opts);
217 qcrypto_init(&error_fatal);
218 bdrv_init();
219
220 if (!trace_init_backends()) {
221 return EXIT_FAILURE;
222 }
223 qemu_set_log(LOG_TRACE);
224
225 qemu_init_main_loop(&error_fatal);
226 process_options(argc, argv);
227
228 return EXIT_SUCCESS;
229}