#!/usr/bin/python
#

# Copyright (C) 2013 Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


"""Script for unittesting the cmdlib module 'instance_storage'"""


import unittest

from ganeti import constants
from ganeti.cmdlib import instance_storage
from ganeti import errors
from ganeti import objects
from ganeti import opcodes

import testutils
import mock
import time

from testsupport import CmdlibTestCase


class TestCheckNodesFreeDiskOnVG(unittest.TestCase):

  def setUp(self):
    self.node_uuid = "12345"
    self.node_uuids = [self.node_uuid]

    self.node_info = mock.Mock()

    self.es = True
    self.ndparams = {constants.ND_EXCLUSIVE_STORAGE: self.es}

    mock_rpc = mock.Mock()
    mock_rpc.call_node_info = mock.Mock()

    mock_cfg = mock.Mock()
    mock_cfg.GetNodeInfo = mock.Mock(return_value=self.node_info)
    mock_cfg.GetNdParams = mock.Mock(return_value=self.ndparams)

    self.hvname = "myhv"
    self.hvparams = mock.Mock()
    self.clusterinfo = mock.Mock()
    self.clusterinfo.hvparams = {self.hvname: self.hvparams}

    mock_cfg.GetHypervisorType = mock.Mock(return_value=self.hvname)
    mock_cfg.GetClusterInfo = mock.Mock(return_value=self.clusterinfo)

    self.lu = mock.Mock()
    self.lu.rpc = mock_rpc
    self.lu.cfg = mock_cfg

    self.vg = "myvg"

    self.node_name = "mynode"
    self.space_info = [{"type": constants.ST_LVM_VG,
                        "name": self.vg,
                        "storage_free": 125,
                        "storage_size": 666}]

  def testPerformNodeInfoCall(self):
    expected_hv_arg = [(self.hvname, self.hvparams)]
    expected_storage_arg = {self.node_uuid:
        [(constants.ST_LVM_VG, self.vg, [self.es]),
         (constants.ST_LVM_PV, self.vg, [self.es])]}
    instance_storage._PerformNodeInfoCall(self.lu, self.node_uuids, self.vg)
    self.lu.rpc.call_node_info.assert_called_with(
        self.node_uuids, expected_storage_arg, expected_hv_arg)

  def testCheckVgCapacityForNode(self):
    requested = 123
    node_info = (None, self.space_info, None)
    instance_storage._CheckVgCapacityForNode(self.node_name, node_info,
                                             self.vg, requested)

  def testCheckVgCapacityForNodeNotEnough(self):
    requested = 250
    node_info = (None, self.space_info, None)
    self.assertRaises(
        errors.OpPrereqError,
        instance_storage._CheckVgCapacityForNode,
        self.node_name, node_info, self.vg, requested)

  def testCheckVgCapacityForNodeNoStorageData(self):
    node_info = (None, [], None)
    self.assertRaises(
        errors.OpPrereqError,
        instance_storage._CheckVgCapacityForNode,
        self.node_name, node_info, self.vg, NotImplemented)

  def testCheckVgCapacityForNodeBogusSize(self):
    broken_space_info = [{"type": constants.ST_LVM_VG,
                        "name": self.vg,
                        "storage_free": "greenbunny",
                        "storage_size": "redbunny"}]
    node_info = (None, broken_space_info, None)
    self.assertRaises(
        errors.OpPrereqError,
        instance_storage._CheckVgCapacityForNode,
        self.node_name, node_info, self.vg, NotImplemented)


class TestCheckComputeDisksInfo(unittest.TestCase):
  """Tests for instance_storage.ComputeDisksInfo()

  """
  def setUp(self):
    """Set up input data"""
    self.disks = [
      objects.Disk(dev_type=constants.DT_PLAIN, size=1024,
                   logical_id=("ganeti", "disk01234"),
                   name="disk-0", mode="rw", params={},
                   children=[], uuid="disk0"),
      objects.Disk(dev_type=constants.DT_PLAIN, size=2048,
                   logical_id=("ganeti", "disk56789"),
                   name="disk-1", mode="ro", params={},
                   children=[], uuid="disk1")
      ]

    self.ext_params = {
      "provider": "pvdr",
      "param1"  : "value1",
      "param2"  : "value2"
      }

    self.default_vg = "ganeti-vg"

  def testComputeDisksInfo(self):
    """Test instance_storage.ComputeDisksInfo() method"""
    disks_info = instance_storage.ComputeDisksInfo(self.disks,
                                                   constants.DT_EXT,
                                                   self.default_vg,
                                                   self.ext_params)

    for disk, d in zip(disks_info, self.disks):
      self.assertEqual(disk.get("size"), d.size)
      self.assertEqual(disk.get("mode"), d.mode)
      self.assertEqual(disk.get("name"), d.name)
      self.assertEqual(disk.get("param1"), self.ext_params.get("param1"))
      self.assertEqual(disk.get("param2"), self.ext_params.get("param2"))
      self.assertEqual(disk.get("provider"), self.ext_params.get("provider"))

  def testComputeDisksInfoPlainToDrbd(self):
    disks = [{constants.IDISK_TYPE: constants.DT_DRBD8,
              constants.IDISK_SIZE: d.size,
              constants.IDISK_MODE: d.mode,
              constants.IDISK_VG: d.logical_id[0],
              constants.IDISK_NAME: d.name}
             for d in self.disks]

    disks_info = instance_storage.ComputeDisksInfo(self.disks,
                                                   constants.DT_DRBD8,
                                                   self.default_vg, {})
    self.assertEqual(disks, disks_info)

  def testComputeDisksInfoFails(self):
    """Test instance_storage.ComputeDisksInfo() method fails"""
    self.assertRaises(
      errors.OpPrereqError, instance_storage.ComputeDisksInfo,
      self.disks, constants.DT_EXT, self.default_vg, {})
    self.assertRaises(
      errors.OpPrereqError, instance_storage.ComputeDisksInfo,
      self.disks, constants.DT_DRBD8, self.default_vg, self.ext_params)

    self.ext_params.update({"size": 128})
    self.assertRaises(
      AssertionError, instance_storage.ComputeDisksInfo,
      self.disks, constants.DT_EXT, self.default_vg, self.ext_params)


class TestLUInstanceReplaceDisks(CmdlibTestCase):
  """Tests for LUInstanceReplaceDisks."""

  def setUp(self):
    super(TestLUInstanceReplaceDisks, self).setUp()

    self.MockOut(time, 'sleep')

    self.node1 = self.cfg.AddNewNode()
    self.node2 = self.cfg.AddNewNode()

  def MakeOpCode(self, disks, early_release=False, ignore_ipolicy=False,
                 remote_node=False, mode='replace_auto', iallocator=None):
    return opcodes.OpInstanceReplaceDisks(
        instance_name=self.instance.name,
        instance_uuid=self.instance.uuid,
        early_release=early_release,
        ignore_ipolicy=ignore_ipolicy,
        mode=mode,
        disks=disks,
        remote_node=self.node2.name if remote_node else None,
        remote_node_uuid=self.node2.uuid if remote_node else None,
        iallocator=iallocator)

  def testInvalidTemplate(self):
    self.instance = self.cfg.AddNewInstance(admin_state=constants.ADMINST_UP,
                                            disk_template='diskless',
                                            primary_node=self.node1)

    opcode = self.MakeOpCode([])
    self.ExecOpCodeExpectOpPrereqError(
        opcode, 'strange layout')

  def SimulateDiskFailure(self, node, disk):
    def Faulty(node_uuid):
      disks = self.cfg.GetInstanceDisks(node_uuid)
      return [i for i,d in enumerate(disks)
              if i == disk and node.uuid == node_uuid]
    self.MockOut(instance_storage.TLReplaceDisks, '_FindFaultyDisks',
                 side_effect=Faulty)
    self.MockOut(instance_storage.TLReplaceDisks, '_CheckDevices')
    self.MockOut(instance_storage.TLReplaceDisks, '_CheckVolumeGroup')
    self.MockOut(instance_storage.TLReplaceDisks, '_CheckDisksExistence')
    self.MockOut(instance_storage.TLReplaceDisks, '_CheckDisksConsistency')
    self.MockOut(instance_storage.LUInstanceReplaceDisks, 'AssertReleasedLocks')
    self.MockOut(instance_storage, 'WaitForSync')
    self.rpc.call_blockdev_addchildren().fail_msg = None

  def testReplacePrimary(self):
    self.instance = self.cfg.AddNewInstance(admin_state=constants.ADMINST_UP,
                                            disk_template='drbd',
                                            primary_node=self.node1,
                                            secondary_node=self.node2)

    self.SimulateDiskFailure(self.node1, 0)

    opcode = self.MakeOpCode([0], mode='replace_on_primary')
    self.ExecOpCode(opcode)
    self.rpc.call_blockdev_rename.assert_any_call(self.node1.uuid, [])

  def testReplaceSecondary(self):
    self.instance = self.cfg.AddNewInstance(admin_state=constants.ADMINST_UP,
                                            disk_template='drbd',
                                            primary_node=self.node1,
                                            secondary_node=self.node2)

    self.SimulateDiskFailure(self.node2, 0)

    opcode = self.MakeOpCode([0], mode='replace_on_secondary')
    self.ExecOpCode(opcode)
    self.rpc.call_blockdev_rename.assert_any_call(self.node2.uuid, [])

  def testReplaceSecondaryNew(self):
    disk = self.cfg.CreateDisk(dev_type=constants.DT_DRBD8,
                               primary_node=self.node1,
                               secondary_node=self.node2)
    self.instance = self.cfg.AddNewInstance(admin_state=constants.ADMINST_UP,
                                            disk_template='drbd',
                                            disks=[disk],
                                            primary_node=self.node1,
                                            secondary_node=self.node2)

    self.SimulateDiskFailure(self.node2, 0)
    node3 = self.cfg.AddNewNode()
    self.MockOut(instance_storage.TLReplaceDisks, '_RunAllocator',
                 return_value=node3.uuid)
    self.rpc.call_drbd_disconnect_net().__getitem__().fail_msg = None
    self.rpc.call_blockdev_shutdown().fail_msg = None
    self.rpc.call_drbd_attach_net().fail_msg = None

    opcode = self.MakeOpCode([], mode='replace_new_secondary',
                             iallocator='hail')
    self.ExecOpCode(opcode)
    self.rpc.call_blockdev_shutdown.assert_any_call(
        self.node2.uuid, (disk, self.instance))
    self.rpc.call_drbd_attach_net.assert_any_call(
        [self.node1.uuid, node3.uuid], ([disk], self.instance),
        False)

if __name__ == "__main__":
  testutils.GanetiTestProgram()
