spacewalk 0.0.2
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/CHANGELOG +3 -0
- data/Gemfile +4 -0
- data/LICENSE +58 -0
- data/README.rdoc +35 -0
- data/Rakefile +6 -0
- data/bin/actions.rb +6 -0
- data/doc/protocol.doc +203 -0
- data/lib/spacewalk.rb +6 -0
- data/lib/spacewalk/capabilities.rb +18 -0
- data/lib/spacewalk/config.rb +26 -0
- data/lib/spacewalk/server.rb +155 -0
- data/lib/spacewalk/status_report.rb +20 -0
- data/lib/spacewalk/system_id.rb +26 -0
- data/lib/spacewalk/version.rb +3 -0
- data/lib/spacewalk/xmlrpc.rb +58 -0
- data/spacewalk.gemspec +28 -0
- data/tasks/clean.rake +8 -0
- data/tasks/doc.rake +14 -0
- data/tasks/test.rake +6 -0
- metadata +117 -0
data/CHANGELOG
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.co.jp>.
|
2
|
+
You can redistribute it and/or modify it under either the terms of the GPL
|
3
|
+
(see COPYING.txt file), or the conditions below:
|
4
|
+
|
5
|
+
1. You may make and give away verbatim copies of the source form of the
|
6
|
+
software without restriction, provided that you duplicate all of the
|
7
|
+
original copyright notices and associated disclaimers.
|
8
|
+
|
9
|
+
2. You may modify your copy of the software in any way, provided that
|
10
|
+
you do at least ONE of the following:
|
11
|
+
|
12
|
+
a) place your modifications in the Public Domain or otherwise
|
13
|
+
make them Freely Available, such as by posting said
|
14
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
15
|
+
the author to include your modifications in the software.
|
16
|
+
|
17
|
+
b) use the modified software only within your corporation or
|
18
|
+
organization.
|
19
|
+
|
20
|
+
c) rename any non-standard executables so the names do not conflict
|
21
|
+
with standard executables, which must also be provided.
|
22
|
+
|
23
|
+
d) make other distribution arrangements with the author.
|
24
|
+
|
25
|
+
3. You may distribute the software in object code or executable
|
26
|
+
form, provided that you do at least ONE of the following:
|
27
|
+
|
28
|
+
a) distribute the executables and library files of the software,
|
29
|
+
together with instructions (in the manual page or equivalent)
|
30
|
+
on where to get the original distribution.
|
31
|
+
|
32
|
+
b) accompany the distribution with the machine-readable source of
|
33
|
+
the software.
|
34
|
+
|
35
|
+
c) give non-standard executables non-standard names, with
|
36
|
+
instructions on where to get the original software distribution.
|
37
|
+
|
38
|
+
d) make other distribution arrangements with the author.
|
39
|
+
|
40
|
+
4. You may modify and include the part of the software into any other
|
41
|
+
software (possibly commercial). But some files in the distribution
|
42
|
+
are not written by the author, so that they are not under this terms.
|
43
|
+
|
44
|
+
They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
|
45
|
+
files under the ./missing directory. See each file for the copying
|
46
|
+
condition.
|
47
|
+
|
48
|
+
5. The scripts and library files supplied as input to or produced as
|
49
|
+
output from the software do not automatically fall under the
|
50
|
+
copyright of the software, but belong to whomever generated them,
|
51
|
+
and may be sold commercially, and may be aggregated with this
|
52
|
+
software.
|
53
|
+
|
54
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
55
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
56
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
57
|
+
PURPOSE.
|
58
|
+
|
data/README.rdoc
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
= About Spacewalk
|
2
|
+
|
3
|
+
* http://github.com/kkaempf/ruby-spacewalk
|
4
|
+
* http://spacewalk.redhat.com/
|
5
|
+
* http://www.suse.com/products/suse-manager
|
6
|
+
|
7
|
+
== DESCRIPTION:
|
8
|
+
|
9
|
+
Spacewalk is a pure-Ruby implementation of the Spacewalk client
|
10
|
+
protocol stack.
|
11
|
+
|
12
|
+
== SYNOPSIS:
|
13
|
+
|
14
|
+
require 'spacewalk'
|
15
|
+
|
16
|
+
# Assuming that /etc/sysconfig/rhn/ exists
|
17
|
+
server = Spacewalk::Server.new
|
18
|
+
# get pending action for system
|
19
|
+
action = server.actions
|
20
|
+
|
21
|
+
== REQUIREMENTS:
|
22
|
+
|
23
|
+
* - none -
|
24
|
+
|
25
|
+
== INSTALL:
|
26
|
+
|
27
|
+
* sudo gem install spacewalk
|
28
|
+
|
29
|
+
== LICENSE:
|
30
|
+
|
31
|
+
(The Ruby License)
|
32
|
+
|
33
|
+
Copyright (c) 2011 SUSE Linux Products GmbH
|
34
|
+
|
35
|
+
See http://www.ruby-lang.org/en/LICENSE.txt for the full text
|
data/Rakefile
ADDED
data/bin/actions.rb
ADDED
data/doc/protocol.doc
ADDED
@@ -0,0 +1,203 @@
|
|
1
|
+
Client protocol
|
2
|
+
|
3
|
+
From looking at spacewalk/client/rhel/rhn-client-tools/src/up2date_client/up2dateAuth.py
|
4
|
+
|
5
|
+
- client configuration
|
6
|
+
- /etc/sysconfig/rhn/up2date
|
7
|
+
- text
|
8
|
+
- augmented <key>[<comment>] = <value>
|
9
|
+
'cfg'
|
10
|
+
|
11
|
+
- where is my server ?
|
12
|
+
- ./rhn-client-tools/src/up2date_client/rpcServer.py
|
13
|
+
- access through proxy
|
14
|
+
if cfg["enableProxy"]:
|
15
|
+
proxyHost = config.getProxySetting()
|
16
|
+
|
17
|
+
if cfg["enableProxyAuth"]:
|
18
|
+
proxyUser = cfg["proxyUser"] or None
|
19
|
+
proxyPassword = cfg["proxyPassword"] or None
|
20
|
+
|
21
|
+
- support for multiple servers
|
22
|
+
serverUrls = config.getServerlURL()
|
23
|
+
./rhn-client-tools/src/up2date_client/config.py
|
24
|
+
-> cfg["serverURL"] = https://manager.suse.de/XMLRPC
|
25
|
+
handler = /RPC2
|
26
|
+
-> could be multiple
|
27
|
+
serverList = ServerList(serverUrls)
|
28
|
+
|
29
|
+
- secure communication with server
|
30
|
+
ca = cfg["sslCACert"]
|
31
|
+
if isinstance(ca, basestring):
|
32
|
+
ca = [ca]
|
33
|
+
|
34
|
+
rhns_ca_certs = ca or ["/usr/share/rhn/RHNS-CA-CERT"]
|
35
|
+
|
36
|
+
- build up http(s) header
|
37
|
+
s.add_header("X-Up2date-Version", up2dateUtils.version())
|
38
|
+
|
39
|
+
- send up the (client) capabality info
|
40
|
+
headerlist = clientCaps.caps.headerFormat()
|
41
|
+
for (headerName, value) in headerlist:
|
42
|
+
s.add_header(headerName, value)
|
43
|
+
|
44
|
+
- client needs to authenticate
|
45
|
+
- cfg["systemIdPath] -> systemIdPath=/etc/sysconfig/rhn/systemid
|
46
|
+
- /etc/sysconfig/rhn/systemid
|
47
|
+
- xml formatted
|
48
|
+
|
49
|
+
- does a version check of rpmdb with systemid
|
50
|
+
- spacewalk/client/rhel/rhn-client-tools/src/up2date_client/up2dateUtils.py
|
51
|
+
- spacewalk/client/rhel/rhn-client-tools/src/up2date_client/transaction.py
|
52
|
+
- checks provider of redhat-release or distribution-release
|
53
|
+
- if the system was updated, client will get a new id
|
54
|
+
- can be overridden via cfg["versionOverride"]
|
55
|
+
|
56
|
+
- populates http header
|
57
|
+
from /etc/sysconfig/rhn/clientCaps.d
|
58
|
+
with "X-RHN-Client-Capability: <name>(<version>)=<value>"
|
59
|
+
|
60
|
+
- report = { "uname" => [<uname>], "uptime" => <uptime>]
|
61
|
+
os.uname(): ('Linux', 'kkaempf', '3.0.4-43-desktop', '#1 SMP PREEMPT Wed Aug 31 09:30:44 UTC 2011 (a432f18)', 'i686')
|
62
|
+
(uname -s, uname -n, uname -r, uname -v, uname -m)
|
63
|
+
uptime : /proc/uptime as [int, int]
|
64
|
+
|
65
|
+
= server side xmlrpc
|
66
|
+
spacewalk/backend/server/handlers/xmlrpc
|
67
|
+
call <file>.<method>
|
68
|
+
|
69
|
+
- call registration.welcome_message
|
70
|
+
=> sets 'checked in' in database
|
71
|
+
|
72
|
+
- call get.actions systemid, ACTION_VERSION, report until empty
|
73
|
+
Remove example:
|
74
|
+
{"action"=>["packages.remove", [[["alsa-devel", "1.0.24.1", "30.1", "", ""]]]], "id"=>1061, "version"=>2}
|
75
|
+
id == action id
|
76
|
+
-> https://manager.suse.de/rhn/schedule/ActionDetails.do?aid=1061
|
77
|
+
Install/Update example:
|
78
|
+
{"action"=>["packages.update", [[["aqbanking", "5.0.10", "5.12", "", ""], ["epdfview", "0.1.8", "5.1", "", ""]]]], "id"=>1063, "version"=>2}
|
79
|
+
Reboot action:
|
80
|
+
{"action"=>["reboot.reboot", []], "id"=>1066, "version"=>2}
|
81
|
+
Hardware refresh:
|
82
|
+
{"action"=>["hardware.refresh_list", []], "id"=>1067, "version"=>2}
|
83
|
+
|
84
|
+
=> only gets the next scheduled action, not all scheduled actions
|
85
|
+
|
86
|
+
queue.submit(up2dateAuth.getSystemId(), action_id, status, message,data)
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
- run local actions
|
91
|
+
LOCAL_ACTIONS = [("packages.checkNeedUpdate", ("rhnsd=1",))]
|
92
|
+
-> method = getMethod.getMethod(method, "/usr/share/rhn/","actions")
|
93
|
+
(status,message,data) = method(*params, **kwargs)
|
94
|
+
|
95
|
+
- packages.checkNeedUpdate
|
96
|
+
compate st_mtime of (cfg["dbpath"] || "/var/lib/rpm")/Packages with /var/lib/up2date/dbtimestamp
|
97
|
+
-> rhnPackageInfo.updatePackageProfile
|
98
|
+
rhel/rhn-client-tools/src/up2date_client/rhnPackageInfo.py
|
99
|
+
get package hash (pkgUtils.getInstalledPackageList(getArch=1)
|
100
|
+
rhel/rhn-client-tools/src/up2date_client/rpmUtils.py
|
101
|
+
"Return list of packages. Package is hash with keys name, epoch,
|
102
|
+
version, release and optionaly arch and cookie"
|
103
|
+
"name": <string-value>
|
104
|
+
"epoch": <string-value>
|
105
|
+
"version": <string-value>
|
106
|
+
"release": <string-value>
|
107
|
+
"installtime": <string-value>
|
108
|
+
"arch": <string-value>
|
109
|
+
"cookie"
|
110
|
+
unless server.has_capability xmlrpc.packages.extended_profile=2
|
111
|
+
convert hash to list
|
112
|
+
xmlrpc registration.update_packages(systemid, packages)
|
113
|
+
|
114
|
+
============
|
115
|
+
|
116
|
+
First call to Server: registration.welcome_message
|
117
|
+
returns
|
118
|
+
Header
|
119
|
+
- "x-transport-info"=>["Extended Capabilities Transport (C) Red Hat, Inc (version $Revision$)"],
|
120
|
+
- "x-rhn-server-capability"=>
|
121
|
+
["registration.finish_message(1)=1",
|
122
|
+
"applet.has_base_channel(1)=1",
|
123
|
+
"rhncfg.filetype.directory(1)=1",
|
124
|
+
"registration.register_osad(1)=1",
|
125
|
+
"registration.delta_packages(1)=1",
|
126
|
+
"xmlrpc.packages.extended_profile(1-2)=1",
|
127
|
+
"registration.remaining_subscriptions(1)=1",
|
128
|
+
"registration.update_contact_info(1)=1",
|
129
|
+
"staging_content(1)=1",
|
130
|
+
"registration.extended_update_support(1)=1",
|
131
|
+
"xmlrpc.packages.suse_products(1)=1",
|
132
|
+
"rhncfg.content.base64_decode(1)=1",
|
133
|
+
"registration.smbios(1)=1",
|
134
|
+
"xmlrpc.errata.patch_names(1)=1",
|
135
|
+
"xmlrpc.login.extra_data(1)=1"],
|
136
|
+
- "x-rhn-client-version"=>["0"],
|
137
|
+
- "content-transfer-encoding"=>["base64"],
|
138
|
+
- "connection"=>["close"],
|
139
|
+
- "content-type"=>["text/base64"],
|
140
|
+
- "x-rhn-proxy-version"=>["None"],
|
141
|
+
- "date"=>["Wed, 14 Dec 2011 10:54:55 GMT"],
|
142
|
+
- "server"=>["Apache"],
|
143
|
+
- "content-length"=>["163"],
|
144
|
+
- "content-encoding"=>["x-zlib"]
|
145
|
+
Body
|
146
|
+
eJyzsa/IzVEoSy0qzszPs1U31DNQt7fjsslNLcnITwlKLS7IzytOBQoUJBYl5hbDGEC6LDGnNNXO
|
147
|
+
prikKDMv3S4oNUXBI7FEwS+1pDy/KFshPDUnOT83VcE3tbg4MT3VRh+qzkYfoo/LRh9mkD7caH10
|
148
|
+
WwGMyDXu
|
149
|
+
-> zlib.deflate.decodebase64
|
150
|
+
<?xml version='1.0'?>
|
151
|
+
<methodResponse>
|
152
|
+
<params>
|
153
|
+
<param>
|
154
|
+
<value><string>Red Hat Network Welcome Message</string></value>
|
155
|
+
</param>
|
156
|
+
</params>
|
157
|
+
</methodResponse>
|
158
|
+
===========
|
159
|
+
|
160
|
+
rhnreg_ks
|
161
|
+
|
162
|
+
- needs user/pass or activation code
|
163
|
+
|
164
|
+
- registered? cfg["systemIdPath] exists
|
165
|
+
|
166
|
+
- server.capabilities.validate()
|
167
|
+
|
168
|
+
- packageList = pkgUtils.getInstalledPackageList(getArch=getArch)
|
169
|
+
hardwareList = hardware.Hardware()
|
170
|
+
profilename = self.options.profilename || RegisterKsCli.__generateProfileName(hardwareList)
|
171
|
+
other = {}
|
172
|
+
if self.options.systemorgid:
|
173
|
+
other['org_id'] = self.options.systemorgid
|
174
|
+
(virt_uuid, virt_type) = rhnreg.get_virt_info()
|
175
|
+
if not virt_uuid is None:
|
176
|
+
other['virt_uuid'] = virt_uuid
|
177
|
+
other['virt_type'] = virt_type
|
178
|
+
systemId = rhnreg.registerSystem(token = self.options.activationkey,
|
179
|
+
profileName = profilename,
|
180
|
+
other = other)
|
181
|
+
rhnreg.sendHardware(systemId, hardwareList)
|
182
|
+
rhnreg.sendPackages(systemId, packageList)
|
183
|
+
# write out the new id
|
184
|
+
if isinstance(systemId, unicode):
|
185
|
+
rhnreg.writeSystemId(unicode.encode(systemId, 'utf-8'))
|
186
|
+
else:
|
187
|
+
rhnreg.writeSystemId(systemId)
|
188
|
+
rhnreg.cfg.save()
|
189
|
+
rhnreg.sendVirtInfo(systemId)
|
190
|
+
rhnreg.startRhnsd()
|
191
|
+
|
192
|
+
- profileName
|
193
|
+
Convert Internationalized domain name from Pune encoding to Unicode
|
194
|
+
for hw in hardwareList:
|
195
|
+
if hw['class'] == 'NETINFO':
|
196
|
+
hostname = hw.get('hostname')
|
197
|
+
ipaddr = hw.get('ipaddr')
|
198
|
+
if hostname:
|
199
|
+
profileName = idn_pune_to_unicode(hostname)
|
200
|
+
else:
|
201
|
+
if ipaddr:
|
202
|
+
profileName = ipaddr
|
203
|
+
|
data/lib/spacewalk.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Spacewalk
|
2
|
+
class Capabilities
|
3
|
+
#
|
4
|
+
def initialize client
|
5
|
+
# hash of <capability> => <version>
|
6
|
+
@caps = {}
|
7
|
+
client.http_last_response["x-rhn-server-capability"].split(",").each do |caps|
|
8
|
+
caps.split(",").each do |cap|
|
9
|
+
# puts "#{cap}"
|
10
|
+
raise "Invalid cap '#{cap}'" unless cap =~ /(\s+)?(((\w+)|\.)+)\((\d(-\d)?)\)=(\d)/
|
11
|
+
# name = [ version, value ]
|
12
|
+
@caps[$2] = [$5, $7]
|
13
|
+
# puts "#{$2}(#{$5})=#{$7}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Spacewalk
|
2
|
+
class Config
|
3
|
+
def initialize path="/etc/sysconfig/rhn/up2date"
|
4
|
+
@path = path
|
5
|
+
@config = {}
|
6
|
+
File.open path do |f|
|
7
|
+
while l = f.gets
|
8
|
+
# split <name>=<value>, drop everything else
|
9
|
+
next unless l =~ /(\w+)=(.*)/
|
10
|
+
key = $1
|
11
|
+
val = $2
|
12
|
+
# fixme: handle array-type values
|
13
|
+
@config[key.downcase] = val.empty? ? nil : val
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def [] key
|
19
|
+
@config[key.downcase]
|
20
|
+
end
|
21
|
+
|
22
|
+
def method_missing name
|
23
|
+
@config[name.to_s.downcase]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
module XMLRPC
|
2
|
+
class Client
|
3
|
+
def get_parser
|
4
|
+
parser
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module Spacewalk
|
10
|
+
class Server
|
11
|
+
# from /usr/sbin/rhn_check
|
12
|
+
# action version we understand
|
13
|
+
ACTION_VERSION = 2
|
14
|
+
|
15
|
+
require "xmlrpc/client"
|
16
|
+
require 'uri'
|
17
|
+
require 'zlib'
|
18
|
+
require 'base64'
|
19
|
+
require 'rexml/document'
|
20
|
+
|
21
|
+
private
|
22
|
+
def call name, *args
|
23
|
+
# puts "Call #{name}(#{args.inspect})"
|
24
|
+
begin
|
25
|
+
# remove trailing nil values, nil is not supported in xmlrpc
|
26
|
+
while args.size > 0 && args[-1].nil? do
|
27
|
+
args.pop
|
28
|
+
end
|
29
|
+
result = @client.call(name, *args)
|
30
|
+
rescue Exception => e
|
31
|
+
raise e unless e.message =~ /Wrong content-type/
|
32
|
+
end
|
33
|
+
response = @client.http_last_response
|
34
|
+
raise "XMLRPC failed with #{response.code}" unless response.code == "200"
|
35
|
+
body = response.body
|
36
|
+
case response["content-type"]
|
37
|
+
when "text/base64"
|
38
|
+
body = Base64.decode64(body)
|
39
|
+
when "text/xml"
|
40
|
+
# fallthru
|
41
|
+
else
|
42
|
+
STDERR.puts "Unhandled content-type #{response['content-type']}"
|
43
|
+
end
|
44
|
+
case response["content-encoding"]
|
45
|
+
when "x-zlib"
|
46
|
+
body = Zlib::Inflate.inflate(body)
|
47
|
+
when nil
|
48
|
+
# fallthru
|
49
|
+
else
|
50
|
+
STDERR.puts "Unhandled content-encoding #{response['content-encoding']}"
|
51
|
+
end
|
52
|
+
ok, result = @client.get_parser.parseMethodResponse(body)
|
53
|
+
raise unless ok
|
54
|
+
result
|
55
|
+
end
|
56
|
+
public
|
57
|
+
|
58
|
+
#
|
59
|
+
# Initialize server xmlrpc port
|
60
|
+
# options:
|
61
|
+
# :noconfig => true - don't load @config
|
62
|
+
# :server => string - url of server (for initial registration)
|
63
|
+
# :systemid => string
|
64
|
+
#
|
65
|
+
def initialize options = {}
|
66
|
+
@config = Spacewalk::Config.new
|
67
|
+
if options[:noconfig]
|
68
|
+
uri = URI.parse(options[:server])
|
69
|
+
uri.path = "/XMLRPC"
|
70
|
+
else
|
71
|
+
uri = URI.parse(@config.serverurl)
|
72
|
+
end
|
73
|
+
|
74
|
+
args = {:host=>uri.host, :path => uri.path, :use_ssl => (uri.scheme == "https")}
|
75
|
+
|
76
|
+
unless options[:noconfig]
|
77
|
+
if @config.httpProxy
|
78
|
+
args[:proxy_host], clientargs[:proxy_port] = @config.httpProxy.split ":"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
@client = XMLRPC::Client.new_from_hash args
|
83
|
+
|
84
|
+
@client.http_header_extra = {}
|
85
|
+
|
86
|
+
welcome
|
87
|
+
|
88
|
+
# parse server capabilities
|
89
|
+
@capabilities = Spacewalk::Capabilities.new @client
|
90
|
+
|
91
|
+
@client.http_header_extra["X-Up2date-Version"] = "1.6.42" # from rhn-client-tools.spec
|
92
|
+
@client.http_header_extra["X-RHN-Client-Capability"] = "packages.extended_profile(2)=1"
|
93
|
+
@systemid = options[:systemid]
|
94
|
+
unless @systemid || options[:noconfig]
|
95
|
+
@systemid = Spacewalk::SystemId.new(@client, @config).to_xml
|
96
|
+
end
|
97
|
+
# check for distribution update
|
98
|
+
# my_id = @systemid.os_release
|
99
|
+
# server_id = osversion
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
# welcome to/from server
|
104
|
+
def welcome
|
105
|
+
result = call "registration.welcome_message"
|
106
|
+
puts "Welcome => #{result.inspect}"
|
107
|
+
end
|
108
|
+
|
109
|
+
# get system O/S version
|
110
|
+
def osversion
|
111
|
+
result = @config.versionOverride
|
112
|
+
unless result
|
113
|
+
# find rpm provider of redhat-release or distribution-release, get its version
|
114
|
+
end
|
115
|
+
result
|
116
|
+
end
|
117
|
+
|
118
|
+
def actions
|
119
|
+
report = Spacewalk::StatusReport.status
|
120
|
+
|
121
|
+
result = call "queue.get", @systemid, ACTION_VERSION, report
|
122
|
+
puts "Actions => #{result.inspect}"
|
123
|
+
|
124
|
+
if action = result["action"]
|
125
|
+
result["action"] = @client.get_parser.parseMethodCall(action)
|
126
|
+
end
|
127
|
+
puts "Actions => #{result.inspect}"
|
128
|
+
end
|
129
|
+
|
130
|
+
def register activationkey, profile_name, other = {}
|
131
|
+
auth_dict = {}
|
132
|
+
auth_dict["profile_name"] = profile_name
|
133
|
+
#"os_release" : up2dateUtils.getVersion(),
|
134
|
+
#"release_name" : up2dateUtils.getOSRelease(),
|
135
|
+
#"architecture" : up2dateUtils.getArch() }
|
136
|
+
# dict of other bits to send
|
137
|
+
auth_dict.update other
|
138
|
+
auth_dict["token"] = activationkey
|
139
|
+
# auth_dict["username"] = username
|
140
|
+
# auth_dict["password"] = password
|
141
|
+
|
142
|
+
# if cfg['supportsSMBIOS']:
|
143
|
+
# auth_dict["smbios"] = _encode_characters(hardware.get_smbios())
|
144
|
+
STDERR.puts "registration.new_system #{auth_dict.inspect}"
|
145
|
+
@systemid = call "registration.new_system", auth_dict
|
146
|
+
end
|
147
|
+
|
148
|
+
def send_packages packages
|
149
|
+
call "registration.add_packages", @systemid, packages
|
150
|
+
end
|
151
|
+
def refresh_hardware devices
|
152
|
+
call "registration.refresh_hw_profile", @systemid, devices
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Spacewalk
|
2
|
+
class StatusReport
|
3
|
+
def self.status
|
4
|
+
status = {}
|
5
|
+
# Return a 5-tuple containing information identifying the current operating system.
|
6
|
+
# The tuple contains 5 strings: (sysname, nodename, release, version, machine).
|
7
|
+
# (uname -s, uname -n, uname -r, uname -v, uname -m)
|
8
|
+
status["uname"] = [`uname -s`.chomp, `uname -n`.chomp, `uname -r`.chomp, `uname -v`.chomp, `uname -m`.chomp]
|
9
|
+
begin
|
10
|
+
File.open("/proc/uptime") do |f|
|
11
|
+
status["uptime"] = f.read.split(" ").map{|v| v.to_i}
|
12
|
+
end
|
13
|
+
rescue
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
# puts status.inspect
|
17
|
+
status
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Spacewalk
|
2
|
+
class SystemId
|
3
|
+
require 'xmlrpc/client'
|
4
|
+
def initialize client, config
|
5
|
+
raise "Expecting a Spacewalk::Config parameter to #{self.class}.new" unless config.is_a?(Spacewalk::Config)
|
6
|
+
@path = config["systemIdPath"]
|
7
|
+
raise "systemIdPath is empty !" unless @path
|
8
|
+
# <params>
|
9
|
+
# <param>
|
10
|
+
# <value>
|
11
|
+
# <struct>
|
12
|
+
# <member>
|
13
|
+
# <name>username</name>
|
14
|
+
# <value><string>admin</string></value>
|
15
|
+
# </member>
|
16
|
+
File.open(@path) do |f|
|
17
|
+
@raw = f.read
|
18
|
+
@members = client.get_parser.parseMethodResponse(@raw)
|
19
|
+
end
|
20
|
+
puts "SystemId => #{@members.inspect}"
|
21
|
+
end
|
22
|
+
def to_xml
|
23
|
+
@raw
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Spacewalk
|
2
|
+
class Xmlrpc
|
3
|
+
require 'rexml/document'
|
4
|
+
private
|
5
|
+
def self.value2ruby element
|
6
|
+
puts "value2ruby element #{element}"
|
7
|
+
node = element[0]
|
8
|
+
puts "value2ruby node #{node}"
|
9
|
+
case node.name
|
10
|
+
when "string"
|
11
|
+
node.text
|
12
|
+
when "struct"
|
13
|
+
raise "value2ruby: <member> not following <struct>" unless node[0].name == "member"
|
14
|
+
value = {}
|
15
|
+
puts "Struct #{node}"
|
16
|
+
node.each_element("member") do |e|
|
17
|
+
name = e.elements["member/name"].text
|
18
|
+
v = value2ruby m.elements["member/value"]
|
19
|
+
value[name] = v
|
20
|
+
end
|
21
|
+
value
|
22
|
+
when "array"
|
23
|
+
raise "value2ruby: <data> not following <array>" unless node[0].name == "data"
|
24
|
+
value = []
|
25
|
+
# puts "Array #{node}"
|
26
|
+
node.each_element("data/value") do |e|
|
27
|
+
# puts "recursive #{e}"
|
28
|
+
value << value2ruby(e)
|
29
|
+
end
|
30
|
+
value
|
31
|
+
else
|
32
|
+
raise "value2ruby: Can't handle element '#{element.name}'"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
public
|
36
|
+
# <params>
|
37
|
+
# <param>
|
38
|
+
# <value>
|
39
|
+
# <struct>
|
40
|
+
# <member>
|
41
|
+
# <name>username</name>
|
42
|
+
# <value><string>admin</string></value>
|
43
|
+
# </member>
|
44
|
+
# <value><string>...
|
45
|
+
# <value><array><data>...
|
46
|
+
#
|
47
|
+
def self.decode what
|
48
|
+
@doc.root.elements["params/param"]
|
49
|
+
|
50
|
+
initialize config
|
51
|
+
raise "Expecting a Spacewalk::Config parameter to #{self.class}.new" unless config.is_a?(Spacewalk::Config)
|
52
|
+
@path = config["systemIdPath"]
|
53
|
+
raise "systemIdPath is empty !" unless @path
|
54
|
+
@doc = REXML::Document.new(File.open(@path))
|
55
|
+
@members = @doc.root.elements["params/param"]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/spacewalk.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "spacewalk/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "spacewalk"
|
7
|
+
s.version = Spacewalk::VERSION
|
8
|
+
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.authors = ["Klaus Kämpf"]
|
11
|
+
s.email = ["kkaempf@suse.de"]
|
12
|
+
s.homepage = "https://github.com/kkaempf/ruby-spacewalk"
|
13
|
+
s.summary = %q{A pure-Ruby implementation of the Spacewalk client side}
|
14
|
+
s.description = %q{Can be used for testing or to attach 'foreign'
|
15
|
+
systems}
|
16
|
+
|
17
|
+
s.rubyforge_project = "spacewalk"
|
18
|
+
|
19
|
+
s.add_development_dependency('rake')
|
20
|
+
s.add_development_dependency('bundler')
|
21
|
+
|
22
|
+
s.files = `git ls-files`.split("\n")
|
23
|
+
s.files.reject! { |fn| fn == '.gitignore' }
|
24
|
+
s.extra_rdoc_files = Dir['README*', 'TODO*', 'CHANGELOG*', 'LICENSE']
|
25
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
26
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
27
|
+
s.require_paths = ["lib"]
|
28
|
+
end
|
data/tasks/clean.rake
ADDED
data/tasks/doc.rake
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
begin
|
2
|
+
require 'yard'
|
3
|
+
YARD::Rake::YardocTask.new(:doc) do |t|
|
4
|
+
t.files = ['lib/**/*.rb']
|
5
|
+
t.options = ['--no-private']
|
6
|
+
end
|
7
|
+
rescue LoadError
|
8
|
+
STDERR.puts "Install yard if you want prettier docs"
|
9
|
+
require 'rdoc/task'
|
10
|
+
Rake::RDocTask.new(:doc) do |rdoc|
|
11
|
+
rdoc.rdoc_dir = "doc"
|
12
|
+
rdoc.title = "Spacewalk #{Spacewalk::VERSION}"
|
13
|
+
end
|
14
|
+
end
|
data/tasks/test.rake
ADDED
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: spacewalk
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- "Klaus K\xC3\xA4mpf"
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-01-17 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rake
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: bundler
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
49
|
+
description: |-
|
50
|
+
Can be used for testing or to attach 'foreign'
|
51
|
+
systems
|
52
|
+
email:
|
53
|
+
- kkaempf@suse.de
|
54
|
+
executables:
|
55
|
+
- actions.rb
|
56
|
+
extensions: []
|
57
|
+
|
58
|
+
extra_rdoc_files:
|
59
|
+
- README.rdoc
|
60
|
+
- CHANGELOG
|
61
|
+
- LICENSE
|
62
|
+
files:
|
63
|
+
- CHANGELOG
|
64
|
+
- Gemfile
|
65
|
+
- LICENSE
|
66
|
+
- README.rdoc
|
67
|
+
- Rakefile
|
68
|
+
- bin/actions.rb
|
69
|
+
- doc/protocol.doc
|
70
|
+
- lib/spacewalk.rb
|
71
|
+
- lib/spacewalk/capabilities.rb
|
72
|
+
- lib/spacewalk/config.rb
|
73
|
+
- lib/spacewalk/server.rb
|
74
|
+
- lib/spacewalk/status_report.rb
|
75
|
+
- lib/spacewalk/system_id.rb
|
76
|
+
- lib/spacewalk/version.rb
|
77
|
+
- lib/spacewalk/xmlrpc.rb
|
78
|
+
- spacewalk.gemspec
|
79
|
+
- tasks/clean.rake
|
80
|
+
- tasks/doc.rake
|
81
|
+
- tasks/test.rake
|
82
|
+
has_rdoc: true
|
83
|
+
homepage: https://github.com/kkaempf/ruby-spacewalk
|
84
|
+
licenses: []
|
85
|
+
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
hash: 3
|
97
|
+
segments:
|
98
|
+
- 0
|
99
|
+
version: "0"
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
hash: 3
|
106
|
+
segments:
|
107
|
+
- 0
|
108
|
+
version: "0"
|
109
|
+
requirements: []
|
110
|
+
|
111
|
+
rubyforge_project: spacewalk
|
112
|
+
rubygems_version: 1.5.0
|
113
|
+
signing_key:
|
114
|
+
specification_version: 3
|
115
|
+
summary: A pure-Ruby implementation of the Spacewalk client side
|
116
|
+
test_files: []
|
117
|
+
|