Blob Blame History Raw
From 45732498ed6d77ee783b6713a50190098b1678ac Mon Sep 17 00:00:00 2001
From: Ivan Devat <idevat@redhat.com>
Date: Thu, 7 Feb 2019 11:08:11 +0100
Subject: [PATCH] squash, fix web UI dashboard data loading timeout

load systemctl/chkconfig services list only once

Systemctl/chkconfig services have been retrived repeatedly for each
service (pacemaker, pacemaker_remote, corosync, pcsd, sbd). It had
a performace impact on loading clusters overview.

clean up a check whether services are installed
---
 pcsd/cluster_entity.rb |  3 +-
 pcsd/pcs.rb            | 81 ++++++++++++++++++++++++++++++------------
 pcsd/remote.rb         |  4 ++-
 3 files changed, 64 insertions(+), 24 deletions(-)

diff --git a/pcsd/cluster_entity.rb b/pcsd/cluster_entity.rb
index 79f25450..861dd0c5 100644
--- a/pcsd/cluster_entity.rb
+++ b/pcsd/cluster_entity.rb
@@ -1177,10 +1177,11 @@ module ClusterEntity
 
     def self.load_current_node(crm_dom=nil)
       node = ClusterEntity::Node.new
+      service_checker = get_service_installed_checker()
       node.services.each do |service, info|
         info[:running] = is_service_running?(service.to_s)
         info[:enabled] = is_service_enabled?(service.to_s)
-        info[:installed] = is_service_installed?(service.to_s)
+        info[:installed] = service_checker.is_installed?(service.to_s)
       end
       node.corosync = node.services[:corosync][:running]
       node.corosync_enabled = node.services[:corosync][:enabled]
diff --git a/pcsd/pcs.rb b/pcsd/pcs.rb
index 1f86ae04..7035f4f2 100644
--- a/pcsd/pcs.rb
+++ b/pcsd/pcs.rb
@@ -1728,35 +1728,72 @@ def is_service_running?(service)
   return (retcode == 0)
 end
 
-def is_service_installed?(service)
-  unless ISSYSTEMCTL
-    stdout, _, retcode = run_cmd(PCSAuth.getSuperuserAuth(), 'chkconfig')
-    if retcode != 0
+class ServiceInstalledChecker
+  def initialize()
+    @list_unit_files_output = self.load_unit_files_list()
+  end
+
+  def is_installed?(service)
+    if @list_unit_files_output.nil?
       return nil
     end
-    stdout.each { |line|
-      if line.split(' ')[0] == service
+
+    @list_unit_files_output.each { |line|
+      if self.contains_line_service?(line, service)
         return true
       end
     }
     return false
   end
 
-  # currently we are not using systemd instances (service_name@instance) in pcsd
-  # for proper implementation of is_service_installed see
-  # pcs/lib/external.py:is_service_installed
-  stdout, _, retcode = run_cmd(
-    PCSAuth.getSuperuserAuth(), 'systemctl', 'list-unit-files', '--full'
-  )
-  if retcode != 0
-    return nil
-  end
-  stdout.each { |line|
-    if line.strip().start_with?("#{service}.service")
-      return true
+  protected
+  def load_unit_files_list()
+    stdout, _, retcode = self.run_command()
+    if retcode != 0
+      return nil
     end
-  }
-  return false
+    return stdout
+  end
+end
+
+class ServiceInstalledCheckerSystemctl < ServiceInstalledChecker
+  protected
+  def run_command
+    # currently we are not using systemd instances (service_name@instance) in pcsd
+    # for proper implementation of is_service_installed see
+    # pcs/lib/external.py:is_service_installed
+    return run_cmd(
+      PCSAuth.getSuperuserAuth(), 'systemctl', 'list-unit-files', '--full'
+    )
+  end
+
+  def contains_line_service?(line, service)
+    return line.strip().start_with?("#{service}.service")
+  end
+end
+
+class ServiceInstalledCheckerChkconfig < ServiceInstalledChecker
+  protected
+  def run_command
+    return run_cmd(PCSAuth.getSuperuserAuth(), 'chkconfig')
+  end
+
+  def contains_line_service?(line, service)
+    return line.split(' ')[0] == service
+  end
+end
+
+def get_service_installed_checker
+  if ISSYSTEMCTL
+    return ServiceInstalledCheckerSystemctl.new
+  else
+    return ServiceInstalledCheckerChkconfig.new
+  end
+end
+
+
+def is_service_installed?(service)
+  return get_service_installed_checker().is_installed?(service)
 end
 
 def enable_service(service)
@@ -1888,9 +1925,9 @@ def get_alerts(auth_user)
   end
 end
 
-def get_service_info(service_name)
+def get_service_info(service_name, service_checker)
   return {
-    :installed => is_service_installed?(service_name),
+    :installed => service_checker.is_installed?(service_name),
     :enabled => is_service_enabled?(service_name),
     :running => is_service_running?(service_name),
     :version => nil,
diff --git a/pcsd/remote.rb b/pcsd/remote.rb
index 0154c78c..6f454681 100644
--- a/pcsd/remote.rb
+++ b/pcsd/remote.rb
@@ -2911,8 +2911,10 @@ def check_host(params, request, auth_user)
       File.exist?(Cfgsync::CorosyncConf.file_path) or File.exist?(CIB_PATH)
     )
   }
+
+  service_checker = get_service_installed_checker
   service_list.each do |service|
-    output[:services][service] = get_service_info(service.to_s)
+    output[:services][service] = get_service_info(service.to_s, service_checker)
   end
   service_version_getter.each do |service, version_getter|
     version = version_getter.call()
-- 
2.20.1