Having a dedicated Cfg2Cmd class allows having a cleaner interface by
only calling into pre-defined methods. Important, global information
about the VM like machine type or OS version will be recorded by the
object and can be queried via methods. For now, there is only
windows_version(). There will be sub-classes, each concerning a
dedicated part of the configuration. The first one is for the timer.

Signed-off-by: Fiona Ebner <[email protected]>
---

Changes in v2:
* Actually commit new Makefile in Cfg2Cmd directory.
* Rename $self -> $cfg2cmd in Timer.pm submodule to avoid potential
  confusion.

 src/PVE/QemuServer.pm               | 32 +++-------
 src/PVE/QemuServer/Cfg2Cmd.pm       | 91 +++++++++++++++++++++++++++++
 src/PVE/QemuServer/Cfg2Cmd/Makefile |  9 +++
 src/PVE/QemuServer/Cfg2Cmd/Timer.pm | 37 ++++++++++++
 src/PVE/QemuServer/Makefile         |  2 +
 5 files changed, 146 insertions(+), 25 deletions(-)
 create mode 100644 src/PVE/QemuServer/Cfg2Cmd.pm
 create mode 100644 src/PVE/QemuServer/Cfg2Cmd/Makefile
 create mode 100644 src/PVE/QemuServer/Cfg2Cmd/Timer.pm

diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
index 7d5ab718..cb7755b6 100644
--- a/src/PVE/QemuServer.pm
+++ b/src/PVE/QemuServer.pm
@@ -56,6 +56,7 @@ use PVE::QemuMigrate::Helpers;
 use PVE::QemuServer::Agent qw(qga_check_running);
 use PVE::QemuServer::Blockdev;
 use PVE::QemuServer::BlockJob;
+use PVE::QemuServer::Cfg2Cmd;
 use PVE::QemuServer::Helpers
     qw(config_aware_timeout get_iscsi_initiator_name min_version 
kvm_user_version windows_version);
 use PVE::QemuServer::Cloudinit;
@@ -3569,31 +3570,12 @@ sub config_to_command {
         push @$cmd, '-nographic';
     }
 
-    # time drift fix
-    my $tdf = defined($conf->{tdf}) ? $conf->{tdf} : $defaults->{tdf};
-    my $useLocaltime = $conf->{localtime};
-
-    if ($winversion >= 5) { # windows
-        $useLocaltime = 1 if !defined($conf->{localtime});
-
-        # use time drift fix when acpi is enabled
-        if (!(defined($conf->{acpi}) && $conf->{acpi} == 0)) {
-            $tdf = 1 if !defined($conf->{tdf});
-        }
-    }
-
-    if ($winversion >= 6) {
-        push $cmd->@*, '-global', 'kvm-pit.lost_tick_policy=discard';
-        push @$machineFlags, 'hpet=off';
-    }
-
-    push @$rtcFlags, 'driftfix=slew' if $tdf;
-
-    if ($conf->{startdate} && $conf->{startdate} ne 'now') {
-        push @$rtcFlags, "base=$conf->{startdate}";
-    } elsif ($useLocaltime) {
-        push @$rtcFlags, 'base=localtime';
-    }
+    # For now, handles only specific parts, but the final goal is to cover 
everything.
+    my $cfg2cmd = PVE::QemuServer::Cfg2Cmd->new($conf, $defaults);
+    my $generated = $cfg2cmd->generate();
+    push $cmd->@*, '-global', $_ for ($generated->global_flags() // [])->@*;
+    push $machineFlags->@*, ($generated->machine_flags() // [])->@*;
+    push $rtcFlags->@*, ($generated->rtc_flags() // [])->@*;
 
     if ($forcecpu) {
         push @$cmd, '-cpu', $forcecpu;
diff --git a/src/PVE/QemuServer/Cfg2Cmd.pm b/src/PVE/QemuServer/Cfg2Cmd.pm
new file mode 100644
index 00000000..6b26ab23
--- /dev/null
+++ b/src/PVE/QemuServer/Cfg2Cmd.pm
@@ -0,0 +1,91 @@
+package PVE::QemuServer::Cfg2Cmd;
+
+use warnings;
+use strict;
+
+use PVE::QemuServer::Cfg2Cmd::Timer;
+use PVE::QemuServer::Helpers;
+
+sub new {
+    my ($class, $conf, $defaults) = @_;
+
+    my $self = bless {
+        conf => $conf,
+        defaults => $defaults,
+    }, $class;
+
+    my $ostype = $self->get_prop('ostype');
+    $self->{'windows-version'} = 
PVE::QemuServer::Helpers::windows_version($ostype);
+
+    return $self;
+}
+
+=head3 get_prop
+
+    my $value = $self->get_prop($prop);
+
+Return the configured value for the property C<$prop>. If no fallback to the 
default value should be
+made, use C<$only_explicit>. Note that any such usage is likely an indication 
that the default value
+is not actually a static default, but that the default depends on context.
+
+=cut
+
+sub get_prop {
+    my ($self, $prop, $only_explicit) = @_;
+
+    my ($conf, $defaults) = $self->@{qw(conf defaults)};
+    return $conf->{$prop} if $only_explicit;
+    return defined($conf->{$prop}) ? $conf->{$prop} : $defaults->{$prop};
+}
+
+sub add_global_flag {
+    my ($self, $flag) = @_;
+
+    push $self->{'global-flags'}->@*, $flag;
+}
+
+sub global_flags {
+    my ($self) = @_;
+
+    return $self->{'global-flags'};
+}
+
+sub add_machine_flag {
+    my ($self, $flag) = @_;
+
+    push $self->{'machine-flags'}->@*, $flag;
+}
+
+sub machine_flags {
+    my ($self) = @_;
+
+    return $self->{'machine-flags'};
+}
+
+sub add_rtc_flag {
+    my ($self, $flag) = @_;
+
+    push $self->{'rtc-flags'}->@*, $flag;
+}
+
+sub rtc_flags {
+    my ($self) = @_;
+
+    return $self->{'rtc-flags'};
+}
+
+sub windows_version {
+    my ($self) = @_;
+
+    return $self->{'windows-version'};
+}
+
+sub generate {
+    my ($self) = @_;
+
+    PVE::QemuServer::Cfg2Cmd::Timer::generate($self);
+
+    return $self;
+}
+
+1;
diff --git a/src/PVE/QemuServer/Cfg2Cmd/Makefile 
b/src/PVE/QemuServer/Cfg2Cmd/Makefile
new file mode 100644
index 00000000..1c0ea0b2
--- /dev/null
+++ b/src/PVE/QemuServer/Cfg2Cmd/Makefile
@@ -0,0 +1,9 @@
+DESTDIR=
+PREFIX=/usr
+PERLDIR=$(PREFIX)/share/perl5
+
+SOURCES=Timer.pm
+
+.PHONY: install
+install: $(SOURCES)
+       for i in $(SOURCES); do install -D -m 0644 $$i 
$(DESTDIR)$(PERLDIR)/PVE/QemuServer/Cfg2Cmd/$$i; done
diff --git a/src/PVE/QemuServer/Cfg2Cmd/Timer.pm 
b/src/PVE/QemuServer/Cfg2Cmd/Timer.pm
new file mode 100644
index 00000000..d4b16af0
--- /dev/null
+++ b/src/PVE/QemuServer/Cfg2Cmd/Timer.pm
@@ -0,0 +1,37 @@
+package PVE::QemuServer::Cfg2Cmd::Timer;
+
+use warnings;
+use strict;
+
+sub generate {
+    my ($cfg2cmd) = @_;
+
+    my $time_drift_fix = $cfg2cmd->get_prop('tdf', 1);
+    my $acpi = $cfg2cmd->get_prop('acpi');
+    my $localtime = $cfg2cmd->get_prop('localtime', 1);
+    my $startdate = $cfg2cmd->get_prop('startdate');
+
+    if ($cfg2cmd->windows_version() >= 5) { # windows
+        $localtime = 1 if !defined($localtime);
+
+        # use time drift fix when acpi is enabled, but prefer explicitly set 
value
+        $time_drift_fix = 1 if $acpi && !defined($time_drift_fix);
+    }
+
+    if ($cfg2cmd->windows_version() >= 6) {
+        $cfg2cmd->add_global_flag('kvm-pit.lost_tick_policy=discard');
+        $cfg2cmd->add_machine_flag('hpet=off');
+    }
+
+    $cfg2cmd->add_rtc_flag('driftfix=slew') if $time_drift_fix;
+
+    if ($startdate ne 'now') {
+        $cfg2cmd->add_rtc_flag("base=$startdate");
+    } elsif ($localtime) {
+        $cfg2cmd->add_rtc_flag('base=localtime');
+    }
+
+    return;
+}
+
+1;
diff --git a/src/PVE/QemuServer/Makefile b/src/PVE/QemuServer/Makefile
index 23c136bc..df56cffa 100644
--- a/src/PVE/QemuServer/Makefile
+++ b/src/PVE/QemuServer/Makefile
@@ -5,6 +5,7 @@ PERLDIR=$(PREFIX)/share/perl5
 SOURCES=Agent.pm       \
        Blockdev.pm     \
        BlockJob.pm     \
+       Cfg2Cmd.pm      \
        CGroup.pm       \
        Cloudinit.pm    \
        CPUConfig.pm    \
@@ -30,3 +31,4 @@ SOURCES=Agent.pm      \
 .PHONY: install
 install: $(SOURCES)
        for i in $(SOURCES); do install -D -m 0644 $$i 
$(DESTDIR)$(PERLDIR)/PVE/QemuServer/$$i; done
+       $(MAKE) -C Cfg2Cmd install
-- 
2.47.3



_______________________________________________
pve-devel mailing list
[email protected]
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to