Add simple operations for RHEL guests using subscription-manager, so it
is possible to e.g. install software on them.
---
customize/Makefile.am | 8 +++-
customize/customize_run.ml | 58 ++++++++++++++++++++++++++
generator/customize.ml | 101 +++++++++++++++++++++++++++++++++++++++++++++
sysprep/Makefile.am | 8 +++-
4 files changed, 173 insertions(+), 2 deletions(-)
diff --git a/customize/Makefile.am b/customize/Makefile.am
index 8f0a2d8..d664ba4 100644
--- a/customize/Makefile.am
+++ b/customize/Makefile.am
@@ -67,6 +67,10 @@ SOURCES_C = \
$(top_srcdir)/fish/file-edit.c \
$(top_srcdir)/fish/file-edit.h \
$(top_srcdir)/mllib/uri-c.c \
+ $(top_srcdir)/mllib/index-parse.c \
+ $(top_srcdir)/mllib/index-scan.c \
+ $(top_srcdir)/mllib/index-struct.c \
+ $(top_srcdir)/mllib/index-parser-c.c \
crypt-c.c \
perl_edit-c.c
@@ -85,7 +89,8 @@ virt_customize_CPPFLAGS = \
virt_customize_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
$(LIBVIRT_CFLAGS) \
- $(LIBXML2_CFLAGS)
+ $(LIBXML2_CFLAGS) \
+ -Wno-unused-macros
BOBJECTS = \
$(top_builddir)/mllib/config.cmo \
@@ -93,6 +98,7 @@ BOBJECTS = \
$(top_builddir)/mllib/common_utils.cmo \
$(top_builddir)/mllib/regedit.cmo \
$(top_builddir)/mllib/uRI.cmo \
+ $(top_builddir)/mllib/ini_reader.cmo \
$(SOURCES_ML:.ml=.cmo)
XOBJECTS = $(BOBJECTS:.cmo=.cmx)
diff --git a/customize/customize_run.ml b/customize/customize_run.ml
index d9547a0..9fb2b14 100644
--- a/customize/customize_run.ml
+++ b/customize/customize_run.ml
@@ -153,6 +153,33 @@ exec >>%s 2>&1
Hashtbl.replace passwords user pw
in
+ (* Parse the subscription-manager configuration. *)
+ let sm_config =
+ match ops.flags.sm_config with
+ | None -> None
+ | Some c ->
+ try
+ Some (Ini_reader.read_ini ~check_duplicated_sections:true
+ ~check_duplicated_fields:true c)
+ with exn ->
+ error (f_"cannot parse the subscription-manager configuration: %s")
+ (Printexc.to_string exn)
+ in
+ let sm_config_get_value group key =
+ let conf =
+ match sm_config with
+ | None ->
+ error (f_"subscription-manager configuration required for this
operation")
+ | Some c -> c in
+ try Ini_reader.ini_get_value conf group key
+ with
+ | Ini_reader.Section_not_found s ->
+ error (f_"subscription-manager configuration lacks the group
'%s'") s
+ | Ini_reader.Key_not_found (s, k, _) ->
+ error (f_"subscription-manager configuration lacks the key '%s' in
group '%s'")
+ k s
+ in
+
(* Perform the remaining customizations in command-line order. *)
List.iter (
function
@@ -249,6 +276,37 @@ exec >>%s 2>&1
message (f_"Scrubbing: %s") path;
g#scrub_file path
+ | `SMAttach id ->
+ (match id with
+ | "auto" ->
+ message (f_"Attaching to compatible subscriptions");
+ let cmd = "subscription-manager attach --auto" in
+ do_run ~display:cmd cmd
+ | id ->
+ let pool_id = sm_config_get_value ("attach-" ^ id) "pool" in
+ message (f_"Attaching to the pool %s") pool_id;
+ let cmd = sprintf "subscription-manager attach --pool=%s" pool_id in
+ do_run ~display:cmd cmd
+ )
+
+ | `SMRegister ->
+ message (f_"Registering with subscription-manager");
+ let username = sm_config_get_value "general" "username" in
+ let password = sm_config_get_value "general" "password" in
+ let cmd = sprintf "subscription-manager register --username='%s'
--password='%s'"
+ username password in
+ do_run ~display:"subscription-manager register" cmd
+
+ | `SMRemove ->
+ message (f_"Removing all the subscriptions");
+ let cmd = "subscription-manager remove --all" in
+ do_run ~display:cmd cmd
+
+ | `SMUnregister ->
+ message (f_"Unregistering with subscription-manager");
+ let cmd = "subscription-manager unregister" in
+ do_run ~display:cmd cmd
+
| `SSHInject (user, selector) ->
(match g#inspect_get_type root with
| "linux" | "freebsd" | "netbsd" |
"openbsd" | "hurd" ->
diff --git a/generator/customize.ml b/generator/customize.ml
index f57aba6..bb31c25 100644
--- a/generator/customize.ml
+++ b/generator/customize.ml
@@ -327,6 +327,64 @@ It cannot delete directories, only regular files.
=back";
};
+ { op_name = "sm-attach";
+ op_type = String "ID";
+ op_discrim = "`SMAttach";
+ op_shortdesc = "Attach to a subscription-manager pool";
+ op_pod_longdesc = "\
+Attach to a pool using C<subscription-manager>. C<ID> can be any of
+the following:
+
+=over 4
+
+=item C<auto>
+
+subscription-manager attaches to the best-fitting subscriptions for
+the system.
+
+=item C<ID>
+
+This requires a configuration file specified with the settings
+(see also I<--sm-config>), containing the following:
+
+ [attach-ID]
+ pool=0123...
+
+That is, a group named after the specified C<ID>, containing a C<pool>
+key with the actual pool ID.
+
+=back";
+ };
+
+ { op_name = "sm-register";
+ op_type = Unit;
+ op_discrim = "`SMRegister";
+ op_shortdesc = "Register using subscription-manager";
+ op_pod_longdesc = "\
+Register the guest using C<subscription-manager>.
+
+This requires a configuration file specified with the settings
+(see also I<--sm-config>), with the C<username> and C<password>
+keys in the C<general> group.";
+ };
+
+ { op_name = "sm-remove";
+ op_type = Unit;
+ op_discrim = "`SMRemove";
+ op_shortdesc = "Remove all the subscriptions";
+ op_pod_longdesc = "\
+Remove all the subscriptions from the guest using
+C<subscription-manager>.";
+ };
+
+ { op_name = "sm-unregister";
+ op_type = Unit;
+ op_discrim = "`SMUnregister";
+ op_shortdesc = "Unregister using subscription-manager";
+ op_pod_longdesc = "\
+Unregister the guest using C<subscription-manager>.";
+ };
+
{ op_name = "ssh-inject";
op_type = SSHKeySelector "USER[:SELECTOR]";
op_discrim = "`SSHInject";
@@ -428,6 +486,7 @@ type flag = {
and flag_type =
| FlagBool of bool (* boolean is the default value *)
| FlagPasswordCrypto of string
+| FlagSMConfig of string
let flags = [
{ flag_name = "no-logfile";
@@ -477,6 +536,25 @@ Relabel files in the guest so that they have the correct SELinux
label.
You should only use this option for guests which support SELinux.";
};
+
+ { flag_name = "sm-config";
+ flag_type = FlagSMConfig "config";
+ flag_ml_var = "sm_config";
+ flag_shortdesc = "configuration for subscription-manager";
+ flag_pod_longdesc = "\
+Defines a configuration for subscription-manager operations.
+This file has a simple text like the following:
+
+ [general]
+ username=user
+ password=secret
+
+ [attach-0]
+ pool=0123...
+
+Different subscription-manager commands may require different sections.";
+ };
+
]
let rec generate_customize_cmdline_mli () =
@@ -532,6 +610,8 @@ let rec argspec () =
pr " let %s = ref %b in\n" var default
| { flag_type = FlagPasswordCrypto _; flag_ml_var = var } ->
pr " let %s = ref None in\n" var
+ | { flag_type = FlagSMConfig _; flag_ml_var = var } ->
+ pr " let %s = ref None in\n" var
) flags;
pr "\
@@ -699,6 +779,18 @@ let rec argspec () =
pr " \"%s\" ^ \" \" ^ s_\"%s\"\n" v
shortdesc;
pr " ),\n";
pr " Some %S, %S;\n" v longdesc
+ | { flag_type = FlagSMConfig v; flag_ml_var = var;
+ flag_name = name; flag_shortdesc = shortdesc;
+ flag_pod_longdesc = longdesc } ->
+ pr " (\n";
+ pr " \"--%s\",\n" name;
+ pr " Arg.String (\n";
+ pr " fun s ->\n";
+ pr " %s := Some s\n" var;
+ pr " ),\n";
+ pr " \"%s\" ^ \" \" ^ s_\"%s\"\n" v
shortdesc;
+ pr " ),\n";
+ pr " Some %S, %S;\n" v longdesc
) flags;
pr " ]
@@ -809,6 +901,10 @@ type ops = {
flag_name = name } ->
pr " %s : Password.password_crypto option;\n (* --%s %s *)\n"
var name v
+ | { flag_type = FlagSMConfig v; flag_ml_var = var;
+ flag_name = name } ->
+ pr " %s : string option;\n (* --%s %s *)\n"
+ var name v
) flags;
pr "}\n"
@@ -832,6 +928,8 @@ let generate_customize_synopsis_pod () =
n, sprintf "[--%s]" n
| { flag_type = FlagPasswordCrypto v; flag_name = n } ->
n, sprintf "[--%s %s]" n v
+ | { flag_type = FlagSMConfig v; flag_name = n } ->
+ n, sprintf "[--%s %s]" n v
) flags in
(* Print the option names in the synopsis, line-wrapped. *)
@@ -874,6 +972,9 @@ let generate_customize_options_pod () =
| { flag_type = FlagPasswordCrypto v;
flag_name = n; flag_pod_longdesc = ld } ->
n, sprintf "B<--%s> %s" n v, ld
+ | { flag_type = FlagSMConfig v;
+ flag_name = n; flag_pod_longdesc = ld } ->
+ n, sprintf "B<--%s> %s" n v, ld
) flags in
let cmp (arg1, _, _) (arg2, _, _) =
compare (String.lowercase arg1) (String.lowercase arg2)
diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am
index c1d1245..e7977bd 100644
--- a/sysprep/Makefile.am
+++ b/sysprep/Makefile.am
@@ -81,6 +81,10 @@ SOURCES_ML = \
SOURCES_C = \
$(top_srcdir)/mllib/uri-c.c \
$(top_srcdir)/mllib/mkdtemp-c.c \
+ $(top_srcdir)/mllib/index-parse.c \
+ $(top_srcdir)/mllib/index-scan.c \
+ $(top_srcdir)/mllib/index-struct.c \
+ $(top_srcdir)/mllib/index-parser-c.c \
$(top_srcdir)/customize/crypt-c.c \
$(top_srcdir)/customize/perl_edit-c.c \
$(top_srcdir)/fish/uri.c \
@@ -100,7 +104,8 @@ virt_sysprep_CPPFLAGS = \
-I$(top_srcdir)/fish
virt_sysprep_CFLAGS = \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
- $(LIBXML2_CFLAGS)
+ $(LIBXML2_CFLAGS) \
+ -Wno-unused-macros
BOBJECTS = \
$(top_builddir)/mllib/config.cmo \
@@ -109,6 +114,7 @@ BOBJECTS = \
$(top_builddir)/mllib/uRI.cmo \
$(top_builddir)/mllib/mkdtemp.cmo \
$(top_builddir)/mllib/regedit.cmo \
+ $(top_builddir)/mllib/ini_reader.cmo \
$(top_builddir)/customize/customize_utils.cmo \
$(top_builddir)/customize/crypt.cmo \
$(top_builddir)/customize/urandom.cmo \
--
2.1.0