chef-vpc-toolkit 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
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