• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

yast / yast-yast2 / 8248418554

12 Mar 2024 12:02PM UTC coverage: 40.575% (+0.02%) from 40.555%
8248418554

push

github

web-flow
Merge pull request #1307 from yast/slehpc_sp3

13 of 14 new or added lines in 1 file covered. (92.86%)

2 existing lines in 1 file now uncovered.

12003 of 29582 relevant lines covered (40.58%)

6.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/library/control/src/modules/ProductProfile.rb
1
# File:  modules/ProductProfile.ycp
2
# Package:  yast2
3
# Summary:  Functions for handling Product Profiles
4
# Authors:  Jiri Suchomel <jsuchome@suse.cz>
5
#
6
# $Id$
7
require "yast"
×
8
require "shellwords"
×
9
require "y2packager/resolvable"
×
10

11
module Yast
×
12
  class ProductProfileClass < Module
×
13
    def main
×
14
      textdomain "base"
×
15

16
      Yast.import "Directory"
×
17
      Yast.import "Label"
×
18
      Yast.import "Mode"
×
19
      Yast.import "Pkg"
×
20
      Yast.import "Report"
×
21

22
      # path to the profile file on the media
23
      @profile_path = "/product.profile"
×
24

25
      # Result map of isCompliance call.
26
      # If map is not empty, contains reasons why system is not compliant.
27
      @compliance = {}
×
28

29
      # profiles for all installed products
30
      # (full paths to the temporary copies)
31
      @all_profiles = []
×
32

33
      # mapping of product id's to product names
34
      @productid2name = {}
×
35

36
      # remember products already checked
37
      @compliance_checked = {}
×
38

39
      # directory to store profiles temporary during installation
40
      @profiles_dir = ""
×
41
    end
×
42

43
    # return the result of last compliance test
44
    def GetComplianceMap
×
45
      deep_copy(@compliance)
×
46
    end
×
47

48
    # Return the list of paths to gpg keyfiles present in the root of given product media
49
    # @param the product id
50
    def GetSigKeysForProduct(src_id)
×
51
      # find the list of sigkeys
52
      dir_file = Pkg.SourceProvideOptionalFile(src_id, 1, "/directory.yast")
×
53
      out = Convert.to_map(
×
54
        SCR.Execute(
×
55
          path(".target.bash_output"),
×
56
          Builtins.sformat("/usr/bin/grep 'gpg-pubkey' %1 2>/dev/null", dir_file.shellescape)
×
57
        )
×
58
      )
×
59
      keys = []
×
60
      Builtins.foreach(
×
61
        Builtins.splitstring(Ops.get_string(out, "stdout", ""), "\n")
×
62
      ) do |k|
×
63
        if k != ""
×
64
          key = Pkg.SourceProvideOptionalFile(src_id, 1, Ops.add("/", k))
×
65
          keys = Builtins.add(keys, key) if !key.nil?
×
66
        end
×
67
      end
×
68
      deep_copy(keys)
×
69
    end
×
70

71
    # Checks the profile compliance with the system.
72
    # @param if product_id is not nil, check only compliance with given product
73
    # (once new product is added, function should be called to with new product ID)
74
    # @ret true if the system is compliant
75
    def IsCompliant(product_id)
×
76
      profiles = []
×
77
      products = []
×
78
      sigkeys = []
×
79

80
      if @profiles_dir == ""
×
81
        @profiles_dir = Ops.add(Directory.tmpdir, "/profiles/")
×
82
        SCR.Execute(path(".target.mkdir"), @profiles_dir)
×
83
      end
×
84

85
      # iterate all (or given) products and get the info about them
86
      Y2Packager::Resolvable.find(kind: :product).each do |product|
×
87
        src_id = product.source
×
88
        name = product.name
×
89
        if product_id.nil? &&
×
90
            product.status != :selected
×
91
          next
×
92
        end
×
93
        next if !product_id.nil? && src_id != product_id
×
94

95
        Ops.set(@compliance_checked, src_id, true)
×
96
        profile = Pkg.SourceProvideOptionalFile(src_id, 1, @profile_path)
×
97
        if !profile.nil?
×
98
          profiles = Builtins.add(profiles, profile)
×
99
          # backup profiles so they can be copied them to the installed system
100
          tmp_path = Ops.add(Ops.add(@profiles_dir, name), ".profile")
×
101
          SCR.Execute(
×
102
            path(".target.bash"),
×
103
            Builtins.sformat("/bin/cp -a %1 %2", profile.shellescape, tmp_path.shellescape)
×
104
          )
×
105
          @all_profiles = Builtins.add(@all_profiles, tmp_path)
×
106
          Ops.set(@productid2name, src_id, name)
×
107
        else
×
108
          Builtins.y2debug("no profile found for product %1", name)
×
109
          next
×
110
        end
×
111
        # generate product map:
112
        version_release = Builtins.splitstring(
×
113
          product.version,
×
114
          "-"
×
115
        )
×
116
        products = Builtins.add(
×
117
          products,
×
118
          "arch"    => product.arch,
×
119
          "name"    => name,
×
120
          "version" => Ops.get(version_release, 0, ""),
×
121
          "release" => Ops.get(version_release, 1, ""),
×
122
          "vendor"  => product.vendor
×
123
        )
×
124
        sigkeys = Convert.convert(
×
125
          Builtins.union(sigkeys, GetSigKeysForProduct(src_id)),
×
126
          from: "list",
×
127
          to:   "list <string>"
×
128
        )
×
129
      end
×
130

131
      if profiles == []
×
132
        Builtins.y2milestone("no product profile present")
×
133
        @compliance = {}
×
134
        return true
×
135
      end
×
136

137
      @compliance = YaPI::SubscriptionTools.isCompliant(profiles, products, sigkeys)
×
138
      @compliance.nil?
×
139
    end
×
140

141
    # Checks the profile compliance with the system.
142
    # If system is not complient, shows a popup with reasons and asks
143
    # to continue with the installation.
144
    # @ret Returns true if system is complient or user agrees to continue
145
    # although the complience test failed.
146
    # @param if product_id is not nil, check only compliance with given product
147
    # (once new product is added, function should be called to with new product ID)
148
    def CheckCompliance(product_id)
×
149
      # behavior for non-installation not defined yet
150
      return true if !Mode.installation
×
151

152
      # no need to check same products twice
153
      if product_id.nil? && @compliance_checked != {} ||
×
154
          !product_id.nil? && Ops.get(@compliance_checked, product_id, false)
×
155
        return true
×
156
      end
×
157

158
      begin
×
159
        # YaPI::SubscriptionTools are only available for SLES
160
        Yast.import "YaPI::SubscriptionTools"
×
161
      rescue NameError
×
162
        Builtins.y2milestone("subscription-tools package not present: no compliance checking")
×
163
        return true
×
164
      end
×
165

166
      return true if IsCompliant(product_id)
×
167

168
      reasons = []
×
169
      Builtins.foreach(@compliance) do |_key, val|
×
170
        if Ops.is_map?(val) && Builtins.haskey(Convert.to_map(val), "message")
×
171
          reasons = Builtins.add(
×
172
            reasons,
×
173
            Ops.get_string(Convert.to_map(val), "message", "")
×
174
          )
×
175
        end
×
176
      end
×
177
      reasons_s = Builtins.mergestring(reasons, "\n")
×
178
      # last part of the question (variable)
179
      end_question = _("Do you want to continue or abort the installation?")
×
180

181
      # button label
182
      continue_button = _("&Continue Installation")
×
183
      # button label
184
      cancel_button = _("&Abort Installation")
×
185

186
      # checking specific product
187
      if !product_id.nil?
×
188
        # last part of the question (variable)
189
        end_question = _("Do you want to add new product anyway?")
×
190
        continue_button = Label.YesButton
×
191
        cancel_button = Label.NoButton
×
192
      end
×
193

194
      ret = Report.AnyQuestion(
×
195
        # popup dialog caption
196
        _("Warning"),
×
197
        # popup message, %1 is list of problems
198
        Builtins.sformat(
×
199
          _(
×
200
            "The profile does not allow you to run the products on this system.\n" \
×
201
              "Proceeding to run this installation will leave you in an unsupported state\n" \
×
202
              "and might impact your compliance requirements.\n" \
×
203
              "     \n" \
×
204
              "The following requirements are not fulfilled on this system:\n" \
×
205
              "    \n" \
×
206
              "%1\n" \
×
207
              "\n" \
×
208
              "%2"
×
209
          ),
×
210
          reasons_s,
×
211
          end_question
×
212
        ),
×
213
        continue_button,
×
214
        cancel_button,
×
215
        :focus_no
×
216
      )
×
217
      if !ret && !product_id.nil?
×
218
        # canceled adding add-on: remove profile stored before
219
        name = Ops.get(@productid2name, product_id, "")
×
220
        tmp_path = Ops.add(Ops.add(@profiles_dir, name), ".profile")
×
221
        Builtins.y2milestone("deleting %1", tmp_path)
×
222
        SCR.Execute(path(".target.bash"), "/bin/rm #{tmp_path.shellescape}")
×
223
        @all_profiles = Builtins.filter(@all_profiles) { |p| p != tmp_path }
×
224
      end
×
225
      ret
×
226
    end
×
227

228
    publish variable: :all_profiles, type: "list <string>"
×
229
    publish variable: :productid2name, type: "map <integer, string>"
×
230
    publish variable: :compliance_checked, type: "map <integer, boolean>"
×
231
    publish function: :GetComplianceMap, type: "map <string, any> ()"
×
232
    publish function: :GetSigKeysForProduct, type: "list <string> (integer)"
×
233
    publish function: :IsCompliant, type: "boolean (integer)"
×
234
    publish function: :CheckCompliance, type: "boolean (integer)"
×
235
  end
×
236

237
  ProductProfile = ProductProfileClass.new
×
238
  ProductProfile.main
×
239
end
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc