Class: ChefVPCToolkit::CloudServersVPC::ServerGroup

Inherits:
Object
  • Object
show all
Defined in:
lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb

Constant Summary collapse

CONFIG_FILE =
CHEF_VPC_PROJECT + File::SEPARATOR + "config" + File::SEPARATOR + "server_group.json"
@@data_dir =
File.join(CHEF_VPC_PROJECT, "tmp", "server_groups")

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ ServerGroup

Returns a new instance of ServerGroup.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 37

def initialize(options={})
		@id=options[:id]
		@name=options[:name]
		@description=options[:description]
		@domain_name=options[:domain_name]
		@vpn_device=options[:vpn_device] or @vpn_device="tun"
		@vpn_proto=options[:vpn_proto] or @vpn_proto="tcp"
		@vpn_network=options[:vpn_network] or @vpn_network="172.19.0.0"
		@vpn_subnet=options[:vpn_subnet] or @vpn_subnet="255.255.128.0"
		@owner_name=options[:owner_name] or @owner_name=ENV['USER']

		@servers=[]
		@clients=[]
		@ssh_public_keys=[]
end

Instance Attribute Details

#descriptionObject

Returns the value of attribute description.



27
28
29
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 27

def description
  @description
end

#domain_nameObject

Returns the value of attribute domain_name.



28
29
30
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 28

def domain_name
  @domain_name
end

#idObject

Returns the value of attribute id.



25
26
27
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 25

def id
  @id
end

#nameObject

Returns the value of attribute name.



26
27
28
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 26

def name
  @name
end

#owner_nameObject

Returns the value of attribute owner_name.



33
34
35
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 33

def owner_name
  @owner_name
end

#ssh_public_keysObject (readonly)

Returns the value of attribute ssh_public_keys.



35
36
37
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 35

def ssh_public_keys
  @ssh_public_keys
end

#vpn_deviceObject

Returns the value of attribute vpn_device.



29
30
31
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 29

def vpn_device
  @vpn_device
end

#vpn_networkObject

Returns the value of attribute vpn_network.



31
32
33
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 31

def vpn_network
  @vpn_network
end

#vpn_protoObject

Returns the value of attribute vpn_proto.



30
31
32
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 30

def vpn_proto
  @vpn_proto
end

#vpn_subnetObject

Returns the value of attribute vpn_subnet.



32
33
34
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 32

def vpn_subnet
  @vpn_subnet
end

Class Method Details

.create(sg) ⇒ Object



320
321
322
323
324
325
326
327
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 320

def self.create(sg)

	xml=Connection.post("/server_groups.xml", sg.to_xml)
	sg=ServerGroup.from_xml(xml)
	sg.cache_to_disk
	sg

end

.data_dirObject



15
16
17
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 15

def self.data_dir
	@@data_dir
end

.data_dir=(dir) ⇒ Object



19
20
21
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 19

def self.data_dir=(dir)
	@@data_dir=dir
end

.fetch(options = {}) ⇒ Object

Fetch a server group. The following options are available:

:id - The ID of the server group to fetch. Defaults to ENV :source - valid options are ‘remote’ and ‘cache’



333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 333

def self.fetch(options={})

	source = options[:source] or source = "remote"
	id=options[:id] or id = ENV['GROUP_ID']
	if id.nil? then
		group=ServerGroup.most_recent
		raise "No server group files exist." if group.nil?
		id=group.id
	end

	if source == "remote" then
		xml=Connection.get("/server_groups/#{id}.xml")
		ServerGroup.from_xml(xml)
	elsif source == "cache" then
		out_file=File.join(@@data_dir, "#{id}.xml")
		raise "No server group files exist." if not File.exists?(out_file)
           ServerGroup.from_xml(IO.read(out_file))
	else
		raise "Invalid fetch :source specified."
	end

end

.from_json_config(json) ⇒ Object

generate a Server Group XML from server_group.json



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
110
111
112
113
114
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 82

def self.from_json_config(json)

	json_hash=JSON.parse(json)

	sg=ServerGroup.new(
		:name => json_hash["name"],
		:description => json_hash["description"],
		:domain_name => json_hash["domain_name"],
		:vpn_device => json_hash["vpn_device"],
		:vpn_proto => json_hash["vpn_proto"],
		:vpn_network => json_hash["vpn_network"],
		:vpn_subnet => json_hash["vpn_subnet"]
		)
	json_hash["servers"].each_pair do |server_name, server_config|
		sg.servers << Server.new(
			:name => server_name,
			:description => server_config["description"],
			:flavor_id => server_config["flavor_id"],
			:image_id => server_config["image_id"],
			:openvpn_server => server_config["openvpn_server"]
		)
	end

	# automatically add a key for the current user
	sg.ssh_public_keys << SshPublicKey.new(
		:description => "#{ENV['USER']}'s public key",
		:public_key => Util.load_public_key

	)

	return sg

end

.from_xml(xml) ⇒ Object



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 176

def self.from_xml(xml)

	sg=nil
       dom = REXML::Document.new(xml)
       REXML::XPath.each(dom, "/server-group") do |sg_xml|
		sg=ServerGroup.new(
			:name => XMLUtil.element_text(sg_xml, "name"),
			:id => XMLUtil.element_text(sg_xml, "id").to_i,
			:owner_name => XMLUtil.element_text(sg_xml, "owner-name"),
			:domain_name => XMLUtil.element_text(sg_xml, "domain-name"),
			:description => XMLUtil.element_text(sg_xml, "description"),
			:vpn_device => XMLUtil.element_text(sg_xml, "vpn-device"),
			:vpn_proto => XMLUtil.element_text(sg_xml, "vpn-proto"),
			:vpn_network => XMLUtil.element_text(sg_xml, "vpn-network"),
			:vpn_subnet => XMLUtil.element_text(sg_xml, "vpn-subnet")
		)
		REXML::XPath.each(dom, "//server") do |server_xml|

			server=Server.new(
				:id => XMLUtil.element_text(server_xml, "id").to_i,
				:name => XMLUtil.element_text(server_xml, "name"),
				:cloud_server_id_number => XMLUtil.element_text(server_xml, "cloud-server-id-number"),
				:status => XMLUtil.element_text(server_xml, "status"),
				:external_ip_addr => XMLUtil.element_text(server_xml, "external-ip-addr"),
				:internal_ip_addr => XMLUtil.element_text(server_xml, "internal-ip-addr"),
				:error_message => XMLUtil.element_text(server_xml, "error-message"),
				:image_id => XMLUtil.element_text(server_xml, "image-id"),
				:admin_password => XMLUtil.element_text(server_xml, "admin-password"),
				:flavor_id => XMLUtil.element_text(server_xml, "flavor-id"),
				:retry_count => XMLUtil.element_text(server_xml, "retry-count"),
				:openvpn_server => XMLUtil.element_text(server_xml, "openvpn-server")
			)
			sg.servers << server
		end
		REXML::XPath.each(dom, "//client") do |client_xml|

			client=Client.new(
				:id => XMLUtil.element_text(client_xml, "id").to_i,
				:name => XMLUtil.element_text(client_xml, "name"),
				:description => XMLUtil.element_text(client_xml, "description"),
				:status => XMLUtil.element_text(client_xml, "status")
			)
			sg.clients << client
		end

	end

	sg

end

.list(options = {}) ⇒ Object

:source - valid options are ‘remote’ and ‘cache’



357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 357

def self.list(options={})

	source = options[:source] or source = "cache"
	server_groups=[]
	if source == "remote" then
		xml=Connection.get("/server_groups.xml")
		dom = REXML::Document.new(xml)
		REXML::XPath.each(dom, "//server-group") do |group_xml|
			server_groups << ServerGroup.from_xml(group_xml.to_s)
		end
	else
		Dir[File.join(ServerGroup.data_dir, '*.xml')].each do  |file|
			server_groups << ServerGroup.from_xml(IO.read(file))
		end
	end

	server_groups

end

.most_recentObject



377
378
379
380
381
382
383
384
385
386
387
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 377

def self.most_recent
       server_groups=[]
       Dir[File.join(@@data_dir, "*.xml")].each do  |file|
           server_groups << ServerGroup.from_xml(IO.read(file))
       end
	if server_groups.size > 0 then
		server_groups.sort { |a,b| b.id <=> a.id }[0]
	else
		nil
	end
end

Instance Method Details

#cache_to_diskObject



265
266
267
268
269
270
271
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 265

def cache_to_disk
	FileUtils.mkdir_p(@@data_dir)
       File.open(File.join(@@data_dir, "#{@id}.xml"), 'w') do |f|
           f.chmod(0600)
           f.write(self.to_xml)
       end
end

#client(name) ⇒ Object



61
62
63
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 61

def client(name)
	@clients.select {|s| s.name == name}[0] if @clients.size > 0
end

#clientsObject



65
66
67
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 65

def clients
    @clients
end

#deleteObject



273
274
275
276
277
278
279
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 273

def delete

       Connection.delete("/server_groups/#{@id}.xml")
       out_file=File.join(@@data_dir, "#{@id}.xml")
       File.delete(out_file) if File.exists?(out_file)

end

#os_typesObject



389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 389

def os_types

	os_types={}
	self.servers.each do |server|
		os_type = case server.image_id
			when 51 # Centos 5.5
				"centos"
			when 187811 # Centos 5.4
				"centos"
			when 78 # Fedora 15
				"fedora"
			when 71 # Fedora 14
				"fedora"
			when 53 # Fedora 13
				"fedora"
			when 17 # Fedora 12
				"fedora"
			when 14 # RHEL 5.4
				"rhel"
			when 62 # RHEL 5.5
				"rhel"
			when 75 # Debian 6.0
				"debian"
			when 76 # Ubuntu 11.04
				"ubuntu"
			when 69 # Ubuntu 10.10
				"ubuntu"
			when 49 # Ubuntu 10.04
				"ubuntu"
			when 14362 # Ubuntu 9.10
				"ubuntu"
			when 8 # Ubuntu 9.04
				"ubuntu"
			else
				"unknown"
		end
		if block_given? then
			yield server.name, os_type
		else
			os_types.store(server.name, os_type)
		end
	end
	os_types

end

#poll_until_online(options = {}) ⇒ Object

Poll the server group until it is online. :timeout - max number of seconds to wait before raising an exception.

Defaults to 1500


284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 284

def poll_until_online(options={})

	timeout=options[:timeout] or timeout = ENV['TIMEOUT']
	if timeout.nil? or timeout.empty? then
		timeout=1500 # defaults to 25 minutes
	end	

	online = false
	count=0
	until online or (count*20) >= timeout.to_i do
		count+=1
		begin
			sg=ServerGroup.fetch(:id => @id, :source => "remote")

			online=true
			sg.servers.each do |server|
				if ["Pending", "Rebuilding"].include?(server.status) then
					online=false
				end
				if server.status == "Failed" then
					raise "Failed to create server group with the following message: #{server.error_message}"
				end
			end
			if not online
				yield sg if block_given?
				sleep 20
			end
		rescue EOFError
		end
	end
	if (count*20) >= timeout.to_i then
		raise "Timeout waiting for server groups to come online."
	end

end

#pretty_printObject



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 227

def pretty_print

	puts "Group ID: #{@id}"
	puts "name: #{@name}"
	puts "description: #{@description}"
	puts "domain name: #{@domain_name}"
	puts "VPN gateway IP: #{self.vpn_gateway_ip}"
	puts "Servers:"
	servers.each do |server|
		puts "\tname: #{server.name} (id: #{server.id})"
		puts "\tstatus: #{server.status}"
		if server.openvpn_server?
			puts "\tOpenVPN server: #{server.openvpn_server?}"
		end
		if server.error_message then
			puts "\tlast error message: #{server.error_message}"
		end
		puts "\t--"
	end

end

#server(name) ⇒ Object



53
54
55
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 53

def server(name)
	@servers.select {|s| s.name == name}[0] if @servers.size > 0
end

#server_namesObject



249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 249

def server_names

	names=[]	

	servers.each do |server|
		if block_given? then
			yield server.name
		else
			names << server.name
		end	
	end

	names
	
end

#serversObject



57
58
59
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 57

def servers
	@servers
end

#to_xmlObject



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 116

def to_xml

	xml = Builder::XmlMarkup.new
	xml.tag! "server-group" do |sg|
		sg.id(@id)
		sg.name(@name)
		sg.description(@description)
		sg.tag! "owner-name", @owner_name
		sg.tag! "domain-name", @domain_name
		sg.tag! "vpn-device", @vpn_device if @vpn_device != "tun"
		sg.tag! "vpn-proto", @vpn_proto if @vpn_proto != "tcp"
		sg.tag! "vpn-network", @vpn_network
		sg.tag! "vpn-subnet", @vpn_subnet
		sg.servers("type" => "array") do |xml_servers|
			self.servers.each do |server|
				xml_servers.server do |xml_server|
					xml_server.id(server.id)
					xml_server.name(server.name)
					xml_server.description(server.description)
					xml_server.tag! "flavor-id", server.flavor_id
					xml_server.tag! "image-id", server.image_id
                       if server.admin_password then
					    xml_server.tag! "admin-password", server.admin_password
                       end
					xml_server.tag! "cloud-server-id-number", server.cloud_server_id_number if server.cloud_server_id_number
					xml_server.tag! "status", server.status if server.status
					xml_server.tag! "external-ip-addr", server.external_ip_addr if server.external_ip_addr
					xml_server.tag! "internal-ip-addr", server.internal_ip_addr if server.internal_ip_addr
					xml_server.tag! "error-message", server.error_message if server.error_message
					xml_server.tag! "retry-count", server.retry_count if server.retry_count
					if server.openvpn_server?
						xml_server.tag! "openvpn-server", "true", { "type" => "boolean"}
					end
				end
			end
		end
		sg.tag! "ssh-public-keys", { "type" => "array"} do |xml_ssh_pub_keys|
			self.ssh_public_keys.each do |ssh_public_key|
				xml_ssh_pub_keys.tag! "ssh-public-key" do |xml_ssh_pub_key|
					xml_ssh_pub_key.description ssh_public_key.description
					xml_ssh_pub_key.tag! "public-key", ssh_public_key.public_key
				end
			end
		end
		sg.tag! "clients", { "type" => "array"} do |xml_clients|
			self.clients.each do |client|
				xml_clients.tag! "client" do |xml_client|
					xml_client.id client.id
					xml_client.name client.name
					xml_client.description client.description
					xml_client.status client.status
				end
			end
		end

	end
	xml.target!

end

#vpn_gateway_ipObject



73
74
75
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 73

def vpn_gateway_ip
	@servers.select {|s| s.openvpn_server? }[0].external_ip_addr if @servers.size > 0
end

#vpn_gateway_nameObject



69
70
71
# File 'lib/chef-vpc-toolkit/cloud-servers-vpc/server_group.rb', line 69

def vpn_gateway_name
	@servers.select {|s| s.openvpn_server? }[0].name if @servers.size > 0
end