Class: HybridPlatformsConductor::HpcPlugins::Provisioner::Docker

Inherits:
Provisioner
  • Object
show all
Defined in:
lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb

Overview

Provision Docker containers

Constant Summary

Constants included from LoggerHelpers

LoggerHelpers::LEVELS_MODIFIERS, LoggerHelpers::LEVELS_TO_STDERR

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Provisioner

#default_timeout, #initialize, #wait_for_port, #wait_for_port!, #wait_for_state, #wait_for_state!, #with_running_instance

Methods included from LoggerHelpers

#err, #init_loggers, #log_component=, #log_debug?, #log_level=, #out, #section, #set_loggers_format, #stderr_device, #stderr_device=, #stderr_displayed?, #stdout_device, #stdout_device=, #stdout_displayed?, #stdouts_to_s, #with_progress_bar

Methods inherited from Plugin

extend_config_dsl_with, #initialize

Constructor Details

This class inherits a constructor from HybridPlatformsConductor::Provisioner

Class Method Details

.valid?Boolean

Are dependencies met before using this plugin?

API
  • This method is optional

Result
  • Boolean: Are dependencies met before using this plugin?

Returns:

  • (Boolean)


18
19
20
21
22
23
24
25
26
27
# File 'lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb', line 18

def self.valid?
  docker_ok = false
  begin
    ::Docker.validate_version!
    docker_ok = true
  rescue
    log_error "[ #{@node}/#{@environment} ] - Docker is not installed correctly. Please install it. Error: #{$!}"
  end
  docker_ok
end

Instance Method Details

#createObject

Create an instance. Reuse an existing one if it already exists.

API
  • This method is mandatory



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
# File 'lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb', line 32

def create
  # Get the image name for this node
  image = @nodes_handler.get_image_of(@node).to_sym
  # Find if we have such an image registered
  if @config.known_os_images.include?(image)
    # Build the image if it does not exist
    image_tag = "hpc_image_#{image}"
    docker_image = nil
    image_futex_file = "#{Dir.tmpdir}/hpc_docker_image_futexes/#{image_tag}"
    FileUtils.mkdir_p File.dirname(image_futex_file)
    Futex.new(image_futex_file).open do
      docker_image = ::Docker::Image.all.find { |search_image| !search_image.info['RepoTags'].nil? && search_image.info['RepoTags'].include?("#{image_tag}:latest") }
      unless docker_image
        log_debug "[ #{@node}/#{@environment} ] - Creating Docker image #{image_tag}..."
        Excon.defaults[:read_timeout] = 600
        docker_image = ::Docker::Image.build_from_dir(@config.os_image_dir(image))
        docker_image.tag repo: image_tag
      end
    end
    container_name = "hpc_docker_container_#{@node}_#{@environment}"
    container_futex_file = "#{Dir.tmpdir}/hpc_docker_container_futexes/#{image_tag}"
    FileUtils.mkdir_p File.dirname(container_futex_file)
    Futex.new(container_futex_file).open do
      old_docker_container = ::Docker::Container.all(all: true).find { |container| container.info['Names'].include? "/#{container_name}" }
      @container =
        if old_docker_container
          old_docker_container
        else
          log_debug "[ #{@node}/#{@environment} ] - Creating Docker container #{container_name}..."
          # We add the SYS_PTRACE capability as some images need to restart services (for example postfix) and those services need the rights to ls in /proc/{PID}/exe to check if a status is running. Without SYS_PTRACE such ls returns permission denied and the service can't be stopped (as init.d always returns it as stopped even when running).
          # We add the privileges as some containers need to install and configure the udev package, which needs RW access to /sys.
          # We add the bind to cgroup volume to be able to test systemd specifics (enabling/disabling services for example).
          ::Docker::Container.create(
            name: container_name,
            image: image_tag,
            CapAdd: 'SYS_PTRACE',
            Privileged: true,
            Binds: ['/sys/fs/cgroup:/sys/fs/cgroup:ro'],
            # Some playbooks need the hostname to be set to a correct FQDN
            Hostname: "#{@node}.testdomain"
          )
        end
    end
  else
    raise "[ #{@node}/#{@environment} ] - Unknown OS image #{image} defined for node #{@node}"
  end
end

#destroyObject

Destroy an instance Prerequisite: create has been called before

API
  • This method is mandatory



99
100
101
102
103
# File 'lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb', line 99

def destroy
  log_debug "[ #{@node}/#{@environment} ] - Destroy Docker Container #{@container.refresh!.info['Name'][1..-1]} ..."
  @container.remove
  @container = nil
end

#ipObject

Return the IP address of an instance. Prerequisite: create has been called before.

API
  • This method is optional

Result
  • String or nil: The instance IP address, or nil if this information is not relevant



134
135
136
137
138
139
140
# File 'lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb', line 134

def ip
  # Get its IP that could have changed upon restart
  # cf https://github.com/moby/moby/issues/2801
  # Make sure we refresh its info before querying it, as we could hit a cache of a previous IP.
  @container.refresh!
  @container.json['NetworkSettings']['IPAddress']
end

#startObject

Start an instance Prerequisite: create has been called before

API
  • This method is mandatory



83
84
85
86
# File 'lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb', line 83

def start
  log_debug "[ #{@node}/#{@environment} ] - Start Docker Container #{@container.refresh!.info['Name'][1..-1]} ..."
  @container.start
end

#stateObject

Return the state of an instance

API
  • This method is mandatory

Result
  • Symbol: The state the instance is in. Possible values are:

    • :missing: The instance does not exist

    • :created: The instance has been created but is not running

    • :running: The instance is running

    • :exited: The instance has run and is now stopped

    • :error: The instance is in error



115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb', line 115

def state
  if !defined?(@container) || @container.nil?
    :missing
  else
    begin
      @container.refresh!.info['State']['Status'].to_sym
    rescue
      log_error "[ #{@node}/#{@environment} ] - Error while reading state of Docker container: #{$!}"
      :error
    end
  end
end

#stopObject

Stop an instance Prerequisite: create has been called before

API
  • This method is mandatory



91
92
93
94
# File 'lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb', line 91

def stop
  log_debug "[ #{@node}/#{@environment} ] - Stop Docker Container #{@container.refresh!.info['Name'][1..-1]} ..."
  @container.stop
end