Statistics
| Branch: | Tag: | Revision:

one / src / onedb / fsck.rb @ 27e61bae

History | View | Annotate | Download (16.9 KB)

1
# -------------------------------------------------------------------------- #
2
# Copyright 2002-2017, OpenNebula Project, OpenNebula Systems                #
3
#                                                                            #
4
# Licensed under the Apache License, Version 2.0 (the "License"); you may    #
5
# not use this file except in compliance with the License. You may obtain    #
6
# a copy of the License at                                                   #
7
#                                                                            #
8
# http://www.apache.org/licenses/LICENSE-2.0                                 #
9
#                                                                            #
10
# Unless required by applicable law or agreed to in writing, software        #
11
# distributed under the License is distributed on an "AS IS" BASIS,          #
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
13
# See the License for the specific language governing permissions and        #
14
# limitations under the License.                                             #
15
#--------------------------------------------------------------------------- #
16

    
17
if !ONE_LOCATION
18
    LOG_LOCATION = "/var/log/one"
19
else
20
    LOG_LOCATION = ONE_LOCATION + "/var"
21
end
22

    
23
LOG              = LOG_LOCATION + "/onedb-fsck.log"
24

    
25
require "rexml/document"
26
include REXML
27
require 'ipaddr'
28
require 'set'
29

    
30
require 'nokogiri'
31

    
32
require 'opennebula'
33

    
34
require 'fsck/pool_control'
35
require 'fsck/user'
36
require 'fsck/group'
37

    
38
require 'fsck/cluster'
39
require 'fsck/host'
40
require 'fsck/datastore'
41
require 'fsck/network'
42

    
43
require 'fsck/image'
44
require 'fsck/marketplaceapp'
45
require 'fsck/marketplace'
46
require 'fsck/vm'
47
require 'fsck/cluster_vnc_bitmap'
48
require 'fsck/history'
49
require 'fsck/vrouter'
50
require 'fsck/template'
51

    
52
require 'fsck/quotas'
53

    
54
module OneDBFsck
55
    VERSION = "5.4.0"
56
    LOCAL_VERSION = "5.4.0"
57

    
58
    def db_version
59
        if defined?(@db_version) && @db_version
60
            @db_version
61
        else
62
            @db_version = read_db_version
63
        end
64
    end
65

    
66
    def check_db_version()
67
        # db_version = read_db_version()
68

    
69
        if ( db_version[:version] != VERSION ||
70
             db_version[:local_version] != LOCAL_VERSION )
71

    
72
            raise <<-EOT
73
Version mismatch: fsck file is for version
74
Shared: #{VERSION}, Local: #{LOCAL_VERSION}
75

76
Current database is version
77
Shared: #{db_version[:version]}, Local: #{db_version[:local_version]}
78
EOT
79
        end
80
    end
81

    
82
    def one_version
83
        "OpenNebula #{VERSION}"
84
    end
85

    
86
    # def db_version
87
    #     one_version()
88
    # end
89

    
90
    VM_BIN      = 0x0000001000000000
91
    NET_BIN     = 0x0000004000000000
92
    VROUTER_BIN = 0x0004000000000000
93
    HOLD        = 0xFFFFFFFF
94

    
95
    TABLES = ["group_pool", "user_pool", "acl", "image_pool", "host_pool",
96
        "network_pool", "template_pool", "vm_pool", "cluster_pool",
97
        "datastore_pool", "document_pool", "zone_pool", "secgroup_pool",
98
        "vdc_pool", "vrouter_pool", "marketplace_pool",
99
        "marketplaceapp_pool"].freeze
100

    
101
    FEDERATED_TABLES = ["group_pool", "user_pool", "acl", "zone_pool",
102
        "vdc_pool", "marketplace_pool", "marketplaceapp_pool"].freeze
103

    
104
    def tables
105
        TABLES
106
    end
107

    
108
    def federated_tables
109
        FEDERATED_TABLES
110
    end
111

    
112
    def nokogiri_doc(body)
113
        Nokogiri::XML(body, nil, NOKOGIRI_ENCODING) do |c|
114
            c.default_xml.noblanks
115
        end
116
    end
117

    
118
    def add_element(elem, name)
119
        return elem.add_child(elem.document.create_element(name))
120
    end
121

    
122
    def add_cdata(elem, name, text)
123
        # The cleaner doc.create_cdata(txt) is not supported in
124
        # old versions of nokogiri
125
        return add_element(elem, name).add_child(
126
                        Nokogiri::XML::CDATA.new(elem.document(), text))
127
    end
128

    
129
    ########################################################################
130
    # Acl
131
    ########################################################################
132

    
133
    ########################################################################
134
    # Users
135
    #
136
    # USER/GNAME
137
    ########################################################################
138

    
139
    ########################################################################
140
    # Datastore
141
    #
142
    # DATASTORE/UID
143
    # DATASTORE/UNAME
144
    # DATASTORE/GID
145
    # DATASTORE/GNAME
146
    # DATASTORE/SYSTEM ??
147
    ########################################################################
148

    
149
    ########################################################################
150
    # VM Template
151
    #
152
    # VMTEMPLATE/UID
153
    # VMTEMPLATE/UNAME
154
    # VMTEMPLATE/GID
155
    # VMTEMPLATE/GNAME
156
    ########################################################################
157

    
158
    ########################################################################
159
    # Documents
160
    #
161
    # DOCUMENT/UID
162
    # DOCUMENT/UNAME
163
    # DOCUMENT/GID
164
    # DOCUMENT/GNAME
165
    ########################################################################
166

    
167
    ########################################################################
168
    # VM
169
    #
170
    # VM/UID
171
    # VM/UNAME
172
    # VM/GID
173
    # VM/GNAME
174
    #
175
    # VM/STATE        <--- Check transitioning states?
176
    # VM/LCM_STATE    <---- Check consistency state/lcm_state ?
177
    ########################################################################
178

    
179
    ########################################################################
180
    # Image
181
    #
182
    # IMAGE/UID
183
    # IMAGE/UNAME
184
    # IMAGE/GID
185
    # IMAGE/GNAME
186
    ########################################################################
187

    
188
    ########################################################################
189
    # VNet
190
    #
191
    # VNET/UID
192
    # VNET/UNAME
193
    # VNET/GID
194
    # VNET/GNAME
195
    ########################################################################
196

    
197

    
198
    def counters
199
        if !defined?(@counters)
200
            @counters = {}
201
            @counters[:host]  = {}
202
            @counters[:image] = {}
203
            @counters[:vnet]  = {}
204
            @counters[:vrouter]  = {}
205
        end
206

    
207
        @counters
208
    end
209

    
210
    # Initialize all the vrouter counters to 0
211
    def init_vrouter_counters
212
        @db.fetch("SELECT oid FROM vrouter_pool") do |row|
213
            counters[:vrouter][row[:oid]] = {
214
                :vms   => Set.new
215
            }
216
        end
217
    end
218

    
219
    def fsck
220
        init_log_time()
221

    
222
        @errors = 0
223
        @repaired_errors = 0
224
        @unrepaired_errors = 0
225

    
226
        puts
227

    
228
        db_version = read_db_version()
229

    
230
        ########################################################################
231
        # pool_control
232
        ########################################################################
233

    
234
        check_pool_control
235

    
236
        fix_pool_control
237

    
238
        log_time()
239

    
240
        ########################################################################
241
        # Groups
242
        #
243
        # GROUP/USERS/ID
244
        ########################################################################
245

    
246
        ########################################################################
247
        # Users
248
        #
249
        # USER/GID
250
        ########################################################################
251

    
252
        check_user
253
        fix_user
254

    
255
        log_time
256

    
257
        check_group
258
        fix_group
259

    
260
        log_time
261

    
262
        ########################################################################
263
        # Clusters
264
        #
265
        # CLUSTER/SYSTEM_DS
266
        # CLUSTER/HOSTS/ID
267
        # CLUSTER/DATASTORES/ID
268
        # CLUSTER/VNETS/ID
269
        ########################################################################
270
        # Datastore
271
        #
272
        # DATASTORE/CLUSTER_ID
273
        # DATASTORE/CLUSTER
274
        ########################################################################
275
        # VNet
276
        #
277
        # VNET/CLUSTER_ID
278
        # VNET/CLUSTER
279
        ########################################################################
280
        # Hosts
281
        #
282
        # HOST/CLUSTER_ID
283
        # HOST/CLUSTER
284
        ########################################################################
285

    
286
        init_cluster
287

    
288
        check_host_cluster
289
        fix_host_cluster
290

    
291
        log_time
292

    
293
        check_datastore_cluster
294
        fix_datastore_cluster
295

    
296
        log_time
297

    
298
        check_network_cluster
299
        fix_network_cluster
300

    
301
        log_time
302

    
303
        check_fix_cluster
304

    
305
        log_time
306

    
307
        check_fix_cluster_relations
308

    
309
        log_time
310

    
311
        ########################################################################
312
        # Datastore
313
        #
314
        # DATASTORE/IMAGES/ID
315
        ########################################################################
316
        # Image
317
        #
318
        # IMAGE/DATASTORE_ID
319
        # IMAGE/DATASTORE
320
        ########################################################################
321

    
322
        init_datastore_counters
323

    
324
        log_time
325

    
326
        check_datastore_image
327
        fix_datastore_image
328

    
329
        log_time
330

    
331
        check_fix_datastore
332

    
333
        log_time
334

    
335
        ########################################################################
336
        # VM Counters for host, image and vnet usage
337
        ########################################################################
338

    
339
        init_host_counters
340

    
341
        log_time
342

    
343
        init_image_counters
344

    
345
        log_time
346

    
347
        init_network_counters
348

    
349
        log_time
350

    
351
        init_vrouter_counters
352

    
353
        log_time
354

    
355
        check_vm
356
        fix_vm
357

    
358
        log_time
359

    
360
        # VNC
361

    
362
        # DATA: VNC Bitmap
363

    
364
        check_cluster_vnc_bitmap
365
        fix_cluster_vnc_bitmap
366

    
367
        log_time
368

    
369
        # history
370

    
371
        check_history
372
        fix_history
373

    
374
        log_time
375

    
376
        ########################################################################
377
        # Virtual Routers
378
        #
379
        # VROUTER/VMS/ID
380
        ########################################################################
381

    
382
        check_vrouter
383
        fix_vrouter
384

    
385
        log_time
386

    
387
        ########################################################################
388
        # DATA: Hosts
389
        #
390
        # HOST/HOST_SHARE/MEM_USAGE
391
        # HOST/HOST_SHARE/CPU_USAGE
392
        # HOST/HOST_SHARE/RUNNING_VMS
393
        # HOST/VMS/ID
394
        ########################################################################
395

    
396
        check_host
397
        fix_host
398

    
399
        log_time
400

    
401
        ########################################################################
402
        # DATA: Marketplace
403
        #
404
        # MARKETPLACE/MARKETPLACEAPPS/ID
405
        ########################################################################
406
        # DATA: App
407
        #
408
        # MARKETPLACEAPP/MARKETPLACE_ID
409
        # MARKETPLACEAPP/MARKETPLACE
410
        # MARKETPLACEAPP/ORIGIN_ID
411
        ########################################################################
412

    
413
        check_marketplaceapp
414

    
415
        fix_marketplaceapp
416

    
417
        log_time()
418

    
419
        check_marketplace
420

    
421
        fix_marketplace
422

    
423
        log_time()
424

    
425
        ########################################################################
426
        # DATA: Image
427
        #
428
        # IMAGE/RUNNING_VMS
429
        # IMAGE/VMS/ID
430
        #
431
        # IMAGE/CLONING_OPS
432
        # IMAGE/CLONES/ID
433
        # IMAGE/APP_CLONES/ID
434
        #
435
        # IMAGE/CLONING_ID
436
        #
437
        # IMAGE/STATE
438
        ########################################################################
439

    
440
        check_image
441

    
442
        fix_image
443

    
444
        log_time
445

    
446
        ########################################################################
447
        # VNet
448
        #
449
        # LEASES
450
        ########################################################################
451

    
452
        init_network_lease_counters
453

    
454
        check_network
455
        fix_network
456

    
457
        log_time
458

    
459
        ########################################################################
460
        # Users
461
        #
462
        # USER QUOTAS
463
        ########################################################################
464

    
465
        check_fix_user_quotas
466

    
467
        log_time
468

    
469
        ########################################################################
470
        # Groups
471
        #
472
        # GROUP QUOTAS
473
        ########################################################################
474

    
475
        check_fix_group_quotas
476

    
477
        log_time
478

    
479
        ########################################################################
480
        # VM Templates
481
        #
482
        # TEMPLATE/OS/BOOT
483
        ########################################################################
484

    
485
        check_template
486
        fix_template
487

    
488
        log_time
489

    
490
        log_total_errors
491

    
492
        return true
493
    end
494

    
495
    def log_error(message, repaired=true)
496
        @errors += 1
497

    
498
        if repaired
499
            @repaired_errors += 1
500
        else
501
            @unrepaired_errors += 1
502
        end
503

    
504
        if !repaired
505
            message = "[UNREPAIRED] " + message
506
        end
507

    
508
        log_msg(message)
509
    end
510

    
511
    def log_msg(message)
512
        @log_file ||= File.open(LOG, "w")
513

    
514
        puts message
515

    
516
        @log_file.puts(message)
517
        @log_file.flush
518
    end
519

    
520
    def log_total_errors()
521
        puts
522
        log_msg "Total errors found: #{@errors}"
523
        log_msg "Total errors repaired: #{@repaired_errors}"
524
        log_msg "Total errors unrepaired: #{@unrepaired_errors}"
525

    
526
        puts "A copy of this output was stored in #{LOG}"
527
    end
528

    
529
    def mac_s_to_i(mac)
530
        return nil if mac.empty?
531
        return mac.split(":").map {|e|
532
            e.to_i(16).to_s(16).rjust(2,"0")}.join("").to_i(16)
533
    end
534

    
535
    def mac_i_to_s(mac)
536
        mac_s = mac.to_s(16).rjust(12, "0")
537
        return "#{mac_s[0..1]}:#{mac_s[2..3]}:#{mac_s[4..5]}:"<<
538
               "#{mac_s[6..7]}:#{mac_s[8..9]}:#{mac_s[10..11]}"
539
    end
540

    
541
    def ip6_prefix_s_to_i(prefix)
542
        return nil if prefix.empty?
543
        return prefix.split(":", 4).map {|e|
544
            e.to_i(16).to_s(16).rjust(4, "0")}.join("").to_i(16)
545
    end
546

    
547
    # Copied from AddressRange::set_ip6 in AddressRange.cc
548
    def mac_to_ip6_suffix(mac_i)
549
        mac = [
550
            mac_i & 0x00000000FFFFFFFF,
551
            (mac_i & 0xFFFFFFFF00000000) >> 32
552
        ]
553

    
554
        mlow = mac[0]
555
        eui64 = [
556
            4261412864 + (mlow & 0x00FFFFFF),
557
            ((mac[1]+512)<<16) + ((mlow & 0xFF000000)>>16) + 0x000000FF
558
        ]
559

    
560
        return (eui64[1] << 32) + eui64[0]
561
    end
562

    
563
    def lease_to_s(lease)
564
        return lease[:ip].nil? ? lease[:mac].to_s : lease[:ip].to_s
565
    end
566

    
567
    # Returns the ID of the # disk of a type
568
    # Params:
569
    # +type+:: type name of the disk, can be “hd” or “cdrom”
570
    # +doc+:: Nokogiri::XML::Node describing the VM template
571
    def get_disk_id(type, index, doc)
572
        found_i = -1
573

    
574
        doc.root.xpath("TEMPLATE/DISK").each_with_index do |disk, disk_i|
575
            id = disk.at_xpath("IMAGE_ID")
576
            if ! id.nil?
577
                image = get_image_from_id(id.content)
578
            else
579
                image = get_image_from_name(disk)
580
            end
581

    
582
            next if image.nil?
583

    
584
            if is_image_type_matching?(image, type)
585
                found_i += 1
586

    
587
                if (found_i == index)
588
                    return disk_i
589
                end
590
            end
591
        end
592

    
593
        return nil
594
    end
595

    
596
    # Returns a Nokogiri::XML::Node describing an image
597
    # Params:
598
    # +id+:: ID of the image
599
    def get_image_from_id(id)
600
        row = @db.fetch("SELECT body from image_pool where oid=#{id}").first
601
        # No image found, so unable to get image TYPE
602
        return nil if row.nil?
603

    
604
        image = Nokogiri::XML(row[:body], nil,NOKOGIRI_ENCODING){|c| c.default_xml.noblanks}
605
        return image
606
    end
607

    
608
    # Returns a Nokogiri::XML::Node describing an image
609
    # Params:
610
    # +disk+:: Nokogiri::XML::Node describing a disk used by a template
611
    def get_image_from_name(disk)
612
      name = disk.at_xpath("IMAGE") && disk.at_xpath("IMAGE").content
613
      uid = disk.at_xpath("IMAGE_UID")
614
      uname = disk.at_xpath("IMAGE_UNAME")
615

    
616
      if ! name.nil? and (! uid.nil? or ! uname.nil?)
617
        if uid.nil?
618
          uid = get_user_id(uname.content)
619
        else
620
          uid = uid.content
621
        end
622

    
623
        return nil if uid.nil?
624

    
625
        row = @db.fetch("SELECT body from image_pool where name=\"#{name}\" and uid=#{uid}").first
626
        # No image found, so unable to get image TYPE
627
        return nil if row.nil?
628

    
629
        image = Nokogiri::XML(row[:body], nil,NOKOGIRI_ENCODING){|c| c.default_xml.noblanks}
630
        return image
631
      end
632

    
633
      return nil
634
    end
635

    
636
    # Returns the ID of a user name
637
    # Params:
638
    # +name+:: name of a user
639
    def get_user_id(name)
640
        row = @db.fetch("SELECT uid from user_pool WHERE name=\"#{name}\"").first
641

    
642
        return nil if row.nil?
643

    
644
        return row[:uid]
645
    end
646

    
647
    # Check if an image type match the type used in template BOOT
648
    # Params:
649
    # +image_type+:: doc
650
    # +wanted_type+:: string type extracted from VM template BOOT
651
    def is_image_type_matching?(image, wanted_type)
652
        return false if image.nil? || image.at_xpath("IMAGE/TYPE").nil?
653

    
654
        img_type = OpenNebula::Image::IMAGE_TYPES[image.at_xpath("IMAGE/TYPE").text.to_i]
655

    
656
        if wanted_type == "hd"
657
            return img_type == "OS" || img_type == "DATABLOCK"
658
        else
659
            return img_type == "CDROM"
660
        end
661
    end
662
end