Module: Beaker::HostPrebuiltSteps

Includes:
DSL::Patterns
Included in:
Hypervisor
Defined in:
lib/beaker/host_prebuilt_steps.rb

Overview

Provides convienience methods for commonly run actions on hosts

Constant Summary collapse

NTPSERVER =
'pool.ntp.org'
SLEEPWAIT =
5
TRIES =
5
UNIX_PACKAGES =
['curl', 'ntpdate']
WINDOWS_PACKAGES =
['curl']
SLES_PACKAGES =
['curl', 'ntp']
DEBIAN_PACKAGES =
['curl', 'ntpdate', 'lsb-release']
ETC_HOSTS_PATH =
"/etc/hosts"
ETC_HOSTS_PATH_SOLARIS =
"/etc/inet/hosts"
ROOT_KEYS_SCRIPT =
"https://raw.githubusercontent.com/puppetlabs/puppetlabs-sshkeys/master/templates/scripts/manage_root_authorized_keys"
ROOT_KEYS_SYNC_CMD =
"curl -k -o - -L #{ROOT_KEYS_SCRIPT} | %s"
APT_CFG =
%q{ Acquire::http::Proxy "http://proxy.puppetlabs.net:3128/"; }
IPS_PKG_REPO =
"http://solaris-11-internal-repo.delivery.puppetlabs.net"

Instance Method Summary collapse

Methods included from DSL::Patterns

#block_on

Instance Method Details

#add_el_extras(host, opts) ⇒ Object

Install EPEL on host or hosts with platform = /el-(5|6)/. Do nothing on host or hosts of other platforms.

Parameters:

  • host (Host, Array<Host>)

    One or more hosts to act upon. Will use individual host epel_url, epel_arch and epel_pkg before using defaults provided in opts.

  • opts (Hash{Symbol=>String})

    Options to alter execution.

Options Hash (opts):

  • :debug (Boolean)

    If true, print verbose rpm information when installing EPEL

  • :logger (Beaker::Logger)

    A Logger object

  • :epel_url (String)

    Link to download from

  • :epel_arch (String)

    Architecture of epel to download (i386, x86_64, etc)

  • :epel_6_pkg (String)

    Package to download from provided link for el-6

  • :epel_5_pkg (String)

    Package to download from provided link for el-5



230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/beaker/host_prebuilt_steps.rb', line 230

def add_el_extras( host, opts )
  #add_el_extras
  #only supports el-* platforms
  logger = opts[:logger]
  debug_opt = opts[:debug] ? 'vh' : ''
  block_on host do |host|
    case
    when host['platform'] =~ /el-(5|6)/
      result = host.exec(Command.new('rpm -qa | grep epel-release'), :acceptable_exit_codes => [0,1])
      if result.exit_code == 1
        url, arch, pkg = epel_info_for host, opts
        host.exec(Command.new("rpm -i#{debug_opt} #{url}/#{arch}/#{pkg}"))
        #update /etc/yum.repos.d/epel.repo for new baseurl
        host.exec(Command.new("sed -i -e 's;#baseurl.*$;baseurl=#{Regexp.escape(url)}/\$basearch;' /etc/yum.repos.d/epel.repo"))
        #remove mirrorlist
        host.exec(Command.new("sed -i -e '/mirrorlist/d' /etc/yum.repos.d/epel.repo"))
        host.exec(Command.new('yum clean all && yum makecache'))
      end
    else
      logger.debug "#{host}: package repo configuration not modified"
    end
  end
rescue => e
  report_and_raise(logger, e, "add_repos")
end

#apt_get_update(hosts) ⇒ Object

Run ‘apt-get update’ on the provided host or hosts. If the platform of the provided host is not ubuntu or debian do nothing.

Parameters:

  • hosts (Host, Array<Host>)

    One or more hosts to act upon



166
167
168
169
170
171
172
# File 'lib/beaker/host_prebuilt_steps.rb', line 166

def apt_get_update hosts
  block_on hosts do |host|
    if host[:platform] =~ /(ubuntu)|(debian)/
      host.exec(Command.new("apt-get update"))
    end
  end
end

#copy_file_to_remote(host, file_path, file_content) ⇒ Object

Create a file on host or hosts at the provided file path with the provided file contents.

Parameters:

  • host (Host, Array<Host>)

    One or more hosts to act upon

  • file_path (String)

    The path at which the new file will be created on the host or hosts.

  • file_content (String)

    The contents of the file to be created on the host or hosts.



178
179
180
181
182
183
184
185
186
# File 'lib/beaker/host_prebuilt_steps.rb', line 178

def copy_file_to_remote(host, file_path, file_content)
  block_on host do |host|
    Tempfile.open 'beaker' do |tempfile|
      File.open(tempfile.path, 'w') {|file| file.puts file_content }

      host.do_scp_to(tempfile.path, file_path, @options)
    end
  end
end

#copy_ssh_to_root(host, opts) ⇒ Object

Make it possible to log in as root by copying the current users ssh keys to the root account

Parameters:

  • host (Host, Array<Host>)

    One or more hosts to act upon

  • opts (Hash{Symbol=>String})

    Options to alter execution.

Options Hash (opts):



291
292
293
294
295
296
297
298
299
300
301
302
# File 'lib/beaker/host_prebuilt_steps.rb', line 291

def copy_ssh_to_root host, opts
  logger = opts[:logger]
  block_on host do |host|
    logger.debug "Give root a copy of current user's keys, on #{host.name}"
    if host['platform'] =~ /windows/
      host.exec(Command.new('cp -r .ssh /cygdrive/c/Users/Administrator/.'))
      host.exec(Command.new('chown -R Administrator /cygdrive/c/Users/Administrator/.ssh'))
    else
      host.exec(Command.new('sudo su -c "cp -r .ssh /root/."'), {:pty => true})
    end
  end
end

#disable_iptables(host, opts) ⇒ Object

Disable iptables on centos, does nothing on other platforms

Parameters:

  • host (Host, Array<Host>)

    One or more hosts to act upon

  • opts (Hash{Symbol=>String})

    Options to alter execution.

Options Hash (opts):



360
361
362
363
364
365
366
367
368
369
370
# File 'lib/beaker/host_prebuilt_steps.rb', line 360

def disable_iptables host, opts
  logger = opts[:logger]
  block_on host do |host|
    if host['platform'] =~ /centos|el-|redhat|fedora/
      logger.debug("Disabling iptables on #{host.name}")
      host.exec(Command.new("sudo su -c \"/etc/init.d/iptables stop\""), {:pty => true})
    else
      logger.warn("Attempting to disable iptables on non-supported platform: #{host.name}: #{host['platform']}")
    end
  end
end

#disable_se_linux(host, opts) ⇒ Object

Disable SELinux on centos, does nothing on other platforms

Parameters:

  • host (Host, Array<Host>)

    One or more hosts to act upon

  • opts (Hash{Symbol=>String})

    Options to alter execution.

Options Hash (opts):



344
345
346
347
348
349
350
351
352
353
354
# File 'lib/beaker/host_prebuilt_steps.rb', line 344

def disable_se_linux host, opts
  logger = opts[:logger]
  block_on host do |host|
    if host['platform'] =~ /centos|el-|redhat|fedora/
      @logger.debug("Disabling se_linux on #{host.name}")
      host.exec(Command.new("sudo su -c \"setenforce 0\""), {:pty => true})
    else
      @logger.warn("Attempting to disable SELinux on non-supported platform: #{host.name}: #{host['platform']}")
    end
  end
end

#enable_root_login(host, opts) ⇒ Object

Update sshd_config on debian, ubuntu, centos, el, redhat and fedora boxes to allow for root login, does nothing on other platfoms

Parameters:

  • host (Host, Array<Host>)

    One or more hosts to act upon

  • opts (Hash{Symbol=>String})

    Options to alter execution.

Options Hash (opts):



323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/beaker/host_prebuilt_steps.rb', line 323

def  host, opts
  logger = opts[:logger]
  block_on host do |host|
    logger.debug "Update /etc/ssh/sshd_config to allow root login"
    host.exec(Command.new("sudo su -c \"sed -i 's/PermitRootLogin no/PermitRootLogin yes/' /etc/ssh/sshd_config\""), {:pty => true}
  )
    #restart sshd
    if host['platform'] =~ /debian|ubuntu/
      host.exec(Command.new("sudo su -c \"service ssh restart\""), {:pty => true})
    elsif host['platform'] =~ /centos|el-|redhat|fedora/
      host.exec(Command.new("sudo su -c \"service sshd restart\""), {:pty => true})
    else
      @logger.warn("Attempting to update ssh on non-supported platform: #{host.name}: #{host['platform']}")
    end
  end
end

#epel_info_for(host, opts) ⇒ String

Determine the Extra Packages for Enterprise Linux URL for the provided Enterprise Linux host.

Parameters:

  • host (Host, Array<Host>)

    One host to act on. Will use host epel_url, epel_arch and epel_pkg before using defaults provided in opts.

  • opts (Hash{Symbol=>String})

    Options to alter execution.

Options Hash (opts):

  • :epel_url (String)

    Link to download

  • :epel_arch (String)

    Architecture to download (i386, x86_64, etc), defaults to i386

  • :epel_6_pkg (String)

    Package to download from provided link for el-6

  • :epel_5_pkg (String)

    Package to download from provided link for el-5

Returns:

  • (String, String, String)

    The URL, arch and package name for EPL for the provided host

Raises:

  • (Exception)

    Raises an error if the host provided’s platform != /el-(5|6)/



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/beaker/host_prebuilt_steps.rb', line 146

def epel_info_for host, opts
  version = host['platform'].version
  if not version
    raise "epel_info_for not available for #{host.name} on platform #{host['platform']}"
  end
  if version == '6'
    url = "#{host[:epel_url] || opts[:epel_url]}/#{version}"
    pkg = host[:epel_pkg] || opts[:epel_6_pkg]
  elsif version == '5'
    url = "#{host[:epel_url] || opts[:epel_url]}/#{version}"
    pkg = host[:epel_pkg] || opts[:epel_5_pkg]
  else
    raise "epel_info_for does not support el version #{version}, on #{host.name}"
  end
  return url, host[:epel_arch] || opts[:epel_arch] || 'i386', pkg
end

#get_domain_name(host) ⇒ Object

Determine the domain name of the provided host from its /etc/resolv.conf

Parameters:

  • host (Host)

    the host to act upon



258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/beaker/host_prebuilt_steps.rb', line 258

def get_domain_name(host)
  domain = nil
  search = nil
  resolv_conf = host.exec(Command.new("cat /etc/resolv.conf")).stdout
  resolv_conf.each_line { |line|
    if line =~ /^\s*domain\s+(\S+)/
      domain = $1
    elsif line =~ /^\s*search\s+(\S+)/
      search = $1
    end
  }
  return domain if domain
  return search if search
end

#get_ip(host) ⇒ Object

Deprecated.

Determine the ip address of the provided host

Parameters:

  • host (Host)

    the host to act upon



276
277
278
# File 'lib/beaker/host_prebuilt_steps.rb', line 276

def get_ip(host)
  host.get_ip
end

#hack_etc_hosts(hosts, opts) ⇒ Object

Update /etc/hosts to make it possible for each provided host to reach each other host by name. Assumes that each provided host has host set.

Parameters:

  • hosts (Host, Array<Host>)

    An array of hosts to act upon

  • opts (Hash{Symbol=>String})

    Options to alter execution.

Options Hash (opts):



309
310
311
312
313
314
315
316
317
# File 'lib/beaker/host_prebuilt_steps.rb', line 309

def hack_etc_hosts hosts, opts
  etc_hosts = "127.0.0.1\tlocalhost localhost.localdomain\n"
  hosts.each do |host|
    etc_hosts += "#{host['ip'].to_s}\t#{host[:vmhostname] || host.name}\n"
  end
  hosts.each do |host|
    set_etc_hosts(host, etc_hosts)
  end
end

#package_proxy(host, opts) ⇒ Object

Setup files for enabling requests to pass to a proxy server This works for the APT package manager on debian and ubuntu and YUM package manager on el, centos, fedora and redhat.

Parameters:

  • host (Host, Array<Host>, String, Symbol)

    One or more hosts to act upon

  • opts (Hash{Symbol=>String})

    Options to alter execution.

Options Hash (opts):



378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
# File 'lib/beaker/host_prebuilt_steps.rb', line 378

def package_proxy host, opts
  logger = opts[:logger]

  block_on host do |host|
    logger.debug("enabling proxy support on #{host.name}")
    case host['platform']
      when /ubuntu/, /debian/
        host.exec(Command.new("echo 'Acquire::http::Proxy \"#{opts[:package_proxy]}/\";' >> /etc/apt/apt.conf.d/10proxy"))
      when /^el-/, /centos/, /fedora/, /redhat/
        host.exec(Command.new("echo 'proxy=#{opts[:package_proxy]}/' >> /etc/yum.conf"))
    else
      logger.debug("Attempting to enable package manager proxy support on non-supported platform: #{host.name}: #{host['platform']}")
    end
  end
end

#proxy_config(host, opts) ⇒ Object

Alter apt configuration on ubuntu and debian host or hosts to internal Puppet Labs proxy APT_CFG proxy, alter pkg on solaris-11 host or hosts to point to interal Puppetlabs proxy IPS_PKG_REPO. Do nothing on non-ubuntu, debian or solaris-11 platform host or hosts.

Parameters:

  • host (Host, Array<Host>)

    One or more hosts to act upon

  • opts (Hash{Symbol=>String})

    Options to alter execution.

Options Hash (opts):



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/beaker/host_prebuilt_steps.rb', line 195

def proxy_config( host, opts )
  # repo_proxy
  # supports ubuntu, debian and solaris platforms
  logger = opts[:logger]
  block_on host do |host|
    case
    when host['platform'] =~ /ubuntu/
      host.exec(Command.new("if test -f /etc/apt/apt.conf; then mv /etc/apt/apt.conf /etc/apt/apt.conf.bk; fi"))
      copy_file_to_remote(host, '/etc/apt/apt.conf', APT_CFG)
      apt_get_update(host)
    when host['platform'] =~ /debian/
      host.exec(Command.new("if test -f /etc/apt/apt.conf; then mv /etc/apt/apt.conf /etc/apt/apt.conf.bk; fi"))
      copy_file_to_remote(host, '/etc/apt/apt.conf', APT_CFG)
      apt_get_update(host)
    when host['platform'] =~ /solaris-11/
      host.exec(Command.new("/usr/bin/pkg unset-publisher solaris || :"))
      host.exec(Command.new("/usr/bin/pkg set-publisher -g %s solaris" % IPS_PKG_REPO))
    else
      logger.debug "#{host}: repo proxy configuration not modified"
    end
  end
rescue => e
  report_and_raise(logger, e, "proxy_config")
end

#set_etc_hosts(host, etc_hosts) ⇒ Object

Append the provided string to the /etc/hosts file of the provided host

Parameters:

  • host (Host)

    the host to act upon

  • etc_hosts (String)

    The string to append to the /etc/hosts file



283
284
285
# File 'lib/beaker/host_prebuilt_steps.rb', line 283

def set_etc_hosts(host, etc_hosts)
  host.exec(Command.new("echo '#{etc_hosts}' > /etc/hosts"))
end

#sync_root_keys(host, opts) ⇒ Object

Install a set of authorized keys using ROOT_KEYS_SCRIPT. This is a convenience method to allow for easy login to hosts after they have been provisioned with Beaker.

Parameters:

  • host (Host, Array<Host>)

    One or more hosts to act upon

  • opts (Hash{Symbol=>String})

    Options to alter execution.

Options Hash (opts):



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/beaker/host_prebuilt_steps.rb', line 117

def sync_root_keys host, opts
  # JJM This step runs on every system under test right now.  We're anticipating
  # issues on Windows and maybe Solaris.  We will likely need to filter this step
  # but we're deliberately taking the approach of "assume it will work, fix it
  # when reality dictates otherwise"
  logger = opts[:logger]
  block_on host do |host|
  logger.notify "Sync root authorized_keys from github on #{host.name}"
    # Allow all exit code, as this operation is unlikely to cause problems if it fails.
    if host['platform'].include? 'solaris'
      host.exec(Command.new(ROOT_KEYS_SYNC_CMD % "bash"), :acceptable_exit_codes => (0..255))
    else
      host.exec(Command.new(ROOT_KEYS_SYNC_CMD % "env PATH=/usr/gnu/bin:$PATH bash"), :acceptable_exit_codes => (0..255))
    end
  end
rescue => e
  report_and_raise(logger, e, "sync_root_keys")
end

#timesync(host, opts) ⇒ Object

Run timesync on the provided hosts

Parameters:

  • host (Host, Array<Host>)

    One or more hosts to act upon

  • opts (Hash{Symbol=>String})

    Options to alter execution.

Options Hash (opts):



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
# File 'lib/beaker/host_prebuilt_steps.rb', line 28

def timesync host, opts
  logger = opts[:logger]
  ntp_server = opts[:ntp_server] ? opts[:ntp_server] : NTPSERVER
  block_on host do |host|
    logger.notify "Update system time sync for '#{host.name}'"
    if host['platform'].include? 'windows'
      # The exit code of 5 is for Windows 2008 systems where the w32tm /register command
      # is not actually necessary.
      host.exec(Command.new("w32tm /register"), :acceptable_exit_codes => [0,5])
      host.exec(Command.new("net start w32time"), :acceptable_exit_codes => [0,2])
      host.exec(Command.new("w32tm /config /manualpeerlist:#{ntp_server} /syncfromflags:manual /update"))
      host.exec(Command.new("w32tm /resync"))
      logger.notify "NTP date succeeded on #{host}"
    else
      case
        when host['platform'] =~ /sles-/
          ntp_command = "sntp #{ntp_server}"
        else
          ntp_command = "ntpdate -t 20 #{ntp_server}"
      end
      success=false
      try = 0
      until try >= TRIES do
        try += 1
        if host.exec(Command.new(ntp_command), :acceptable_exit_codes => (0..255)).exit_code == 0
          success=true
          break
        end
        sleep SLEEPWAIT
      end
      if success
        logger.notify "NTP date succeeded on #{host} after #{try} tries"
      else
        raise "NTP date was not successful after #{try} tries"
      end
    end
  end
rescue => e
  report_and_raise(logger, e, "timesync (--ntp)")
end

#validate_host(host, opts) ⇒ Object

Validate that hosts are prepared to be used as SUTs, if packages are missing attempt to install them. Verifies the presence of #UNIX_PACKAGES on unix platform hosts, SLES_PACKAGES on SUSE platform hosts, #on debian platform hosts and {HostPrebuiltSteps::WINDOWS_PACKAGES on windows platforms.

Parameters:

  • host (Host, Array<Host>, String, Symbol)

    One or more hosts to act upon

  • opts (Hash{Symbol=>String})

    Options to alter execution.

Options Hash (opts):



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
# File 'lib/beaker/host_prebuilt_steps.rb', line 77

def validate_host host, opts
  logger = opts[:logger]
  block_on host do |host|
    case
    when host['platform'] =~ /sles-/
      SLES_PACKAGES.each do |pkg|
        if not host.check_for_package pkg
          host.install_package pkg
        end
      end
    when host['platform'] =~ /debian/
      DEBIAN_PACKAGES.each do |pkg|
        if not host.check_for_package pkg
          host.install_package pkg
        end
      end
    when host['platform'] =~ /windows/
      WINDOWS_PACKAGES.each do |pkg|
        if not host.check_for_package pkg
          host.install_package pkg
        end
      end
    when host['platform'] !~ /debian|aix|solaris|windows|sles-|osx-/
      UNIX_PACKAGES.each do |pkg|
        if not host.check_for_package pkg
          host.install_package pkg
        end
      end
    end
  end
rescue => e
  report_and_raise(logger, e, "validate")
end