Project

General

Profile

Download (4.14 KB) Statistics
| Branch: | Tag: | Revision:

foreman-docker / app / models / foreman_docker / docker.rb @ f02a9ce2

1
require 'uri'
2

    
3
module ForemanDocker
4
  class Docker < ::ComputeResource
5
    validates :url, :format => { :with => URI.regexp }
6
    validates :email, :format => { :with => /.+@.+\..+/i }, :allow_blank => true
7

    
8
    def self.model_name
9
      ComputeResource.model_name
10
    end
11

    
12
    def self.get_container(container)
13
      conn = container.compute_resource.docker_connection
14
      ::Docker::Container.get(container.uuid, {}, conn)
15
    end
16

    
17
    def capabilities
18
      []
19
    end
20

    
21
    def supports_update?
22
      false
23
    end
24

    
25
    def provided_attributes
26
      super.merge(:mac => :mac)
27
    end
28

    
29
    def max_memory
30
      16 * 1024 * 1024 * 1024
31
    end
32

    
33
    def max_cpu_count
34
      ::Docker.info['NCPU'] || 1
35
    end
36

    
37
    def available_images
38
      ::Docker::Image.all({}, docker_connection)
39
    end
40

    
41
    def local_images(filter = '')
42
      ::Docker::Image.all({ 'filter' => filter }, docker_connection)
43
    end
44

    
45
    def tags_for_local_image(image)
46
      image.info['RepoTags'].map do |image_tag|
47
        _, tag = image_tag.split(':')
48
        tag
49
      end
50
    end
51

    
52
    def exist?(name)
53
      ::Docker::Image.exist?(name, {}, docker_connection)
54
    end
55

    
56
    def image(id)
57
      ::Docker::Image.get(id, {}, docker_connection)
58
    end
59

    
60
    def tags(image_name)
61
      if exist?(image_name)
62
        tags_for_local_image(image(image_name))
63
      else
64
        Service::RegistryApi.docker_hub.tags(image_name).map { |tag| tag['name'] }
65
      end
66
    end
67

    
68
    def search(term = '')
69
      client.images.image_search(:term => term)
70
    end
71

    
72
    def provider_friendly_name
73
      'Docker'
74
    end
75

    
76
    def create_container(args = {})
77
      options = vm_instance_defaults.merge(args)
78
      logger.debug("Creating container with the following options: #{options.inspect}")
79
      docker_command do
80
        ::Docker::Container.create(options, docker_connection)
81
      end
82
    end
83

    
84
    def create_image(args = {})
85
      logger.debug("Creating docker image with the following options: #{args.inspect}")
86
      docker_command do
87
        ::Docker::Image.create(args, credentials, docker_connection)
88
      end
89
    end
90

    
91
    def vm_instance_defaults
92
      ActiveSupport::HashWithIndifferentAccess.new('name' => "foreman_#{Time.now.to_i}",
93
                                                   'Cmd' => ['/bin/bash'])
94
    end
95

    
96
    def console(uuid)
97
      test_connection
98
      container = ::Docker::Container.get(uuid, {}, docker_connection)
99
      {
100
        :name       => container.info['Name'],
101
        'timestamp' => Time.now.utc,
102
        'output'    => container.logs(:stdout => true, :tail => 100)
103
      }
104
    end
105

    
106
    def api_version
107
      ::Docker.version(docker_connection)
108
    end
109

    
110
    def authenticate!
111
      ::Docker.authenticate!(credentials, docker_connection)
112
    end
113

    
114
    def test_connection(options = {})
115
      super
116
      api_version
117
      credentials.empty? ? true : authenticate!
118
    # This should only rescue Fog::Errors, but Fog returns all kinds of errors...
119
    rescue => e
120
      errors[:base] << e.message
121
      false
122
    end
123

    
124
    def docker_connection
125
      @docker_connection ||= ::Docker::Connection.new(url, credentials)
126
    end
127

    
128
    protected
129

    
130
    def docker_command
131
      yield
132
    rescue Excon::Errors::Error, ::Docker::Error::DockerError => e
133
      logger.debug "Fog error: #{e.message}\n " + e.backtrace.join("\n ")
134
      errors.add(:base,
135
                 _("Error creating communicating with Docker. Check the Foreman logs: %s") %
136
                 e.message.to_s)
137
      false
138
    end
139

    
140
    def bootstrap(args)
141
      client.servers.bootstrap vm_instance_defaults.merge(args.to_hash)
142
    rescue Fog::Errors::Error => e
143
      errors.add(:base, e.to_s)
144
      false
145
    end
146

    
147
    def client
148
      opts = {
149
        :provider => 'fogdocker',
150
        :docker_url => url
151
      }
152
      opts[:docker_username] = user if user.present?
153
      opts[:docker_password] = password if password.present?
154
      opts[:docker_email] = email if email.present?
155
      @client ||= ::Fog::Compute.new(opts)
156
    end
157

    
158
    def credentials
159
      @credentials ||= {}.tap do |options|
160
        options[:username] = user if user.present?
161
        options[:password] = password if password.present?
162
        options[:email] = email if email.present?
163
      end
164
    end
165
  end
166
end