em-winrm 0.5.4 → 0.5.5
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/.gitignore +4 -4
- data/Gemfile +4 -4
- data/LICENSE +200 -200
- data/README.rdoc +158 -158
- data/Rakefile +2 -2
- data/em-winrm.gemspec +27 -27
- data/lib/em-winrm.rb +38 -38
- data/lib/em-winrm/server.rb +88 -88
- data/lib/em-winrm/session.rb +156 -156
- data/lib/em-winrm/shell.rb +83 -83
- data/lib/em-winrm/version.rb +24 -24
- metadata +69 -90
data/Rakefile
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
require 'bundler'
|
2
|
-
Bundler::GemHelper.install_tasks
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
data/em-winrm.gemspec
CHANGED
@@ -1,27 +1,27 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "em-winrm/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |s|
|
6
|
-
s.name = "em-winrm"
|
7
|
-
s.version = EventMachine::WinRM::VERSION
|
8
|
-
s.platform = Gem::Platform::RUBY
|
9
|
-
s.has_rdoc = true
|
10
|
-
s.extra_rdoc_files = ["README.rdoc", "LICENSE" ]
|
11
|
-
s.authors = ["Seth Chisamore"]
|
12
|
-
s.email = ["schisamo@opscode.com"]
|
13
|
-
s.homepage = "http://github.com/schisamo/em-winrm"
|
14
|
-
s.summary = %q{EventMachine based, asynchronous parallel WinRM client}
|
15
|
-
s.description = s.summary
|
16
|
-
|
17
|
-
s.required_ruby_version = '>= 1.9.1'
|
18
|
-
s.add_dependency "eventmachine", "
|
19
|
-
s.add_dependency "winrm", "~> 1.1.
|
20
|
-
s.add_dependency "mixlib-log", ">= 1.3.0"
|
21
|
-
s.add_dependency "uuidtools", "~> 2.1.1"
|
22
|
-
|
23
|
-
s.files = `git ls-files`.split("\n")
|
24
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
25
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
26
|
-
s.require_paths = ["lib"]
|
27
|
-
end
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "em-winrm/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "em-winrm"
|
7
|
+
s.version = EventMachine::WinRM::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.has_rdoc = true
|
10
|
+
s.extra_rdoc_files = ["README.rdoc", "LICENSE" ]
|
11
|
+
s.authors = ["Seth Chisamore"]
|
12
|
+
s.email = ["schisamo@opscode.com"]
|
13
|
+
s.homepage = "http://github.com/schisamo/em-winrm"
|
14
|
+
s.summary = %q{EventMachine based, asynchronous parallel WinRM client}
|
15
|
+
s.description = s.summary
|
16
|
+
|
17
|
+
s.required_ruby_version = '>= 1.9.1'
|
18
|
+
s.add_dependency "eventmachine", "~> 1.0.0"
|
19
|
+
s.add_dependency "winrm", "~> 1.1.2"
|
20
|
+
s.add_dependency "mixlib-log", ">= 1.3.0"
|
21
|
+
s.add_dependency "uuidtools", "~> 2.1.1"
|
22
|
+
|
23
|
+
s.files = `git ls-files`.split("\n")
|
24
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
25
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
26
|
+
s.require_paths = ["lib"]
|
27
|
+
end
|
data/lib/em-winrm.rb
CHANGED
@@ -1,38 +1,38 @@
|
|
1
|
-
#
|
2
|
-
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
-
# Copyright:: Copyright (c) 2011 Seth Chisamore
|
4
|
-
# License:: Apache License, Version 2.0
|
5
|
-
#
|
6
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
-
# you may not use this file except in compliance with the License.
|
8
|
-
# You may obtain a copy of the License at
|
9
|
-
#
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
-
# See the License for the specific language governing permissions and
|
16
|
-
# limitations under the License.
|
17
|
-
#
|
18
|
-
|
19
|
-
require 'mixlib/log'
|
20
|
-
require "rubygems"
|
21
|
-
require "eventmachine"
|
22
|
-
require "winrm"
|
23
|
-
|
24
|
-
module EventMachine
|
25
|
-
module WinRM
|
26
|
-
NAME = 'em-winrm'
|
27
|
-
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
28
|
-
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
29
|
-
class Log
|
30
|
-
extend Mixlib::Log
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
require File.join(EventMachine::WinRM::LIBPATH, "em-winrm/session")
|
36
|
-
require File.join(EventMachine::WinRM::LIBPATH, "em-winrm/server")
|
37
|
-
require File.join(EventMachine::WinRM::LIBPATH, "em-winrm/shell")
|
38
|
-
require File.join(EventMachine::WinRM::LIBPATH, "em-winrm/version")
|
1
|
+
#
|
2
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2011 Seth Chisamore
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'mixlib/log'
|
20
|
+
require "rubygems"
|
21
|
+
require "eventmachine"
|
22
|
+
require "winrm"
|
23
|
+
|
24
|
+
module EventMachine
|
25
|
+
module WinRM
|
26
|
+
NAME = 'em-winrm'
|
27
|
+
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
28
|
+
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
29
|
+
class Log
|
30
|
+
extend Mixlib::Log
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
require File.join(EventMachine::WinRM::LIBPATH, "em-winrm/session")
|
36
|
+
require File.join(EventMachine::WinRM::LIBPATH, "em-winrm/server")
|
37
|
+
require File.join(EventMachine::WinRM::LIBPATH, "em-winrm/shell")
|
38
|
+
require File.join(EventMachine::WinRM::LIBPATH, "em-winrm/version")
|
data/lib/em-winrm/server.rb
CHANGED
@@ -1,88 +1,88 @@
|
|
1
|
-
#
|
2
|
-
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
-
# Copyright:: Copyright (c) 2011 Seth Chisamore
|
4
|
-
# License:: Apache License, Version 2.0
|
5
|
-
#
|
6
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
-
# you may not use this file except in compliance with the License.
|
8
|
-
# You may obtain a copy of the License at
|
9
|
-
#
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
-
# See the License for the specific language governing permissions and
|
16
|
-
# limitations under the License.
|
17
|
-
#
|
18
|
-
|
19
|
-
require 'uuidtools'
|
20
|
-
|
21
|
-
module EventMachine
|
22
|
-
module WinRM
|
23
|
-
class Server
|
24
|
-
include EM::Deferrable
|
25
|
-
|
26
|
-
attr_accessor :master, :host
|
27
|
-
|
28
|
-
def initialize(master, host, options)
|
29
|
-
@master = master
|
30
|
-
@host = host
|
31
|
-
@transport = options[:transport] || :plaintext
|
32
|
-
@options = options
|
33
|
-
@options[:user] = @options.delete(:user) || ENV['USER'] || ENV['USERNAME'] || "unknown"
|
34
|
-
@options[:pass] = @options.delete(:password)
|
35
|
-
@options[:port] = @options.delete(:port) || 5985
|
36
|
-
@options[:basic_auth_only] = true unless defined? @options[:basic_auth_only]
|
37
|
-
end
|
38
|
-
|
39
|
-
#
|
40
|
-
# create a shell and run command
|
41
|
-
#
|
42
|
-
def run_command(data)
|
43
|
-
cid = UUIDTools::UUID.random_create.to_s
|
44
|
-
EM.epoll
|
45
|
-
EM.run do
|
46
|
-
EM.defer(proc do
|
47
|
-
WinRM::Log.debug("#{@host} => :run_command")
|
48
|
-
@shell = Shell.new(client, self)
|
49
|
-
@shell.on_output do |out|
|
50
|
-
@master.relay_output_from_backend(@host, out)
|
51
|
-
end
|
52
|
-
@shell.on_error do |error|
|
53
|
-
@master.relay_error_from_backend(@host, error)
|
54
|
-
end
|
55
|
-
@shell.on_close do |result, exit_code|
|
56
|
-
@master.command_complete(@host, cid, exit_code)
|
57
|
-
end
|
58
|
-
@shell.run_command(data)
|
59
|
-
end)
|
60
|
-
end
|
61
|
-
cid
|
62
|
-
end
|
63
|
-
|
64
|
-
#
|
65
|
-
# Notify upstream master that the backend server is done
|
66
|
-
# processing the request
|
67
|
-
#
|
68
|
-
def unbind
|
69
|
-
WinRM::Log.debug("#{@host} => :unbind")
|
70
|
-
@master.unbind_backend(@host)
|
71
|
-
end
|
72
|
-
|
73
|
-
private
|
74
|
-
|
75
|
-
def client
|
76
|
-
@winrm ||= begin
|
77
|
-
http_method = ( @options[:port].to_s=~/(443|5986)/ ? 'https' : 'http' )
|
78
|
-
endpoint = "#{http_method}://#{@host}:#{@options[:port]}/wsman"
|
79
|
-
client = ::WinRM::WinRMWebService.new(endpoint, @transport, @options)
|
80
|
-
client.set_timeout(@options[:operation_timeout]) if @options[:operation_timeout]
|
81
|
-
client
|
82
|
-
rescue ::WinRM::WinRMAuthorizationError => error
|
83
|
-
raise ::WinRM::WinRMAuthorizationError.new("#{error.message}@#{@host}")
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
1
|
+
#
|
2
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2011 Seth Chisamore
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'uuidtools'
|
20
|
+
|
21
|
+
module EventMachine
|
22
|
+
module WinRM
|
23
|
+
class Server
|
24
|
+
include EM::Deferrable
|
25
|
+
|
26
|
+
attr_accessor :master, :host
|
27
|
+
|
28
|
+
def initialize(master, host, options)
|
29
|
+
@master = master
|
30
|
+
@host = host
|
31
|
+
@transport = options[:transport] || :plaintext
|
32
|
+
@options = options
|
33
|
+
@options[:user] = @options.delete(:user) || ENV['USER'] || ENV['USERNAME'] || "unknown"
|
34
|
+
@options[:pass] = @options.delete(:password)
|
35
|
+
@options[:port] = @options.delete(:port) || 5985
|
36
|
+
@options[:basic_auth_only] = true unless defined? @options[:basic_auth_only]
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# create a shell and run command
|
41
|
+
#
|
42
|
+
def run_command(data)
|
43
|
+
cid = UUIDTools::UUID.random_create.to_s
|
44
|
+
EM.epoll
|
45
|
+
EM.run do
|
46
|
+
EM.defer(proc do
|
47
|
+
WinRM::Log.debug("#{@host} => :run_command")
|
48
|
+
@shell = Shell.new(client, self)
|
49
|
+
@shell.on_output do |out|
|
50
|
+
@master.relay_output_from_backend(@host, out)
|
51
|
+
end
|
52
|
+
@shell.on_error do |error|
|
53
|
+
@master.relay_error_from_backend(@host, error)
|
54
|
+
end
|
55
|
+
@shell.on_close do |result, exit_code|
|
56
|
+
@master.command_complete(@host, cid, exit_code)
|
57
|
+
end
|
58
|
+
@shell.run_command(data)
|
59
|
+
end)
|
60
|
+
end
|
61
|
+
cid
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# Notify upstream master that the backend server is done
|
66
|
+
# processing the request
|
67
|
+
#
|
68
|
+
def unbind
|
69
|
+
WinRM::Log.debug("#{@host} => :unbind")
|
70
|
+
@master.unbind_backend(@host)
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def client
|
76
|
+
@winrm ||= begin
|
77
|
+
http_method = ( @options[:port].to_s=~/(443|5986)/ ? 'https' : 'http' )
|
78
|
+
endpoint = "#{http_method}://#{@host}:#{@options[:port]}/wsman"
|
79
|
+
client = ::WinRM::WinRMWebService.new(endpoint, @transport, @options)
|
80
|
+
client.set_timeout(@options[:operation_timeout]) if @options[:operation_timeout]
|
81
|
+
client
|
82
|
+
rescue ::WinRM::WinRMAuthorizationError => error
|
83
|
+
raise ::WinRM::WinRMAuthorizationError.new("#{error.message}@#{@host}")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/em-winrm/session.rb
CHANGED
@@ -1,157 +1,157 @@
|
|
1
|
-
#
|
2
|
-
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
-
# Copyright:: Copyright (c) 2011 Seth Chisamore
|
4
|
-
# License:: Apache License, Version 2.0
|
5
|
-
#
|
6
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
-
# you may not use this file except in compliance with the License.
|
8
|
-
# You may obtain a copy of the License at
|
9
|
-
#
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
-
# See the License for the specific language governing permissions and
|
16
|
-
# limitations under the License.
|
17
|
-
#
|
18
|
-
|
19
|
-
module EventMachine
|
20
|
-
module WinRM
|
21
|
-
class Session
|
22
|
-
|
23
|
-
attr_reader :exit_codes
|
24
|
-
##### Proxy Methods
|
25
|
-
def on_output(&blk); @on_output = blk; end
|
26
|
-
def on_error(&blk); @on_error = blk; end
|
27
|
-
def on_command_complete(&blk); @on_command_complete = blk; end
|
28
|
-
def on_finish(&blk); @on_finish = blk; end
|
29
|
-
def on_close(&blk); @on_close = blk; end
|
30
|
-
|
31
|
-
def initialize(options={})
|
32
|
-
if options[:logger]
|
33
|
-
WinRM::Log.logger = options[:logger]
|
34
|
-
else
|
35
|
-
log_level = options[:log_level] || :info
|
36
|
-
WinRM::Log.level(log_level)
|
37
|
-
end
|
38
|
-
@servers = {}
|
39
|
-
@commands = []
|
40
|
-
@exit_codes = {}
|
41
|
-
WinRM::Log.debug(":session => :init")
|
42
|
-
end
|
43
|
-
|
44
|
-
#
|
45
|
-
# run command on all servers
|
46
|
-
#
|
47
|
-
def relay_command(data)
|
48
|
-
EM.epoll
|
49
|
-
EM.run do
|
50
|
-
WinRM::Log.debug(":relay_to_servers => #{data}")
|
51
|
-
servers ||= @servers.values.compact
|
52
|
-
servers.each do |s|
|
53
|
-
operation = proc do
|
54
|
-
WinRM::Log.debug(":relayed => #{s.host}")
|
55
|
-
@commands << s.run_command(data)
|
56
|
-
end
|
57
|
-
EM.defer(operation)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
#
|
63
|
-
# initialize connections to a server
|
64
|
-
#
|
65
|
-
def use(host, options)
|
66
|
-
@servers[host] = Server.new(self, host, options)
|
67
|
-
end
|
68
|
-
|
69
|
-
#
|
70
|
-
# return an array of the current servers in the session
|
71
|
-
#
|
72
|
-
def servers
|
73
|
-
@servers.values
|
74
|
-
end
|
75
|
-
|
76
|
-
#
|
77
|
-
# set the current servers in the session
|
78
|
-
#
|
79
|
-
def servers=(servers)
|
80
|
-
@servers = {}
|
81
|
-
servers.each{|s| @servers[s.host] = s}
|
82
|
-
end
|
83
|
-
|
84
|
-
#
|
85
|
-
# returns a new EventMachine::WinRM::Session instance
|
86
|
-
# consisting of a specific sub-set of servers
|
87
|
-
#
|
88
|
-
# inspired by Net::SSH::Multi::Session.on
|
89
|
-
#
|
90
|
-
def on(*new_servers)
|
91
|
-
subsession = self.clone
|
92
|
-
subsession.servers = new_servers & servers
|
93
|
-
yield subsession if block_given?
|
94
|
-
subsession
|
95
|
-
end
|
96
|
-
|
97
|
-
#
|
98
|
-
# relay output from backend server to client
|
99
|
-
#
|
100
|
-
def relay_output_from_backend(host, data)
|
101
|
-
WinRM::Log.debug(":relay_output_from_backend => #{[host, data]}")
|
102
|
-
data = @on_output.call(host, data) if @on_output
|
103
|
-
end
|
104
|
-
|
105
|
-
#
|
106
|
-
# relay error output from backend server to client
|
107
|
-
#
|
108
|
-
def relay_error_from_backend(host, data)
|
109
|
-
WinRM::Log.debug(":relay_error_from_backend => #{[host, data]}")
|
110
|
-
data = @on_error.call(host, data) if @on_error
|
111
|
-
end
|
112
|
-
|
113
|
-
#
|
114
|
-
# called by backend server when it completes a command
|
115
|
-
#
|
116
|
-
def command_complete(host, cid,exit_code)
|
117
|
-
WinRM::Log.debug(":command_complete => #{host} with return code #{exit_code}")
|
118
|
-
@commands.delete(cid)
|
119
|
-
@on_command_complete.call(host) if @on_command_complete
|
120
|
-
@exit_codes[host] = exit_code
|
121
|
-
if @commands.compact.size.zero?
|
122
|
-
@on_command_complete.call(:all) if @on_command_complete
|
123
|
-
EM.stop
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
def unbind
|
128
|
-
WinRM::Log.debug(":unbind => :connection")
|
129
|
-
# terminate any unfinished connections
|
130
|
-
@servers.values.compact.each do |s|
|
131
|
-
s.unbind
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def unbind_backend(host)
|
136
|
-
WinRM::Log.debug(":unbind_backend => #{host}")
|
137
|
-
@servers[host] = nil
|
138
|
-
@on_finish.call(host) if @on_finish
|
139
|
-
if @servers.values.compact.size.zero?
|
140
|
-
@on_finish.call(:all) if @on_finish
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
#
|
145
|
-
# clean up servers and stop
|
146
|
-
# the EventMachine event loop
|
147
|
-
#
|
148
|
-
def close
|
149
|
-
unbind
|
150
|
-
# try to stop eventmachine loop
|
151
|
-
EM.stop rescue
|
152
|
-
@on_close.call if @on_close
|
153
|
-
WinRM::Log.debug(":session => :close")
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
1
|
+
#
|
2
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2011 Seth Chisamore
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
module EventMachine
|
20
|
+
module WinRM
|
21
|
+
class Session
|
22
|
+
|
23
|
+
attr_reader :exit_codes
|
24
|
+
##### Proxy Methods
|
25
|
+
def on_output(&blk); @on_output = blk; end
|
26
|
+
def on_error(&blk); @on_error = blk; end
|
27
|
+
def on_command_complete(&blk); @on_command_complete = blk; end
|
28
|
+
def on_finish(&blk); @on_finish = blk; end
|
29
|
+
def on_close(&blk); @on_close = blk; end
|
30
|
+
|
31
|
+
def initialize(options={})
|
32
|
+
if options[:logger]
|
33
|
+
WinRM::Log.logger = options[:logger]
|
34
|
+
else
|
35
|
+
log_level = options[:log_level] || :info
|
36
|
+
WinRM::Log.level(log_level)
|
37
|
+
end
|
38
|
+
@servers = {}
|
39
|
+
@commands = []
|
40
|
+
@exit_codes = {}
|
41
|
+
WinRM::Log.debug(":session => :init")
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# run command on all servers
|
46
|
+
#
|
47
|
+
def relay_command(data)
|
48
|
+
EM.epoll
|
49
|
+
EM.run do
|
50
|
+
WinRM::Log.debug(":relay_to_servers => #{data}")
|
51
|
+
servers ||= @servers.values.compact
|
52
|
+
servers.each do |s|
|
53
|
+
operation = proc do
|
54
|
+
WinRM::Log.debug(":relayed => #{s.host}")
|
55
|
+
@commands << s.run_command(data)
|
56
|
+
end
|
57
|
+
EM.defer(operation)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# initialize connections to a server
|
64
|
+
#
|
65
|
+
def use(host, options)
|
66
|
+
@servers[host] = Server.new(self, host, options)
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
# return an array of the current servers in the session
|
71
|
+
#
|
72
|
+
def servers
|
73
|
+
@servers.values
|
74
|
+
end
|
75
|
+
|
76
|
+
#
|
77
|
+
# set the current servers in the session
|
78
|
+
#
|
79
|
+
def servers=(servers)
|
80
|
+
@servers = {}
|
81
|
+
servers.each{|s| @servers[s.host] = s}
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
# returns a new EventMachine::WinRM::Session instance
|
86
|
+
# consisting of a specific sub-set of servers
|
87
|
+
#
|
88
|
+
# inspired by Net::SSH::Multi::Session.on
|
89
|
+
#
|
90
|
+
def on(*new_servers)
|
91
|
+
subsession = self.clone
|
92
|
+
subsession.servers = new_servers & servers
|
93
|
+
yield subsession if block_given?
|
94
|
+
subsession
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
# relay output from backend server to client
|
99
|
+
#
|
100
|
+
def relay_output_from_backend(host, data)
|
101
|
+
WinRM::Log.debug(":relay_output_from_backend => #{[host, data]}")
|
102
|
+
data = @on_output.call(host, data) if @on_output
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
# relay error output from backend server to client
|
107
|
+
#
|
108
|
+
def relay_error_from_backend(host, data)
|
109
|
+
WinRM::Log.debug(":relay_error_from_backend => #{[host, data]}")
|
110
|
+
data = @on_error.call(host, data) if @on_error
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# called by backend server when it completes a command
|
115
|
+
#
|
116
|
+
def command_complete(host, cid,exit_code)
|
117
|
+
WinRM::Log.debug(":command_complete => #{host} with return code #{exit_code}")
|
118
|
+
@commands.delete(cid)
|
119
|
+
@on_command_complete.call(host) if @on_command_complete
|
120
|
+
@exit_codes[host] = exit_code
|
121
|
+
if @commands.compact.size.zero?
|
122
|
+
@on_command_complete.call(:all) if @on_command_complete
|
123
|
+
EM.stop
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def unbind
|
128
|
+
WinRM::Log.debug(":unbind => :connection")
|
129
|
+
# terminate any unfinished connections
|
130
|
+
@servers.values.compact.each do |s|
|
131
|
+
s.unbind
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def unbind_backend(host)
|
136
|
+
WinRM::Log.debug(":unbind_backend => #{host}")
|
137
|
+
@servers[host] = nil
|
138
|
+
@on_finish.call(host) if @on_finish
|
139
|
+
if @servers.values.compact.size.zero?
|
140
|
+
@on_finish.call(:all) if @on_finish
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
#
|
145
|
+
# clean up servers and stop
|
146
|
+
# the EventMachine event loop
|
147
|
+
#
|
148
|
+
def close
|
149
|
+
unbind
|
150
|
+
# try to stop eventmachine loop
|
151
|
+
EM.stop rescue
|
152
|
+
@on_close.call if @on_close
|
153
|
+
WinRM::Log.debug(":session => :close")
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
157
|
end
|