satops 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'satops'
4
+
5
+ Launcher.new(ARGV)
@@ -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