Class: ClusterChef::Server

Inherits:
ComputeBuilder show all
Defined in:
lib/cluster_chef/server.rb,
lib/cluster_chef/deprecated.rb

Overview

A server is a specific (logical) member of a facet within a cluster.

It may have extra attributes if it also exists in the Chef server, or if it exists in the real world (as revealed by Fog)

Instance Attribute Summary collapse

Attributes inherited from ComputeBuilder

#chef_roles, #cloud, #volumes

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from ComputeBuilder

#bogus?, #ec2, #raid_group, #recipe, #role, role_implication, #root_volume, #run_list, #run_list_groups, #volume

Methods inherited from DslObject

#configure, #die, #dump, has_keys, #reverse_merge!, #safely, #set, #step, #to_hash, #to_mash, #ui, ui

Constructor Details

#initialize(facet, idx) ⇒ Server

Returns a new instance of Server.



15
16
17
18
19
20
21
22
23
24
# File 'lib/cluster_chef/server.rb', line 15

def initialize facet, idx
  @cluster     = facet.cluster
  @facet       = facet
  @facet_index = idx
  @fullname    = [cluster_name, facet_name, facet_index].join('-')
  super(@fullname)
  @tags = { "name" => name, "cluster" => cluster_name, "facet"   => facet_name, "index" => facet_index, }
  ui.warn("Duplicate server #{[self, facet.name, idx]} vs #{@@all[fullname]}") if @@all[fullname]
  @@all[fullname] = self
end

Instance Attribute Details

#chef_nodeObject

Returns the value of attribute chef_node.



11
12
13
# File 'lib/cluster_chef/server.rb', line 11

def chef_node
  @chef_node
end

#clusterObject (readonly)

Returns the value of attribute cluster.



10
11
12
# File 'lib/cluster_chef/server.rb', line 10

def cluster
  @cluster
end

#facetObject (readonly)

Returns the value of attribute facet.



10
11
12
# File 'lib/cluster_chef/server.rb', line 10

def facet
  @facet
end

#facet_indexObject (readonly)

Returns the value of attribute facet_index.



10
11
12
# File 'lib/cluster_chef/server.rb', line 10

def facet_index
  @facet_index
end

#fog_serverObject

Returns the value of attribute fog_server.



11
12
13
# File 'lib/cluster_chef/server.rb', line 11

def fog_server
  @fog_server
end

#tagsObject (readonly)

Returns the value of attribute tags.



10
11
12
# File 'lib/cluster_chef/server.rb', line 10

def tags
  @tags
end

Class Method Details

.allObject



222
223
224
# File 'lib/cluster_chef/server.rb', line 222

def self.all
  @@all
end

.get(cluster_name, facet_name, facet_index) ⇒ Object

retrieval



211
212
213
214
215
216
217
218
219
220
# File 'lib/cluster_chef/server.rb', line 211

def self.get(cluster_name, facet_name, facet_index)
  cluster = ClusterChef.cluster(cluster_name)
  had_facet = cluster.has_facet?(facet_name)
  facet = cluster.facet(facet_name)
  facet.bogosity true unless had_facet
  had_server = facet.has_server?( facet_index )
  server = facet.server(facet_index)
  server.bogosity :not_defined_in_facet unless had_server
  return server
end

Instance Method Details

#announce_as_startedObject

ugh. non-dry below.



268
269
270
271
272
# File 'lib/cluster_chef/server.rb', line 268

def announce_as_started
  return unless chef_node
  announce_state('start')
  chef_node.save
end

#announce_as_stoppedObject



274
275
276
277
278
# File 'lib/cluster_chef/server.rb', line 274

def announce_as_stopped
  return unless chef_node
  announce_state('stop')
  chef_node.save
end

#block_device_mappingObject



262
263
264
# File 'lib/cluster_chef/server.rb', line 262

def block_device_mapping
  composite_volumes.values.map(&:block_device_mapping).compact
end

#bogosity(val = nil) ⇒ Object



43
44
45
46
47
48
49
# File 'lib/cluster_chef/server.rb', line 43

def bogosity val=nil
  @settings[:bogosity] = val  if not val.nil?
  return @settings[:bogosity] if not @settings[:bogosity].nil?
  return :bogus_facet         if facet.bogus?
  # return :out_of_range      if (self.facet_index.to_i >= facet.instances)
  false
end

#chef_node_name(name) ⇒ Object

DEPRECATED: Please use fullname instead.



20
21
22
23
# File 'lib/cluster_chef/deprecated.rb', line 20

def chef_node_name name
  ui.warn "[DEPRECATION] `chef_node_name` is deprecated.  Please use `fullname` instead."
  fullname name
end

#cluster_nameObject



31
32
33
# File 'lib/cluster_chef/server.rb', line 31

def cluster_name
  cluster.name
end

#combined_run_listObject

Assembles the combined runlist.

  • run_list :first items – cluster then facet then server

  • run_list :normal items – cluster then facet then server

  • own roles: cluster_role then facet_role

  • run_list :last items – cluster then facet then server

    ClusterChef.cluster(:my_cluster) do
      role('f',  :last)
      role('c')
      facet(:my_facet) do
        role('d')
        role('e')
        role('b', :first)
        role('h',  :last)
      end
      role('a', :first)
      role('g', :last)
    end
    

produces

cluster list  [a] [c]  [cluster_role] [fg]
facet list    [b] [de] [facet_role]   [h]

yielding run_list

['a', 'b', 'c', 'd', 'e', 'cr', 'fr', 'f', 'g', 'h']

Avoid duplicate conflicting declarations. If you say define things more than once, the *earliest encountered* one wins, even if it is elsewhere marked :last.



166
167
168
169
170
171
172
173
174
# File 'lib/cluster_chef/server.rb', line 166

def combined_run_list
  cg = @cluster.run_list_groups
  fg = @facet.run_list_groups
  sg = self.run_list_groups
  [ cg[:first],  fg[:first],  sg[:first],
    cg[:normal], fg[:normal], sg[:normal],
    cg[:own],    fg[:own],
    cg[:last],   fg[:last],   sg[:last], ].flatten.compact.uniq
end

#composite_volumesObject

This prepares a composited view of the volumes – it shows the cluster definition overlaid by the facet definition overlaid by the server definition.

This method does auto-vivify an empty volume declaration on the server, but doesn’t modify it.

This code is pretty smelly, but so is the resolve! behavior. advice welcome.



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/cluster_chef/server.rb', line 186

def composite_volumes
  vols = {}
  facet.volumes.each do |vol_name, vol|
    self.volumes[vol_name] ||= ClusterChef::Volume.new(:parent => self, :name => vol_name)
    vols[vol_name]         ||= self.volumes[vol_name].dup
    vols[vol_name].reverse_merge!(vol)
  end
  cluster.volumes.each do |vol_name, vol|
    self.volumes[vol_name] ||= ClusterChef::Volume.new(:parent => self, :name => vol_name)
    vols[vol_name]         ||= self.volumes[vol_name].dup
    vols[vol_name].reverse_merge!(vol)
  end
  vols.each{|vol_name, vol| vol.availability_zone self.default_availability_zone }
  vols
end

#create_serverObject

FIXME: a lot of AWS logic in here. This probably lives in the facet.cloud but for the one or two things that come from the facet



245
246
247
248
# File 'lib/cluster_chef/server.rb', line 245

def create_server
  return nil if created? # only create a server if it does not already exist
  fog_create_server
end

#create_tagsObject



250
251
252
253
254
255
256
257
258
259
260
# File 'lib/cluster_chef/server.rb', line 250

def create_tags
  return unless created?
  step("  labeling servers and volumes")
  fog_create_tags(fog_server, self.fullname, tags)
  composite_volumes.each do |vol_name, vol|
    if vol.fog_volume
      fog_create_tags(vol.fog_volume, vol.desc,
        { "server" => self.fullname, "name" => "#{name}-#{vol.name}", "device" => vol.device, "mount_point" => vol.mount_point, "cluster" => cluster_name, "facet"   => facet_name, "index"   => facet_index, })
    end
  end
end

#created?Boolean

Returns:

  • (Boolean)


67
68
69
# File 'lib/cluster_chef/server.rb', line 67

def created?
  in_cloud? && (not ['terminated', 'shutting-down'].include?(fog_server.state))
end

#default_availability_zoneObject

FIXME – this will break on some edge case wehre a bogus node is discovered after everything is resolve!d



204
205
206
# File 'lib/cluster_chef/server.rb', line 204

def default_availability_zone
  cloud.default_availability_zone
end

#exists?Boolean

Returns:

  • (Boolean)


63
64
65
# File 'lib/cluster_chef/server.rb', line 63

def exists?
  created? || in_chef?
end

#facet_nameObject



35
36
37
# File 'lib/cluster_chef/server.rb', line 35

def facet_name
  facet.name
end

#fullname(fn = nil) ⇒ Object



26
27
28
29
# File 'lib/cluster_chef/server.rb', line 26

def fullname fn=nil
  @fullname = fn if fn
  @fullname
end

#has_cloud_state?(*states) ⇒ Boolean

Returns:

  • (Boolean)


59
60
61
# File 'lib/cluster_chef/server.rb', line 59

def has_cloud_state?(*states)
  in_cloud? && states.flatten.include?(fog_server.state)
end

#in_chef?Boolean

Returns:

  • (Boolean)


55
56
57
# File 'lib/cluster_chef/server.rb', line 55

def in_chef?
  chef_node || chef_client
end

#in_cloud?Boolean

Returns:

  • (Boolean)


51
52
53
# File 'lib/cluster_chef/server.rb', line 51

def in_cloud?
  !! fog_server
end

#killable?Boolean

Returns:

  • (Boolean)


87
88
89
# File 'lib/cluster_chef/server.rb', line 87

def killable?
  in_chef? || created?
end

#launchable?Boolean

Returns:

  • (Boolean)


79
80
81
# File 'lib/cluster_chef/server.rb', line 79

def launchable?
  not created?
end

#resolve!Object

Resolve:



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
# File 'lib/cluster_chef/server.rb', line 107

def resolve!
  reverse_merge!(facet)
  reverse_merge!(cluster)
  @settings[:run_list] = combined_run_list
  #
  cloud.reverse_merge!(facet.cloud)
  cloud.reverse_merge!(cluster.cloud)
  #
  cloud.user_data({
      :chef_server            => Chef::Config.chef_server_url,
      :validation_client_name => Chef::Config.validation_client_name,
      #
      :node_name              => fullname,
      :cluster_name           => cluster_name,
      :facet_name             => facet_name,
      :facet_index            => facet_index,
      #
      :run_list               => run_list,
    })
  #
  if client_key.body then cloud.user_data({ :client_key     => client_key.body, })
  else                    cloud.user_data({ :validation_key => cloud.validation_key }) ; end
  cloud.keypair(cluster_name) if cloud.keypair.nil?
  #
  self
end

#running?Boolean

Returns:

  • (Boolean)


71
72
73
# File 'lib/cluster_chef/server.rb', line 71

def running?
  has_cloud_state?('running')
end

#serversObject



39
40
41
# File 'lib/cluster_chef/server.rb', line 39

def servers
  ClusterChef::ServerGroup.new(cluster, [self])
end

#sshable?Boolean

Returns:

  • (Boolean)


83
84
85
# File 'lib/cluster_chef/server.rb', line 83

def sshable?
  in_chef?
end

#startable?Boolean

Returns:

  • (Boolean)


75
76
77
# File 'lib/cluster_chef/server.rb', line 75

def startable?
  has_cloud_state?('stopped')
end

#sync_to_chefObject



237
238
239
240
241
# File 'lib/cluster_chef/server.rb', line 237

def sync_to_chef
  step "Syncing to chef server"
  sync_chef_node
  true
end

#sync_to_cloudObject

Actions!



230
231
232
233
234
235
# File 'lib/cluster_chef/server.rb', line 230

def sync_to_cloud
  step "Syncing to cloud"
  attach_volumes
  create_tags
  associate_public_ip
end

#tag(key, value = nil) ⇒ Object

Attributes



99
100
101
102
# File 'lib/cluster_chef/server.rb', line 99

def tag key, value=nil
  if value then @tags[key] = value ; end
  @tags[key]
end

#to_sObject



91
92
93
# File 'lib/cluster_chef/server.rb', line 91

def to_s
  super[0..-3] + " chef: #{in_chef? && chef_node.name} fog: #{in_cloud? && fog_server.id}}>"
end