machinery-tool 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/NEWS +12 -0
  3. data/export_helpers/autoyast_export_readme.md +48 -0
  4. data/{kiwi_helpers → export_helpers}/kiwi_export_readme.md +0 -0
  5. data/{kiwi_helpers → export_helpers}/merge_users_and_groups.pl.erb +0 -0
  6. data/{kiwi_helpers → export_helpers}/unmanaged_files_build_excludes +2 -0
  7. data/html/index.html.haml +1 -0
  8. data/lib/analyze_config_file_diffs_task.rb +11 -5
  9. data/lib/autoyast.rb +157 -7
  10. data/lib/build_task.rb +0 -10
  11. data/lib/cli.rb +14 -13
  12. data/lib/compare_task.rb +8 -1
  13. data/lib/exceptions.rb +1 -0
  14. data/lib/export_task.rb +12 -1
  15. data/lib/exporter.rb +24 -0
  16. data/lib/html.rb +1 -1
  17. data/lib/inspect_task.rb +5 -4
  18. data/lib/kiwi_config.rb +14 -11
  19. data/lib/list_task.rb +1 -1
  20. data/lib/local_system.rb +2 -1
  21. data/lib/machinery.rb +6 -0
  22. data/lib/manifest.rb +88 -0
  23. data/lib/migration.rb +2 -1
  24. data/lib/scope_file_store.rb +72 -0
  25. data/lib/system_description.rb +83 -52
  26. data/lib/system_description_memory_store.rb +28 -0
  27. data/lib/system_description_store.rb +74 -63
  28. data/lib/ui.rb +1 -1
  29. data/lib/validate_task.rb +1 -1
  30. data/lib/version.rb +1 -1
  31. data/lib/zypper.rb +40 -15
  32. data/man/generated/machinery.1.gz +0 -0
  33. data/man/generated/machinery.1.html +1144 -0
  34. data/plugins/inspect/changed_managed_files_inspector.rb +6 -4
  35. data/plugins/inspect/config_files_inspector.rb +4 -3
  36. data/plugins/inspect/patterns_inspector.rb +12 -1
  37. data/plugins/inspect/unmanaged_files_inspector.rb +31 -19
  38. data/plugins/model/os_model.rb +3 -1
  39. data/plugins/model/repositories_model.rb +3 -0
  40. data/plugins/show/config_files_renderer.rb +1 -4
  41. metadata +128 -122
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c161742e300133d4d5a6514ddfe3e4284fc29b52
4
- data.tar.gz: 28c974344534d7ad4df48e43dce31b60125bb1b1
3
+ metadata.gz: f3e26096068d827b9178938a39eead5000562a09
4
+ data.tar.gz: 78c08edb97fc7993b173cf477821f6eee75bb27c
5
5
  SHA512:
6
- metadata.gz: ddd663cea68dfa8a41b8cd8921c91436a5e70a049439ee5b628b4d628f427ef4375923f9b33e967e4d6604ba487950cad0ebed0e2b62291ba66fed49ebfa1087
7
- data.tar.gz: 285ed630148abb78038681ed823dd2079501a18ecd64d0882e642300c8d6f648b62dfb7f672e8efd4dcdfc1fc3131401cf82e88f09c6d3cdb6c886423f69302f
6
+ metadata.gz: 370cb5832ee25886ade589381967014b8bb8d746d9b3451fcd52e30d08ff32ce4a71670ab2c2debfa451d8c2673f5dc7fd5e7fbf66db76e616af7e1753d2fbfa
7
+ data.tar.gz: 74487bdaf7324bc54bf8b1a62f0437d69086570a1f61de8f7517c7c6c7d2c6debfdd8f83c60954432be28c40fa2505831bf910a80aecdcb1db879157aac582f5
data/NEWS CHANGED
@@ -1,6 +1,18 @@
1
1
  # Machinery Release Notes
2
2
 
3
3
 
4
+ ## Version 1.2.0 - Mon Dec 22 15:06:20 CET 2014 - aduffeck@suse.de
5
+
6
+ * Added AutoYaST export for system descriptions
7
+ * Handle zypper locks gracefully (gh#SUSE/machinery#415)
8
+ * Prevent scopes from being inspected multiple times (gh#SUSE/machinery#303)
9
+ * Keep already extracted results after canceling an inspection (gh#SUSE/machinery#364)
10
+ * Don't fail on file validation errors, but report them as warnings (gh#SUSE/machinery#391)
11
+ * List scopes more natural with a space after comma (gh#SUSE/machinery#356)
12
+ * Use UTF-8 for displaying HTML report (gh#SUSE/machinery#429)
13
+ * Do not ignore Btrfs subvolumes during unmanaged-files inspection (gh#SUSE/machinery#427)
14
+ * Store KIWI and AutoYaST exports in subdirectories
15
+
4
16
  ## Version 1.1.1 - Tue Dec 02 13:24:38 CET 2014 - thardeck@suse.de
5
17
 
6
18
  * Skip Gnome Virtual File System mounts on inspection (issue #393)
@@ -0,0 +1,48 @@
1
+ # README for AutoYaST export from Machinery
2
+
3
+ This directory contains an AutoYaST configuration that was exported by
4
+ Machinery.
5
+
6
+ The user is expected to be familiar with using AutoYaST.
7
+
8
+ ## Using the AutoYaST export
9
+
10
+ The export directory contains both the AutoYaST profile and additional data that
11
+ is required during installation. This directory needs to be made available to
12
+ the installer via network, e.g. by running:
13
+
14
+ cd /path/to/autoyast_export; python -m SimpleHTTPServer
15
+
16
+ You can then point the installer to the profile by specifying the AutoYaST
17
+ option on the kernel command line.
18
+
19
+ For SLES12 and openSUSE 13.2:
20
+
21
+ autoyast2=http://192.168.121.1:8000/autoinst.xml
22
+
23
+ For SLES11:
24
+
25
+ autoyast=http://192.168.121.1:8000/autoinst.xml netsetup=dhcp
26
+
27
+ ## Changing permissions of the AutoYaST export
28
+
29
+ By default the AutoYaST export is only accessible by the user. This is also the
30
+ case for all sub directories.
31
+
32
+ The installation via for example an HTTP server is only possible if all files
33
+ and sub directories are readable by the HTTP server user.
34
+ To make the export directory readable for all users run:
35
+
36
+ chmod -R a+rX /path/to/autoyast_export
37
+
38
+ ## Reference
39
+
40
+ Additional information regarding AutoYaST is available in the official documentation:
41
+
42
+ For SLES12:
43
+
44
+ https://www.suse.com/documentation/sles-12/singlehtml/book_autoyast/book_autoyast.html
45
+
46
+ For SLES11
47
+
48
+ https://www.suse.com/documentation/sles11/singlehtml/book_autoyast/book_autoyast.html
@@ -3,3 +3,5 @@ etc/passwd*
3
3
  etc/shadow*
4
4
  etc/group*
5
5
  etc/fstab
6
+ lib/mkinitrd
7
+ etc/udev/rules.d/70-persistent-net.rules
data/html/index.html.haml CHANGED
@@ -3,6 +3,7 @@
3
3
  %head
4
4
  %title
5
5
  = description.name + " - Machinery System Description"
6
+ %meta{:charset => 'utf-8'}/
6
7
  %link{:href => "assets/machinery-base.css", :rel => "stylesheet", :type => "text/css"}/
7
8
  %link{:href => "assets/machinery.css", :rel => "stylesheet", :type => "text/css"}/
8
9
  %script{:src => "assets/jquery-2.1.1.min.js"}
@@ -17,15 +17,20 @@
17
17
 
18
18
  class AnalyzeConfigFileDiffsTask
19
19
  def analyze(description)
20
- description.assert_scopes("repositories", "config_files")
20
+ description.assert_scopes(
21
+ "repositories",
22
+ "config_files",
23
+ "os"
24
+ )
21
25
  if !description.scope_extracted?("config_files")
22
26
  raise Machinery::Errors::MissingExtractedFiles.new(description, ["config_files"])
23
27
  end
24
28
 
25
29
  with_repositories(description) do |zypper|
26
- description.initialize_file_store("config-file-diffs")
27
- diffs_path = description.file_store("config-file-diffs")
28
- extracted_files_path = description.file_store("config_files")
30
+ file_store = description.scope_file_store("config-file-diffs")
31
+ file_store.create
32
+ diffs_path = file_store.path
33
+ extracted_files_path = description.scope_file_store("config_files").path
29
34
 
30
35
  Machinery::Ui.puts "Generating diffs..."
31
36
  cnt = 1
@@ -90,7 +95,8 @@ class AnalyzeConfigFileDiffsTask
90
95
 
91
96
  def with_repositories(description, &block)
92
97
  Machinery::Ui.puts "Setting up repository access..."
93
- Zypper.isolated do |zypper|
98
+ arch = description.os.architecture
99
+ Zypper.isolated(arch: arch) do |zypper|
94
100
  begin
95
101
  remote_repos = description.repositories.reject do |repo|
96
102
  repo.url.start_with?("cd://") || repo.url.start_with?("dvd://")
data/lib/autoyast.rb CHANGED
@@ -15,13 +15,44 @@
15
15
  # To contact SUSE about this file by physical or electronic mail,
16
16
  # you may find current contact information at www.suse.com
17
17
 
18
- class Autoyast
18
+ class Autoyast < Exporter
19
19
  def initialize(description)
20
+ @chroot_scripts = []
20
21
  @system_description = description
22
+ @system_description.assert_scopes(
23
+ "repositories",
24
+ "packages"
25
+ )
21
26
  end
22
27
 
23
28
  def write(output_dir)
29
+ FileUtils.cp(
30
+ File.join(Machinery::ROOT, "export_helpers/unmanaged_files_build_excludes"),
31
+ output_dir
32
+ )
33
+ # Filter log files to prevent an issue with hanging gzip during installation
34
+ File.open(File.join(output_dir, "unmanaged_files_build_excludes"), "a") do |file|
35
+ file.puts "var/log/*"
36
+ end
37
+ FileUtils.chmod(0600, File.join(output_dir, "unmanaged_files_build_excludes"))
38
+ FileUtils.cp(
39
+ File.join(Machinery::ROOT, "export_helpers/autoyast_export_readme.md"),
40
+ File.join(output_dir, "README.md")
41
+ )
42
+ Dir["#{@system_description.description_path}/*"].each do |content|
43
+ FileUtils.cp_r(content, output_dir, preserve: true)
44
+ end
24
45
  File.write(File.join(output_dir, "autoinst.xml"), profile)
46
+ FileUtils.chmod(0600, File.join(output_dir, "autoinst.xml"))
47
+ Machinery::Ui.puts(
48
+ "Note: The permssions of the AutoYaST directory are restricted to be" \
49
+ " only accessible by the current user. Further instructions are" \
50
+ " provided by the README.md in the exported directory."
51
+ )
52
+ end
53
+
54
+ def export_name
55
+ "#{@system_description.name}-autoyast"
25
56
  end
26
57
 
27
58
  def profile
@@ -31,6 +62,8 @@ class Autoyast
31
62
  "xmlns" => "http://www.suse.com/1.0/yast2ns",
32
63
  "xmlns:config" => "http://www.suse.com/1.0/configns"
33
64
  ) do
65
+ apply_non_interactive_mode(xml)
66
+ apply_basic_network(xml)
34
67
  apply_repositories(xml)
35
68
  xml.software do
36
69
  apply_packages(xml)
@@ -39,6 +72,20 @@ class Autoyast
39
72
  apply_users(xml)
40
73
  apply_groups(xml)
41
74
  apply_services(xml)
75
+
76
+ apply_extracted_files("config_files")
77
+ apply_extracted_files("changed_managed_files")
78
+ apply_unmanaged_files
79
+ xml.scripts do
80
+ apply_url_extraction(xml)
81
+ xml.send("chroot-scripts", "config:type" => "list") do
82
+ xml.script do
83
+ xml.source do
84
+ xml.cdata @chroot_scripts.join("\n")
85
+ end
86
+ end
87
+ end
88
+ end
42
89
  end
43
90
  end
44
91
 
@@ -47,19 +94,55 @@ class Autoyast
47
94
 
48
95
  private
49
96
 
97
+ def apply_non_interactive_mode(xml)
98
+ xml.general do
99
+ xml.mode do
100
+ xml.confirm "false", "config:type" => "boolean"
101
+ end
102
+ end
103
+ end
104
+
105
+ def apply_basic_network(xml)
106
+ xml.networking do
107
+ xml.keep_install_network "true", "config:type" => "boolean"
108
+ end
109
+ end
110
+
50
111
  def apply_repositories(xml)
51
112
  return if !@system_description.repositories
52
113
 
53
114
  xml.send("add-on") do
54
115
  xml.add_on_products("config:type" => "list") do
55
116
  @system_description.repositories.each do |repository|
56
- xml.listentry do
57
- xml.media_url repository.url
58
- xml.name repository.alias
117
+ if repository.enabled && !repository.external_medium?
118
+ xml.listentry do
119
+ xml.media_url repository.url
120
+ xml.name repository.alias
121
+ end
59
122
  end
60
123
  end
61
124
  end
62
125
  end
126
+
127
+ @system_description.repositories.each do |repository|
128
+ # Disabled repositories or external media can't be added by AutoYaST so we add them manually
129
+ if !repository.enabled || repository.external_medium?
130
+ zypper_ar = "zypper -n ar --name='#{repository.name}'"
131
+ zypper_ar << " --type='#{repository.type}'" if repository.type
132
+ zypper_ar << " --disable" if !repository.enabled
133
+ zypper_ar << " '#{repository.url}' '#{repository.alias}'"
134
+ @chroot_scripts << zypper_ar.strip
135
+ end
136
+
137
+ zypper_mr = "zypper -n mr --priority=#{repository.priority} '#{repository.alias}'"
138
+ zypper_mr << " --name='#{repository.name}'"
139
+ if repository.autorefresh
140
+ zypper_mr << " --refresh"
141
+ else
142
+ zypper_mr << " --no-refresh"
143
+ end
144
+ @chroot_scripts << zypper_mr.strip
145
+ end
63
146
  end
64
147
 
65
148
  def apply_packages(xml)
@@ -125,20 +208,28 @@ class Autoyast
125
208
  end
126
209
 
127
210
  def apply_services(xml)
211
+ return if !@system_description.services
212
+
128
213
  xml.send("services-manager") do
129
- xml.services do
214
+ xml.services("config:type" => "list") do
130
215
  @system_description.services.services.each do |service|
216
+ name = service.name
217
+ if @system_description.services.init_system == "systemd"
218
+ # Yast can only handle services right now
219
+ next if !(name =~ /\.service$/)
220
+ name = name.gsub(/\.service$/, "")
221
+ end
131
222
  # systemd service states like "masked" and "static" are
132
223
  # not supported by Autoyast
133
224
  if service.enabled?
134
225
  xml.service do
135
- xml.service_name service.name
226
+ xml.service_name name
136
227
  xml.service_status "enable"
137
228
  end
138
229
  end
139
230
  if service.disabled?
140
231
  xml.service do
141
- xml.service_name service.name
232
+ xml.service_name name
142
233
  xml.service_status "disable"
143
234
  end
144
235
  end
@@ -146,4 +237,63 @@ class Autoyast
146
237
  end
147
238
  end
148
239
  end
240
+
241
+ def apply_url_extraction(xml)
242
+ xml.send("pre-scripts", "config:type" => "list") do
243
+ xml.script do
244
+ xml.source do
245
+ xml.cdata 'sed -n \'/.*autoyast2\?=\(.*\)\/.*[^\s]*/s//\1/p\'' \
246
+ ' /proc/cmdline > /tmp/description_url'
247
+ end
248
+ end
249
+ end
250
+ end
251
+
252
+ def apply_extracted_files(scope)
253
+ return if !@system_description[scope] || !@system_description[scope].extracted
254
+
255
+ base = Pathname(@system_description.scope_file_store(scope).path)
256
+ Dir["#{base}/**/*"].sort.each do |path|
257
+ next if File.directory?(path)
258
+
259
+ relative_path = Pathname(path).relative_path_from(base).to_s
260
+ url = "`cat /tmp/description_url`/#{URI.escape(File.join(scope, relative_path))}"
261
+
262
+ @chroot_scripts << "mkdir -p '#{File.join("/mnt", File.dirname(relative_path))}'"
263
+ @chroot_scripts << "curl -o '#{File.join("/mnt", relative_path)}' \"#{url}\""
264
+ end
265
+
266
+ @system_description[scope].files.map do |file|
267
+ if file.user
268
+ @chroot_scripts << "chown #{file.user}:#{file.group} '#{File.join("/mnt", file.name)}'"
269
+ end
270
+ if file.mode
271
+ @chroot_scripts << "chmod #{file.mode} '#{File.join("/mnt", file.name)}'"
272
+ end
273
+ end
274
+ end
275
+
276
+ def apply_unmanaged_files
277
+ return if !@system_description.unmanaged_files ||
278
+ !@system_description.unmanaged_files.extracted
279
+
280
+ base = Pathname(@system_description.scope_file_store("unmanaged_files").path)
281
+ @chroot_scripts << <<-EOF
282
+ curl -o '/mnt/tmp/filter' "`cat /tmp/description_url`/unmanaged_files_build_excludes"
283
+ EOF
284
+
285
+ Dir["#{base}/**/*.tgz"].sort.each do |path|
286
+ next if !path.end_with?(".tgz")
287
+
288
+ relative_path = Pathname(path).relative_path_from(base).to_s
289
+ tarball_name = File.basename(path)
290
+ url = "`cat /tmp/description_url`#{URI.escape(File.join("/unmanaged_files", relative_path))}"
291
+
292
+ @chroot_scripts << <<-EOF
293
+ curl -o '/mnt/tmp/#{tarball_name}' "#{url}"
294
+ tar -C /mnt/ -X '/mnt/tmp/filter' -xf '#{File.join("/mnt/tmp", tarball_name)}'
295
+ rm '#{File.join("/mnt/tmp", tarball_name)}'
296
+ EOF
297
+ end
298
+ end
149
299
  end
data/lib/build_task.rb CHANGED
@@ -28,16 +28,6 @@ class BuildTask
28
28
  config = KiwiConfig.new(system_description, options)
29
29
  config.write(tmp_config_dir)
30
30
 
31
- if system_description["unmanaged_files"]
32
- filters = File.read(
33
- File.join(Machinery::ROOT, "kiwi_helpers/unmanaged_files_build_excludes")
34
- )
35
- Machinery::Ui.puts "\nUnmanaged files following these patterns are not added " \
36
- "to the built image:"
37
- Machinery::Ui.puts filters
38
- Machinery::Ui.puts "\n"
39
- end
40
-
41
31
  FileUtils.mkdir_p(output_path)
42
32
  if tmp_image_dir.start_with?("/tmp/") && tmp_config_dir.start_with?("/tmp/")
43
33
  tmp_script = write_kiwi_wrapper(tmp_config_dir, tmp_image_dir,
data/lib/cli.rb CHANGED
@@ -179,7 +179,7 @@ class Cli
179
179
  )
180
180
  end
181
181
 
182
- scopes
182
+ scopes.uniq
183
183
  end
184
184
 
185
185
  AVAILABLE_SCOPE_LIST = Machinery::Ui.internal_scope_list_to_string(
@@ -203,7 +203,7 @@ class Cli
203
203
  c.action do |global_options,options,args|
204
204
  name = shift_arg(args, "NAME")
205
205
  store = SystemDescriptionStore.new
206
- description = store.load(name)
206
+ description = SystemDescription.load(name, store)
207
207
 
208
208
  case options[:operation]
209
209
  when "config-file-diffs"
@@ -238,7 +238,7 @@ class Cli
238
238
  c.action do |global_options,options,args|
239
239
  name = shift_arg(args, "NAME")
240
240
  store = SystemDescriptionStore.new
241
- description = store.load(name)
241
+ description = SystemDescription.load(name, store)
242
242
 
243
243
  task = BuildTask.new
244
244
  task.build(description, File.expand_path(options["image-dir"]), {:enable_dhcp => options["enable-dhcp"], :enable_ssh => options["enable-ssh"]})
@@ -272,8 +272,8 @@ class Cli
272
272
  name1 = shift_arg(args, "NAME1")
273
273
  name2 = shift_arg(args, "NAME2")
274
274
  store = SystemDescriptionStore.new
275
- description1 = store.load(name1)
276
- description2 = store.load(name2)
275
+ description1 = SystemDescription.load(name1, store)
276
+ description2 = SystemDescription.load(name2, store)
277
277
  scope_list = process_scope_option(options[:scope], options["exclude-scope"])
278
278
 
279
279
  task = CompareTask.new
@@ -327,7 +327,7 @@ class Cli
327
327
  c.action do |global_options,options,args|
328
328
  name = shift_arg(args, "NAME")
329
329
  store = SystemDescriptionStore.new
330
- description = store.load(name)
330
+ description = SystemDescription.load(name, store)
331
331
 
332
332
  task = DeployTask.new
333
333
  opts = {
@@ -345,8 +345,8 @@ class Cli
345
345
  long_desc <<-LONGDESC
346
346
  Export system description as KIWI image description.
347
347
 
348
- The description will be placed in the given location. The image format in the
349
- description is 'vmx'.
348
+ The description will be placed in a subdirectory at the given location. The image format in
349
+ the description is 'vmx'.
350
350
  LONGDESC
351
351
  arg "NAME"
352
352
  command "export-kiwi" do |c|
@@ -358,7 +358,7 @@ class Cli
358
358
  c.action do |global_options,options,args|
359
359
  name = shift_arg(args, "NAME")
360
360
  store = SystemDescriptionStore.new
361
- description = store.load(name)
361
+ description = SystemDescription.load(name, store)
362
362
  exporter = KiwiConfig.new(description)
363
363
 
364
364
  task = ExportTask.new(exporter)
@@ -375,7 +375,8 @@ class Cli
375
375
  long_desc <<-LONGDESC
376
376
  Export system description as AutoYaST profile
377
377
 
378
- The profile will be placed in the location given by the 'autoyast-dir' option.
378
+ The profile will be placed in a subdirectory at the given location by the 'autoyast-dir'
379
+ option.
379
380
  LONGDESC
380
381
  arg "NAME"
381
382
  command "export-autoyast" do |c|
@@ -387,7 +388,7 @@ class Cli
387
388
  c.action do |_global_options, options, args|
388
389
  name = shift_arg(args, "NAME")
389
390
  store = SystemDescriptionStore.new
390
- description = store.load(name)
391
+ description = SystemDescription.load(name, store)
391
392
  exporter = Autoyast.new(description)
392
393
 
393
394
  task = ExportTask.new(exporter)
@@ -544,7 +545,7 @@ class Cli
544
545
  end
545
546
 
546
547
  store = SystemDescriptionStore.new
547
- description = store.load(name)
548
+ description = SystemDescription.load(name, store)
548
549
  scope_list = process_scope_option(options[:scope], options["exclude-scope"])
549
550
 
550
551
 
@@ -605,7 +606,7 @@ class Cli
605
606
  name = shift_arg(args, "NAME")
606
607
 
607
608
  store = SystemDescriptionStore.new
608
- description = store.load(name)
609
+ description = SystemDescription.load(name, store)
609
610
  task = GenerateHtmlTask.new
610
611
  task.generate(description)
611
612
  end