syncwrap 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,151 @@
1
+ #--
2
+ # Copyright (c) 2011-2012 David Kellum
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
5
+ # may not use this file except in compliance with the License. You may
6
+ # obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
+ # implied. See the License for the specific language governing
14
+ # permissions and limitations under the License.
15
+ #++
16
+
17
+ require 'syncwrap/base'
18
+
19
+ # Common utility methods and variables.
20
+ module SyncWrap::Common
21
+
22
+ # The prefix for local non-distro installs (default: /usr/local)
23
+ attr_accessor :common_prefix
24
+
25
+ def initialize
26
+ super
27
+ @common_prefix = '/usr/local'
28
+ end
29
+
30
+ # Return true if remote file exists, as per "test -e"
31
+ def exist?( file )
32
+ exec_conditional { run "test -e #{file}" } == 0
33
+ end
34
+
35
+ # Put files or entire directories to remote.
36
+ #
37
+ # rput( src..., dest, {options} )
38
+ # rput( src, {options} )
39
+ #
40
+ # A trailing hash is interpreted as options, see below.
41
+ #
42
+ # If there is two or more remaining arguments, the last is
43
+ # interpreted as the remote destination. If there is a single
44
+ # remaining argument, the destination is implied by finding its base
45
+ # directory and prepending '/'. Thus for example:
46
+ #
47
+ # rput( 'etc/gemrc', :user => 'root' )
48
+ #
49
+ # has an implied destination of: `/etc/`. The src and destination
50
+ # are intrepreted as by `rsync`: glob patterns are expanded and
51
+ # trailing '/' is significant.
52
+ #
53
+ # ==== Options
54
+ # :user:: Files should be owned on destination by a user other than
55
+ # installer (ex: 'root') (implies sudo)
56
+ # :perms:: Permissions to set for install files.
57
+ # :excludes:: One or more rsync compatible --filter excludes, or
58
+ # :dev which excludes common developmoent tree droppings
59
+ # like '*~'
60
+ def rput( *args )
61
+ opts = args.last.is_a?( Hash ) && args.pop || {}
62
+
63
+ if args.length == 1
64
+ abspath = "/" + args.first
65
+ abspath = File.dirname( abspath ) + '/' unless abspath =~ %r{/$}
66
+ else
67
+ abspath = args.pop
68
+ end
69
+
70
+ flags = []
71
+
72
+ excludes = Array( opts[ :excludes ] )
73
+ flags += excludes.map do |e|
74
+ if e == :dev
75
+ '--cvs-exclude'
76
+ else
77
+ "--filter=#{e}"
78
+ end
79
+ end
80
+
81
+ if opts[ :perms ]
82
+ flags << '-p'
83
+ flags << "--chmod=#{opts[ :perms ]}"
84
+ end
85
+
86
+ if opts[ :user ]
87
+ # Use sudo to place files at remote.
88
+ user = opts[ :user ] || 'root'
89
+ flags << ( if user != 'root'
90
+ "--rsync-path=sudo -u #{user} rsync"
91
+ else
92
+ "--rsync-path=sudo rsync"
93
+ end )
94
+ end
95
+
96
+ cmd = [ flags, args, [ target_host, abspath ].join(':') ].flatten.compact
97
+ rsync( *cmd )
98
+
99
+ end
100
+
101
+ # Run args as shell command on the remote host. A line delimited
102
+ # argument is interpreted as multiple commands, otherwise arguments
103
+ # are joined as a single command.
104
+ #
105
+ # A trailing Hash is interpreted as options, see below.
106
+ #
107
+ # ==== options
108
+ # :error:: Set the error handling mode: If `:exit`, causes "set -e" to
109
+ # be passed as the first line of a multi-line
110
+ # command. (Default: :exit)
111
+ def run( *args )
112
+ raise "Include a remoting-specific module, e.g. RemoteTask"
113
+ end
114
+
115
+ # Run args under sudo on remote host. A line delimited argument is
116
+ # interpreted as multiple commands, otherwise arguments are joined
117
+ # as a single command.
118
+ #
119
+ # A trailing Hash is interpreted as options, see below.
120
+ #
121
+ # ==== options
122
+ # :user:: Run as specified user (default: root)
123
+ # :flags:: Additional sudo flags
124
+ # :shell:: Run command in a shell by wrapping it in sh -c "", and
125
+ # escaping quotes in the original joined args command.
126
+ # (default: true)
127
+ # :error:: Set the error handling mode: If `:exit`, causes "set -e" to
128
+ # be passed as the first line of a multi-line
129
+ # command. (Default: :exit, only applies if :shell)
130
+ def sudo( *args )
131
+ raise "Include a remoting-specific module, e.g. RemoteTask"
132
+ end
133
+
134
+ # Return the exit status of the first non-zero command result, or 0
135
+ # if all commands succeeded.
136
+ def exec_conditional
137
+ raise "Include a remoting-specific module, e.g. RemoteTask"
138
+ end
139
+
140
+ # Implement rsync as used by rput. Note that args should not be
141
+ # passed through shell interpretation, eg run via system( Array )
142
+ def rsync( *args )
143
+ raise "Include a remoting-specific module, e.g. RemoteTask"
144
+ end
145
+
146
+ # Returns the current target host when called from a running task.
147
+ def target_host
148
+ raise "Include a remoting-specific module, e.g. RemoteTask"
149
+ end
150
+
151
+ end
@@ -0,0 +1,64 @@
1
+ #--
2
+ # Copyright (c) 2011-2012 David Kellum
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
5
+ # may not use this file except in compliance with the License. You may
6
+ # obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
+ # implied. See the License for the specific language governing
14
+ # permissions and limitations under the License.
15
+ #++
16
+
17
+ require 'syncwrap/base'
18
+
19
+ # Support for distro specializations.
20
+ module SyncWrap::Distro
21
+
22
+ # A Hash of internal/common package names to distro specific package
23
+ # names. Here defined as empty.
24
+ attr_reader :packages_map
25
+
26
+ def initialize
27
+ super
28
+
29
+ @packages_map = {}
30
+ end
31
+
32
+ # Map internal/common names and return distro-specific names. If a
33
+ # mapping does not exist, assume internal name is a common name and
34
+ # return.
35
+ def dist_map_packages( *pkgs )
36
+ pkgs.flatten.compact.map { |pkg| packages_map[ pkg ] || pkg }
37
+ end
38
+
39
+ # Install the specified packages using distro-specific mapped
40
+ # package names and command.
41
+ def dist_install( *pkgs )
42
+ raise "Include a distro-specific module, e.g. Ubuntu, RHEL"
43
+ end
44
+
45
+ # Uninstall specified packages using distro-specific mapped
46
+ # package names and command.
47
+ def dist_uninstall( *pkgs )
48
+ raise "Include a distro-specific module, e.g. Ubuntu, RHEL"
49
+ end
50
+
51
+ # Install a System V style init.d script (already placed at remote
52
+ # /etc/init.d/<name>) via distro-specific command
53
+ def dist_install_init_service( name )
54
+ raise "Include a distro-specific module, e.g. Ubuntu, RHEL"
55
+ end
56
+
57
+ # Distro (and System V replacement) specific service command,
58
+ # typically supporting 'start', 'stop', 'restart', 'status',
59
+ # etc. argumnets.
60
+ def dist_service( *args )
61
+ raise "Include a distro-specific module, e.g. Ubuntu, RHEL"
62
+ end
63
+
64
+ end
@@ -0,0 +1,59 @@
1
+ #--
2
+ # Copyright (c) 2011-2012 David Kellum
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
5
+ # may not use this file except in compliance with the License. You may
6
+ # obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
+ # implied. See the License for the specific language governing
14
+ # permissions and limitations under the License.
15
+ #++
16
+
17
+ require 'syncwrap/common'
18
+
19
+ # Provisions for common Amazon EC2 image tasks.
20
+ module SyncWrap::EC2
21
+ include SyncWrap::Common
22
+
23
+ # The device name of the EBS device mounted on /mnt
24
+ # (default: 'xvdb')
25
+ attr_accessor :ec2_ebs_mnt_device
26
+
27
+ def initialize
28
+ super
29
+
30
+ @ec2_ebs_mnt_device = 'xvdb'
31
+ end
32
+
33
+ # WARNING: Destructive if run!
34
+ # Re-mkfs /mnt partition as ext4 if its ec2_ebs_mnt_device and is
35
+ # currently ext3
36
+ def ec2_reformat_mnt_as_ext4
37
+ rc = exec_conditional do
38
+ run "mount | grep '/dev/#{ec2_ebs_mnt_device} on /mnt'"
39
+ end
40
+ raise "Device /dev/#{ec2_ebs_mnt_device} not mounted on /mnt" unless rc == 0
41
+
42
+ rc = exec_conditional do
43
+ run "mount | grep '/dev/#{ec2_ebs_mnt_device} on /mnt type ext3'"
44
+ end
45
+ ec2_reformat_mnt_as_ext4! if rc == 0
46
+ end
47
+
48
+ # WARNING: Destructive!
49
+ # Re-mkfs /mnt partition as ext4
50
+ # See: http://serverfault.com/questions/317009
51
+ def ec2_reformat_mnt_as_ext4!
52
+ sudo <<-SH
53
+ umount /mnt
54
+ mkfs -t ext4 /dev/#{ec2_ebs_mnt_device}
55
+ mount /mnt
56
+ SH
57
+ end
58
+
59
+ end
@@ -0,0 +1,70 @@
1
+ #--
2
+ # Copyright (c) 2011-2012 David Kellum
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
5
+ # may not use this file except in compliance with the License. You may
6
+ # obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
+ # implied. See the License for the specific language governing
14
+ # permissions and limitations under the License.
15
+ #++
16
+
17
+ require 'syncwrap/common'
18
+ require 'syncwrap/distro'
19
+
20
+ # Provisions the {Hashdot}[http://hashdot.sourceforge.net/] JVM/script
21
+ # launcher by building it with gcc on the target host.
22
+ module SyncWrap::Hashdot
23
+ include SyncWrap::Common
24
+ include SyncWrap::Distro
25
+
26
+ # Hashdot version (default: 1.4.0)
27
+ attr_accessor :hashdot_version
28
+
29
+ def initialize
30
+ super
31
+
32
+ @hashdot_version = '1.4.0'
33
+ end
34
+
35
+ def hashdot_install_system_deps
36
+ dist_install( %w[ make gcc apr apr-devel ] )
37
+ end
38
+
39
+ # Install hashdot if the binary is not found. If the binary is found
40
+ # then still attempt to update the profile config files.
41
+ def hashdot_install
42
+ if !exist?( "#{common_prefix}/bin/hashdot" )
43
+ hashdot_install!
44
+ else
45
+ # Just update config as needed.
46
+ rput( 'src/hashdot/profiles/',
47
+ "#{common_prefix}/lib/hashdot/profiles/",
48
+ :excludes => :dev, :user => 'root' )
49
+ end
50
+ end
51
+
52
+ def hashdot_install!
53
+ hashdot_install_system_deps
54
+
55
+ url = ( "http://downloads.sourceforge.net/project/hashdot/" +
56
+ "hashdot/#{hashdot_version}/hashdot-#{hashdot_version}-src.tar.gz" )
57
+ src_root = '/tmp/src'
58
+ hd_src = "#{src_root}/hashdot-#{hashdot_version}"
59
+
60
+ run <<-SH
61
+ mkdir -p #{src_root}
62
+ rm -rf #{hd_src}
63
+ curl -sSL #{url} | tar -C #{src_root} -zxf -
64
+ SH
65
+ rput( 'src/hashdot/', "#{hd_src}/", :excludes => :dev )
66
+ run "cd #{hd_src} && make"
67
+ sudo "cd #{hd_src} && make install"
68
+ end
69
+
70
+ end
@@ -0,0 +1,124 @@
1
+ #--
2
+ # Copyright (c) 2011-2012 David Kellum
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
5
+ # may not use this file except in compliance with the License. You may
6
+ # obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
+ # implied. See the License for the specific language governing
14
+ # permissions and limitations under the License.
15
+ #++
16
+
17
+ require 'syncwrap/user_run'
18
+ require 'syncwrap/distro'
19
+ require 'syncwrap/jruby'
20
+
21
+ # Provisions the {Iyyov}[http://rubydoc.info/gems/iyyov/] job
22
+ # scheduler and process monitor by jruby_install_gem.
23
+ module SyncWrap::Iyyov
24
+ include SyncWrap::UserRun
25
+ include SyncWrap::Distro
26
+ include SyncWrap::JRuby
27
+
28
+ attr_accessor :iyyov_version
29
+
30
+ def initialize
31
+ super
32
+
33
+ @iyyov_version = '1.1.3'
34
+ end
35
+
36
+ # Install then (re-)start Iyyov if needed, yield to block if given
37
+ # for daemon gem or other setup, then finally update remote
38
+ # (user_run) var/iyyov/jobs.rb; which will trigger any necessary
39
+ # restarts.
40
+ def iyyov_install_jobs
41
+ user_run_dir_setup
42
+
43
+ restart = iyyov_install
44
+ if restart
45
+ iyyov_restart
46
+ sleep 15
47
+ elsif !exist?( "#{iyyov_run_dir}/iyyov.pid" )
48
+ iyyov_start
49
+ sleep 15
50
+ end
51
+
52
+ # FIXME: Need a better solution to wait on Iyyov than an arbitrary
53
+ # sleep.
54
+
55
+ # Any Iyyov restart completes *before* job changes
56
+
57
+ yield if block_given?
58
+
59
+ user_run_rput( 'var/iyyov/jobs.rb', iyyov_run_dir )
60
+
61
+ # FIXME: If no jobs.rb change, still touch file to ensure
62
+ # check, but avoid both an update and a touch...
63
+
64
+ end
65
+
66
+ # Deploy iyyov gem, init.d/iyyov and at least an empty
67
+ # jobs.rb. Returns true if iyyov was installed/upgraded and should
68
+ # be restarted.
69
+ def iyyov_install
70
+ iyyov_install_rundir
71
+
72
+ if iyyov_install_gem
73
+ iyyov_install_init!
74
+ true
75
+ else
76
+ false
77
+ end
78
+
79
+ end
80
+
81
+ def iyyov_run_dir
82
+ "#{user_run_dir}/iyyov"
83
+ end
84
+
85
+ # Create iyyov rundir and make sure there is at minimum an empty
86
+ # jobs file. Avoid touching it if already present
87
+ def iyyov_install_rundir
88
+ run <<-SH
89
+ mkdir -p #{iyyov_run_dir}
90
+ if [ ! -e #{iyyov_run_dir}/jobs.rb ]; then
91
+ touch #{iyyov_run_dir}/jobs.rb
92
+ fi
93
+ SH
94
+ user_run_chown( '-R', iyyov_run_dir )
95
+ end
96
+
97
+ # Ensure install of same gem version as init.d/iyyov script
98
+ # Return true if installed
99
+ def iyyov_install_gem
100
+ jruby_install_gem( 'iyyov', :version => "=#{iyyov_version}",
101
+ :check => true )
102
+ end
103
+
104
+ # Install iyyov daemon init.d script and add to init daemons
105
+ def iyyov_install_init!
106
+ rput( 'etc/init.d/iyyov', :user => 'root' )
107
+
108
+ # Add to init.d
109
+ dist_install_init_service( 'iyyov' )
110
+ end
111
+
112
+ def iyyov_start
113
+ dist_service( 'iyyov', 'start' )
114
+ end
115
+
116
+ def iyyov_stop
117
+ dist_service( 'iyyov', 'stop' )
118
+ end
119
+
120
+ def iyyov_restart
121
+ dist_service( 'iyyov', 'restart' )
122
+ end
123
+
124
+ end
@@ -0,0 +1,61 @@
1
+ #--
2
+ # Copyright (c) 2011-2012 David Kellum
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
5
+ # may not use this file except in compliance with the License. You may
6
+ # obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
+ # implied. See the License for the specific language governing
14
+ # permissions and limitations under the License.
15
+ #++
16
+
17
+ require 'syncwrap/common'
18
+
19
+ # Provisions a JDK via an HTTP accessable binary repository of your
20
+ # making. Sun/Oracle JDK usage terms generally preclude sharing a
21
+ # binary repository for these.
22
+ module SyncWrap::Java
23
+ include SyncWrap::Common
24
+
25
+ # HTTP URL to repo base directory. Note that the default
26
+ # (http://localhost/repo) is unlikely to work here.
27
+ attr_accessor :java_repo_base_url
28
+
29
+ # The name of the JDK, which is used for download via
30
+ # java_repo_base_url/<name>.tar.gz and the expected top level
31
+ # directory when unpackaged.
32
+ attr_accessor :java_jdk_name
33
+
34
+ def initialize
35
+ super
36
+
37
+ @java_repo_base_url = 'http://localhost/repo'
38
+ @java_jdk_name = 'jdk-ora-1.7.0_04-x64'
39
+ end
40
+
41
+ def java_jdk_url
42
+ File.join( @java_repo_base_url, @java_jdk_name + '.tar.gz' )
43
+ end
44
+
45
+ def java_install
46
+ java_install! unless exist?( "#{common_prefix}/lib/#{java_jdk_name}" )
47
+ end
48
+
49
+ def java_install!
50
+ bins = %w[ java jmap jstack jps jinfo jhat javac ].
51
+ map { |b| "../lib/java/bin/#{b}" }.
52
+ join( ' ' )
53
+
54
+ sudo <<-SH
55
+ curl -sSL #{java_jdk_url} | tar -C #{common_prefix}/lib -zxf -
56
+ cd #{common_prefix}/lib && ln -sfn #{java_jdk_name} java
57
+ cd #{common_prefix}/bin && ln -sfn #{bins} .
58
+ SH
59
+
60
+ end
61
+ end
@@ -0,0 +1,107 @@
1
+ #--
2
+ # Copyright (c) 2011-2012 David Kellum
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
5
+ # may not use this file except in compliance with the License. You may
6
+ # obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
+ # implied. See the License for the specific language governing
14
+ # permissions and limitations under the License.
15
+ #++
16
+
17
+ require 'syncwrap/common'
18
+
19
+ # Provisions JRuby by direct download from public S3 repo. Includes
20
+ # utility methods for checking and installing JRuby gems.
21
+ module SyncWrap::JRuby
22
+ include SyncWrap::Common
23
+
24
+ # JRuby version to install (default: 1.6.7)
25
+ attr_accessor :jruby_version
26
+
27
+ # The name of the gem command to be installed/used (default: jgem)
28
+ attr_accessor :jruby_gem_command
29
+
30
+ # Default gem install arguments (default: --no-rdoc, --no-ri)
31
+ attr_accessor :jruby_gem_install_args
32
+
33
+ def initialize
34
+ super
35
+
36
+ @jruby_version = '1.6.7'
37
+ @jruby_gem_command = 'jgem'
38
+ @jruby_gem_install_args = %w[ --no-rdoc --no-ri ]
39
+ end
40
+
41
+ # Install jruby if the jruby_version is not already present.
42
+ def jruby_install
43
+ unless exist?( "#{common_prefix}/lib/jruby/jruby-#{jruby_version}" )
44
+ jruby_install!
45
+ end
46
+ end
47
+
48
+ # Install jruby, including usr/local/bin local contents
49
+ def jruby_install!
50
+ url = ( "http://jruby.org.s3.amazonaws.com/downloads/#{jruby_version}/" +
51
+ "jruby-bin-#{jruby_version}.tar.gz" )
52
+
53
+ root = "#{common_prefix}/lib/jruby"
54
+
55
+ sudo <<-SH
56
+ mkdir -p #{root}
57
+ mkdir -p #{root}/gems
58
+ curl -sSL #{url} | tar -C #{root} -zxf -
59
+ cd #{root} && ln -sf jruby-#{jruby_version} jruby
60
+ cd #{common_prefix}/bin && ln -sf ../lib/jruby/jruby/bin/jirb .
61
+ SH
62
+
63
+ rput( 'usr/local/bin/', :excludes => :dev, :user => 'root' )
64
+ end
65
+
66
+ # Return true if gem is already installed.
67
+ # ==== Options
68
+ # :version:: Version specifier array, like in spec. files
69
+ # (default: none, i.e. latest)
70
+ # :user:: If true, perform a --user-install as current user, else
71
+ # system install with sudo (default: false )
72
+ def jruby_check_gem( gems, opts = {} )
73
+ query = [ jruby_gem_command, 'query', '-i',
74
+ jruby_gem_version_flags( opts[ :version ] ),
75
+ '-n', gems, '>/dev/null' ].flatten.compact
76
+
77
+ status = exec_conditional do
78
+ send( opts[ :user ] ? :run : :sudo, query )
79
+ end
80
+ ( status == 0 )
81
+ end
82
+
83
+ # Install the specified gem(s)
84
+ # ==== Options
85
+ # :version:: Version specifier array, like in spec. files
86
+ # (default: none, i.e. latest)
87
+ # :user:: If true, perform a --user-install as current user, else
88
+ # system install with sudo (default: false )
89
+ def jruby_install_gem( gems, opts = {} )
90
+ if opts[ :check ] && jruby_check_gem( gems, opts )
91
+ false
92
+ else
93
+ cmd = [ jruby_gem_command, 'install',
94
+ jruby_gem_install_args,
95
+ ( '--user-install' if opts[ :user ] ),
96
+ jruby_gem_version_flags( opts[ :version ] ),
97
+ gems ].flatten.compact
98
+ send( opts[ :user ] ? :run : :sudo, cmd )
99
+ true
100
+ end
101
+ end
102
+
103
+ def jruby_gem_version_flags( reqs )
104
+ Array( reqs ).flatten.compact.map { |req| "-v'#{req}'" }
105
+ end
106
+
107
+ end