[Libguestfs] [PATCH] UNTESTED v2v: openstack: Read server-id from metadata service.

Richard W.M. Jones
Wed, 03 Apr 2019 12:14:37 -0000

Unless specified on the command line, read the server-id from the
OpenStack Metadata service.
---
 v2v/output_openstack.ml           | 45 +++++++++++++++++++++----------
 v2v/virt-v2v-output-openstack.pod | 13 +++++----
 v2v/virt-v2v.pod                  |  3 +++
 3 files changed, 42 insertions(+), 19 deletions(-)

diff --git a/v2v/output_openstack.ml b/v2v/output_openstack.ml
index d187f1d5d..b2cb45208 100644
--- a/v2v/output_openstack.ml
+++ b/v2v/output_openstack.ml
@@ -40,14 +40,16 @@ let available_timeout = 300 (* seconds *)
 (* Timeout waiting for Cinder volumes to attach to the appliance. *)
 let attach_timeout = 60 (* seconds *)

+(* Metadata service URL. *)
+let meta_uri =
"http://169.254.169.254/openstack/latest/meta_data.json"
+
 (* The -oo options supported by this output method. *)
 type os_options = {
   (* The server name or UUID of the conversion appliance where
-   * virt-v2v is currently running.  In future we may be able
-   * to make this optional and derive it from the OpenStack
-   * metadata service instead.
+   * virt-v2v is currently running.  If None, we try to fetch it
+   * from the OpenStack Metadata Service.
    *)
-  server_id : string;
+  server_id : string option;

   (* All other OpenStack parameters, passed through unmodified
    * on the openstack command line.
@@ -70,7 +72,7 @@ type os_options = {
 }

 let print_output_options () -  printf (f_"virt-v2v -oo
server-id=<NAME|UUID> [os-*=...]
+  printf (f_"virt-v2v [-oo server-id=<NAME|UUID>] [-oo os-*=...]

 Specify the name or UUID of the conversion appliance using

@@ -128,11 +130,7 @@ let parse_output_options options      | k, _ ->
        error (f_"-o openstack: unknown output option ‘-oo %s’") k
   ) options;
-  let server_id -    match !server_id with
-    | None ->
-       error (f_"openstack: -oo server-id=<NAME|UUID> not
present");
-    | Some server_id -> server_id in
+  let server_id = !server_id in
   let authentication = List.rev !authentication in
   let verify_server_certificate = !verify_server_certificate in
   let guest_id = !guest_id in
@@ -160,6 +158,27 @@ class output_openstack output_conn output_password
output_storage
       List.push_back args "--insecure";
     !args in

+  (* The server ID (the name or UUID of the conversion appliance) can
+   * be supplied on the command line.  If not we get it from the
+   * Metadata Service.  Lazy so we don't evaluate this until we use
+   * it the first time.
+   *)
+  let server_id = lazy (
+    match os_options.server_id with
+    | Some server_id -> server_id
+    | None ->
+       (* This will make Curl fetch the URL to stdout, and fail if
+        * there is a server error.  The failure will cause virt-v2v to
+        * exit with an error.
+        *)
+       let curl_args = ["url", Some meta_uri; "fail", None]
in
+       let curl = Curl.create ~proxy:Curl.UnsetProxy curl_args in
+       let json = Curl.run curl in
+       let json = String.concat "\n" json in
+       let json = json_parser_tree_parse json in
+       object_get_string "uuid" json
+  ) in
+
   let error_unless_openstack_command_exists ()      try ignore (which
openstack_binary)
     with Executable_not_found _ ->
@@ -313,8 +332,7 @@ class output_openstack output_conn output_password
output_storage
    * Returns the block device name.
    *)
   let attach_volume id -    let args = [ "server"; "add";
"volume";
-                 os_options.server_id; id ] in
+    let args = [ "server"; "add"; "volume";
Lazy.force server_id; id ] in
     if run_openstack_command args <> 0 then
       error (f_"openstack: failed to attach cinder volume to VM, see
earlier error messages");

@@ -360,8 +378,7 @@ class output_openstack output_conn output_password
output_storage
    * there's nothing we could do with the error anyway.
    *)
   let detach_volume id -    let args = [ "server";
"remove"; "volume";
-                 os_options.server_id; id ] in
+    let args = [ "server"; "remove"; "volume";
Lazy.force server_id; id ] in
     ignore (run_openstack_command args)
   in

diff --git a/v2v/virt-v2v-output-openstack.pod
b/v2v/virt-v2v-output-openstack.pod
index f5f44bded..4cddce61c 100644
--- a/v2v/virt-v2v-output-openstack.pod
+++ b/v2v/virt-v2v-output-openstack.pod
@@ -5,7 +5,7 @@ virt-v2v-output-openstack - Using virt-v2v to convert guests to
OpenStack
 =head1 SYNOPSIS

  virt-v2v [-i* options] -o openstack
-                        -oo server-id=SERVER
+                        [-oo server-id=SERVER]
                         [-oo guest-id=GUEST]
                         [-oo verify-server-certificate=false]
                         [-oo os-username=admin] [-oo os-*=*]
@@ -20,7 +20,7 @@ I<-o openstack> should be used normally.

 =over 4

-=item B<-o openstack> B<-oo server-id=>SERVER [...]
+=item B<-o openstack>

Full description: L

@@ -57,7 +57,7 @@ Cinder volumes to an OpenStack virtual machine.
 The C<openstack> command must be installed in the appliance.  We use
 it for communicating with OpenStack.

-When virt-v2v is running in the conversion appliance, you must supply
+When virt-v2v is running in the conversion appliance, you may supply
 the name or UUID of the conversion appliance to virt-v2v, eg:

  $ openstack server list
@@ -74,6 +74,9 @@ or:

  # virt-v2v [...] -o openstack -oo server-id=test1

+If the I<-oo server-id> is not supplied then virt-v2v will try to
+get the server ID from the OpenStack Metadata Service.
+
 You can run many parallel conversions inside a single conversion
 appliance if you want, subject to having enough resources available.
 However OpenStack itself imposes a limit that you should be aware of:
@@ -137,12 +140,12 @@ I<--insecure> option to the C<openstack>
command.
 The final command to convert the guest, running as root, will be:

  # virt-v2v [-i options ...] \
-       -o openstack -oo server-id=NAME|UUID [-oo guest-id=ID]
+       -o openstack [-oo server-id=NAME|UUID] [-oo guest-id=ID]

 If you include authentication options on the command line then:

  # virt-v2v [-i options ...] \
-       -o openstack -oo server-id=NAME|UUID -oo os-username=admin [etc]
+       -o openstack [-oo server-id=NAME|UUID] -oo os-username=admin [etc]

 =head2 OpenStack: Booting the guest

diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod
index 9a555c3be..ce3d2ced8 100644
--- a/v2v/virt-v2v.pod
+++ b/v2v/virt-v2v.pod
@@ -611,6 +611,9 @@ Certificate Authority.
 For I<-o openstack> (L<virt-v2v-output-openstack(1)>) only, set the
name
 of the conversion appliance where virt-v2v is running.

+If not set then virt-v2v will try to get the server ID from the
+OpenStack Metadata Service (which must be available).
+
 =item B<-oo vdsm-compat=0.10>

 =item B<-oo vdsm-compat=1.1>
--
2.20.1