satops 1.5.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.
- 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
|