Class: ChefBackup::Strategy::TarRestore

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Exceptions, Helpers, Mixin::DeepMerge
Defined in:
lib/chef_backup/strategy/restore/tar.rb

Overview

Basic Tar Restore Strategy

Constant Summary

Constants included from Helpers

Helpers::DEFAULT_PG_OPTIONS, Helpers::SERVER_ADD_ONS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Mixin::DeepMerge

#deep_merge, #deep_merge!, #hash_only_merge, #hash_only_merge!, #merge, #safe_dup

Methods included from Helpers

#addon_install_dir, #all_services, #backend?, #base_config_dir, #base_install_dir, #chpst, #cleanup, #config, #config_base, #ctl_command, #database_name, #disabled_services, #enabled_addons, #enabled_services, #ensure_file!, #frontend?, #ha?, #log, #marketplace?, #online?, #pg_options, #pgsql, #project_name, #reconfigure_add_ons, #reconfigure_marketplace, #restart_add_ons, #restart_chef_server, #running_filepath, #service_config, #service_enabled?, #shell_out, #shell_out!, #shell_timeout, #standalone?, #start_chef_server, #start_service, #stop_chef_server, #stop_service, #strategy, #tier?, #tmp_dir, #topology, #version_from_manifest_file

Constructor Details

#initialize(path) ⇒ TarRestore

Returns a new instance of TarRestore.



22
23
24
25
# File 'lib/chef_backup/strategy/restore/tar.rb', line 22

def initialize(path)
  @tarball_path = path
  @log = ChefBackup::Logger.logger(service_config["backup"]["logfile"] || nil)
end

Instance Attribute Details

#manifestObject



52
53
54
55
56
57
58
59
# File 'lib/chef_backup/strategy/restore/tar.rb', line 52

def manifest
  @manifest ||= begin
    manifest = File.expand_path(File.join(ChefBackup::Config["restore_dir"],
      "manifest.json"))
    ensure_file!(manifest, InvalidManifest, "#{manifest} not found")
    JSON.parse(File.read(manifest))
  end
end

#tarball_pathObject

Returns the value of attribute tarball_path.



17
18
19
# File 'lib/chef_backup/strategy/restore/tar.rb', line 17

def tarball_path
  @tarball_path
end

Instance Method Details

#backup_nameObject



112
113
114
# File 'lib/chef_backup/strategy/restore/tar.rb', line 112

def backup_name
  @backup_name ||= Pathname.new(tarball_path).basename.sub_ext("").to_s
end

#check_ha_volumeObject



146
147
148
149
150
151
152
153
# File 'lib/chef_backup/strategy/restore/tar.rb', line 146

def check_ha_volume
  log "Checking that the HA storage volume is mounted"
  ha_data_dir = manifest["ha"]["path"]

  unless ha_data_dir_mounted?(ha_data_dir)
    raise "Please mount the data directory #{ha_data_dir} and perform any DRBD configuration before continuing"
  end
end

#check_manifest_versionObject



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/chef_backup/strategy/restore/tar.rb', line 116

def check_manifest_version
  unless manifest["versions"]
    log "no version information in manifest"
    return true
  end

  manifest["versions"].each_pair do |name, data|
    installed = version_from_manifest_file(data["path"])

    if installed == :no_version
      log "Warning: #{name} @ #{data["version"]} not installed"
    elsif installed["version"] != data["version"]
      log "package #{name} #{installed["version"]} installed, but backup was"\
          " from #{data["version"]}. Please install correct version, restore, then upgrade."
      return false
    end
  end
  true
end

#cleanse_chef_server(agree) ⇒ Object



170
171
172
173
174
175
176
177
178
# File 'lib/chef_backup/strategy/restore/tar.rb', line 170

def cleanse_chef_server(agree)
  log "Cleaning up any old files"
  # The chef-server-ctl cleanse command deliberately waits 60 seconds to give
  # you an option to cancel it.  Therefore, don't count it in the timeout that
  # the user provided.  If the user has eagerly dismissed that wait period,
  # then don't elongate the timeout.  The user can do this with the -c flag.
  timeout = shell_timeout + (agree ? 0 : 60) if shell_timeout
  shell_out!("#{ctl_command} cleanse #{agree || ""}", "timeout" => timeout)
end

#fix_ha_pluginsObject



136
137
138
139
140
141
142
143
144
# File 'lib/chef_backup/strategy/restore/tar.rb', line 136

def fix_ha_plugins
  log "Fixing HA plugins directory (https://github.com/chef/chef-server/issues/115)"
  plugins_dir = "/var/opt/opscode/plugins"
  drbd_plugin = File.join(plugins_dir, "chef-ha-drbd.rb")

  FileUtils.mkdir_p(plugins_dir) unless Dir.exist?(plugins_dir)
  FileUtils.ln_sf("/opt/opscode/chef-server-plugin.rb", drbd_plugin) unless
    File.exist?(drbd_plugin)
end

#ha_data_dir_mounted?(ha_data_dir) ⇒ Boolean

Returns:

  • (Boolean)


155
156
157
# File 'lib/chef_backup/strategy/restore/tar.rb', line 155

def ha_data_dir_mounted?(ha_data_dir)
  File.read("/proc/mounts").split("\n").grep(/#{ha_data_dir}/).count > 0
end

#import_dbObject



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/chef_backup/strategy/restore/tar.rb', line 67

def import_db
  start_service("postgresql")
  sql_file = File.join(ChefBackup::Config["restore_dir"],
    "chef_backup-#{manifest["backup_time"]}.sql")
  ensure_file!(sql_file, InvalidDatabaseDump, "#{sql_file} not found")

  cmd = [chpst,
         "-u #{manifest["services"]["postgresql"]["username"]}",
         pgsql,
         "-U #{manifest["services"]["postgresql"]["username"]}",
         "-d #{database_name}",
         "< #{sql_file}"].join(" ")
  log "Importing Database dump"
  shell_out!(cmd, env: ["PGOPTIONS=#{pg_options}"])
end

#reconfigure_serverObject



165
166
167
168
# File 'lib/chef_backup/strategy/restore/tar.rb', line 165

def reconfigure_server
  log "Reconfiguring the Chef Server"
  shell_out("#{ctl_command} reconfigure")
end

#restoreObject



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/chef_backup/strategy/restore/tar.rb', line 27

def restore
  log "Restoring Chef Server from backup"
  return unless check_manifest_version

  cleanse_chef_server(config["agree_to_cleanse"])
  if ha?
    log "Performing HA restore - please ensure that keepalived is not running on the standby host"
    fix_ha_plugins
    check_ha_volume
    touch_drbd_ready
  end
  restore_configs
  restore_services unless frontend?
  touch_sentinel
  reconfigure_marketplace if marketplace?
  reconfigure_server
  update_config
  import_db if restore_db_dump?
  start_chef_server
  reconfigure_add_ons
  restart_add_ons
  cleanup
  log "Restoration Completed!"
end

#restore_configsObject



89
90
91
92
93
# File 'lib/chef_backup/strategy/restore/tar.rb', line 89

def restore_configs
  manifest.key?("configs") && manifest["configs"].keys.each do |config|
    restore_data(:configs, config)
  end
end

#restore_data(type, name) ⇒ Object



102
103
104
105
106
107
108
109
110
# File 'lib/chef_backup/strategy/restore/tar.rb', line 102

def restore_data(type, name)
  source = File.expand_path(File.join(config["restore_dir"],
    manifest[type.to_s][name]["data_dir"]))
  destination = manifest[type.to_s][name]["data_dir"]
  FileUtils.mkdir_p(destination) unless File.directory?(destination)
  cmd = "rsync -chaz --delete #{source}/ #{destination}"
  log "Restoring the #{name} data"
  shell_out!(cmd)
end

#restore_db_dump?Boolean

Returns:

  • (Boolean)


61
62
63
64
65
# File 'lib/chef_backup/strategy/restore/tar.rb', line 61

def restore_db_dump?
  manifest["services"]["postgresql"]["pg_dump_success"] && !frontend?
rescue NoMethodError
  false
end

#restore_servicesObject



83
84
85
86
87
# File 'lib/chef_backup/strategy/restore/tar.rb', line 83

def restore_services
  manifest.key?("services") && manifest["services"].keys.each do |service|
    restore_data(:services, service)
  end
end

#running_configObject



180
181
182
183
# File 'lib/chef_backup/strategy/restore/tar.rb', line 180

def running_config
  @running_config ||=
    JSON.parse(File.read(running_filepath)) || {}
end

#touch_drbd_readyObject



159
160
161
162
163
# File 'lib/chef_backup/strategy/restore/tar.rb', line 159

def touch_drbd_ready
  log "Touching drbd_ready file"
  FileUtils.touch("/var/opt/opscode/drbd/drbd_ready") unless
    File.exist?("/var/opt/opscode/drbd/drbd_ready")
end

#touch_sentinelObject



95
96
97
98
99
100
# File 'lib/chef_backup/strategy/restore/tar.rb', line 95

def touch_sentinel
  dir = "/var/opt/opscode"
  sentinel = File.join(dir, "bootstrapped")
  FileUtils.mkdir_p(dir) unless File.directory?(dir)
  File.open(sentinel, "w") { |file| file.write "bootstrapped!" }
end

#update_configObject



185
186
187
# File 'lib/chef_backup/strategy/restore/tar.rb', line 185

def update_config
  ChefBackup::Config.config = deep_merge(config.dup, running_config)
end