blob: 5904d3c5b4df0d2c0d035fc97236ac4cad3b3233 [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 Wolf39411122020-02-24 15:29:59 +010073" --export [type=]nbd,device=<node-name>[,name=<export-name>]\n"
74" [,writable=on|off][,bitmap=<name>]\n"
75" export the specified block node over NBD\n"
76" (requires --nbd-server)\n"
77"\n"
Kevin Wolfeed8b692020-02-24 15:29:57 +010078" --nbd-server addr.type=inet,addr.host=<host>,addr.port=<port>\n"
79" [,tls-creds=<id>][,tls-authz=<id>]\n"
80" --nbd-server addr.type=unix,addr.path=<path>\n"
81" [,tls-creds=<id>][,tls-authz=<id>]\n"
82" start an NBD server for exporting block nodes\n"
83"\n"
Kevin Wolfd6da78b2020-02-24 15:29:56 +010084" --object help list object types that can be added\n"
85" --object <type>,help list properties for the given object type\n"
86" --object <type>[,<property>=<value>...]\n"
87" create a new object of type <type>, setting\n"
88" properties in the order they are specified. Note\n"
89" that the 'id' property must be set.\n"
90" See the qemu(1) man page for documentation of the\n"
91" objects that can be added.\n"
92"\n"
Kevin Wolff3534152020-02-24 15:29:49 +010093QEMU_HELP_BOTTOM "\n",
94 error_get_progname());
95}
96
Kevin Wolf14837c62020-02-24 15:29:54 +010097enum {
98 OPTION_BLOCKDEV = 256,
Kevin Wolf39411122020-02-24 15:29:59 +010099 OPTION_EXPORT,
Kevin Wolfeed8b692020-02-24 15:29:57 +0100100 OPTION_NBD_SERVER,
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100101 OPTION_OBJECT,
102};
103
104static QemuOptsList qemu_object_opts = {
105 .name = "object",
106 .implied_opt_name = "qom-type",
107 .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head),
108 .desc = {
109 { }
110 },
Kevin Wolf14837c62020-02-24 15:29:54 +0100111};
112
Kevin Wolf39411122020-02-24 15:29:59 +0100113static void init_export(BlockExport *export, Error **errp)
114{
115 switch (export->type) {
116 case BLOCK_EXPORT_TYPE_NBD:
117 qmp_nbd_server_add(&export->u.nbd, errp);
118 break;
119 default:
120 g_assert_not_reached();
121 }
122}
123
Kevin Wolff3534152020-02-24 15:29:49 +0100124static void process_options(int argc, char *argv[])
125{
126 int c;
127
128 static const struct option long_options[] = {
Kevin Wolf14837c62020-02-24 15:29:54 +0100129 {"blockdev", required_argument, NULL, OPTION_BLOCKDEV},
Kevin Wolf39411122020-02-24 15:29:59 +0100130 {"export", required_argument, NULL, OPTION_EXPORT},
Kevin Wolff3534152020-02-24 15:29:49 +0100131 {"help", no_argument, NULL, 'h'},
Kevin Wolfeed8b692020-02-24 15:29:57 +0100132 {"nbd-server", required_argument, NULL, OPTION_NBD_SERVER},
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100133 {"object", required_argument, NULL, OPTION_OBJECT},
Kevin Wolff3534152020-02-24 15:29:49 +0100134 {"trace", required_argument, NULL, 'T'},
135 {"version", no_argument, NULL, 'V'},
136 {0, 0, 0, 0}
137 };
138
139 /*
140 * In contrast to the system emulator, options are processed in the order
141 * they are given on the command lines. This means that things must be
142 * defined first before they can be referenced in another option.
143 */
144 while ((c = getopt_long(argc, argv, "hT:V", long_options, NULL)) != -1) {
145 switch (c) {
146 case '?':
147 exit(EXIT_FAILURE);
148 case 'h':
149 help();
150 exit(EXIT_SUCCESS);
151 case 'T':
152 {
153 char *trace_file = trace_opt_parse(optarg);
154 trace_init_file(trace_file);
155 g_free(trace_file);
156 break;
157 }
158 case 'V':
159 printf("qemu-storage-daemon version "
160 QEMU_FULL_VERSION "\n" QEMU_COPYRIGHT "\n");
161 exit(EXIT_SUCCESS);
Kevin Wolf14837c62020-02-24 15:29:54 +0100162 case OPTION_BLOCKDEV:
163 {
164 Visitor *v;
165 BlockdevOptions *options;
166
167 v = qobject_input_visitor_new_str(optarg, "driver",
168 &error_fatal);
169
170 visit_type_BlockdevOptions(v, NULL, &options, &error_fatal);
171 visit_free(v);
172
173 qmp_blockdev_add(options, &error_fatal);
174 qapi_free_BlockdevOptions(options);
175 break;
176 }
Kevin Wolf39411122020-02-24 15:29:59 +0100177 case OPTION_EXPORT:
178 {
179 Visitor *v;
180 BlockExport *export;
181
182 v = qobject_input_visitor_new_str(optarg, "type", &error_fatal);
183 visit_type_BlockExport(v, NULL, &export, &error_fatal);
184 visit_free(v);
185
186 init_export(export, &error_fatal);
187 qapi_free_BlockExport(export);
188 break;
189 }
Kevin Wolfeed8b692020-02-24 15:29:57 +0100190 case OPTION_NBD_SERVER:
191 {
192 Visitor *v;
193 NbdServerOptions *options;
194
195 v = qobject_input_visitor_new_str(optarg, NULL, &error_fatal);
196 visit_type_NbdServerOptions(v, NULL, &options, &error_fatal);
197 visit_free(v);
198
199 nbd_server_start_options(options, &error_fatal);
200 qapi_free_NbdServerOptions(options);
201 break;
202 }
Kevin Wolfd6da78b2020-02-24 15:29:56 +0100203 case OPTION_OBJECT:
204 {
205 QemuOpts *opts;
206 const char *type;
207 QDict *args;
208 QObject *ret_data = NULL;
209
210 /* FIXME The keyval parser rejects 'help' arguments, so we must
211 * unconditionall try QemuOpts first. */
212 opts = qemu_opts_parse(&qemu_object_opts,
213 optarg, true, &error_fatal);
214 type = qemu_opt_get(opts, "qom-type");
215 if (type && user_creatable_print_help(type, opts)) {
216 exit(EXIT_SUCCESS);
217 }
218 qemu_opts_del(opts);
219
220 args = keyval_parse(optarg, "qom-type", &error_fatal);
221 qmp_object_add(args, &ret_data, &error_fatal);
222 qobject_unref(args);
223 qobject_unref(ret_data);
224 break;
225 }
Kevin Wolff3534152020-02-24 15:29:49 +0100226 default:
227 g_assert_not_reached();
228 }
229 }
230 if (optind != argc) {
231 error_report("Unexpected argument: %s", argv[optind]);
232 exit(EXIT_FAILURE);
233 }
234}
235
236int main(int argc, char *argv[])
237{
238#ifdef CONFIG_POSIX
239 signal(SIGPIPE, SIG_IGN);
240#endif
241
242 error_init(argv[0]);
243 qemu_init_exec_dir(argv[0]);
244
245 module_call_init(MODULE_INIT_QOM);
246 module_call_init(MODULE_INIT_TRACE);
247 qemu_add_opts(&qemu_trace_opts);
248 qcrypto_init(&error_fatal);
249 bdrv_init();
250
251 if (!trace_init_backends()) {
252 return EXIT_FAILURE;
253 }
254 qemu_set_log(LOG_TRACE);
255
256 qemu_init_main_loop(&error_fatal);
257 process_options(argc, argv);
258
259 return EXIT_SUCCESS;
260}