aaalex-cloudy_integrate 0.0.1
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/README.textile +0 -0
- data/bin/cloudy_integrate +70 -0
- data/lib/cloudy_integrate.rb +18 -0
- data/lib/cloudy_integrate/list_command.rb +22 -0
- data/lib/cloudy_integrate/session.rb +41 -0
- data/lib/cloudy_integrate/start_command.rb +94 -0
- data/lib/cloudy_integrate/stop_command.rb +18 -0
- metadata +68 -0
data/README.textile
ADDED
File without changes
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'getoptlong'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'rake'
|
6
|
+
require 'net/ssh'
|
7
|
+
|
8
|
+
require 'cloudy_integrate'
|
9
|
+
|
10
|
+
|
11
|
+
include CloudyIntegrate
|
12
|
+
|
13
|
+
USAGE = "USAGE: cloudy_integrate [options] [command] (try cloudy_integrate --help)"
|
14
|
+
|
15
|
+
HELP = <<-end_doc
|
16
|
+
cloudy_integrate - virtually integrate an EC2 instance into your local network
|
17
|
+
|
18
|
+
USAGE: cloudy_integrate [options] [command]
|
19
|
+
|
20
|
+
COMMANDS:
|
21
|
+
#{CloudyIntegrate::Session.commands_with_description.map{|method, desc| " %-17s %s" % [method, desc]}.join("\n")}
|
22
|
+
The default command is "list"
|
23
|
+
|
24
|
+
OPTIONS:
|
25
|
+
--help -h You're reading it
|
26
|
+
--verbose -v Show work
|
27
|
+
--version -V Show version
|
28
|
+
--backtrace Show ruby backtrace on error
|
29
|
+
|
30
|
+
end_doc
|
31
|
+
|
32
|
+
VERSION_STRING = <<-end_doc
|
33
|
+
#{USAGE}
|
34
|
+
Version: #{CloudyIntegrate::Version::String}
|
35
|
+
|
36
|
+
end_doc
|
37
|
+
|
38
|
+
@verbose = false
|
39
|
+
|
40
|
+
GetoptLong.new(
|
41
|
+
['--help', '-h', GetoptLong::NO_ARGUMENT],
|
42
|
+
['--verbose', '-v', GetoptLong::NO_ARGUMENT],
|
43
|
+
['--version', '-V', GetoptLong::NO_ARGUMENT],
|
44
|
+
['--backtrace', GetoptLong::NO_ARGUMENT]
|
45
|
+
).each do |opt, arg|
|
46
|
+
case opt
|
47
|
+
when '--help' then STDOUT << HELP; exit true
|
48
|
+
when '--verbose' then @verbose = true
|
49
|
+
when '--version' then STDOUT << VERSION_STRING; exit true
|
50
|
+
when '--backtrace' then @backtrace = true
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
begin
|
55
|
+
# run a cloudy_integrate command
|
56
|
+
raise "Unknown command: #{ARGV.first}" unless ARGV.empty? || CloudyIntegrate::Session.commands.include?(ARGV.first)
|
57
|
+
|
58
|
+
# configure the garlic runner
|
59
|
+
CloudyIntegrate::Session.runner.verbose = @verbose
|
60
|
+
# garlic.run_targets = @run_targets
|
61
|
+
|
62
|
+
# run the command
|
63
|
+
ARGV << 'list' if ARGV.empty?
|
64
|
+
CloudyIntegrate::Session.call_command *ARGV
|
65
|
+
|
66
|
+
rescue Exception => e
|
67
|
+
STDERR << "\n#{USAGE}\n\nError: #{e.message}\n\n"
|
68
|
+
raise e if @backtrace
|
69
|
+
exit false
|
70
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "cloudy_integrate/session"
|
2
|
+
require "cloudy_integrate/help_command"
|
3
|
+
require "cloudy_integrate/check_command"
|
4
|
+
require "cloudy_integrate/list_command"
|
5
|
+
require "cloudy_integrate/start_command"
|
6
|
+
require "cloudy_integrate/stop_command"
|
7
|
+
|
8
|
+
module CloudyIntegrate
|
9
|
+
|
10
|
+
module Version
|
11
|
+
Major = 0
|
12
|
+
Minor = 0
|
13
|
+
Tiny = 1
|
14
|
+
|
15
|
+
String = [Major, Minor, Tiny].join('.')
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module CloudyIntegrate
|
2
|
+
|
3
|
+
class Session
|
4
|
+
|
5
|
+
define_command :list, "List all running tunnels on remote host" do |a_end_name|
|
6
|
+
|
7
|
+
ssh = Net::SSH.start(a_end_name, 'root', :forward_agent => true, :paranoid => false)
|
8
|
+
res = ssh.exec!("ps -ef | egrep autossh.*-Nqw | grep -v egrep")
|
9
|
+
if res
|
10
|
+
while( mtch = res.match( /\w+ *(\d+).*-Nqw (\d+):(\d+).*Checking=no ([\w\d.\-]+)/ )) do
|
11
|
+
puts "#{mtch[1]} #{mtch[2]} #{mtch[3]} #{mtch[4]}"
|
12
|
+
res = mtch.post_match
|
13
|
+
end
|
14
|
+
else
|
15
|
+
puts "no tunnels found on #{a_end_name}"
|
16
|
+
end
|
17
|
+
ssh.close
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module CloudyIntegrate
|
2
|
+
# this class runs the top level garlic commands
|
3
|
+
class Session
|
4
|
+
|
5
|
+
attr_accessor :verbose
|
6
|
+
|
7
|
+
# meta data about command methods which can be used by both rake and the cli tool
|
8
|
+
@@commands, @@command_descriptions = [], {}
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def define_command(name, desc, &block)
|
12
|
+
@@commands << name
|
13
|
+
@@command_descriptions[name] = desc
|
14
|
+
define_method name, &block
|
15
|
+
end
|
16
|
+
|
17
|
+
def commands_with_description
|
18
|
+
@@commands.map{ |m| [m, @@command_descriptions[m]]}
|
19
|
+
end
|
20
|
+
|
21
|
+
def command_description(name)
|
22
|
+
@@command_descriptions[name]
|
23
|
+
end
|
24
|
+
|
25
|
+
def commands
|
26
|
+
@@command_descriptions.keys.map { |c| c.to_s}
|
27
|
+
end
|
28
|
+
|
29
|
+
def call_command(id, *args)
|
30
|
+
meth = runner.method(id.to_sym)
|
31
|
+
raise ArgumentError.new("Wrong number of arguments for #{meth.to_s}. Need #{meth.arity}}") unless meth.arity == args.size
|
32
|
+
meth.call *args
|
33
|
+
end
|
34
|
+
|
35
|
+
def runner
|
36
|
+
@runner ||= new
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# TODO: make tun interface discovery automatic
|
2
|
+
# TODO: make tun ip discovery dynamic
|
3
|
+
|
4
|
+
module CloudyIntegrate
|
5
|
+
|
6
|
+
class Session
|
7
|
+
|
8
|
+
define_command :start, "Integrate a cloudy instance into your network" do |a_end_name, b_end_name, a_end_ip, b_end_ip|
|
9
|
+
puts "connecting #{a_end_name} to #{b_end_name}"
|
10
|
+
|
11
|
+
# require 'ifconfig'
|
12
|
+
class Node
|
13
|
+
attr_reader :name, :tun, :tun_ip
|
14
|
+
def initialize(name)
|
15
|
+
@name = name
|
16
|
+
@ssh = Net::SSH.start(name, 'root', :forward_agent => true, :paranoid => false)
|
17
|
+
end
|
18
|
+
|
19
|
+
def prepare_for_tunneling(tun_ip = nil, tun = nil)
|
20
|
+
# find unused ip on network
|
21
|
+
@tun_ip = tun_ip || find_free_ip
|
22
|
+
# find free tun interface
|
23
|
+
@tun = tun || find_free_tunnel_interface
|
24
|
+
end
|
25
|
+
def find_free_ip
|
26
|
+
raise NotImplementedError.new "find_free_ip not implemented"
|
27
|
+
end
|
28
|
+
def find_free_tunnel_interface
|
29
|
+
tun_arr = exec "netstat -in | tail --lines=+3".inject([]) do |arr,line|
|
30
|
+
f = line.match(/^tun(\d+)/)
|
31
|
+
arr << f[1] if f
|
32
|
+
arr
|
33
|
+
end
|
34
|
+
free_tun = (0..(tun_arr.size)).each do |num|
|
35
|
+
return num unless tun_arr.include? num
|
36
|
+
end
|
37
|
+
free_tun
|
38
|
+
end
|
39
|
+
|
40
|
+
def exec(cmd);
|
41
|
+
# system cmd
|
42
|
+
puts "executing #{name}:#{cmd}" if true
|
43
|
+
@ssh.exec!(cmd)
|
44
|
+
end
|
45
|
+
|
46
|
+
def set_tun_ip(remote_ip)
|
47
|
+
exec "ifconfig tun#{tun} #{tun_ip} pointopoint #{remote_ip}"
|
48
|
+
end
|
49
|
+
def network; "192.168.1.0"; end
|
50
|
+
def netmask; "255.255.255.0"; end
|
51
|
+
def interface; "eth0"; end
|
52
|
+
|
53
|
+
def set_proc_ipv4(proc_name); exec "echo 1 > /proc/sys/net/ipv4/#{ proc_name}"; end
|
54
|
+
def enable_ip_forward; set_proc_ipv4 "ip_forward"; end
|
55
|
+
def enable_proxy_arp; set_proc_ipv4 "conf/#{ interface}/proxy_arp"; end
|
56
|
+
end
|
57
|
+
|
58
|
+
aEnd = Node.new a_end_name
|
59
|
+
aEnd.prepare_for_tunneling a_end_ip, 2
|
60
|
+
bEnd = Node.new b_end_name
|
61
|
+
bEnd.prepare_for_tunneling b_end_ip, 2
|
62
|
+
|
63
|
+
# prepare ssh tunnel
|
64
|
+
|
65
|
+
# check for PermitTunnel option in sshd_config on bEnd
|
66
|
+
# should check if really needed
|
67
|
+
if true
|
68
|
+
bEnd.exec( 'echo "PermitTunnel yes" >> /etc/ssh/sshd_config')
|
69
|
+
bEnd.exec( 'invoke-rc.d ssh reload')
|
70
|
+
end
|
71
|
+
|
72
|
+
# start ssh on aEnd
|
73
|
+
aEnd.exec "autossh -f -Nqw #{aEnd.tun}:#{bEnd.tun} -o StrictHostKeyChecking=no #{bEnd.name}"
|
74
|
+
|
75
|
+
# wait for stable tunnel
|
76
|
+
# TODO: better checking
|
77
|
+
begin
|
78
|
+
sleep 2
|
79
|
+
end while aEnd.exec("ifconfig tun#{aEnd.tun} | grep 'Device not found'")
|
80
|
+
|
81
|
+
# setup ip networking
|
82
|
+
aEnd.set_tun_ip bEnd.tun_ip
|
83
|
+
bEnd.set_tun_ip aEnd.tun_ip
|
84
|
+
bEnd.exec "route add -net #{aEnd.network} netmask #{aEnd.netmask} gw #{aEnd.tun_ip} tun#{aEnd.tun}"
|
85
|
+
|
86
|
+
# enable forwarding and proxy_arp in a_end
|
87
|
+
aEnd.enable_ip_forward
|
88
|
+
aEnd.enable_proxy_arp
|
89
|
+
|
90
|
+
puts "integrated node #{bEnd.name} with IP #{bEnd.tun_ip}"
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module CloudyIntegrate
|
2
|
+
|
3
|
+
class Session
|
4
|
+
|
5
|
+
define_command :stop, "Stop one integration" do |a_end_name, local_tun|
|
6
|
+
|
7
|
+
ssh = Net::SSH.start(a_end_name, 'root', :forward_agent => true, :paranoid => false)
|
8
|
+
res = ssh.exec!("ps -ef | grep -v egrep | egrep 'autossh.*-Nqw #{local_tun}'")
|
9
|
+
if res
|
10
|
+
pid = res.match( /\w+ *(\d+)/ )[1]
|
11
|
+
ssh.exec!("kill -TERM #{pid}")
|
12
|
+
ssh.close
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aaalex-cloudy_integrate
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alex Peuchert
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-12-11 00:00:00 -08:00
|
13
|
+
default_executable: cloudy_integrate
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: aaalex-ruby-ifconfig
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.2.3
|
23
|
+
version:
|
24
|
+
description: Set of commands/rake-tasks .
|
25
|
+
email: apeuchert@googlemail.com
|
26
|
+
executables:
|
27
|
+
- cloudy_integrate
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files: []
|
31
|
+
|
32
|
+
files:
|
33
|
+
- lib/cloudy_integrate/session.rb
|
34
|
+
- lib/cloudy_integrate/list_command.rb
|
35
|
+
- lib/cloudy_integrate/start_command.rb
|
36
|
+
- lib/cloudy_integrate/stop_command.rb
|
37
|
+
- lib/cloudy_integrate.rb
|
38
|
+
- README.textile
|
39
|
+
- History.txt
|
40
|
+
- bin/cloudy_integrate
|
41
|
+
has_rdoc: false
|
42
|
+
homepage: http://github.com/aaalex/cloudy_integrate
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: "0"
|
53
|
+
version:
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "0"
|
59
|
+
version:
|
60
|
+
requirements: []
|
61
|
+
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 1.2.0
|
64
|
+
signing_key:
|
65
|
+
specification_version: 2
|
66
|
+
summary: Virtually integrate an EC2 instance into your local network.
|
67
|
+
test_files: []
|
68
|
+
|