chef-vpc-toolkit 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG CHANGED
@@ -1,3 +1,10 @@
1
+ * Thu Apr 14 2011 Dan Prince <dan.prince@rackspace.com> - 2.5.0
2
+ - Make /root/cookbook-repos on the Chef server if it doesn't exist.
3
+ - Add cache_file option to the VPC Client class.
4
+ - Implement 'rdesktop' task for Windows servers.
5
+ - Implement 'group:vpn_gateway_ip' task.
6
+ - Store client information in the server group cache.
7
+
1
8
  * Thu Mar 27 2011 Dan Prince <dan.prince@rackspace.com> - 2.4.0
2
9
  - Implement 'chef:poll_clients' task.
3
10
 
data/README.rdoc CHANGED
@@ -73,6 +73,11 @@ Example commands:
73
73
 
74
74
  $ rake vpn:disconnect
75
75
 
76
+ - Connect to a Windows machine using rdesktop.
77
+
78
+ $ rake rdesktop SERVER_NAME=win1
79
+
80
+
76
81
  == Bash Automation Script
77
82
  The following is an example bash script to spin up a group and run commands via SSH. Useful for CI automation in Hudson, etc.
78
83
 
@@ -81,10 +86,15 @@ The following is an example bash script to spin up a group and run commands via
81
86
  chef-vpc-toolkit -v
82
87
  trap "rake group:delete" INT TERM EXIT # cleanup the group on exit
83
88
 
89
+ # create a server group and Chef (includes Chef Server, cookbooks, clients)
84
90
  rake create
85
- VPN_GW=$(rake group:show | grep "VPN gateway IP" | sed -e "s|VPN gateway IP: ||")
86
- ssh root@$VPN_GW bash <<-EOF_BASH
87
- # do stuff here
91
+
92
+ # wait for Chef clients to finish running
93
+ rake chef:poll_clients
94
+
95
+ # Run some scripts on the login server
96
+ rake ssh bash <<-EOF_BASH
97
+ echo 'It works!'
88
98
  EOF_BASH
89
99
 
90
100
  == Author
@@ -94,4 +104,4 @@ Dan Prince <dan.prince@rackspace.com>
94
104
  == License
95
105
 
96
106
  See COPYING for license information.
97
- Copyright (c) 2010, Rackspace US, Inc.
107
+ Copyright (c) 2010-2011, Rackspace US, Inc.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.4.0
1
+ 2.5.0
@@ -207,6 +207,7 @@ echo -n "Downloading $CB_REPO..."
207
207
  download_cloud_file "$CB_REPO" "/tmp/cookbook-repo.tar.gz"
208
208
  fi
209
209
  echo "OK"
210
+ [ -d "$REPOS_BASEDIR" ] || mkdir -p "$REPOS_BASEDIR"
210
211
  cd $REPOS_BASEDIR
211
212
  echo -n "Extracting $CB_REPO..."
212
213
  tar xzf /tmp/cookbook-repo.tar.gz
@@ -19,6 +19,7 @@ class Client
19
19
  attr_accessor :description
20
20
  attr_accessor :status
21
21
  attr_accessor :server_group_id
22
+ attr_accessor :cache_file
22
23
 
23
24
  def initialize(options={})
24
25
  @id=options[:id].to_i
@@ -26,6 +27,7 @@ class Client
26
27
  @description=options[:description]
27
28
  @status=options[:status] or @status = "Pending"
28
29
  @server_group_id=options[:server_group_id]
30
+ @cache_file=options[:cache_file] or options[:server_group_id]
29
31
 
30
32
  @vpn_network_interfaces=[]
31
33
  end
@@ -36,14 +38,14 @@ class Client
36
38
 
37
39
  def cache_to_disk
38
40
  FileUtils.mkdir_p(@@data_dir)
39
- File.open(File.join(@@data_dir, "#{@server_group_id}.xml"), 'w') do |f|
41
+ File.open(File.join(@@data_dir, "#{@cache_file}.xml"), 'w') do |f|
40
42
  f.chmod(0600)
41
43
  f.write(self.to_xml)
42
44
  end
43
45
  end
44
46
 
45
47
  def delete
46
- client_xml_file=File.join(@@data_dir, "#{@server_group_id}.xml")
48
+ client_xml_file=File.join(@@data_dir, "#{@cache_file}.xml")
47
49
  if File.exists?(client_xml_file) then
48
50
  File.delete(client_xml_file)
49
51
  end
@@ -139,7 +141,7 @@ class Client
139
141
 
140
142
  end
141
143
 
142
- def self.create(server_group, client_name)
144
+ def self.create(server_group, client_name, cache_to_disk=true)
143
145
 
144
146
  xml = Builder::XmlMarkup.new
145
147
  xml.client do |client|
@@ -150,14 +152,14 @@ class Client
150
152
 
151
153
  xml=Connection.post("/clients.xml", xml.target!)
152
154
  client=Client.from_xml(xml)
153
- client.cache_to_disk
155
+ client.cache_to_disk if cache_to_disk
154
156
  client
155
157
 
156
158
  end
157
159
 
158
- # Fetch a server group. The following options are available:
160
+ # Fetch a client. The following options are available:
159
161
  #
160
- # :id - The ID of the group containing the client to fetch.
162
+ # :id - The ID of the client to fetch.
161
163
  # :source - valid options are 'remote' and 'cache'
162
164
  #
163
165
  def self.fetch(options = {})
@@ -17,6 +17,7 @@ class Server
17
17
  attr_accessor :retry_count
18
18
  attr_accessor :error_message
19
19
  attr_accessor :status
20
+ attr_accessor :admin_password
20
21
 
21
22
  def initialize(options={})
22
23
  @id=options[:id].to_i
@@ -27,6 +28,7 @@ class Server
27
28
  @cloud_server_id_number=options[:cloud_server_id_number].to_i
28
29
  @flavor_id=options[:flavor_id].to_i
29
30
  @image_id=options[:image_id].to_i
31
+ @admin_password=options[:admin_password]
30
32
  @server_group_id=options[:server_group_id].to_i
31
33
  @openvpn_server = [true, "true"].include?(options[:openvpn_server])
32
34
  @retry_count=options[:retry_count].to_i or 0
@@ -51,6 +53,7 @@ class Server
51
53
  server.tag! "cloud-server-id-number", @cloud_server_id_number if @cloud_server_id_number
52
54
  server.tag! "flavor-id", @flavor_id
53
55
  server.tag! "image-id", @image_id
56
+ server.tag! "admin-password", @admin_password
54
57
  server.tag! "server-group-id", @server_group_id
55
58
  server.tag! "openvpn-server", "true" if openvpn_server?
56
59
  server.tag! "error-message", @error_message if @error_message
@@ -70,6 +73,7 @@ class Server
70
73
  :name => XMLUtil.element_text(sg_xml, "name"),
71
74
  :flavor_id => XMLUtil.element_text(sg_xml, "flavor-id"),
72
75
  :image_id => XMLUtil.element_text(sg_xml, "image-id"),
76
+ :admin_password => XMLUtil.element_text(sg_xml, "admin-password"),
73
77
  :description => XMLUtil.element_text(sg_xml, "description"),
74
78
  :cloud_server_id_number => XMLUtil.element_text(sg_xml, "cloud-server-id-number"),
75
79
  :description => XMLUtil.element_text(sg_xml, "description"),
@@ -44,6 +44,7 @@ class ServerGroup
44
44
  @owner_name=options[:owner_name] or @owner_name=ENV['USER']
45
45
 
46
46
  @servers=[]
47
+ @clients=[]
47
48
  @ssh_public_keys=[]
48
49
  end
49
50
 
@@ -55,6 +56,14 @@ class ServerGroup
55
56
  @servers
56
57
  end
57
58
 
59
+ def client(name)
60
+ @clients.select {|s| s.name == name}[0] if @clients.size > 0
61
+ end
62
+
63
+ def clients
64
+ @clients
65
+ end
66
+
58
67
  def vpn_gateway_name
59
68
  @servers.select {|s| s.openvpn_server? }[0].name if @servers.size > 0
60
69
  end
@@ -121,6 +130,9 @@ class ServerGroup
121
130
  xml_server.description(server.description)
122
131
  xml_server.tag! "flavor-id", server.flavor_id
123
132
  xml_server.tag! "image-id", server.image_id
133
+ if server.admin_password then
134
+ xml_server.tag! "admin-password", server.admin_password
135
+ end
124
136
  xml_server.tag! "cloud-server-id-number", server.cloud_server_id_number if server.cloud_server_id_number
125
137
  xml_server.tag! "status", server.status if server.status
126
138
  xml_server.tag! "external-ip-addr", server.external_ip_addr if server.external_ip_addr
@@ -141,6 +153,17 @@ class ServerGroup
141
153
  end
142
154
  end
143
155
  end
156
+ sg.tag! "clients", { "type" => "array"} do |xml_clients|
157
+ self.clients.each do |client|
158
+ xml_clients.tag! "client" do |xml_client|
159
+ xml_client.id client.id
160
+ xml_client.name client.name
161
+ xml_client.description client.description
162
+ xml_client.status client.status
163
+ end
164
+ end
165
+ end
166
+
144
167
  end
145
168
  xml.target!
146
169
 
@@ -172,12 +195,24 @@ class ServerGroup
172
195
  :internal_ip_addr => XMLUtil.element_text(server_xml, "internal-ip-addr"),
173
196
  :error_message => XMLUtil.element_text(server_xml, "error-message"),
174
197
  :image_id => XMLUtil.element_text(server_xml, "image-id"),
198
+ :admin_password => XMLUtil.element_text(server_xml, "admin-password"),
175
199
  :flavor_id => XMLUtil.element_text(server_xml, "flavor-id"),
176
200
  :retry_count => XMLUtil.element_text(server_xml, "retry-count"),
177
201
  :openvpn_server => XMLUtil.element_text(server_xml, "openvpn-server")
178
202
  )
179
203
  sg.servers << server
180
204
  end
205
+ REXML::XPath.each(dom, "//client") do |client_xml|
206
+
207
+ client=Client.new(
208
+ :id => XMLUtil.element_text(client_xml, "id").to_i,
209
+ :name => XMLUtil.element_text(client_xml, "name"),
210
+ :description => XMLUtil.element_text(client_xml, "description"),
211
+ :status => XMLUtil.element_text(client_xml, "status")
212
+ )
213
+ sg.clients << client
214
+ end
215
+
181
216
  end
182
217
 
183
218
  sg
@@ -217,6 +217,10 @@ module VpnNetworkManager
217
217
  puts %x{#{sudo_display} nmcli con down id "VPC Group: #{server_group_id}"}
218
218
  end
219
219
 
220
+ def self.connected?(server_group_id)
221
+ return system("#{sudo_display} nmcli con status | grep -c 'VPC Group: #{server_group_id}' &> /dev/null")
222
+ end
223
+
220
224
  def self.ip_to_integer(ip_string)
221
225
  return 0 if ip_string.nil?
222
226
  ip_arr=ip_string.split(".").collect{ |s| s.to_i }
@@ -137,6 +137,12 @@ namespace :group do
137
137
  puts "Server '#{server_name}' deleted."
138
138
  end
139
139
 
140
+ desc "Print the VPN gateway IP address"
141
+ task :vpn_gateway_ip do
142
+ group=ServerGroup.fetch(:source => "cache")
143
+ puts group.vpn_gateway_ip
144
+ end
145
+
140
146
  end
141
147
 
142
148
  namespace :server do
@@ -393,6 +399,40 @@ task :rechef => [ "server:rebuild", "group:poll" ] do
393
399
 
394
400
  end
395
401
 
402
+ desc "Use rdesktop to connect to Windows servers."
403
+ task :rdesktop => 'group:init' do
404
+
405
+ server_name=ENV['SERVER_NAME']
406
+ raise "Please specify a SERVER_NAME." if server_name.nil?
407
+
408
+ # VPC machines have their public IPs disabled
409
+ # This option is useful for debugging failed VPN connections
410
+ use_public_ip=ENV['PUBLIC_IP']
411
+
412
+ sg=ServerGroup.fetch(:source => "cache")
413
+ pass=sg.server(server_name).admin_password
414
+
415
+ if use_public_ip.nil? then
416
+ if ChefVPCToolkit::VpnNetworkManager.connected?(sg.id)
417
+ # on the VPN we connect directly to the windows machine
418
+ local_ip=%x{ssh -o \"StrictHostKeyChecking no\" root@#{sg.vpn_gateway_ip} grep #{server_name}.#{sg.domain_name} /etc/hosts | cut -f 1}.chomp
419
+ exec("rdesktop #{local_ip} -u Administrator -p #{pass}")
420
+ else
421
+ # when not on the VPN create an SSH tunnel for rdesktop traffic
422
+ local_ip=%x{ssh -o \"StrictHostKeyChecking no\" root@#{sg.vpn_gateway_ip} grep #{server_name}.#{sg.domain_name} /etc/hosts | cut -f 1}.chomp
423
+ %x{
424
+ ssh root@#{sg.vpn_gateway_ip} -L 1234:#{local_ip}:3389 'sleep 3 & exit' &
425
+ sleep 1
426
+ rdesktop localhost:1234 -u Administrator -p #{pass}
427
+ }
428
+ end
429
+ else
430
+ public_ip=sg.server(server_name).external_ip_addr
431
+ exec("rdesktop #{public_ip} -u Administrator -p #{pass}")
432
+ end
433
+
434
+ end
435
+
396
436
  desc "Alias to the vpn:connect task."
397
437
  task :vpn => "vpn:connect"
398
438
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-vpc-toolkit
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 2
8
- - 4
8
+ - 5
9
9
  - 0
10
- version: 2.4.0
10
+ version: 2.5.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Dan Prince
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-03-28 00:00:00 -04:00
18
+ date: 2011-04-14 00:00:00 -04:00
19
19
  default_executable: chef-vpc-toolkit
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency