satops 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/satops +5 -0
- data/lib/satops.rb +495 -0
- data/lib/satops/helpers.rb +11 -0
- data/lib/satops/operator.rb +1254 -0
- data/lib/satops/rhsat.rb +574 -0
- metadata +52 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c50c6ccd15bff68d7d331e38292b7d1eef82b28e
|
4
|
+
data.tar.gz: b9aee7b12949d768be4f3e2913aaabbcf050ef96
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5924fc672cbff9eb174cc6557cd03309c7f8620da06a4b1949cb974df83ffaf2410850c4c2434350f37633a1169a1b938587d2aaefc1ff98ab7616be219e519e
|
7
|
+
data.tar.gz: 3a1c18114cb95595e52e5fccffd171408780a8ef75a0f65cda39eb447ddb81db29942b5a996ad94643a64e60338b3d279b98b7c5a3bb494bf2cd1d19db545339
|
data/bin/satops
ADDED
data/lib/satops.rb
ADDED
@@ -0,0 +1,495 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
@@version='1.5.0'
|
3
|
+
=begin header
|
4
|
+
* Name: satops
|
5
|
+
* Description: RHN Satellite API Operator
|
6
|
+
* URL: https://github.com/SatOps/SatOps
|
7
|
+
* Date: 10 Nov 2013
|
8
|
+
* Author: Gilles Dubreuil <gilles@redhat.com>
|
9
|
+
* License: Copyright 2011, 2013 Gilles Dubreuil
|
10
|
+
|
11
|
+
This file is part of SatOps.
|
12
|
+
|
13
|
+
SatOps is free software: you can redistribute it and/or modify
|
14
|
+
it under the terms of the GNU General Public License as published by
|
15
|
+
the Free Software Foundation, either version 3 of the License, or
|
16
|
+
(at your option) any later version.
|
17
|
+
|
18
|
+
SatOps is distributed in the hope that it will be useful,
|
19
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
20
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
21
|
+
GNU General Public License for more details.
|
22
|
+
|
23
|
+
You should have received a copy of the GNU General Public License
|
24
|
+
along with SatOps. If not, see <http://www.gnu.org/licenses/>.
|
25
|
+
=end
|
26
|
+
|
27
|
+
=begin rdoc
|
28
|
+
Commands provided as parameters at command line are filtered by the Launcher class.
|
29
|
+
The latter creates a SatOperator object coordinating the operation.
|
30
|
+
|
31
|
+
The "Operation" Groups correspond to RHN Satellite objects such as Activation Keys, Software channels, etc.
|
32
|
+
|
33
|
+
The SatOperator controls the initial command execution flow for each Operation group.
|
34
|
+
Every Operation Group builds OperationSet objects, i.e RHN Satellite Set of objects, providing interface to RHN Satellite API to manipulate list of those objects.
|
35
|
+
|
36
|
+
At lower level, are RHN Satellite equivalent objects to be copied from or to a Satellite.
|
37
|
+
|
38
|
+
Example with RHN Satellite Activation keys.
|
39
|
+
Activationkey - Class mapping with RHN Satellite objects
|
40
|
+
Low level as it interface with RHN API
|
41
|
+
|
42
|
+
ActivationkeysSet - Notice plural before the Set
|
43
|
+
Subclass of OperationSet
|
44
|
+
Wrap/interface/group Activationkey objects
|
45
|
+
|
46
|
+
Activationkeys
|
47
|
+
Subclass of Operation
|
48
|
+
High level view, interfacing commands (export/import/sync,etc) to execute onto the ActivationkeysSet or Activationkey objects.
|
49
|
+
|
50
|
+
List of all Operations classes:
|
51
|
+
Activationkeys, Channels, Configchannels, Kickstarts, KickstartFilepreservations, KickstartKeys, KickstartSnippets, Orgs, OrgTrusts, Systems, SystemCustominfos, Systemgroups, Users
|
52
|
+
=end
|
53
|
+
|
54
|
+
require "logger"
|
55
|
+
require "xmlrpc/client"
|
56
|
+
require 'yaml'
|
57
|
+
|
58
|
+
def overwrite_net_http
|
59
|
+
# https: Client certificate isn't verified by server so each session generates:
|
60
|
+
# "warning: peer certificate won't be verified in this SSL session"
|
61
|
+
# To get rid of this warning: thanks to http://www.5dollarwhitebox.org/drupal/node/64
|
62
|
+
Net::HTTP.class_eval do
|
63
|
+
alias_method :old_initialize, :initialize
|
64
|
+
def initialize(*args)
|
65
|
+
old_initialize(*args)
|
66
|
+
@ssl_context = OpenSSL::SSL::SSLContext.new
|
67
|
+
@ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
require 'satops/helpers'
|
73
|
+
require 'satops/rhsat'
|
74
|
+
require 'satops/operator'
|
75
|
+
|
76
|
+
def syntax
|
77
|
+
%s{
|
78
|
+
satops #{@@version}
|
79
|
+
|
80
|
+
Usage:
|
81
|
+
satops show sat | config
|
82
|
+
satops -s <sat file> -c <config file> [-dltw] destroy
|
83
|
+
satops -s <sat file> -c <config file> [-dltw] export <directory> ascii | bin
|
84
|
+
satops -s <sat file> -c <config file> [-dltw] import <directory> ascii | bin
|
85
|
+
satops -s <sat file> -c <config file> [-dltw] run <Ruby file>
|
86
|
+
satops -s <sat file> -c <config file> [-dltw] extras
|
87
|
+
satops -s <sat file> -c <config file> [-dltw] sync
|
88
|
+
satops [-h]
|
89
|
+
|
90
|
+
Mandatory Configuration:
|
91
|
+
Sat file: Source and Target RHN Satellites definition
|
92
|
+
Config file: RHN Satellite objects and options
|
93
|
+
Objects must be included to be processed
|
94
|
+
Use 'show sat|config' command for generating either templates
|
95
|
+
|
96
|
+
Options:
|
97
|
+
-d, --debug Activate debug output
|
98
|
+
-l, --log Append logs to file. By default logs go to Standard Output
|
99
|
+
-t, --tls Activate SSL (HTTPS) sessions
|
100
|
+
-w, --warnings Activate Ruby Verbose
|
101
|
+
|
102
|
+
-h, --help Display Version number, help and exit
|
103
|
+
|
104
|
+
Commands:
|
105
|
+
destroy Delete all objects on target RHN Satellite
|
106
|
+
export Export RHN Satellite objects to files (ascci or binary formats) into <directory>
|
107
|
+
extras Remove objects on target RHN Satellite not present in source RHN Satellite
|
108
|
+
import Import RHN Satellite object from files (ascii or binary) located into <directory>
|
109
|
+
run Execute Ruby 'plug-in' file
|
110
|
+
sync Synchronise objects from source RHN Satellite to target RHN Satellite
|
111
|
+
show Generate configuration file examples
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
115
|
+
def config_syntax
|
116
|
+
%s{
|
117
|
+
# SatOps YAML comprehensive configuration file example
|
118
|
+
#
|
119
|
+
# Red Hat Network Satellite object groups
|
120
|
+
# Activation Keys, Kickstart Profile, etc, with their specific options
|
121
|
+
# An object group must be must be present to have a command executed against it
|
122
|
+
#
|
123
|
+
# Options
|
124
|
+
# 'update' is a common option to allow corresponding object on target to be updated or not
|
125
|
+
# Options are not mandatory - Default values are always either false, '' (empty) or nil
|
126
|
+
#
|
127
|
+
# Notes
|
128
|
+
# YAML Format
|
129
|
+
# Respect indentations using spaces not tabulations
|
130
|
+
# Boolean values can be either yes/no or true/false
|
131
|
+
# Receivers - left part of assignment are keywords: Do not change them!
|
132
|
+
#
|
133
|
+
Activationkeys:
|
134
|
+
update: true
|
135
|
+
Configchannels:
|
136
|
+
update: true
|
137
|
+
# 'exclude' option provide a way to ignore some Config Channel objects
|
138
|
+
# This is a list of regular expressions - Replace
|
139
|
+
#exclude:
|
140
|
+
# - !ruby/regexp /^name1$/
|
141
|
+
# - !ruby/regexp /^name2$/
|
142
|
+
Channels:
|
143
|
+
update: true
|
144
|
+
delete: false
|
145
|
+
# Triggers satellite-sync on Target providing the Source software channels
|
146
|
+
iss: false
|
147
|
+
Kickstarts:
|
148
|
+
update: true
|
149
|
+
KickstartFilepreservations:
|
150
|
+
update: true
|
151
|
+
KickstartKeys:
|
152
|
+
update: true
|
153
|
+
# Type of keys. Default value is GPG. Other value would be SSL
|
154
|
+
key_type: GPG
|
155
|
+
KickstartSnippets:
|
156
|
+
update: true
|
157
|
+
Orgs:
|
158
|
+
update: true
|
159
|
+
entitlements: false
|
160
|
+
OrgTrusts:
|
161
|
+
update: true
|
162
|
+
SystemCustominfos:
|
163
|
+
update: true
|
164
|
+
Systems:
|
165
|
+
update: true
|
166
|
+
Systemgroups:
|
167
|
+
update: true
|
168
|
+
Users:
|
169
|
+
update: true
|
170
|
+
# Ignore deactivated users
|
171
|
+
deactivated: false
|
172
|
+
# By default extras users are deactivated not deleted
|
173
|
+
delete: false
|
174
|
+
# List of accounts to ignore
|
175
|
+
exclude:
|
176
|
+
- admin
|
177
|
+
- satadmin
|
178
|
+
# Default password used when creating user on target
|
179
|
+
# It cannot be blank
|
180
|
+
# When not using password then make sure PAM is activated
|
181
|
+
password: "rhnapi"
|
182
|
+
}
|
183
|
+
end
|
184
|
+
|
185
|
+
def satellites_syntax
|
186
|
+
%s{
|
187
|
+
# This is an example of a Satellite configuration file for the satOps
|
188
|
+
#
|
189
|
+
# This is a YAML formatted file
|
190
|
+
# Respect indentations using spaces not tabulations
|
191
|
+
# Boolean values can be either yes/no or true/false
|
192
|
+
#
|
193
|
+
# Do not remove any line
|
194
|
+
# Change only login and passwd values
|
195
|
+
--- !ruby/object:Configuration
|
196
|
+
source: !ruby/object:Host
|
197
|
+
name: sat1.example.org
|
198
|
+
user:
|
199
|
+
:login: admin
|
200
|
+
:passwd: redhat
|
201
|
+
target: !ruby/object:Host
|
202
|
+
name: sat2.example.org
|
203
|
+
user:
|
204
|
+
:login: admin
|
205
|
+
:passwd: redhat
|
206
|
+
}
|
207
|
+
end
|
208
|
+
|
209
|
+
class Configuration
|
210
|
+
attr_reader :source, :target
|
211
|
+
end
|
212
|
+
|
213
|
+
class Host
|
214
|
+
attr_reader :name
|
215
|
+
|
216
|
+
def login
|
217
|
+
@user[:login]
|
218
|
+
end
|
219
|
+
|
220
|
+
def auth
|
221
|
+
@user[:passwd]
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# Satellite Interfacer
|
226
|
+
class SatOperator
|
227
|
+
attr_reader :source, :target, :operations
|
228
|
+
|
229
|
+
# Operations are ordered - It matters for object dependencies
|
230
|
+
OPS = [Orgs,
|
231
|
+
OrgTrusts,
|
232
|
+
Systemgroups,
|
233
|
+
Configchannels,
|
234
|
+
SystemCustominfos,
|
235
|
+
Systems,
|
236
|
+
Users,
|
237
|
+
Channels,
|
238
|
+
Activationkeys,
|
239
|
+
KickstartFilepreservations,
|
240
|
+
KickstartKeys,
|
241
|
+
KickstartSnippets,
|
242
|
+
Kickstarts]
|
243
|
+
|
244
|
+
def initialize(options, log)
|
245
|
+
@log=log
|
246
|
+
@operations=Array.new
|
247
|
+
|
248
|
+
OPS.each do |klass|
|
249
|
+
if options.has_key?(klass.to_s)
|
250
|
+
# Populate options (class variables) with their values
|
251
|
+
klass.class_eval do
|
252
|
+
options[klass.to_s].each do |key, val|
|
253
|
+
self.instance_variable_set("@#{key}", val)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
# Create Operation objects
|
257
|
+
@operations << klass.class_eval { self.new(log) }
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def destroy(target)
|
263
|
+
@operations.each do |op|
|
264
|
+
op.destroy(target)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def export(type, sat_source, path)
|
269
|
+
@operations.each do |op|
|
270
|
+
case type
|
271
|
+
when :bin
|
272
|
+
op.export(:mrb, sat_source, path)
|
273
|
+
when :ascii
|
274
|
+
op.export(:yaml, sat_source, path)
|
275
|
+
else
|
276
|
+
raise "FATAL: No such export format"
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
# Extra objects are only present in destination
|
282
|
+
# Delete is default operation unless overloaded by OperationSet subclasses.
|
283
|
+
def extra(*args)
|
284
|
+
@operations.each do |op|
|
285
|
+
op.extra(*args)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
def import(type, *args)
|
290
|
+
@operations.each do |op|
|
291
|
+
case type
|
292
|
+
when :bin
|
293
|
+
op.import(:mrb, *args)
|
294
|
+
when :ascii
|
295
|
+
op.import(:yaml, *args)
|
296
|
+
else
|
297
|
+
raise "FATAL: No such import format"
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
def sync(*args)
|
303
|
+
@operations.each do |op|
|
304
|
+
op.sync(*args)
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
def context
|
309
|
+
str="\nSatellite Synchronisation Context:\n"
|
310
|
+
str << "#{@operations}\n"
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
class Launcher
|
315
|
+
def self.usage
|
316
|
+
puts syntax
|
317
|
+
exit
|
318
|
+
end
|
319
|
+
|
320
|
+
def operation_size?(param, size)
|
321
|
+
if param.size != size
|
322
|
+
Launcher.usage
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
def init_source
|
327
|
+
RHN::Session.running?(@sat_config.source.name, @ssl)
|
328
|
+
@sat_source=RHN::Satellite.new(@sat_config.source, @ssl, @log)
|
329
|
+
@sat_source.connect(@sat_config.source)
|
330
|
+
end
|
331
|
+
|
332
|
+
def init_target
|
333
|
+
RHN::Session.running?(@sat_config.target.name, @ssl)
|
334
|
+
@sat_target=RHN::Satellite.new(@sat_config.target, @ssl, @log)
|
335
|
+
@sat_target.connect(@sat_config.target)
|
336
|
+
end
|
337
|
+
|
338
|
+
def initialize(params)
|
339
|
+
@command=""
|
340
|
+
@config_file=nil
|
341
|
+
@file_to_run=nil
|
342
|
+
@options=nil
|
343
|
+
@log_file=STDOUT
|
344
|
+
@sat_file=nil
|
345
|
+
@sat_source=nil
|
346
|
+
@sat_target=nil
|
347
|
+
@ssl=false
|
348
|
+
|
349
|
+
unless (params.include?('-s') && params.include?('-c')) || params.include?('show')
|
350
|
+
Launcher.usage
|
351
|
+
end
|
352
|
+
|
353
|
+
until params.empty?
|
354
|
+
case params[0]
|
355
|
+
when '-c', '--config='
|
356
|
+
params.shift
|
357
|
+
@config_file=params[0]
|
358
|
+
when '-d', '--debug'
|
359
|
+
$DEBUG=true
|
360
|
+
when '-h', '--help'
|
361
|
+
Launcher.usage
|
362
|
+
when '-t', '--tls'
|
363
|
+
@ssl=true
|
364
|
+
overwrite_net_http
|
365
|
+
when '-l', '--log='
|
366
|
+
params.shift
|
367
|
+
@log_file=params[0]
|
368
|
+
when '-s', '--satfile='
|
369
|
+
params.shift
|
370
|
+
@sat_file=params[0]
|
371
|
+
when '-w', '--warnings'
|
372
|
+
$VERBOSE=true
|
373
|
+
when 'clone'
|
374
|
+
operation_size?(params, 3)
|
375
|
+
@command='clone'
|
376
|
+
params.shift
|
377
|
+
@name=params[0].to_sym
|
378
|
+
params.shift
|
379
|
+
@new_name=params[0]
|
380
|
+
when 'destroy'
|
381
|
+
operation_size?(params, 1)
|
382
|
+
@command='destroy'
|
383
|
+
when 'sync'
|
384
|
+
operation_size?(params, 1)
|
385
|
+
@command='sync'
|
386
|
+
when 'extras'
|
387
|
+
operation_size?(params, 1)
|
388
|
+
@command='extra'
|
389
|
+
when 'export'
|
390
|
+
operation_size?(params, 3)
|
391
|
+
@command='export'
|
392
|
+
params.shift
|
393
|
+
@path=params[0]
|
394
|
+
params.shift
|
395
|
+
@format=params[0].to_sym
|
396
|
+
when 'import'
|
397
|
+
operation_size?(params, 3)
|
398
|
+
@command='import'
|
399
|
+
params.shift
|
400
|
+
@path=params[0]
|
401
|
+
params.shift
|
402
|
+
@format=params[0].to_sym
|
403
|
+
when 'run'
|
404
|
+
operation_size?(params, 2)
|
405
|
+
@command='run'
|
406
|
+
params.shift
|
407
|
+
@file_to_run=params[0]
|
408
|
+
when 'show'
|
409
|
+
params.shift
|
410
|
+
case params[0]
|
411
|
+
when 'sat'
|
412
|
+
puts satellites_syntax
|
413
|
+
when 'config'
|
414
|
+
puts config_syntax
|
415
|
+
else
|
416
|
+
puts "Use 'show sat' or 'show config' commands"
|
417
|
+
end
|
418
|
+
exit
|
419
|
+
else
|
420
|
+
Launcher.usage
|
421
|
+
end
|
422
|
+
params.shift
|
423
|
+
end
|
424
|
+
|
425
|
+
begin
|
426
|
+
@log = Logger.new(@log_file)
|
427
|
+
@log.datetime_format = "%d/%m/%Y %H:%M:%S"
|
428
|
+
if $DEBUG
|
429
|
+
@log.level = Logger::DEBUG
|
430
|
+
else
|
431
|
+
@log.level = Logger::INFO
|
432
|
+
end
|
433
|
+
@log.info("Starting #{@command.upcase} command")
|
434
|
+
|
435
|
+
# Load satellites details file
|
436
|
+
File.open(@sat_file) do |f|
|
437
|
+
@sat_config = YAML.load(f)
|
438
|
+
end
|
439
|
+
|
440
|
+
# Load operations configuration file
|
441
|
+
File.open(@config_file) do |f|
|
442
|
+
@options = YAML.load(f)
|
443
|
+
end
|
444
|
+
|
445
|
+
case @command
|
446
|
+
when 'clone'
|
447
|
+
init_target
|
448
|
+
SatOperator.new(@options, @log).clone(@name, @new_name)
|
449
|
+
when 'destroy'
|
450
|
+
init_target
|
451
|
+
SatOperator.new(@options, @log).destroy(@sat_target)
|
452
|
+
when 'export'
|
453
|
+
init_source
|
454
|
+
SatOperator.new(@options, @log).export(@format, @sat_source, @path)
|
455
|
+
when 'extra'
|
456
|
+
init_source
|
457
|
+
init_target
|
458
|
+
SatOperator.new(@options, @log).extra(@sat_source, @sat_target)
|
459
|
+
when 'import'
|
460
|
+
init_target
|
461
|
+
SatOperator.new(@options, @log).import(@format, @sat_target, @path)
|
462
|
+
when 'sync'
|
463
|
+
init_source
|
464
|
+
init_target
|
465
|
+
SatOperator.new(@options, @log).sync(@sat_source, @sat_target)
|
466
|
+
when 'run'
|
467
|
+
def run
|
468
|
+
puts "###\nExcuting #@file_to_run\n###"
|
469
|
+
yield
|
470
|
+
end
|
471
|
+
init_source
|
472
|
+
init_target
|
473
|
+
lines=""
|
474
|
+
File.open(@file_to_run).each do |line|
|
475
|
+
lines << line
|
476
|
+
end
|
477
|
+
block=eval(lines)
|
478
|
+
run(&block)
|
479
|
+
end
|
480
|
+
rescue SystemCallError => e
|
481
|
+
@log.fatal "#{e}"
|
482
|
+
exit
|
483
|
+
ensure
|
484
|
+
# Clean-up
|
485
|
+
if @sat_source
|
486
|
+
@sat_source.terminate
|
487
|
+
end
|
488
|
+
if @sat_target
|
489
|
+
@sat_target.terminate
|
490
|
+
end
|
491
|
+
@log.info("Finished #{@command.upcase} command")
|
492
|
+
@log.close
|
493
|
+
end
|
494
|
+
end
|
495
|
+
end
|