/
before_fb_fstab.rb
156 lines (146 loc) · 5.42 KB
/
before_fb_fstab.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#
# Cookbook Name:: fb_swap
# Recipe:: before_fb_fstab
#
# Copyright (c) 2016-present, Facebook, Inc.
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require 'shellwords'
# Newly provisioned hosts end up with a swap device in /etc/fstab which
# is referenced by UUID (or label, or path). We use data from ohai's
# filesystem2 plugin (which is backed by the state of the machine, not what
# is in /etc/fstab). We want to create/manage our own units with predictable
# names
#
node.default['fb_fstab']['exclude_base_swap'] = true
whyrun_safe_ruby_block 'Validate and calculate swap sizes' do
block do
FB::FbSwap._validate(node)
end
end
template '/usr/local/libexec/manage-additional-swap-file' do
source 'manage-additional-swap-file.sh.erb'
owner 'root'
group 'root'
# read/execute for root, read only for everyone else.
mode '0544'
notifies :run, 'execute[manage-additional-swap-file]', :immediately
end
execute 'manage-additional-swap-file' do
only_if do
node['fb_swap']['_calculated']['additional_file_size_bytes'].
positive? &&
node['fb_swap']['_calculated']['additional_file_current_size_bytes'].
negative?
end
command '/usr/local/libexec/manage-additional-swap-file'
end
['device', 'file', 'additional_file'].each do |type|
next if type == 'device' && FB::FbSwap._device(node).nil?
whyrun_safe_ruby_block "Add #{type} swap to fstab" do
only_if { node['fb_swap']['_calculated']["#{type}_size_bytes"].positive? }
block do
# ask fb_fstab to create the unit
device = FB::FbSwap._path(node, type)
if type == 'device'
label = FB::FbSwap._label(node)
if label
device = "LABEL=#{label}"
end
end
node.default['fb_fstab']['mounts']["swap_#{type}"] = {
'mount_point' => 'swap',
'device' => device,
'type' => 'swap',
# prioritize swap file in case that swap partition is on a spinning disk
'opts' => type == 'device' ? 'pri=5' : 'pri=10',
}
end
end
end
['device', 'file'].each do |type|
next if type == 'device' && FB::FbSwap._device(node).nil?
manage_unit = "manage-swap-#{type}.service"
template "/etc/systemd/system/#{manage_unit}" do
source "#{manage_unit}.erb"
owner 'root'
group 'root'
mode '0644'
notifies :run, 'fb_systemd_reload[system instance]', :immediately
notifies :restart, "service[#{manage_unit}]"
end
# Note: FC022 is masked because the unit name is derived from the type
# variable in the loop
service manage_unit do # ~FC022
# we can get restarted, but we don't need to enable/start this explicitly
# due to the use of BindsTo on the swap unit
action :nothing
# make the resource disappear if the measured size is the same as the
# expected size. This fixes the bootstrap case where manage_unit
# is first created and swap is already enabled and correct.
not_if do
node['fb_swap']['_calculated']["#{type}_size_bytes"] ==
node['fb_swap']['_calculated']["#{type}_current_size_bytes"]
end
# Restarting this unit itself is fairly fast but it's tied to the swap unit
# by a PartOf relationship. The systemd provider for the service resource
# will block because systemctl will block until the service is started.
#
# The systemd provider for the service resource has no way to pass
# --no-block to systemctl, so we have to call it ourselves.
restart_command '/usr/bin/systemctl --system --no-block restart ' +
Shellwords.escape(manage_unit)
end
# Override the fb_fstab -> fstab-generator unit with some extra deps
# Note that swap units are more limited in what systemd options they
# take from the options column.
fb_systemd_override "#{type} swap override" do
only_if { node['fb_swap']['_calculated']["#{type}_size_bytes"].positive? }
override_name 'manage'
unit_name lazy { FB::FbSwap._swap_unit(node, type) }
content(
lazy do
{
'Unit' => {
'BindsTo' => manage_unit,
'After' => manage_unit,
'PartOf' => manage_unit,
},
# Stopping swap is pathologically slow on Linux today. The general
# default for stopping units in systemd is 90s. Here we'll use
# 100s per GiB as a heuristic on top of the default.
'Swap' => {
'TimeoutSec' => 90 + 100 *
(node['fb_swap']['_calculated']["#{type}_size_bytes"] / 2**30),
},
}
end,
)
end
fb_systemd_override "remove #{type} swap override" do
not_if { node['fb_swap']['_calculated']["#{type}_size_bytes"].positive? }
override_name 'manage'
unit_name lazy { FB::FbSwap._swap_unit(node, type) }
action :delete
end
end
template '/usr/local/libexec/manage-swap-file' do
source 'manage-swap-file.sh.erb'
owner 'root'
group 'root'
# read/execute for root, read only for everyone else.
mode '0544'
notifies :restart, 'service[manage-swap-file.service]', :immediately
end