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.
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
+