As a side effect, a lot more fields are now settable on the
kernel command line.
Existing kernel command lines & corresponding documentation should
still remain backwards compatible.
---
.gitignore | 2 +
generator/main.ml | 4 +
generator/p2v_config.ml | 458 ++++++++++++++++++++++++++++++++++++++-
generator/p2v_config.mli | 2 +
p2v/Makefile.am | 8 +-
p2v/kernel.c | 154 -------------
p2v/p2v.h | 4 +-
p2v/virt-p2v.pod | 131 +----------
po-docs/language.mk | 8 +
po-docs/podfiles | 1 +
10 files changed, 475 insertions(+), 297 deletions(-)
diff --git a/.gitignore b/.gitignore
index 4c0ff4e1e..d855459f3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -435,6 +435,7 @@ Makefile.in
/p2v/dependencies.debian
/p2v/dependencies.redhat
/p2v/dependencies.suse
+/p2v/kernel-config.c
/p2v/p2v-config.h
/p2v/stamp-test-virt-p2v-pxe-data-files
/p2v/stamp-test-virt-p2v-pxe-hostkey
@@ -457,6 +458,7 @@ Makefile.in
/p2v/virt-p2v.1
/p2v/virt-p2v.i686
/p2v/virt-p2v.img
+/p2v/virt-p2v-kernel-config.pod
/p2v/virt-p2v-make-disk
/p2v/virt-p2v-make-disk.1
/p2v/virt-p2v-make-kickstart
diff --git a/generator/main.ml b/generator/main.ml
index ecc551f72..72f31ecab 100644
--- a/generator/main.ml
+++ b/generator/main.ml
@@ -367,6 +367,10 @@ Run it from the top source directory using the command
P2v_config.generate_p2v_config_h;
output_to "p2v/config.c"
P2v_config.generate_p2v_config_c;
+ output_to "p2v/kernel-config.c"
+ P2v_config.generate_p2v_kernel_config_c;
+ output_to "p2v/virt-p2v-kernel-config.pod"
+ P2v_config.generate_p2v_kernel_config_pod;
(* Generate the list of files generated -- last. *)
printf "generated %d lines of code\n" (get_lines_generated ());
diff --git a/generator/p2v_config.ml b/generator/p2v_config.ml
index e0347d6c2..11aec5ee3 100644
--- a/generator/p2v_config.ml
+++ b/generator/p2v_config.ml
@@ -26,7 +26,7 @@ open Pr
let generate_header = generate_header ~inputs:["generator/p2v_config.ml"]
-type enum_choice = string * string (* name, comment *)
+type enum_choice = string * string * string (* name, cmdline, comment *)
type enum = string * enum_choice list
type config_entry =
@@ -39,17 +39,22 @@ type config_entry =
| ConfigStringList of string
| ConfigSection of string * config_entry list
+type manual_entry = {
+ shortopt : string;
+ description : string;
+}
+
(* Enums. *)
let enums = [
"basis", [
- "BASIS_UNKNOWN", "RTC could not be read";
- "BASIS_UTC", "RTC is either UTC or an offset from UTC";
- "BASIS_LOCALTIME", "RTC is localtime";
+ "BASIS_UNKNOWN", "unknown", "RTC could not be
read";
+ "BASIS_UTC", "utc", "RTC is either UTC or an
offset from UTC";
+ "BASIS_LOCALTIME", "localtime", "RTC is localtime";
];
"output_allocation", [
- "OUTPUT_ALLOCATION_NONE", "output allocation not set";
- "OUTPUT_ALLOCATION_SPARSE", "sparse";
- "OUTPUT_ALLOCATION_PREALLOCATED", "preallocated";
+ "OUTPUT_ALLOCATION_NONE", "none", "output allocation
not set";
+ "OUTPUT_ALLOCATION_SPARSE", "sparse",
"sparse";
+ "OUTPUT_ALLOCATION_PREALLOCATED", "preallocated",
"preallocated";
];
]
@@ -99,6 +104,245 @@ let fields = [
]);
]
+(* Some /proc/cmdline p2v.* options were renamed when we introduced
+ * the generator. This map creates backwards compatibility mappings
+ * for these.
+ *)
+let cmdline_aliases = [
+ "p2v.remote.server", ["p2v.server"];
+ "p2v.remote.port", ["p2v.port"];
+ "p2v.auth.username", ["p2v.username"];
+ "p2v.auth.password", ["p2v.password"];
+ "p2v.auth.identity.url", ["p2v.identity"];
+ "p2v.auth.sudo", ["p2v.sudo"];
+ "p2v.guestname", ["p2v.name"];
+ "p2v.network_map", ["p2v.network"];
+ "p2v.output.type", ["p2v.o"];
+ "p2v.output.allocation", ["p2v.oa"];
+ "p2v.output.connection", ["p2v.oc"];
+ "p2v.output.format", ["p2v.of"];
+ "p2v.output.storage", ["p2v.os"];
+]
+
+(* Some config entries are not exposed on the kernel command line. *)
+let cmdline_ignore = [
+ "p2v.auth.identity.file";
+ "p2v.auth.identity.file_needs_update";
+]
+
+(* Man page snippets for each kernel command line setting. *)
+let cmdline_manual = [
+ "p2v.remote.server", {
+ shortopt = "SERVER";
+ description = "
+The name or IP address of the conversion server.
+
+This is always required if you are using the kernel configuration
+method. If virt-p2v does not find this on the kernel command line
+then it switches to the GUI (interactive) configuration method.";
+ };
+ "p2v.remote.port", {
+ shortopt = "PORT";
+ description = "
+The SSH port number on the conversion server (default: C<22>).";
+ };
+ "p2v.auth.username", {
+ shortopt = "USERNAME";
+ description = "
+The SSH username that we log in as on the conversion server
+(default: C<root>).";
+ };
+ "p2v.auth.password", {
+ shortopt = "PASSWORD";
+ description = "
+The SSH password that we use to log in to the conversion server.
+
+The default is to try with no password. If this fails then virt-p2v
+will ask the user to type the password (probably several times during
+conversion).
+
+This setting is ignored if C<p2v.auth.identity.url> is present.";
+ };
+ "p2v.auth.identity.url", {
+ shortopt = "URL";
+ description = "
+Provide a URL pointing to an SSH identity (private key) file. The URL
+is interpreted by L<curl(1)> so any URL that curl supports can be used
+here, including C<https://> and C<file://>. For more information on
+using SSH identities, see L</SSH IDENTITIES> below.
+
+If C<p2v.auth.identity.url> is present, it overrides C<p2v.auth.password>.
+There is no fallback.";
+ };
+ "p2v.auth.sudo", {
+ shortopt = ""; (* ignored for booleans *)
+ description = "
+Use C<p2v.sudo> to tell virt-p2v to use L<sudo(8)> to gain root
+privileges on the conversion server after logging in as a non-root
+user (default: do not use sudo).";
+ };
+ "p2v.guestname", {
+ shortopt = "GUESTNAME";
+ description = "
+The name of the guest that is created. The default is to try to
+derive a name from the physical machine’s hostname (if possible) else
+use a randomly generated name.";
+ };
+ "p2v.vcpus", {
+ shortopt = "N";
+ description = "
+The number of virtual CPUs to give to the guest. The default is to
+use the same as the number of physical CPUs.";
+ };
+ "p2v.memory", {
+ shortopt = "n(M|G)";
+ description = "
+The size of the guest memory. You must specify the unit such as
+megabytes or gigabytes by using for example C<p2v.memory=1024M> or
+C<p2v.memory=1G>.
+
+The default is to use the same amount of RAM as on the physical
+machine.";
+ };
+ "p2v.cpu.vendor", {
+ shortopt = "VENDOR";
+ description = "
+The vCPU vendor, eg. \"Intel\" or \"AMD\". The default is to use
+the same CPU vendor as the physical machine.";
+ };
+ "p2v.cpu.model", {
+ shortopt = "MODEL";
+ description = "
+The vCPU model, eg. \"IvyBridge\". The default is to use the same
+CPU model as the physical machine.";
+ };
+ "p2v.cpu.sockets", {
+ shortopt = "N";
+ description = "
+Number of vCPU sockets to use. The default is to use the same as the
+physical machine.";
+ };
+ "p2v.cpu.cores", {
+ shortopt = "N";
+ description = "
+Number of vCPU cores to use. The default is to use the same as the
+physical machine.";
+ };
+ "p2v.cpu.threads", {
+ shortopt = "N";
+ description = "
+Number of vCPU hyperthreads to use. The default is to use the same
+as the physical machine.";
+ };
+ "p2v.cpu.acpi", {
+ shortopt = ""; (* ignored for booleans *)
+ description = "
+Whether to enable ACPI in the remote virtual machine. The default is
+to use the same as the physical machine.";
+ };
+ "p2v.cpu.apic", {
+ shortopt = ""; (* ignored for booleans *)
+ description = "
+Whether to enable APIC in the remote virtual machine. The default is
+to use the same as the physical machine.";
+ };
+ "p2v.cpu.pae", {
+ shortopt = ""; (* ignored for booleans *)
+ description = "
+Whether to enable PAE in the remote virtual machine. The default is
+to use the same as the physical machine.";
+ };
+ "p2v.rtc.basis", {
+ shortopt = ""; (* ignored for enums. *)
+ description = "
+Set the basis of the Real Time Clock in the virtual machine. The
+default is to try to detect this setting from the physical machine.";
+ };
+ "p2v.rtc.offset", {
+ shortopt = "[+|-]HOURS";
+ description = "
+The offset of the Real Time Clock from UTC. The default is to try
+to detect this setting from the physical machine.";
+ };
+ "p2v.disks", {
+ shortopt = "sda,sdb,...";
+ description = "
+A list of physical hard disks to convert, for example:
+
+ p2v.disks=sda,sdc
+
+The default is to convert all local hard disks that are found.";
+ };
+ "p2v.removable", {
+ shortopt = "sra,srb,...";
+ description = "
+A list of removable media to convert. The default is to create
+virtual removable devices for every physical removable device found.
+Note that the content of removable media is never copied over.";
+ };
+ "p2v.interfaces", {
+ shortopt = "em1,...";
+ description = "
+A list of network interfaces to convert. The default is to create
+virtual network interfaces for every physical network interface found.";
+ };
+ "p2v.network_map", {
+ shortopt = "interface:target,...";
+ description = "
+Controls how network interfaces are connected to virtual networks on
+the target hypervisor. The default is to connect all network
+interfaces to the target C<default> network.
+
+You give a comma-separated list of C<interface:target> pairs, plus
+optionally a default target. For example:
+
+ p2v.network=em1:ovirtmgmt
+
+maps interface C<em1> to target network C<ovirtmgmt>.
+
+ p2v.network=em1:ovirtmgmt,em2:management,other
+
+maps interface C<em1> to C<ovirtmgmt>, and C<em2> to
C<management>,
+and any other interface that is found to C<other>.";
+ };
+ "p2v.output.type", {
+ shortopt = "(libvirt|local|...)";
+ description = "
+Set the output mode. This is the same as the virt-v2v I<-o> option.
+See L<virt-v2v(1)/OPTIONS>.
+
+If not specified, the default is C<local>, and the converted guest is
+written to F</var/tmp>.";
+ };
+ "p2v.output.allocation", {
+ shortopt = ""; (* ignored for enums *)
+ description = "
+Set the output allocation mode. This is the same as the virt-v2v
+I<-oa> option. See L<virt-v2v(1)/OPTIONS>.";
+ };
+ "p2v.output.connection", {
+ shortopt = "URI";
+ description = "
+Set the output connection libvirt URI. This is the same as the
+virt-v2v I<-oc> option. See L<virt-v2v(1)/OPTIONS> and
+L<http://libvirt.org/uri.html>";
+ };
+ "p2v.output.format", {
+ shortopt = "(raw|qcow2|...)";
+ description = "
+Set the output format. This is the same as the virt-v2v I<-of>
+option. See L<virt-v2v(1)/OPTIONS>.";
+ };
+ "p2v.output.storage", {
+ shortopt = "STORAGE";
+ description = "
+Set the output storage. This is the same as the virt-v2v I<-os>
+option. See L<virt-v2v(1)/OPTIONS>.
+
+If not specified, the default is F</var/tmp> (on the conversion server).";
+ };
+]
+
let name_of_config_entry = function
| ConfigString n
| ConfigInt (n, _)
@@ -126,7 +370,7 @@ let rec generate_p2v_config_h () =
fun (name, fields) ->
pr "enum %s {\n" name;
List.iter (
- fun (n, comment) ->
+ fun (n, _, comment) ->
pr " %-25s /* %s */\n" (n ^ ",") comment
) fields;
pr "};\n";
@@ -256,9 +500,9 @@ pr "\
pr "{\n";
pr " switch (v) {\n";
List.iter (
- fun (n, comment) ->
+ fun (n, cmdline, _) ->
pr " case %s:\n" n;
- pr " fprintf (fp, \"%s\");\n" comment;
+ pr " fprintf (fp, \"%s\");\n" cmdline;
pr " break;\n";
) fields;
pr " }\n";
@@ -395,3 +639,197 @@ and generate_field_print prefix v fields =
let v = sprintf "%s%s." v n in
generate_field_print (Some printable_name) v fields
) fields
+
+let rec generate_p2v_kernel_config_c () =
+ generate_header CStyle GPLv2plus;
+
+ pr "\
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <errno.h>
+#include <error.h>
+
+#include \"xstrtol.h\"
+
+#include \"p2v.h\"
+#include \"p2v-config.h\"
+
+/**
+ * Read the kernel command line and parse out any C<p2v.*> fields that
+ * we understand into the config struct.
+ */
+void
+update_config_from_kernel_cmdline (struct config *c, char **cmdline)
+{
+ const char *p;
+ strtol_error xerr;
+ unsigned long long ull;
+
+";
+
+ generate_field_config "p2v" "c->" fields;
+
+ pr " if (c->auth.identity.url != NULL)
+ c->auth.identity.file_needs_update = 1;
+
+ /* Undocumented command line parameter used for testing command line
+ * parsing.
+ */
+ p = get_cmdline_key (cmdline, \"p2v.dump_config_and_exit\");
+ if (p) {
+ print_config (c, stdout);
+ exit (EXIT_SUCCESS);
+ }
+}
+"
+
+and generate_field_config prefix v fields =
+ List.iter (
+ function
+ | ConfigSection (n, fields) ->
+ let prefix = sprintf "%s.%s" prefix n in
+ let v = sprintf "%s%s." v n in
+ generate_field_config prefix v fields
+
+ | field ->
+ let n = name_of_config_entry field in
+ let key = sprintf "%s.%s" prefix n in
+
+ if not (List.mem key cmdline_ignore) then (
+ (* Is there an alias for this field? *)
+ let aliases =
+ try List.assoc key cmdline_aliases
+ with Not_found -> [] in
+
+ pr " if ((p = get_cmdline_key (cmdline, \"%s\")) != NULL"
key;
+ List.iter (
+ fun alias ->
+ pr " ||\n";
+ pr " (p = get_cmdline_key (cmdline, \"%s\")) !=
NULL" alias;
+ ) aliases;
+ pr ") {\n";
+
+ (* Parse the field. *)
+ (match field with
+ | ConfigString n ->
+ pr " free (%s%s);\n" v n;
+ pr " %s%s = strdup (p);\n" v n;
+ pr " if (%s%s == NULL)\n" v n;
+ pr " error (EXIT_FAILURE, errno, \"strdup\");\n"
+ | ConfigStringList n ->
+ pr " guestfs_int_free_string_list (%s%s);\n" v n;
+ pr " %s%s = guestfs_int_split_string (',', p);\n" v n;
+ pr " if (%s%s == NULL)\n" v n;
+ pr " error (EXIT_FAILURE, errno, \"strdup\");\n"
+ | ConfigInt (n, _) ->
+ pr " if (sscanf (p, \"%%d\", &%s%s) != 1)\n" v n;
+ pr " error (EXIT_FAILURE, errno,\n";
+ pr " \"cannot parse %%s=%%s from the kernel command
line\",\n";
+ pr " %S, p);\n" key
+ | ConfigUnsigned n ->
+ pr " if (sscanf (p, \"%%u\", &%s%s) != 1)\n" v n;
+ pr " error (EXIT_FAILURE, errno,\n";
+ pr " \"cannot parse %%s=%%s from the kernel command
line\",\n";
+ pr " %S, p);\n" key
+ | ConfigUInt64 n ->
+ pr " xerr = xstrtoull (p, NULL, 0, &ull,
\"0kKMGTPEZY\");\n";
+ pr " if (xerr != LONGINT_OK)\n";
+ pr " error (EXIT_FAILURE, 0,\n";
+ pr " \"cannot parse %%s=%%s from the kernel command
line\",\n";
+ pr " %S, p);\n" key;
+ pr " %s%s = ull;\n" v n
+ | ConfigEnum (n, enum) ->
+ let enum_choices =
+ try List.assoc enum enums
+ with Not_found -> failwithf "cannot find ConfigEnum %s" enum
in
+ pr " ";
+ List.iter (
+ fun (name, cmdline, _) ->
+ pr "if (STREQ (p, \"%s\"))\n" cmdline;
+ pr " %s%s = %s;\n" v n name;
+ pr " else ";
+ ) enum_choices;
+ pr "{\n";
+ pr " error (EXIT_FAILURE, 0,\n";
+ pr " \"invalid value %%s=%%s from the kernel command
line\",\n";
+ pr " %S, p);\n" key;
+ pr " }\n"
+ | ConfigBool n ->
+ pr " %s%s = guestfs_int_is_true (p) || STREQ (p,
\"\");\n" v n
+
+ | ConfigSection _ -> assert false (* see above *)
+ );
+
+ pr " }\n";
+ pr "\n";
+ )
+ ) fields
+
+let rec generate_p2v_kernel_config_pod () =
+ generate_field_config_pod "p2v" fields
+
+and generate_field_config_pod prefix fields =
+ List.iter (
+ function
+ | ConfigSection (n, fields) ->
+ let prefix = sprintf "%s.%s" prefix n in
+ generate_field_config_pod prefix fields
+
+ | field ->
+ let n = name_of_config_entry field in
+ let key = sprintf "%s.%s" prefix n in
+
+ if not (List.mem key cmdline_ignore) then (
+ let manual_entry =
+ try List.assoc key cmdline_manual
+ with Not_found ->
+ failwithf "generator/p2v_config.ml: missing manual entry for %s"
+ key in
+
+ (* For booleans there is no shortopt field. For enums
+ * we generate it.
+ *)
+ let shortopt =
+ match field with
+ | ConfigBool _ ->
+ assert (manual_entry.shortopt = "");
+ ""
+ | ConfigEnum (_, enum) ->
+ assert (manual_entry.shortopt = "");
+
+ let enum_choices =
+ try List.assoc enum enums
+ with Not_found -> failwithf "cannot find ConfigEnum %s" enum
in
+ "=(" ^
+ String.concat "|"
+ (List.map (fun (_, cmdline, _) -> cmdline)
+ enum_choices) ^
+ ")"
+ | ConfigString _
+ | ConfigInt _
+ | ConfigUnsigned _
+ | ConfigUInt64 _
+ | ConfigStringList _
+ | ConfigSection _ -> "=" ^ manual_entry.shortopt in
+
+ (* The description must not end with \n *)
+ if String.is_suffix manual_entry.description "\n" then
+ failwithf "generator/p2v_config.ml: description of %s must not end with
\\n"
+ key;
+
+ (* Is there an alias for this field? *)
+ let aliases =
+ try List.assoc key cmdline_aliases
+ with Not_found -> [] in
+ List.iter (
+ fun k -> pr "=item B<%s%s>\n\n" k shortopt
+ ) (key :: aliases);
+
+ pr "%s\n\n" manual_entry.description
+ )
+ ) fields
diff --git a/generator/p2v_config.mli b/generator/p2v_config.mli
index 55d0363a3..43a02e5f1 100644
--- a/generator/p2v_config.mli
+++ b/generator/p2v_config.mli
@@ -18,3 +18,5 @@
val generate_p2v_config_h : unit -> unit
val generate_p2v_config_c : unit -> unit
+val generate_p2v_kernel_config_c : unit -> unit
+val generate_p2v_kernel_config_pod : unit -> unit
diff --git a/p2v/Makefile.am b/p2v/Makefile.am
index f66c2a09b..cfdec535d 100644
--- a/p2v/Makefile.am
+++ b/p2v/Makefile.am
@@ -20,7 +20,9 @@ include $(top_srcdir)/subdir-rules.mk
generator_built = \
about-authors.c \
config.c \
- p2v-config.h
+ kernel-config.c \
+ p2v-config.h \
+ virt-p2v-kernel-config.pod
BUILT_SOURCES = \
$(generator_built)
@@ -89,6 +91,7 @@ virt_p2v_SOURCES = \
inhibit.c \
kernel.c \
kernel-cmdline.c \
+ kernel-config.c \
main.c \
nbd.c \
p2v.h \
@@ -165,10 +168,11 @@ noinst_DATA = \
virt-p2v.1 $(top_builddir)/website/virt-p2v.1.html: stamp-virt-p2v.pod
-stamp-virt-p2v.pod: virt-p2v.pod
+stamp-virt-p2v.pod: virt-p2v.pod virt-p2v-kernel-config.pod
$(PODWRAPPER) \
--man virt-p2v.1 \
--html $(top_builddir)/website/virt-p2v.1.html \
+ --insert $(srcdir)/virt-p2v-kernel-config.pod:__KERNEL_CONFIG__ \
--license GPLv2+ \
--warning safe \
$<
diff --git a/p2v/kernel.c b/p2v/kernel.c
index 4f999755e..33fff0356 100644
--- a/p2v/kernel.c
+++ b/p2v/kernel.c
@@ -42,160 +42,6 @@
static void notify_ui_callback (int type, const char *data);
static void run_command (const char *stage, const char *command);
-void
-update_config_from_kernel_cmdline (struct config *config, char **cmdline)
-{
- const char *p;
-
- p = get_cmdline_key (cmdline, "p2v.server");
- if (p) {
- free (config->remote.server);
- config->remote.server = strdup (p);
- }
-
- p = get_cmdline_key (cmdline, "p2v.port");
- if (p) {
- if (sscanf (p, "%d", &config->remote.port) != 1)
- error (EXIT_FAILURE, 0,
- "cannot parse p2v.port from kernel command line");
- }
-
- p = get_cmdline_key (cmdline, "p2v.username");
- if (p) {
- free (config->auth.username);
- config->auth.username = strdup (p);
- }
-
- p = get_cmdline_key (cmdline, "p2v.password");
- if (p) {
- free (config->auth.password);
- config->auth.password = strdup (p);
- }
-
- p = get_cmdline_key (cmdline, "p2v.identity");
- if (p) {
- free (config->auth.identity.url);
- config->auth.identity.url = strdup (p);
- config->auth.identity.file_needs_update = 1;
- }
-
- p = get_cmdline_key (cmdline, "p2v.sudo");
- if (p)
- config->auth.sudo = 1;
-
- p = get_cmdline_key (cmdline, "p2v.name");
- if (p) {
- free (config->guestname);
- config->guestname = strdup (p);
- }
-
- p = get_cmdline_key (cmdline, "p2v.vcpus");
- if (p) {
- if (sscanf (p, "%d", &config->vcpus) != 1)
- error (EXIT_FAILURE, 0,
- "cannot parse p2v.vcpus from kernel command line");
- }
-
- p = get_cmdline_key (cmdline, "p2v.memory");
- if (p) {
- char mem_code;
-
- if (sscanf (p, "%" SCNu64 "%c", &config->memory,
&mem_code) != 2)
- error (EXIT_FAILURE, 0,
- "cannot parse p2v.memory from kernel command line");
- config->memory *= 1024;
- if (mem_code == 'M' || mem_code == 'm'
- || mem_code == 'G' || mem_code == 'g')
- config->memory *= 1024;
- if (mem_code == 'G' || mem_code == 'g')
- config->memory *= 1024;
- if (mem_code != 'M' && mem_code != 'm'
- && mem_code != 'G' && mem_code != 'g')
- error (EXIT_FAILURE, 0,
- "p2v.memory on kernel command line must be followed by 'G' or
'M'");
- }
-
- p = get_cmdline_key (cmdline, "p2v.disks");
- if (p) {
- CLEANUP_FREE char *t;
-
- t = strdup (p);
- guestfs_int_free_string_list (config->disks);
- config->disks = guestfs_int_split_string (',', t);
- }
-
- p = get_cmdline_key (cmdline, "p2v.removable");
- if (p) {
- CLEANUP_FREE char *t;
-
- t = strdup (p);
- guestfs_int_free_string_list (config->removable);
- config->removable = guestfs_int_split_string (',', t);
- }
-
- p = get_cmdline_key (cmdline, "p2v.interfaces");
- if (p) {
- CLEANUP_FREE char *t;
-
- t = strdup (p);
- guestfs_int_free_string_list (config->interfaces);
- config->interfaces = guestfs_int_split_string (',', t);
- }
-
- p = get_cmdline_key (cmdline, "p2v.network");
- if (p) {
- CLEANUP_FREE char *t;
-
- t = strdup (p);
- guestfs_int_free_string_list (config->network_map);
- config->network_map = guestfs_int_split_string (',', t);
- }
-
- p = get_cmdline_key (cmdline, "p2v.o");
- if (p) {
- free (config->output.type);
- config->output.type = strdup (p);
- }
-
- p = get_cmdline_key (cmdline, "p2v.oa");
- if (p) {
- if (STREQ (p, "sparse"))
- config->output.allocation = OUTPUT_ALLOCATION_SPARSE;
- else if (STREQ (p, "preallocated"))
- config->output.allocation = OUTPUT_ALLOCATION_PREALLOCATED;
- else
- fprintf (stderr, "%s: warning: don't know what p2v.oa=%s means\n",
- getprogname (), p);
- }
-
- p = get_cmdline_key (cmdline, "p2v.oc");
- if (p) {
- free (config->output.connection);
- config->output.connection = strdup (p);
- }
-
- p = get_cmdline_key (cmdline, "p2v.of");
- if (p) {
- free (config->output.format);
- config->output.format = strdup (p);
- }
-
- p = get_cmdline_key (cmdline, "p2v.os");
- if (p) {
- free (config->output.storage);
- config->output.storage = strdup (p);
- }
-
- /* Undocumented command line parameter used for testing command line
- * parsing.
- */
- p = get_cmdline_key (cmdline, "p2v.dump_config_and_exit");
- if (p) {
- print_config (config, stdout);
- exit (EXIT_SUCCESS);
- }
-}
-
/* Perform conversion using the kernel method. */
void
kernel_conversion (struct config *config, char **cmdline, int cmdline_source)
diff --git a/p2v/p2v.h b/p2v/p2v.h
index 021ea2946..ee661514c 100644
--- a/p2v/p2v.h
+++ b/p2v/p2v.h
@@ -74,8 +74,10 @@ extern const char *get_cmdline_key (char **cmdline, const char *key);
#define CMDLINE_SOURCE_COMMAND_LINE 1 /* --cmdline */
#define CMDLINE_SOURCE_PROC_CMDLINE 2 /* /proc/cmdline */
-/* kernel.c */
+/* kernel-config.c */
extern void update_config_from_kernel_cmdline (struct config *config, char **cmdline);
+
+/* kernel.c */
extern void kernel_conversion (struct config *, char **cmdline, int cmdline_source);
/* gui.c */
diff --git a/p2v/virt-p2v.pod b/p2v/virt-p2v.pod
index fc2e7d310..48548f8c6 100644
--- a/p2v/virt-p2v.pod
+++ b/p2v/virt-p2v.pod
@@ -302,136 +302,7 @@ You have to set some or all of the following command line
arguments:
=over 4
-=item B<p2v.server=SERVER>
-
-The name or IP address of the conversion server.
-
-This is always required if you are using the kernel configuration
-method. If virt-p2v does not find this on the kernel command line
-then it switches to the GUI (interactive) configuration method.
-
-=item B<p2v.port=NN>
-
-The SSH port number on the conversion server (default: C<22>).
-
-=item B<p2v.username=USERNAME>
-
-The SSH username that we log in as on the conversion server
-(default: C<root>).
-
-=item B<p2v.password=PASSWORD>
-
-The SSH password that we use to log in to the conversion server.
-
-The default is to try with no password. If this fails then virt-p2v
-will ask the user to type the password (probably several times during
-conversion).
-
-This setting is ignored if C<p2v.identity> is present.
-
-=item B<p2v.identity=URL>
-
-Provide a URL pointing to an SSH identity (private key) file. The URL
-is interpreted by L<curl(1)> so any URL that curl supports can be used
-here, including C<https://> and C<file://>. For more information on
-using SSH identities, see L</SSH IDENTITIES> below.
-
-If C<p2v.identity> is present, it overrides C<p2v.password>. There is
-no fallback.
-
-=item B<p2v.sudo>
-
-Use C<p2v.sudo> to tell virt-p2v to use L<sudo(8)> to gain root
-privileges on the conversion server after logging in as a non-root
-user (default: do not use sudo).
-
-=item B<p2v.name=GUESTNAME>
-
-The name of the guest that is created. The default is to try to
-derive a name from the physical machine’s hostname (if possible) else
-use a randomly generated name.
-
-=item B<p2v.vcpus=NN>
-
-The number of virtual CPUs to give to the guest. The default is to
-use the same as the number of physical CPUs.
-
-=item B<p2v.memory=NN(M|G)>
-
-The size of the guest memory. You must specify the unit as either
-megabytes or gigabytes by using (eg) C<p2v.memory=1024M> or
-C<p2v.memory=1G>.
-
-The default is to use the same amount of RAM as on the physical
-machine.
-
-=item B<p2v.disks=sdX,sdY,..>
-
-A list of physical hard disks to convert, for example:
-
- p2v.disks=sda,sdc
-
-The default is to convert all local hard disks that are found.
-
-=item B<p2v.removable=srX,srY,..>
-
-A list of removable media to convert. The default is to create
-virtual removable devices for every physical removable device found.
-Note that the content of removable media is never copied over.
-
-=item B<p2v.interfaces=em1,..>
-
-A list of network interfaces to convert. The default is to create
-virtual network interfaces for every physical network interface found.
-
-=item B<p2v.network=interface:target,...>
-
-Controls how network interfaces are connected to virtual networks on
-the target hypervisor. The default is to connect all network
-interfaces to the target C<default> network.
-
-You give a comma-separated list of C<interface:target> pairs, plus
-optionally a default target. For example:
-
- p2v.network=em1:ovirtmgmt
-
-maps interface C<em1> to target network C<ovirtmgmt>.
-
- p2v.network=em1:ovirtmgmt,em2:management,other
-
-maps interface C<em1> to C<ovirtmgmt>, and C<em2> to
C<management>,
-and any other interface that is found to C<other>.
-
-=item B<p2v.o=[libvirt|local|...]>
-
-Set the output mode. This is the same as the virt-v2v I<-o> option.
-See L<virt-v2v(1)/OPTIONS>.
-
-If not specified, the default is C<local>, and the converted guest is
-written to F</var/tmp>.
-
-=item B<p2v.oa=sparse|preallocated>
-
-Set the output allocation mode. This is the same as the virt-v2v
-I<-oa> option. See L<virt-v2v(1)/OPTIONS>.
-
-=item B<p2v.oc=...>
-
-Set the output connection libvirt URI. This is the same as the
-virt-v2v I<-oc> option. See L<virt-v2v(1)/OPTIONS> and
-L<http://libvirt.org/uri.html>
-
-=item B<p2v.of=raw|qcow2|...>
-
-Set the output format. This is the same as the virt-v2v I<-of>
-option. See L<virt-v2v(1)/OPTIONS>.
-
-=item B<p2v.os=...>
-
-Set the output storage. This is the same as the virt-v2v I<-os>
-option. See L<virt-v2v(1)/OPTIONS>.
-
-If not specified, the default is F</var/tmp> (on the conversion server).
+__KERNEL_CONFIG__
=item B<p2v.pre=COMMAND>
diff --git a/po-docs/language.mk b/po-docs/language.mk
index 3eeb058e0..0163edab3 100644
--- a/po-docs/language.mk
+++ b/po-docs/language.mk
@@ -148,6 +148,14 @@ virt-sysprep.1: virt-sysprep.pod sysprep-extra-options.pod
sysprep-operations.po
--insert $(srcdir)/sysprep-operations.pod:__OPERATIONS__ \
$<
+virt-p2v.1: virt-p2v.pod virt-p2v-kernel-config.pod
+ $(PODWRAPPER) \
+ --no-strict-checks \
+ --man $@ \
+ --license GPLv2+ \
+ --insert $(srcdir)/virt-p2v-kernel-config.pod:__KERNEL_CONFIG__ \
+ $<
+
%.1: %.pod
$(PODWRAPPER) \
--no-strict-checks \
diff --git a/po-docs/podfiles b/po-docs/podfiles
index 31a3aca3a..b6bd39b68 100644
--- a/po-docs/podfiles
+++ b/po-docs/podfiles
@@ -53,6 +53,7 @@
../lua/examples/guestfs-lua.pod
../make-fs/virt-make-fs.pod
../ocaml/examples/guestfs-ocaml.pod
+../p2v/virt-p2v-kernel-config.pod
../p2v/virt-p2v-make-disk.pod
../p2v/virt-p2v-make-kickstart.pod
../p2v/virt-p2v-make-kiwi.pod
--
2.17.1