syncwrap 1.0.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.
@@ -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