getch 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG.md +9 -0
  5. data/README.md +18 -4
  6. data/lib/getch.rb +14 -7
  7. data/lib/getch/command.rb +18 -4
  8. data/lib/getch/filesystem.rb +5 -0
  9. data/lib/getch/filesystem/clean.rb +51 -0
  10. data/lib/getch/filesystem/device.rb +55 -0
  11. data/lib/getch/filesystem/ext4/config.rb +8 -9
  12. data/lib/getch/filesystem/ext4/device.rb +2 -7
  13. data/lib/getch/filesystem/ext4/encrypt/config.rb +9 -9
  14. data/lib/getch/filesystem/ext4/encrypt/deps.rb +1 -1
  15. data/lib/getch/filesystem/ext4/encrypt/device.rb +3 -8
  16. data/lib/getch/filesystem/ext4/encrypt/format.rb +3 -5
  17. data/lib/getch/filesystem/ext4/encrypt/mount.rb +6 -43
  18. data/lib/getch/filesystem/ext4/encrypt/partition.rb +19 -38
  19. data/lib/getch/filesystem/ext4/format.rb +3 -5
  20. data/lib/getch/filesystem/ext4/mount.rb +7 -46
  21. data/lib/getch/filesystem/ext4/partition.rb +16 -39
  22. data/lib/getch/filesystem/lvm/config.rb +5 -5
  23. data/lib/getch/filesystem/lvm/deps.rb +3 -2
  24. data/lib/getch/filesystem/lvm/device.rb +23 -7
  25. data/lib/getch/filesystem/lvm/encrypt/config.rb +3 -3
  26. data/lib/getch/filesystem/lvm/encrypt/deps.rb +1 -1
  27. data/lib/getch/filesystem/lvm/encrypt/device.rb +23 -7
  28. data/lib/getch/filesystem/lvm/encrypt/format.rb +3 -3
  29. data/lib/getch/filesystem/lvm/encrypt/mount.rb +7 -46
  30. data/lib/getch/filesystem/lvm/encrypt/partition.rb +19 -31
  31. data/lib/getch/filesystem/lvm/format.rb +11 -7
  32. data/lib/getch/filesystem/lvm/mount.rb +7 -46
  33. data/lib/getch/filesystem/lvm/partition.rb +19 -31
  34. data/lib/getch/filesystem/mount.rb +56 -0
  35. data/lib/getch/filesystem/partition.rb +77 -0
  36. data/lib/getch/filesystem/zfs/config.rb +4 -5
  37. data/lib/getch/filesystem/zfs/deps.rb +3 -6
  38. data/lib/getch/filesystem/zfs/device.rb +30 -9
  39. data/lib/getch/filesystem/zfs/encrypt/config.rb +7 -7
  40. data/lib/getch/filesystem/zfs/encrypt/deps.rb +2 -6
  41. data/lib/getch/filesystem/zfs/encrypt/device.rb +30 -9
  42. data/lib/getch/filesystem/zfs/encrypt/format.rb +84 -1
  43. data/lib/getch/filesystem/zfs/encrypt/mount.rb +4 -20
  44. data/lib/getch/filesystem/zfs/encrypt/partition.rb +15 -111
  45. data/lib/getch/filesystem/zfs/format.rb +84 -2
  46. data/lib/getch/filesystem/zfs/mount.rb +5 -24
  47. data/lib/getch/filesystem/zfs/partition.rb +15 -108
  48. data/lib/getch/gentoo.rb +2 -1
  49. data/lib/getch/gentoo/boot.rb +2 -2
  50. data/lib/getch/gentoo/chroot.rb +10 -24
  51. data/lib/getch/gentoo/config.rb +22 -2
  52. data/lib/getch/gentoo/sources.rb +11 -11
  53. data/lib/getch/helpers.rb +13 -0
  54. data/lib/getch/options.rb +20 -5
  55. data/lib/getch/version.rb +1 -1
  56. metadata +6 -2
  57. metadata.gz.sig +0 -0
@@ -4,16 +4,98 @@ module Getch
4
4
  class Format < Getch::FileSystem::Zfs::Device
5
5
  def initialize
6
6
  super
7
- @state = Getch::States.new()
7
+ @log = Getch::Log.new
8
+ @state = Getch::States.new
9
+ if ! @id
10
+ @log.info "Research pool id for #{@dev_root}..."
11
+ sleep 2 until Helpers::pool_id(@dev_root)
12
+ @id = Helpers::pool_id(@dev_root)
13
+ @boot_pool_name = "bpool-#{@id}"
14
+ @pool_name = "rpool-#{@id}"
15
+ end
8
16
  format
9
17
  end
10
18
 
19
+ private
20
+
11
21
  def format
12
22
  return if STATES[:format]
13
- system("mkfs.fat -F32 #{@dev_boot_efi}") if @dev_boot_efi
23
+ raise "Error, no id found for #{@dev_root}." if ! @id
24
+ @log.info "Create #{@id} for #{@pool_name}"
25
+ system("mkfs.fat -F32 #{@dev_esp}") if @dev_esp
14
26
  system("mkswap -f #{@dev_swap}")
27
+ zfs
28
+ datasets
15
29
  @state.format
16
30
  end
31
+
32
+ def zfs
33
+ bloc=`blockdev --getbsz #{@dev_root}`.chomp
34
+ ashift = case bloc
35
+ when 8096
36
+ 13
37
+ when 4096
38
+ 12
39
+ else # 512
40
+ 9
41
+ end
42
+
43
+ Helpers::mkdir(MOUNTPOINT)
44
+ @log.debug("ashift found for #{bloc} - #{ashift}")
45
+
46
+ if @dev_boot
47
+ # https://openzfs.github.io/openzfs-docs/Getting%20Started/Ubuntu/Ubuntu%2020.04%20Root%20on%20ZFS.html
48
+ @log.info("Creating boot pool on #{@pool_name}")
49
+ exec("zpool create -f \\
50
+ -o ashift=#{ashift} -d \\
51
+ -o feature@async_destroy=enabled \\
52
+ -o feature@bookmarks=enabled \\
53
+ -o feature@embedded_data=enabled \\
54
+ -o feature@empty_bpobj=enabled \\
55
+ -o feature@enabled_txg=enabled \\
56
+ -o feature@extensible_dataset=enabled \\
57
+ -o feature@filesystem_limits=enabled \\
58
+ -o feature@hole_birth=enabled \\
59
+ -o feature@large_blocks=enabled \\
60
+ -o feature@lz4_compress=enabled \\
61
+ -o feature@spacemap_histogram=enabled \\
62
+ -O acltype=posixacl -O canmount=off -O compression=lz4 \\
63
+ -O devices=off -O normalization=formD -O atime=off -O xattr=sa \\
64
+ -O mountpoint=/boot -R #{MOUNTPOINT} \\
65
+ #{@boot_pool_name} #{@dev_boot}
66
+ ")
67
+ end
68
+
69
+ exec("zpool create -f -o ashift=#{ashift} \\
70
+ -O acltype=posixacl -O canmount=off -O compression=lz4 \\
71
+ -O dnodesize=auto -O normalization=formD -O atime=off \\
72
+ -O xattr=sa -O mountpoint=/ -R #{MOUNTPOINT} \\
73
+ #{@pool_name} #{@dev_root}
74
+ ")
75
+ end
76
+
77
+ def datasets
78
+ exec("zfs create -o canmount=off -o mountpoint=none #{@pool_name}/ROOT")
79
+ exec("zfs create -o canmount=off -o mountpoint=none #{@boot_pool_name}/BOOT") if @dev_boot
80
+
81
+ exec("zfs create -o canmount=noauto -o mountpoint=/ #{@pool_name}/ROOT/gentoo")
82
+ exec("zfs create -o canmount=noauto -o mountpoint=/boot #{@boot_pool_name}/BOOT/gentoo") if @dev_boot
83
+
84
+ exec("zfs create -o canmount=off #{@pool_name}/ROOT/gentoo/usr")
85
+ exec("zfs create #{@pool_name}/ROOT/gentoo/usr/src")
86
+ exec("zfs create -o canmount=off #{@pool_name}/ROOT/gentoo/var")
87
+ exec("zfs create #{@pool_name}/ROOT/gentoo/var/log")
88
+ exec("zfs create #{@pool_name}/ROOT/gentoo/var/db")
89
+ exec("zfs create #{@pool_name}/ROOT/gentoo/var/tmp")
90
+
91
+ exec("zfs create -o canmount=off -o mountpoint=/ #{@pool_name}/USERDATA")
92
+ exec("zfs create -o canmount=on -o mountpoint=/root #{@pool_name}/USERDATA/root")
93
+ exec("zfs create -o canmount=on -o mountpoint=/home/#{@user} #{@pool_name}/USERDATA/#{@user}") if @user
94
+ end
95
+
96
+ def exec(cmd)
97
+ Getch::Command.new(cmd).run!
98
+ end
17
99
  end
18
100
  end
19
101
  end
@@ -7,9 +7,8 @@ module Getch
7
7
  def initialize
8
8
  super
9
9
  @root_dir = MOUNTPOINT
10
- @boot_dir = "#{@root_dir}/boot"
11
- @boot_efi_dir = "#{@root_dir}/boot/efi"
12
- @state = Getch::States.new()
10
+ @mount = Getch::FileSystem::Mount.new
11
+ @state = Getch::States.new
13
12
  @log = Getch::Log.new
14
13
  end
15
14
 
@@ -19,47 +18,29 @@ module Getch
19
18
  exec("rm -rf #{MOUNTPOINT}/*")
20
19
  exec("zpool import -N -R #{MOUNTPOINT} #{@pool_name}")
21
20
  exec("zpool import -N -R #{MOUNTPOINT} #{@boot_pool_name}") if @dev_boot
22
- mount_swap
21
+ @mount.swap(@dev_swap)
23
22
  mount_root
24
23
  mount_boot
25
- mount_boot_efi
24
+ @mount.esp(@dev_esp)
26
25
  exec("zfs mount -a")
27
26
  @state.mount
28
27
  end
29
28
 
30
29
  private
31
30
 
32
- def mount_swap
33
- if Helpers::grep?('/proc/swaps', /^\/dev/)
34
- exec("swapoff #{@dev_swap}")
35
- end
36
-
37
- exec("swapon #{@dev_swap}")
38
- end
39
-
40
31
  def mount_root
41
32
  Helpers::mkdir(@root_dir)
42
33
  exec("zfs mount #{@pool_name}/ROOT/gentoo")
43
34
  end
44
35
 
45
- def mount_boot_efi
46
- return if ! @dev_boot_efi
47
- Helpers::mkdir(@boot_efi_dir)
48
- exec("mount #{@dev_boot_efi} #{@boot_efi_dir}")
49
- end
50
-
51
36
  def mount_boot
52
37
  return if ! @dev_boot
53
- Helpers::mkdir(@boot_dir)
54
38
  exec("zfs mount #{@boot_pool_name}/BOOT/gentoo")
55
39
  end
56
40
 
57
41
  def exec(cmd)
58
42
  @log.info("==> #{cmd}")
59
- system(cmd)
60
- unless $?.success?
61
- raise "Error with #{cmd}"
62
- end
43
+ Helpers::sys(cmd)
63
44
  end
64
45
  end
65
46
  end
@@ -4,6 +4,8 @@ module Getch
4
4
  class Partition < Getch::FileSystem::Zfs::Device
5
5
  def initialize
6
6
  super
7
+ @clean = Getch::FileSystem::Clean
8
+ @partition = Getch::FileSystem::Partition.new
7
9
  @state = Getch::States.new()
8
10
  @log = Getch::Log.new()
9
11
  run_partition
@@ -11,126 +13,31 @@ module Getch
11
13
 
12
14
  def run_partition
13
15
  return if STATES[:partition ]
14
- clear_struct
15
- cleaning
16
+ @clean.old_zpool
17
+ @clean.struct(@disk, @cache_disk, @home_disk)
18
+ @clean.hdd(@disk, @cache_disk, @home_disk)
16
19
  partition
17
- zfs
18
20
  @state.partition
19
21
  end
20
22
 
21
23
  private
22
24
 
23
- def clear_struct
24
- oldvg = `vgdisplay | grep #{@vg}`.chomp
25
- oldzpool = `zpool status | grep pool:`.gsub(/pool: /, '').delete(' ').split("\n")
26
- if oldzpool[0] != "" and $?.success?
27
- oldzpool.each { |p| exec("zpool destroy #{p}") if p }
28
- end
29
- exec("vgremove -f #{@vg}") if oldvg != '' # remove older volume group
30
- exec("pvremove -f #{@dev_root}") if oldvg != '' and File.exist? @dev_root # remove older volume group
31
-
32
- exec("sgdisk -Z /dev/#{@disk}")
33
- exec("wipefs -a /dev/#{@disk}")
34
- end
35
-
36
- # See https://wiki.archlinux.org/index.php/Solid_state_drive/Memory_cell_clearing
37
- # for SSD
38
- def cleaning
39
- @bloc=`blockdev --getbsz /dev/#{@disk}`.chomp
40
- puts
41
- print "Cleaning data on #{@disk}, can be long, avoid this on Flash Memory (SSD,USB,...) ? (n,y) "
42
- case gets.chomp
43
- when /^y|^Y/
44
- exec("dd if=/dev/urandom of=/dev/#{@disk} bs=#{@bloc} status=progress")
45
- else
46
- return
47
- end
48
- end
49
-
50
25
  def partition
51
- mem=`awk '/MemTotal/ {print $2}' /proc/meminfo`.chomp + 'K'
52
- if Helpers::efi?
53
- exec("sgdisk -n1:1M:+260M -t1:EF00 /dev/#{@disk}")
54
- exec("sgdisk -n2:0:+#{mem} -t2:8200 /dev/#{@disk}")
55
- exec("sgdisk -n3:0:+0 -t3:BF00 /dev/#{@disk}")
26
+ if @efi
27
+ @partition.efi(@dev_esp)
28
+ @partition.swap(@dev_swap)
29
+ @partition.root(@dev_root, "BF00") if @root_part != 1
56
30
  else
57
- exec("sgdisk -n1:1MiB:+1MiB -t1:EF02 /dev/#{@disk}")
58
- exec("sgdisk -n2:0:+2G -t2:BE00 /dev/#{@disk}") # boot pool GRUB
59
- exec("sgdisk -n3:0:+#{mem} -t3:8200 /dev/#{@disk}")
60
- exec("sgdisk -n4:0:+0 -t4:BF00 /dev/#{@disk}")
31
+ @partition.gpt(@dev_gpt)
32
+ # Boot pool for GRUB2
33
+ @partition.boot(@dev_boot)
34
+ @partition.swap(@dev_swap)
35
+ @partition.root(@dev_root, "BF00") if @root_part != 1
61
36
  end
62
37
  end
63
38
 
64
- def zfs
65
- ashift = case @bloc
66
- when 8096
67
- 13
68
- when 4096
69
- 12
70
- else # 512
71
- 9
72
- end
73
-
74
- Helpers::mkdir(MOUNTPOINT)
75
-
76
- @log.debug("ashift found for #{@bloc} - #{ashift}")
77
- if ! Helpers::efi?
78
- # https://openzfs.github.io/openzfs-docs/Getting%20Started/Ubuntu/Ubuntu%2020.04%20Root%20on%20ZFS.html
79
- @log.info("Creating boot pool on #{@pool_name}")
80
- exec("zpool create -f \\
81
- -o ashift=#{ashift} -d \\
82
- -o feature@async_destroy=enabled \\
83
- -o feature@bookmarks=enabled \\
84
- -o feature@embedded_data=enabled \\
85
- -o feature@empty_bpobj=enabled \\
86
- -o feature@enabled_txg=enabled \\
87
- -o feature@extensible_dataset=enabled \\
88
- -o feature@filesystem_limits=enabled \\
89
- -o feature@hole_birth=enabled \\
90
- -o feature@large_blocks=enabled \\
91
- -o feature@lz4_compress=enabled \\
92
- -o feature@spacemap_histogram=enabled \\
93
- -O acltype=posixacl -O canmount=off -O compression=lz4 \\
94
- -O devices=off -O normalization=formD -O atime=off -O xattr=sa \\
95
- -O mountpoint=/boot -R #{MOUNTPOINT} \\
96
- #{@boot_pool_name} #{@dev_boot}
97
- ")
98
- end
99
-
100
- exec("zpool create -f -o ashift=#{ashift} \\
101
- -O acltype=posixacl -O canmount=off -O compression=lz4 \\
102
- -O dnodesize=auto -O normalization=formD -O atime=off \\
103
- -O xattr=sa -O mountpoint=/ -R #{MOUNTPOINT} \\
104
- #{@pool_name} #{@dev_root}
105
- ")
106
-
107
- add_datasets
108
- end
109
-
110
- def add_datasets
111
- exec("zfs create -o canmount=off -o mountpoint=none #{@pool_name}/ROOT")
112
- exec("zfs create -o canmount=off -o mountpoint=none #{@boot_pool_name}/BOOT") if @dev_boot
113
-
114
- exec("zfs create -o canmount=noauto -o mountpoint=/ #{@pool_name}/ROOT/gentoo")
115
- # set bootfs
116
- #exec("zpool set bootfs=#{@pool_name}/ROOT/gentoo #{@pool_name}")
117
- exec("zfs create -o canmount=noauto -o mountpoint=/boot #{@boot_pool_name}/BOOT/gentoo") if @dev_boot
118
-
119
- exec("zfs create -o canmount=off #{@pool_name}/ROOT/gentoo/usr")
120
- exec("zfs create #{@pool_name}/ROOT/gentoo/usr/src")
121
- exec("zfs create -o canmount=off #{@pool_name}/ROOT/gentoo/var")
122
- exec("zfs create #{@pool_name}/ROOT/gentoo/var/log")
123
- exec("zfs create #{@pool_name}/ROOT/gentoo/var/db")
124
- exec("zfs create #{@pool_name}/ROOT/gentoo/var/tmp")
125
-
126
- exec("zfs create -o canmount=off -o mountpoint=/ #{@pool_name}/USERDATA")
127
- exec("zfs create -o canmount=on -o mountpoint=/root #{@pool_name}/USERDATA/root")
128
- exec("zfs create -o canmount=on -o mountpoint=/home/#{@user} #{@pool_name}/USERDATA/#{@user}") if @user
129
- end
130
-
131
- # Follow https://wiki.archlinux.org/index.php/Partitioning
132
39
  # Partition_efi
133
- # /boot/efi - EFI system partition - 260MB
40
+ # /efi - EFI system partition - 260MB
134
41
  # / - Root
135
42
 
136
43
  # Partition_bios
@@ -39,6 +39,7 @@ module Getch
39
39
  def chroot
40
40
  chroot = Getch::Gentoo::Chroot.new()
41
41
  chroot.update
42
+ chroot.cpuflags
42
43
  chroot.systemd
43
44
  chroot.world
44
45
  return if STATES[:gentoo_kernel]
@@ -52,8 +53,8 @@ module Getch
52
53
  source = Getch::Gentoo::Sources.new()
53
54
  new
54
55
  source.build_kspp
55
- source.init_config
56
56
  source.build_others
57
+ source.localmodconfig
57
58
  source.make
58
59
  @state.kernel
59
60
  end
@@ -30,7 +30,7 @@ module Getch
30
30
  bootctl_dep
31
31
  puts "Configuring systemd-boot."
32
32
  # ref: https://forums.gentoo.org/viewtopic-p-8118822.html
33
- esp = '/boot/efi'
33
+ esp = '/efi'
34
34
  exec_chroot("bootctl --path #{esp} install")
35
35
  datas_loader = [
36
36
  'default gentoo',
@@ -66,7 +66,7 @@ module Getch
66
66
  puts 'Password for root'
67
67
  cmd = "chroot #{MOUNTPOINT} /bin/bash -c \"source /etc/profile && passwd\""
68
68
  system(cmd)
69
- if @user != nil
69
+ if @user
70
70
  puts "Creating user #{@user}"
71
71
  exec_chroot("useradd -m -G users,wheel,audio,video #{@user}")
72
72
  puts "Password for your user #{@user}"
@@ -7,6 +7,12 @@ module Getch
7
7
  mount
8
8
  end
9
9
 
10
+ def cpuflags
11
+ Getch::Emerge.new("app-portage/cpuid2cpuflags").pkg!
12
+ cpuflags = `chroot #{MOUNTPOINT} /bin/bash -c "source /etc/profile; cpuid2cpuflags"`.chomp
13
+ File.write("#{MOUNTPOINT}/etc/portage/package.use/00cpuflags", "*/* #{cpuflags}")
14
+ end
15
+
10
16
  def update
11
17
  return if STATES[:gentoo_update]
12
18
  puts "Downloading the last ebuilds for Gentoo..."
@@ -37,9 +43,9 @@ module Getch
37
43
  end
38
44
 
39
45
  def kernel_deps
40
- puts "Installing Garden..."
41
- get_garden
42
- garden_dep
46
+ Getch::Emerge.new("gentoolkit").pkg!
47
+ exec_chroot("euse -p sys-apps/kmod -E lzma")
48
+ @pkgs << "sys-apps/kmod"
43
49
  end
44
50
 
45
51
  def install_pkgs
@@ -52,22 +58,6 @@ module Getch
52
58
 
53
59
  private
54
60
 
55
- def get_garden
56
- return if Dir.exist? "#{MOUNTPOINT}/root/garden-master"
57
- url = 'https://github.com/szorfein/garden/archive/master.tar.gz'
58
- file = 'garden-master.tar.gz'
59
-
60
- Dir.chdir("#{MOUNTPOINT}/root")
61
- Helpers::get_file_online(url, file)
62
- Getch::Command.new("tar xzf #{file}").run! if ! Dir.exist? 'garden-master'
63
- end
64
-
65
- def garden_dep
66
- Getch::Emerge.new("gentoolkit").pkg!
67
- exec_chroot("euse -p sys-apps/kmod -E lzma")
68
- @pkgs << "sys-apps/kmod"
69
- end
70
-
71
61
  def mount
72
62
  puts "Populate /proc, /sys and /dev."
73
63
  Helpers::exec_or_die("mount --types proc /proc \"#{MOUNTPOINT}/proc\"")
@@ -80,11 +70,7 @@ module Getch
80
70
  end
81
71
 
82
72
  def exec_chroot(cmd)
83
- script = "chroot #{MOUNTPOINT} /bin/bash -c \"
84
- source /etc/profile
85
- #{cmd}
86
- \""
87
- Getch::Command.new(script).run!
73
+ Getch::Chroot.new(cmd).run!
88
74
  end
89
75
  end
90
76
  end
@@ -7,12 +7,32 @@ module Getch
7
7
  class Config
8
8
  def initialize
9
9
  @make = "#{MOUNTPOINT}/etc/portage/make.conf"
10
+ @log = Getch::Log.new
10
11
  end
11
12
 
12
13
  def portage
13
14
  nproc = `nproc`.chomp()
14
15
  grub_pc = Helpers::efi? ? '' : 'GRUB_PLATFORMS="pc"'
15
16
  quiet = DEFAULT_OPTIONS[:verbose] ? '' : "EMERGE_DEFAULT_OPTS=\"--jobs=#{nproc} --load-average=#{nproc}\""
17
+
18
+ # Add cpu name
19
+ cpu=`chroot #{MOUNTPOINT} /bin/bash -c \"source /etc/profile ; gcc -c -Q -march=native --help=target | grep march\" | awk '{print $2}' | head -1`.chomp
20
+ raise "Error, no cpu found" if ! cpu or cpu == ""
21
+ @log.debug "CPU found ==> #{cpu}"
22
+
23
+ tmp = Tempfile.new('make.conf')
24
+
25
+ File.open(@make).each { |l|
26
+ if l.match(/^COMMON_FLAGS/)
27
+ File.write(tmp, "COMMON_FLAGS=\"-march=#{cpu} -O2 -pipe\"\n", mode: 'a')
28
+ else
29
+ File.write(tmp, l, mode: 'a')
30
+ end
31
+ }
32
+
33
+ FileUtils.copy_file(tmp, @make, preserve = true)
34
+
35
+ # Add the rest
16
36
  data = [
17
37
  '',
18
38
  'ACCEPT_KEYWORDS="amd64"',
@@ -42,13 +62,13 @@ module Getch
42
62
  line_count += 1
43
63
  }
44
64
 
45
- FileUtils.copy_file(tmp, "#{dest}/gentoo.conf", preserve = false)
65
+ FileUtils.copy_file(tmp, "#{dest}/gentoo.conf", preserve = true)
46
66
  end
47
67
 
48
68
  def network
49
69
  src = '/etc/resolv.conf'
50
70
  dest = "#{MOUNTPOINT}/etc/resolv.conf"
51
- FileUtils.copy_file(src, dest, preserve = false)
71
+ FileUtils.copy_file(src, dest, preserve = true)
52
72
  end
53
73
 
54
74
  def systemd(options)