Revision 3f78eef2

b/daemons/ganeti-noded
97 97
    """Create a block device.
98 98

  
99 99
    """
100
    bdev_s, size, on_primary, info = params
100
    bdev_s, size, owner, on_primary, info = params
101 101
    bdev = objects.Disk.FromDict(bdev_s)
102 102
    if bdev is None:
103 103
      raise ValueError("can't unserialize data!")
104
    return backend.CreateBlockDevice(bdev, size, on_primary, info)
104
    return backend.CreateBlockDevice(bdev, size, owner, on_primary, info)
105 105

  
106 106
  @staticmethod
107 107
  def perspective_blockdev_remove(params):
......
125 125
    """Assemble a block device.
126 126

  
127 127
    """
128
    bdev_s, on_primary = params
128
    bdev_s, owner, on_primary = params
129 129
    bdev = objects.Disk.FromDict(bdev_s)
130 130
    if bdev is None:
131 131
      raise ValueError("can't unserialize data!")
132
    return backend.AssembleBlockDevice(bdev, on_primary)
132
    return backend.AssembleBlockDevice(bdev, owner, on_primary)
133 133

  
134 134
  @staticmethod
135 135
  def perspective_blockdev_shutdown(params):
b/lib/backend.py
620 620
  return True
621 621

  
622 622

  
623
def CreateBlockDevice(disk, size, on_primary, info):
623
def CreateBlockDevice(disk, size, owner, on_primary, info):
624 624
  """Creates a block device for an instance.
625 625

  
626 626
  Args:
......
638 638
  clist = []
639 639
  if disk.children:
640 640
    for child in disk.children:
641
      crdev = _RecursiveAssembleBD(child, on_primary)
641
      crdev = _RecursiveAssembleBD(child, owner, on_primary)
642 642
      if on_primary or disk.AssembleOnSecondary():
643 643
        # we need the children open in case the device itself has to
644 644
        # be assembled
......
664 664
    device.SetSyncSpeed(constants.SYNC_SPEED)
665 665
    if on_primary or disk.OpenOnSecondary():
666 666
      device.Open(force=True)
667
    DevCacheManager.UpdateCache(device.dev_path, owner,
668
                                on_primary, disk.iv_name)
667 669

  
668 670
  device.SetInfo(info)
669 671

  
......
686 688
    logger.Info("Can't attach to device %s in remove" % disk)
687 689
    rdev = None
688 690
  if rdev is not None:
691
    r_path = rdev.dev_path
689 692
    result = rdev.Remove()
693
    if result:
694
      DevCacheManager.RemoveCache(r_path)
690 695
  else:
691 696
    result = True
692 697
  if disk.children:
......
695 700
  return result
696 701

  
697 702

  
698
def _RecursiveAssembleBD(disk, as_primary):
703
def _RecursiveAssembleBD(disk, owner, as_primary):
699 704
  """Activate a block device for an instance.
700 705

  
701 706
  This is run on the primary and secondary nodes for an instance.
......
715 720
  children = []
716 721
  if disk.children:
717 722
    for chld_disk in disk.children:
718
      children.append(_RecursiveAssembleBD(chld_disk, as_primary))
723
      children.append(_RecursiveAssembleBD(chld_disk, owner, as_primary))
719 724

  
720 725
  if as_primary or disk.AssembleOnSecondary():
721 726
    r_dev = bdev.AttachOrAssemble(disk.dev_type, disk.physical_id, children)
......
725 730
      r_dev.Open()
726 731
    else:
727 732
      r_dev.Close()
733
    DevCacheManager.UpdateCache(r_dev.dev_path, owner,
734
                                as_primary, disk.iv_name)
735

  
728 736
  else:
729 737
    result = True
730 738
  return result
731 739

  
732 740

  
733
def AssembleBlockDevice(disk, as_primary):
741
def AssembleBlockDevice(disk, owner, as_primary):
734 742
  """Activate a block device for an instance.
735 743

  
736 744
  This is a wrapper over _RecursiveAssembleBD.
......
740 748
    True for secondary nodes
741 749

  
742 750
  """
743
  result = _RecursiveAssembleBD(disk, as_primary)
751
  result = _RecursiveAssembleBD(disk, owner, as_primary)
744 752
  if isinstance(result, bdev.BlockDev):
745 753
    result = result.dev_path
746 754
  return result
......
759 767
  """
760 768
  r_dev = _RecursiveFindBD(disk)
761 769
  if r_dev is not None:
770
    r_path = r_dev.dev_path
762 771
    result = r_dev.Shutdown()
772
    if result:
773
      DevCacheManager.RemoveCache(r_path)
763 774
  else:
764 775
    result = True
765 776
  if disk.children:
......
1356 1367
      result = False
1357 1368
      continue
1358 1369
    try:
1370
      old_rpath = dev.dev_path
1359 1371
      dev.Rename(unique_id)
1372
      new_rpath = dev.dev_path
1373
      if old_rpath != new_rpath:
1374
        DevCacheManager.RemoveCache(old_rpath)
1375
        # FIXME: we should add the new cache information here, like:
1376
        # DevCacheManager.UpdateCache(new_rpath, owner, ...)
1377
        # but we don't have the owner here - maybe parse from existing
1378
        # cache? for now, we only lose lvm data when we rename, which
1379
        # is less critical than DRBD or MD
1360 1380
    except errors.BlockDeviceError, err:
1361 1381
      logger.Error("Can't rename device '%s' to '%s': %s" %
1362 1382
                   (dev, unique_id, err))
......
1473 1493
      rr.append(("%s/%s" % (subdir, relname), rrval, output))
1474 1494

  
1475 1495
    return rr
1496

  
1497

  
1498
class DevCacheManager(object):
1499
  """Simple class for managing a chache of block device information.
1500

  
1501
  """
1502
  _DEV_PREFIX = "/dev/"
1503
  _ROOT_DIR = constants.BDEV_CACHE_DIR
1504

  
1505
  @classmethod
1506
  def _ConvertPath(cls, dev_path):
1507
    """Converts a /dev/name path to the cache file name.
1508

  
1509
    This replaces slashes with underscores and strips the /dev
1510
    prefix. It then returns the full path to the cache file
1511

  
1512
    """
1513
    if dev_path.startswith(cls._DEV_PREFIX):
1514
      dev_path = dev_path[len(cls._DEV_PREFIX):]
1515
    dev_path = dev_path.replace("/", "_")
1516
    fpath = "%s/bdev_%s" % (cls._ROOT_DIR, dev_path)
1517
    return fpath
1518

  
1519
  @classmethod
1520
  def UpdateCache(cls, dev_path, owner, on_primary, iv_name):
1521
    """Updates the cache information for a given device.
1522

  
1523
    """
1524
    fpath = cls._ConvertPath(dev_path)
1525
    if on_primary:
1526
      state = "primary"
1527
    else:
1528
      state = "secondary"
1529
    if iv_name is None:
1530
      iv_name = "not_visible"
1531
    fdata = "%s %s %s\n" % (str(owner), state, iv_name)
1532
    try:
1533
      utils.WriteFile(fpath, data=fdata)
1534
    except EnvironmentError, err:
1535
      logger.Error("Can't update bdev cache for %s, error %s" %
1536
                   (dev_path, str(err)))
1537

  
1538
  @classmethod
1539
  def RemoveCache(cls, dev_path):
1540
    """Remove data for a dev_path.
1541

  
1542
    """
1543
    fpath = cls._ConvertPath(dev_path)
1544
    try:
1545
      utils.RemoveFile(fpath)
1546
    except EnvironmentError, err:
1547
      logger.Error("Can't update bdev cache for %s, error %s" %
1548
                   (dev_path, str(err)))
b/lib/cmdlib.py
1821 1821
    for node, node_disk in inst_disk.ComputeNodeTree(instance.primary_node):
1822 1822
      cfg.SetDiskID(node_disk, node)
1823 1823
      is_primary = node == instance.primary_node
1824
      result = rpc.call_blockdev_assemble(node, node_disk, is_primary)
1824
      result = rpc.call_blockdev_assemble(node, node_disk,
1825
                                          instance.name, is_primary)
1825 1826
      if not result:
1826 1827
        logger.Error("could not prepare block device %s on node %s (is_pri"
1827 1828
                     "mary=%s)" % (inst_disk.iv_name, node, is_primary))
......
2560 2561
                               (instance.name, target_node))
2561 2562

  
2562 2563

  
2563
def _CreateBlockDevOnPrimary(cfg, node, device, info):
2564
def _CreateBlockDevOnPrimary(cfg, node, instance, device, info):
2564 2565
  """Create a tree of block devices on the primary node.
2565 2566

  
2566 2567
  This always creates all devices.
......
2568 2569
  """
2569 2570
  if device.children:
2570 2571
    for child in device.children:
2571
      if not _CreateBlockDevOnPrimary(cfg, node, child, info):
2572
      if not _CreateBlockDevOnPrimary(cfg, node, instance, child, info):
2572 2573
        return False
2573 2574

  
2574 2575
  cfg.SetDiskID(device, node)
2575
  new_id = rpc.call_blockdev_create(node, device, device.size, True, info)
2576
  new_id = rpc.call_blockdev_create(node, device, device.size,
2577
                                    instance.name, True, info)
2576 2578
  if not new_id:
2577 2579
    return False
2578 2580
  if device.physical_id is None:
......
2580 2582
  return True
2581 2583

  
2582 2584

  
2583
def _CreateBlockDevOnSecondary(cfg, node, device, force, info):
2585
def _CreateBlockDevOnSecondary(cfg, node, instance, device, force, info):
2584 2586
  """Create a tree of block devices on a secondary node.
2585 2587

  
2586 2588
  If this device type has to be created on secondaries, create it and
......
2593 2595
    force = True
2594 2596
  if device.children:
2595 2597
    for child in device.children:
2596
      if not _CreateBlockDevOnSecondary(cfg, node, child, force, info):
2598
      if not _CreateBlockDevOnSecondary(cfg, node, instance,
2599
                                        child, force, info):
2597 2600
        return False
2598 2601

  
2599 2602
  if not force:
2600 2603
    return True
2601 2604
  cfg.SetDiskID(device, node)
2602
  new_id = rpc.call_blockdev_create(node, device, device.size, False, info)
2605
  new_id = rpc.call_blockdev_create(node, device, device.size,
2606
                                    instance.name, False, info)
2603 2607
  if not new_id:
2604 2608
    return False
2605 2609
  if device.physical_id is None:
......
2754 2758
              (device.iv_name, instance.name))
2755 2759
    #HARDCODE
2756 2760
    for secondary_node in instance.secondary_nodes:
2757
      if not _CreateBlockDevOnSecondary(cfg, secondary_node, device, False,
2758
                                        info):
2761
      if not _CreateBlockDevOnSecondary(cfg, secondary_node, instance,
2762
                                        device, False, info):
2759 2763
        logger.Error("failed to create volume %s (%s) on secondary node %s!" %
2760 2764
                     (device.iv_name, device, secondary_node))
2761 2765
        return False
2762 2766
    #HARDCODE
2763
    if not _CreateBlockDevOnPrimary(cfg, instance.primary_node, device, info):
2767
    if not _CreateBlockDevOnPrimary(cfg, instance.primary_node,
2768
                                    instance, device, info):
2764 2769
      logger.Error("failed to create volume %s on primary!" %
2765 2770
                   device.iv_name)
2766 2771
      return False
......
3206 3211

  
3207 3212
    logger.Info("adding new mirror component on secondary")
3208 3213
    #HARDCODE
3209
    if not _CreateBlockDevOnSecondary(self.cfg, remote_node, new_drbd, False,
3214
    if not _CreateBlockDevOnSecondary(self.cfg, remote_node, instance,
3215
                                      new_drbd, False,
3210 3216
                                      _GetInstanceInfoText(instance)):
3211 3217
      raise errors.OpExecError("Failed to create new component on secondary"
3212 3218
                               " node %s" % remote_node)
3213 3219

  
3214 3220
    logger.Info("adding new mirror component on primary")
3215 3221
    #HARDCODE
3216
    if not _CreateBlockDevOnPrimary(self.cfg, instance.primary_node, new_drbd,
3222
    if not _CreateBlockDevOnPrimary(self.cfg, instance.primary_node,
3223
                                    instance, new_drbd,
3217 3224
                                    _GetInstanceInfoText(instance)):
3218 3225
      # remove secondary dev
3219 3226
      self.cfg.SetDiskID(new_drbd, remote_node)
......
3444 3451
      logger.Info("adding new mirror component on secondary for %s" %
3445 3452
                  dev.iv_name)
3446 3453
      #HARDCODE
3447
      if not _CreateBlockDevOnSecondary(cfg, remote_node, new_drbd, False,
3454
      if not _CreateBlockDevOnSecondary(cfg, remote_node, instance,
3455
                                        new_drbd, False,
3448 3456
                                        _GetInstanceInfoText(instance)):
3449 3457
        raise errors.OpExecError("Failed to create new component on"
3450 3458
                                 " secondary node %s\n"
......
3453 3461

  
3454 3462
      logger.Info("adding new mirror component on primary")
3455 3463
      #HARDCODE
3456
      if not _CreateBlockDevOnPrimary(cfg, instance.primary_node, new_drbd,
3464
      if not _CreateBlockDevOnPrimary(cfg, instance.primary_node,
3465
                                      instance, new_drbd,
3457 3466
                                      _GetInstanceInfoText(instance)):
3458 3467
        # remove secondary dev
3459 3468
        cfg.SetDiskID(new_drbd, remote_node)
......
3558 3567
      # _Create...OnPrimary (which forces the creation), even if we
3559 3568
      # are talking about the secondary node
3560 3569
      for new_lv in new_lvs:
3561
        if not _CreateBlockDevOnPrimary(cfg, tgt_node, new_lv,
3570
        if not _CreateBlockDevOnPrimary(cfg, tgt_node, instance, new_lv,
3562 3571
                                        _GetInstanceInfoText(instance)):
3563 3572
          raise errors.OpExecError("Failed to create new LV named '%s' on"
3564 3573
                                   " node '%s'" %
......
3669 3678
      # _Create...OnPrimary (which forces the creation), even if we
3670 3679
      # are talking about the secondary node
3671 3680
      for new_lv in dev.children:
3672
        if not _CreateBlockDevOnPrimary(cfg, new_node, new_lv,
3681
        if not _CreateBlockDevOnPrimary(cfg, new_node, instance, new_lv,
3673 3682
                                        _GetInstanceInfoText(instance)):
3674 3683
          raise errors.OpExecError("Failed to create new LV named '%s' on"
3675 3684
                                   " node '%s'" %
......
3680 3689
                              logical_id=(pri_node, new_node,
3681 3690
                                          dev.logical_id[2]),
3682 3691
                              children=dev.children)
3683
      if not _CreateBlockDevOnSecondary(cfg, new_node, new_drbd, False,
3692
      if not _CreateBlockDevOnSecondary(cfg, new_node, instance,
3693
                                        new_drbd, False,
3684 3694
                                      _GetInstanceInfoText(instance)):
3685 3695
        raise errors.OpExecError("Failed to create new DRBD on"
3686 3696
                                 " node '%s'" % new_node)
b/lib/constants.py
25 25

  
26 26
# various versions
27 27
CONFIG_VERSION = 3
28
PROTOCOL_VERSION = 4
28
PROTOCOL_VERSION = 5
29 29
RELEASE_VERSION = _autoconf.PACKAGE_VERSION
30 30
OS_API_VERSION = 5
31 31
EXPORT_VERSION = 0
......
33 33

  
34 34
# file paths
35 35
DATA_DIR = _autoconf.LOCALSTATEDIR + "/lib/ganeti"
36
BDEV_CACHE_DIR = _autoconf.LOCALSTATEDIR + "/run/ganeti"
36 37
CLUSTER_CONF_FILE = DATA_DIR + "/config.data"
37 38
SSL_CERT_FILE = DATA_DIR + "/server.pem"
38 39
WATCHER_STATEFILE = DATA_DIR + "/watcher.data"
b/lib/rpc.py
489 489
  return c.getresult()
490 490

  
491 491

  
492
def call_blockdev_create(node, bdev, size, on_primary, info):
492
def call_blockdev_create(node, bdev, size, owner, on_primary, info):
493 493
  """Request creation of a given block device.
494 494

  
495 495
  This is a single-node call.
496 496

  
497 497
  """
498
  params = [bdev.ToDict(), size, on_primary, info]
498
  params = [bdev.ToDict(), size, owner, on_primary, info]
499 499
  c = Client("blockdev_create", params)
500 500
  c.connect(node)
501 501
  c.run()
......
527 527
  return c.getresult().get(node, False)
528 528

  
529 529

  
530
def call_blockdev_assemble(node, disk, on_primary):
530
def call_blockdev_assemble(node, disk, owner, on_primary):
531 531
  """Request assembling of a given block device.
532 532

  
533 533
  This is a single-node call.
534 534

  
535 535
  """
536
  params = [disk.ToDict(), on_primary]
536
  params = [disk.ToDict(), owner, on_primary]
537 537
  c = Client("blockdev_assemble", params)
538 538
  c.connect(node)
539 539
  c.run()

Also available in: Unified diff