Statistics
| Branch: | Tag: | Revision:

one / src / onedb / onedb @ 45bfe9aa

History | View | Annotate | Download (17.1 KB)

1
#!/usr/bin/env ruby
2

    
3
# -------------------------------------------------------------------------- #
4
# Copyright 2002-2017, OpenNebula Project, OpenNebula Systems                #
5
#                                                                            #
6
# Licensed under the Apache License, Version 2.0 (the "License"); you may    #
7
# not use this file except in compliance with the License. You may obtain    #
8
# 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
nk_encoding = nil
20

    
21
if RUBY_VERSION =~ /^1.9/
22
    Encoding.default_external = Encoding::UTF_8
23
    Encoding.default_internal = Encoding::UTF_8
24
    nk_encoding = "UTF-8"
25
end
26

    
27
NOKOGIRI_ENCODING = nk_encoding
28

    
29
ONE_LOCATION = ENV["ONE_LOCATION"]
30

    
31
if !ONE_LOCATION
32
    LIB_LOCATION      = "/usr/lib/one"
33
    RUBY_LIB_LOCATION = LIB_LOCATION + "/ruby"
34
    VAR_LOCATION      = "/var/lib/one"
35
    ETC_LOCATION      = "/etc/one"
36
    LOCK_FILE         = "/var/lock/one/one"
37
else
38
    LIB_LOCATION      = ONE_LOCATION + "/lib"
39
    RUBY_LIB_LOCATION = LIB_LOCATION + "/ruby"
40
    VAR_LOCATION      = ONE_LOCATION + "/var"
41
    ETC_LOCATION      = ONE_LOCATION + "/etc"
42
    LOCK_FILE         = VAR_LOCATION + "/.lock"
43
end
44

    
45
$: << RUBY_LIB_LOCATION
46
$: << RUBY_LIB_LOCATION+'/onedb'
47

    
48
require 'cli/command_parser'
49
require 'optparse/time'
50
require 'onedb'
51
require 'onedb_live'
52
require 'opennebula'
53

    
54
FORCE={
55
    :name => "force",
56
    :short => "-f",
57
    :large => "--force",
58
    :description => "Forces the backup even if the DB exists"
59
}
60

    
61
BACKUP={
62
    :name => "backup",
63
    :short => "-b file",
64
    :large => "--backup file",
65
    :description => "Use this file to store SQL dump",
66
    :format => String
67
}
68

    
69
FEDERATED = {
70
    :name        => "federated",
71
    :large       => "--federated",
72
    :description => "Limit backup/restore to federated tables"
73
}
74

    
75
###############################################################################
76
# SQLite options
77
###############################################################################
78
SQLITE={
79
    :name => "sqlite",
80
    :short => "-s file",
81
    :large => "--sqlite file",
82
    :format => String,
83
    :description => "SQLite DB file",
84
    :proc => lambda { |o, options|
85
        options[:backend] = :sqlite
86
        options[:sqlite]  = o
87
    }
88
}
89

    
90
###############################################################################
91
# MySQL options
92
###############################################################################
93
SERVER={
94
    :name => "server",
95
    :short => "-S host",
96
    :large => "--server host",
97
    :format => String,
98
    :description => "MySQL server hostname or IP. Defaults to localhost",
99
    :proc => lambda { |o, options|
100
        options[:backend] = :mysql
101
        options[:server]  = o
102
    }
103
}
104

    
105
PORT={
106
    :name => "port",
107
    :short => "-P port",
108
    :large => "--port port",
109
    :format => String,
110
    :description => "MySQL server port. Defaults to 3306",
111
    :proc => lambda { |o, options|
112
        options[:backend] = :mysql
113
        options[:port]  = o
114
    }
115
}
116

    
117
USERNAME={
118
    :name => "username",
119
    :short => "-u user",
120
    :large => "--username user",
121
    :format => String,
122
    :description => "MySQL username",
123
    :proc => lambda { |o, options|
124
        options[:backend] = :mysql
125
        options[:user]    = o
126
    }
127
}
128

    
129
PASSWORD={
130
    :name => "password",
131
    :short => "-p pass",
132
    :large => "--password pass",
133
    :format => String,
134
    :description => "MySQL password. Leave unset to be prompted for it",
135
    :proc => lambda { |o, options|
136
        options[:backend] = :mysql
137
        options[:passwd]  = o
138
    }
139
}
140

    
141
DBNAME={
142
    :name => "dbname",
143
    :short => "-d dbname",
144
    :large => "--dbname dbname",
145
    :format => String,
146
    :description => "MySQL DB name for OpenNebula",
147
    :proc => lambda { |o, options|
148
        options[:backend] = :mysql
149
        options[:db_name] = o
150
    }
151
}
152

    
153
###############################################################################
154
# Slave MySQL options
155
###############################################################################
156
SLAVE_SERVER={
157
    :name => "slave-server",
158
    :large => "--slave-server host",
159
    :format => String,
160
    :description => "Slave MySQL server hostname or IP. Defaults to localhost",
161
    :proc => lambda { |o, options|
162
        options[:slave_backend] = :mysql
163
        options[:slave_server]  = o
164
    }
165
}
166

    
167
SLAVE_PORT={
168
    :name => "slave-port",
169
    :large => "--slave-port port",
170
    :format => String,
171
    :description => "Slave MySQL server port. Defaults to 3306",
172
    :proc => lambda { |o, options|
173
        options[:slave_backend] = :mysql
174
        options[:slave_port]  = o
175
    }
176
}
177

    
178
SLAVE_USERNAME={
179
    :name => "slave-username",
180
    :large => "--slave-username user",
181
    :format => String,
182
    :description => "Slave MySQL username",
183
    :proc => lambda { |o, options|
184
        options[:slave_backend] = :mysql
185
        options[:slave_user]    = o
186
    }
187
}
188

    
189
SLAVE_PASSWORD={
190
    :name => "slave-password",
191
    :large => "--slave-password pass",
192
    :format => String,
193
    :description => "Slave MySQL password. Leave unset to be prompted for it",
194
    :proc => lambda { |o, options|
195
        options[:slave_backend] = :mysql
196
        options[:slave_passwd]  = o
197
    }
198
}
199

    
200
SLAVE_DBNAME={
201
    :name => "slave-dbname",
202
    :large => "--slave-dbname dbname",
203
    :format => String,
204
    :description => "Slave MySQL DB name for OpenNebula",
205
    :proc => lambda { |o, options|
206
        options[:slave_backend] = :mysql
207
        options[:slave_db_name] = o
208
    }
209
}
210

    
211
SLAVE_BACKUP={
212
    :name => "slave-backup",
213
    :large => "--slave-backup file",
214
    :description => "Use this file to store SQL dump",
215
    :format => String
216
}
217

    
218
###############################################################################
219
# Extra options
220
###############################################################################
221

    
222
EXTRA={
223
    :name => "extra",
224
    :large => "--extra arg",
225
    :description => "Extra args",
226
    :format => Array
227
}
228

    
229
###############################################################################
230
# Live operation options
231
###############################################################################
232

    
233
START_TIME = {
234
    :name   => "start_time",
235
    :short  => "-s TIME",
236
    :large  => "--start TIME" ,
237
    :description => "First time to process",
238
    :format => Time
239
}
240

    
241
END_TIME = {
242
    :name   => "end_time",
243
    :short  => "-e TIME",
244
    :large  => "--end TIME" ,
245
    :description => "Last time to process",
246
    :format => Time
247
}
248

    
249
ID = {
250
    :name   => "id",
251
    :short  => "-i ID",
252
    :large  => "--id ID" ,
253
    :description => "Filter by ID",
254
    :format => Numeric
255
}
256

    
257
XPATH = {
258
    :name   => "xpath",
259
    :short  => "-x ID",
260
    :large  => "--xpath ID" ,
261
    :description => "Filter by xpath",
262
    :format => String
263
}
264

    
265
EXPR= {
266
    :name   => "expr",
267
    :short  => "-e ID",
268
    :large  => "--expr ID" ,
269
    :description => "Filter by expression (UNAME=oneadmin)",
270
    :format => String
271
}
272

    
273
DRY= {
274
    :name   => "dry",
275
    :large  => "--dry" ,
276
    :description => "Do not write in the database, output xml"
277
}
278

    
279
DELETE= {
280
    :name   => "delete",
281
    :short  => "-d",
282
    :large  => "--delete" ,
283
    :description => "Delete all matched xpaths"
284
}
285

    
286
cmd=CommandParser::CmdParser.new(ARGV) do
287
    description <<-EOT.unindent
288
        This command enables the user to manage the OpenNebula database. It
289
        provides information about the DB version, means to upgrade it to the
290
        latest version, and backup tools.
291
    EOT
292

    
293
    ###########################################################################
294
    # Global options
295
    ###########################################################################
296
    set :option, CommandParser::OPTIONS
297
    set :option, [SQLITE, SERVER, PORT, USERNAME, PASSWORD, DBNAME]
298

    
299
    ###########################################################################
300
    # Backup
301
    ###########################################################################
302
    backup_desc = <<-EOT.unindent
303
        Dumps the DB to a file specified in the argument
304
    EOT
305

    
306
    command :backup, backup_desc, [:output_file, nil],
307
            :options=>[FORCE, FEDERATED] do
308

    
309
        begin
310
            helper = OneDB.new(options)
311
            helper.backup(args[0], options)
312
        rescue Exception => e
313
            [-1, e.message]
314
        end
315
    end
316

    
317
    ###########################################################################
318
    # Version
319
    ###########################################################################
320
    version_desc = <<-EOT.unindent
321
        Prints the current DB version.
322
        Use -v flag to see also OpenNebula version
323
    EOT
324

    
325
    command :version , version_desc do
326
        begin
327
            helper = OneDB.new(options)
328
            helper.version(options)
329
        rescue Exception => e
330
            [-1, e.message]
331
        end
332
    end
333

    
334
    ###########################################################################
335
    # History
336
    ###########################################################################
337
    history_desc = <<-EOT.unindent
338
        Prints the upgrades history
339
    EOT
340

    
341
    command :history , history_desc do
342
        begin
343
            helper = OneDB.new(options)
344
            helper.history
345
        rescue Exception => e
346
            [-1, e.message]
347
        end
348
    end
349

    
350
    ###########################################################################
351
    # Restore
352
    ###########################################################################
353
    restore_desc = <<-EOT.unindent
354
        Restores the DB from a backup file. Only restores backups generated
355
        from the same backend (SQLite or MySQL)
356
    EOT
357

    
358
    command :restore , restore_desc, [:backup_file, nil],
359
            :options=>[FORCE, FEDERATED] do
360

    
361
        begin
362
            helper = OneDB.new(options)
363
            helper.restore(args[0], options)
364
        rescue Exception => e
365
            [-1, e.message]
366
        end
367
    end
368

    
369
    ###########################################################################
370
    # Upgrade
371
    ###########################################################################
372
    upgrade_desc = <<-EOT.unindent
373
        Upgrades the DB to the latest version
374
        where <version> : DB version (e.g. 1, 3) to upgrade.
375
                          By default the DB is upgraded to the latest version
376
    EOT
377

    
378
    command :upgrade , upgrade_desc, [:version, nil], :options=>[FORCE,BACKUP] do
379
        begin
380
            helper = OneDB.new(options)
381
            helper.upgrade(args[0], options)
382
        rescue Exception => e
383
            [-1, e.message]
384
        end
385
    end
386

    
387
    ###########################################################################
388
    # fsck
389
    ###########################################################################
390
    fsck_desc = <<-EOT.unindent
391
        Checks the consistency of the DB, and fixes the problems found
392
    EOT
393

    
394
    command :fsck, fsck_desc, :options=>[FORCE,BACKUP] do
395
        begin
396
            helper = OneDB.new(options)
397
            helper.fsck(options)
398
        rescue Exception => e
399
            [-1, e.message]
400
        end
401
    end
402

    
403
    ###########################################################################
404
    # Import slave
405
    ###########################################################################
406
    import_slave_desc = <<-EOT.unindent
407
        Imports an existing federation slave into the federation master database
408
    EOT
409

    
410
    command :"import-slave", import_slave_desc, :options=>[FORCE,BACKUP,
411
        SLAVE_SERVER,SLAVE_PORT,SLAVE_USERNAME,SLAVE_PASSWORD,
412
        SLAVE_DBNAME,SLAVE_BACKUP] do
413

    
414
        begin
415
            helper = OneDB.new(options)
416
            helper.import_slave(options)
417
        rescue Exception => e
418
            [-1, e.message]
419
        end
420
    end
421

    
422
    ###########################################################################
423
    # Migrate vcenter 54
424
    ###########################################################################
425
    vcenter_one54_desc = <<-EOT.unindent
426
        Migrate VM and templates so they can be used by OpenNebula 5.4
427
    EOT
428

    
429
    command :"vcenter-one54", vcenter_one54_desc, :options=>[FORCE,BACKUP] do
430

    
431
        begin
432
            helper = OneDB.new(options)
433
            helper.vcenter_one54(options)
434
        rescue Exception => e
435
            [-1, e.message]
436
        end
437
    end
438

    
439
    ###########################################################################
440
    # Patch
441
    ###########################################################################
442
    patch_desc = <<-EOT.unindent
443
        Applies a database patch file
444
    EOT
445

    
446
    command :patch , patch_desc, :file, :options=>[BACKUP, EXTRA] do
447
        begin
448
            helper = OneDB.new(options)
449
            helper.patch(args[0], options)
450
        rescue Exception => e
451
            [-1, e.message]
452
        end
453
    end
454

    
455
    ###########################################################################
456
    # Migrate SQLite to MySQL
457
    ###########################################################################
458
    sqlite2mysql_desc = <<-EOT.unindent
459
        Migrates a SQLite OpenNebula Database to MySQL
460
    EOT
461

    
462
    command :sqlite2mysql , sqlite2mysql_desc, :options=>[BACKUP] do
463
        begin
464
            options[:backend] = :sqlite
465
            sqlite = OneDB.new(options)
466

    
467
            options[:backend] = :mysql
468
            mysql = OneDB.new(options)
469

    
470
            mysql.sqlite2mysql(options, sqlite)
471
        rescue Exception => e
472
            [-1, e.message]
473
        end
474
    end
475

    
476
    LIVE_ACTION_HELP = <<-EOT.unindent
477
        **WARNING**: This action is done while OpenNebula is running. Make
478
        a backup of the datasbase before executing.
479
    EOT
480

    
481
    ###########################################################################
482
    # Purge history
483
    ###########################################################################
484
    purge_history_desc = <<-EOT.unindent
485
        Deletes all but the last history records from non DONE VMs
486

    
487
        #{LIVE_ACTION_HELP}
488
    EOT
489

    
490
    command :'purge-history', purge_history_desc,
491
            :options => [START_TIME, END_TIME] do
492
        begin
493
            action = OneDBLive.new
494
            action.purge_history(options)
495
        rescue Exception => e
496
            puts e.message
497
            pp e.backtrace
498
            [-1, e.message]
499
        end
500

    
501
        0
502
    end
503

    
504
    ###########################################################################
505
    # Purge VMs in DONE state
506
    ###########################################################################
507
    purge_done_desc = <<-EOT.unindent
508
        Deletes all VMs in DONE state
509

    
510
        #{LIVE_ACTION_HELP}
511
    EOT
512

    
513
    command :'purge-done', purge_done_desc,
514
            :options => [START_TIME, END_TIME] do
515
        begin
516
            action = OneDBLive.new
517
            action.purge_done_vm(options)
518
        rescue Exception => e
519
            puts e.name
520
            pp e.backtrace
521
            [-1, e.message]
522
        end
523

    
524
        0 # exit code
525
    end
526

    
527
    ###########################################################################
528
    # Change value in object body
529
    ###########################################################################
530
    change_body_desc = <<-EOT.unindent
531
        Changes a value from the body of an object. The possible objects are:
532
            vm, host, vnet, image, cluster, document, group, marketplace,
533
            marketplaceapp, secgroup, template, vrouter or zone
534

    
535
        You can filter the objects to modify using one of these options:
536

    
537
            * --id: object id, example: 156
538
            * --xpath: xpath expression, example: TEMPLATE[count(NIC)>1]
539
            * --expr: xpath expression, can use operators =, !=, <, >, <= or >=
540
                examples: UNAME=oneadmin, TEMPLATE/NIC/NIC_ID>0
541

    
542
        If you want to change a value use a third parameter. In case you want
543
        to delete it use --delete option.
544

    
545
        Change the second network of VMs that belong to "user":
546

    
547
            onedb change-body vm --expr UNAME=user \\
548
                '/VM/TEMPLATE/NIC[NETWORK="service"]/NETWORK' new_network
549

    
550
        Delete cache attribute in all disks, write xml, do not modify DB:
551

    
552
            onedb change-body vm '/VM/TEMPLATE/DISK/CACHE' --delete --dry
553

    
554
        Delete cache attribute in all disks in poweroff:
555

    
556
            onedb change-body vm --expr LCM_STATE=8 \\
557
                '/VM/TEMPLATE/DISK/CACHE' --delete
558

    
559
        #{LIVE_ACTION_HELP}
560
    EOT
561

    
562
    command :'change-body', change_body_desc, :object, :xpath, [:value, nil],
563
            :options => [ID, XPATH, EXPR, DRY, DELETE] do
564
        begin
565
            action = OneDBLive.new
566
            action.change_body(args[0], args[1], args[2], options)
567
        rescue Exception => e
568
            puts e.message
569
            pp e.backtrace
570
            [-1, e.message]
571
        end
572

    
573
        0 # exit code
574
    end
575
end