Revision 27619aac

b/test/py/cmdlib/instance_unittest.py
1713 1713
      op, "Can't compute nodes using iallocator")
1714 1714

  
1715 1715

  
1716
class TestLUInstanceSetParams(CmdlibTestCase):
1717
  def setUp(self):
1718
    super(TestLUInstanceSetParams, self).setUp()
1719

  
1720
    self.inst = self.cfg.AddNewInstance()
1721
    self.op = opcodes.OpInstanceSetParams(instance_name=self.inst.name)
1722

  
1723
    self.running_inst = \
1724
      self.cfg.AddNewInstance(admin_state=constants.ADMINST_UP)
1725
    self.running_op = \
1726
      opcodes.OpInstanceSetParams(instance_name=self.running_inst.name)
1727

  
1728
    self.snode = self.cfg.AddNewNode()
1729

  
1730
    self.mocked_storage_type = constants.ST_LVM_VG
1731
    self.mocked_storage_free = 10000
1732
    self.mocked_master_cpu_total = 16
1733
    self.mocked_master_memory_free = 2048
1734
    self.mocked_snode_cpu_total = 16
1735
    self.mocked_snode_memory_free = 512
1736

  
1737
    self.mocked_running_inst_memory = 1024
1738
    self.mocked_running_inst_vcpus = 8
1739
    self.mocked_running_inst_state = "running"
1740
    self.mocked_running_inst_time = 10938474
1741

  
1742
    bootid = "mock_bootid"
1743
    storage_info = [
1744
      {
1745
        "type": self.mocked_storage_type,
1746
        "storage_free": self.mocked_storage_free
1747
      }
1748
    ]
1749
    hv_info_master = {
1750
      "cpu_total": self.mocked_master_cpu_total,
1751
      "memory_free": self.mocked_master_memory_free
1752
    }
1753
    hv_info_snode = {
1754
      "cpu_total": self.mocked_snode_cpu_total,
1755
      "memory_free": self.mocked_snode_memory_free
1756
    }
1757

  
1758
    self.rpc.call_node_info.return_value = \
1759
      self.RpcResultsBuilder() \
1760
        .AddSuccessfulNode(self.master,
1761
                           (bootid, storage_info, (hv_info_master, ))) \
1762
        .AddSuccessfulNode(self.snode,
1763
                           (bootid, storage_info, (hv_info_snode, ))) \
1764
        .Build()
1765

  
1766
    def _InstanceInfo(_, instance, __, ___):
1767
      if instance == self.inst.name:
1768
        return self.RpcResultsBuilder() \
1769
          .CreateSuccessfulNodeResult(self.master, None)
1770
      elif instance == self.running_inst.name:
1771
        return self.RpcResultsBuilder() \
1772
          .CreateSuccessfulNodeResult(
1773
            self.master, {
1774
              "memory": self.mocked_running_inst_memory,
1775
              "vcpus": self.mocked_running_inst_vcpus,
1776
              "state": self.mocked_running_inst_state,
1777
              "time": self.mocked_running_inst_time
1778
            })
1779
      else:
1780
        raise AssertionError()
1781
    self.rpc.call_instance_info.side_effect = _InstanceInfo
1782

  
1783
    self.rpc.call_bridges_exist.return_value = \
1784
      self.RpcResultsBuilder() \
1785
        .CreateSuccessfulNodeResult(self.master, True)
1786

  
1787
  def testNoChanges(self):
1788
    op = self.CopyOpCode(self.op)
1789
    self.ExecOpCodeExpectOpPrereqError(op, "No changes submitted")
1790

  
1791
  def testGlobalHvparams(self):
1792
    op = self.CopyOpCode(self.op,
1793
                         hvparams={constants.HV_MIGRATION_PORT: 1234})
1794
    self.ExecOpCodeExpectOpPrereqError(
1795
      op, "hypervisor parameters are global and cannot be customized")
1796

  
1797
  def testHvparams(self):
1798
    op = self.CopyOpCode(self.op,
1799
                         hvparams={constants.HV_BOOT_ORDER: "cd"})
1800
    self.ExecOpCode(op)
1801

  
1802
  def testDisksAndDiskTemplate(self):
1803
    op = self.CopyOpCode(self.op,
1804
                         disk_template=constants.DT_PLAIN,
1805
                         disks=[[constants.DDM_ADD, -1, {}]])
1806
    self.ExecOpCodeExpectOpPrereqError(
1807
      op, "Disk template conversion and other disk changes not supported at"
1808
          " the same time")
1809

  
1810
  def testDiskTemplateToMirroredNoRemoteNode(self):
1811
    op = self.CopyOpCode(self.op,
1812
                         disk_template=constants.DT_DRBD8)
1813
    self.ExecOpCodeExpectOpPrereqError(
1814
      op, "Changing the disk template to a mirrored one requires specifying"
1815
          " a secondary node")
1816

  
1817
  def testPrimaryNodeToOldPrimaryNode(self):
1818
    op = self.CopyOpCode(self.op,
1819
                         pnode=self.master.name)
1820
    self.ExecOpCode(op)
1821

  
1822
  def testPrimaryNodeChange(self):
1823
    node = self.cfg.AddNewNode()
1824
    op = self.CopyOpCode(self.op,
1825
                         pnode=node.name)
1826
    self.ExecOpCode(op)
1827

  
1828
  def testPrimaryNodeChangeRunningInstance(self):
1829
    node = self.cfg.AddNewNode()
1830
    op = self.CopyOpCode(self.running_op,
1831
                         pnode=node.name)
1832
    self.ExecOpCodeExpectOpPrereqError(op, "Instance is still running")
1833

  
1834
  def testOsChange(self):
1835
    os = self.cfg.CreateOs(supported_variants=[])
1836
    self.rpc.call_os_get.return_value = \
1837
      self.RpcResultsBuilder() \
1838
        .CreateSuccessfulNodeResult(self.master, os)
1839
    op = self.CopyOpCode(self.op,
1840
                         os_name=os.name)
1841
    self.ExecOpCode(op)
1842

  
1843
  def testVCpuChange(self):
1844
    op = self.CopyOpCode(self.op,
1845
                         beparams={
1846
                           constants.BE_VCPUS: 4
1847
                         })
1848
    self.ExecOpCode(op)
1849

  
1850
  def testWrongCpuMask(self):
1851
    op = self.CopyOpCode(self.op,
1852
                         beparams={
1853
                           constants.BE_VCPUS: 4
1854
                         },
1855
                         hvparams={
1856
                           constants.HV_CPU_MASK: "1,2:3,4"
1857
                         })
1858
    self.ExecOpCodeExpectOpPrereqError(
1859
      op, "Number of vCPUs .* does not match the CPU mask .*")
1860

  
1861
  def testCorrectCpuMask(self):
1862
    op = self.CopyOpCode(self.op,
1863
                         beparams={
1864
                           constants.BE_VCPUS: 4
1865
                         },
1866
                         hvparams={
1867
                           constants.HV_CPU_MASK: "1,2:3,4:all:1,4"
1868
                         })
1869
    self.ExecOpCode(op)
1870

  
1871
  def testOsParams(self):
1872
    op = self.CopyOpCode(self.op,
1873
                         osparams={
1874
                           self.os.supported_parameters[0]: "test_param_val"
1875
                         })
1876
    self.ExecOpCode(op)
1877

  
1878
  def testIncreaseMemoryTooMuch(self):
1879
    op = self.CopyOpCode(self.running_op,
1880
                         beparams={
1881
                           constants.BE_MAXMEM:
1882
                             self.mocked_master_memory_free * 2
1883
                         })
1884
    self.ExecOpCodeExpectOpPrereqError(
1885
      op, "This change will prevent the instance from starting")
1886

  
1887
  def testIncreaseMemory(self):
1888
    op = self.CopyOpCode(self.running_op,
1889
                         beparams={
1890
                           constants.BE_MAXMEM: self.mocked_master_memory_free
1891
                         })
1892
    self.ExecOpCode(op)
1893

  
1894
  def testIncreaseMemoryTooMuchForSecondary(self):
1895
    inst = self.cfg.AddNewInstance(admin_state=constants.ADMINST_UP,
1896
                                   disk_template=constants.DT_DRBD8,
1897
                                   secondary_node=self.snode)
1898
    self.rpc.call_instance_info.side_effect = [
1899
      self.RpcResultsBuilder()
1900
        .CreateSuccessfulNodeResult(self.master,
1901
                                    {
1902
                                      "memory":
1903
                                        self.mocked_snode_memory_free * 2,
1904
                                      "vcpus": self.mocked_running_inst_vcpus,
1905
                                      "state": self.mocked_running_inst_state,
1906
                                      "time": self.mocked_running_inst_time
1907
                                    })]
1908

  
1909
    op = self.CopyOpCode(self.op,
1910
                         instance_name=inst.name,
1911
                         beparams={
1912
                           constants.BE_MAXMEM:
1913
                             self.mocked_snode_memory_free * 2,
1914
                           constants.BE_AUTO_BALANCE: True
1915
                         })
1916
    self.ExecOpCodeExpectOpPrereqError(
1917
      op, "This change will prevent the instance from failover to its"
1918
          " secondary node")
1919

  
1920
  def testInvalidRuntimeMemory(self):
1921
    op = self.CopyOpCode(self.running_op,
1922
                         runtime_mem=self.mocked_master_memory_free * 2)
1923
    self.ExecOpCodeExpectOpPrereqError(
1924
      op, "Instance .* must have memory between .* and .* of memory")
1925

  
1926
  def testIncreaseRuntimeMemory(self):
1927
    op = self.CopyOpCode(self.running_op,
1928
                         runtime_mem=self.mocked_master_memory_free,
1929
                         beparams={
1930
                           constants.BE_MAXMEM: self.mocked_master_memory_free
1931
                         })
1932
    self.ExecOpCode(op)
1933

  
1934
  def testAddNicWithPoolIpNoNetwork(self):
1935
    op = self.CopyOpCode(self.op,
1936
                         nics=[(constants.DDM_ADD, -1,
1937
                                {
1938
                                  constants.INIC_IP: constants.NIC_IP_POOL
1939
                                })])
1940
    self.ExecOpCodeExpectOpPrereqError(
1941
      op, "If ip=pool, parameter network cannot be none")
1942

  
1943
  def testAddNicWithPoolIp(self):
1944
    net = self.cfg.AddNewNetwork()
1945
    self.cfg.ConnectNetworkToGroup(net, self.group)
1946
    op = self.CopyOpCode(self.op,
1947
                         nics=[(constants.DDM_ADD, -1,
1948
                                {
1949
                                  constants.INIC_IP: constants.NIC_IP_POOL,
1950
                                  constants.INIC_NETWORK: net.name
1951
                                })])
1952
    self.ExecOpCode(op)
1953

  
1954
  def testAddNicWithInvalidIp(self):
1955
    op = self.CopyOpCode(self.op,
1956
                         nics=[(constants.DDM_ADD, -1,
1957
                                {
1958
                                  constants.INIC_IP: "invalid"
1959
                                })])
1960
    self.ExecOpCodeExpectOpPrereqError(
1961
      op, "Invalid IP address")
1962

  
1963
  def testAddNic(self):
1964
    op = self.CopyOpCode(self.op,
1965
                         nics=[(constants.DDM_ADD, -1, {})])
1966
    self.ExecOpCode(op)
1967

  
1968
  def testAddNicWithIp(self):
1969
    op = self.CopyOpCode(self.op,
1970
                         nics=[(constants.DDM_ADD, -1,
1971
                                {
1972
                                  constants.INIC_IP: "2.3.1.4"
1973
                                })])
1974
    self.ExecOpCode(op)
1975

  
1976
  def testModifyNicRoutedWithoutIp(self):
1977
    op = self.CopyOpCode(self.op,
1978
                         nics=[(constants.DDM_MODIFY, 0,
1979
                                {
1980
                                  constants.INIC_MODE: constants.NIC_MODE_ROUTED
1981
                                })])
1982
    self.ExecOpCodeExpectOpPrereqError(
1983
      op, "Cannot set the NIC IP address to None on a routed NIC")
1984

  
1985
  def testModifyNicSetMac(self):
1986
    op = self.CopyOpCode(self.op,
1987
                         nics=[(constants.DDM_MODIFY, 0,
1988
                                {
1989
                                  constants.INIC_MAC: "0a:12:95:15:bf:75"
1990
                                })])
1991
    self.ExecOpCode(op)
1992

  
1993
  def testModifyNicWithPoolIpNoNetwork(self):
1994
    op = self.CopyOpCode(self.op,
1995
                         nics=[(constants.DDM_MODIFY, -1,
1996
                                {
1997
                                  constants.INIC_IP: constants.NIC_IP_POOL
1998
                                })])
1999
    self.ExecOpCodeExpectOpPrereqError(
2000
      op, "ip=pool, but no network found")
2001

  
2002
  def testModifyNicSetNet(self):
2003
    old_net = self.cfg.AddNewNetwork()
2004
    self.cfg.ConnectNetworkToGroup(old_net, self.group)
2005
    inst = self.cfg.AddNewInstance(nics=[
2006
      self.cfg.CreateNic(network=old_net,
2007
                         ip="192.168.123.2")])
2008

  
2009
    new_net = self.cfg.AddNewNetwork(mac_prefix="be")
2010
    self.cfg.ConnectNetworkToGroup(new_net, self.group)
2011
    op = self.CopyOpCode(self.op,
2012
                         instance_name=inst.name,
2013
                         nics=[(constants.DDM_MODIFY, 0,
2014
                                {
2015
                                  constants.INIC_NETWORK: new_net.name
2016
                                })])
2017
    self.ExecOpCode(op)
2018

  
2019
  def testModifyNicSetLinkWhileConnected(self):
2020
    old_net = self.cfg.AddNewNetwork()
2021
    self.cfg.ConnectNetworkToGroup(old_net, self.group)
2022
    inst = self.cfg.AddNewInstance(nics=[
2023
      self.cfg.CreateNic(network=old_net)])
2024

  
2025
    op = self.CopyOpCode(self.op,
2026
                         instance_name=inst.name,
2027
                         nics=[(constants.DDM_MODIFY, 0,
2028
                                {
2029
                                  constants.INIC_LINK: "mock_link"
2030
                                })])
2031
    self.ExecOpCodeExpectOpPrereqError(
2032
      op, "Not allowed to change link or mode of a NIC that is connected"
2033
          " to a network")
2034

  
2035
  def testModifyNicSetNetAndIp(self):
2036
    net = self.cfg.AddNewNetwork(mac_prefix="be", network="123.123.123.0/24")
2037
    self.cfg.ConnectNetworkToGroup(net, self.group)
2038
    op = self.CopyOpCode(self.op,
2039
                         nics=[(constants.DDM_MODIFY, 0,
2040
                                {
2041
                                  constants.INIC_NETWORK: net.name,
2042
                                  constants.INIC_IP: "123.123.123.1"
2043
                                })])
2044
    self.ExecOpCode(op)
2045

  
2046
  def testModifyNic(self):
2047
    op = self.CopyOpCode(self.op,
2048
                         nics=[(constants.DDM_MODIFY, 0, {})])
2049
    self.ExecOpCode(op)
2050

  
2051
  def testRemoveLastNic(self):
2052
    op = self.CopyOpCode(self.op,
2053
                         nics=[(constants.DDM_REMOVE, 0, {})])
2054
    self.ExecOpCodeExpectOpPrereqError(
2055
      op, "violates policy")
2056

  
2057
  def testRemoveNic(self):
2058
    inst = self.cfg.AddNewInstance(nics=[self.cfg.CreateNic(),
2059
                                         self.cfg.CreateNic()])
2060
    op = self.CopyOpCode(self.op,
2061
                         instance_name=inst.name,
2062
                         nics=[(constants.DDM_REMOVE, 0, {})])
2063
    self.ExecOpCode(op)
2064

  
2065
  def testSetOffline(self):
2066
    op = self.CopyOpCode(self.op,
2067
                         offline=True)
2068
    self.ExecOpCode(op)
2069

  
2070
  def testUnsetOffline(self):
2071
    op = self.CopyOpCode(self.op,
2072
                         offline=False)
2073
    self.ExecOpCode(op)
2074

  
2075
  def testAddDiskInvalidMode(self):
2076
    op = self.CopyOpCode(self.op,
2077
                         disks=[[constants.DDM_ADD, -1,
2078
                                 {
2079
                                   constants.IDISK_MODE: "invalid"
2080
                                 }]])
2081
    self.ExecOpCodeExpectOpPrereqError(
2082
      op, "Invalid disk access mode 'invalid'")
2083

  
2084
  def testAddDiskMissingSize(self):
2085
    op = self.CopyOpCode(self.op,
2086
                         disks=[[constants.DDM_ADD, -1, {}]])
2087
    self.ExecOpCodeExpectOpPrereqError(
2088
      op, "Required disk parameter 'size' missing")
2089

  
2090
  def testAddDiskInvalidSize(self):
2091
    op = self.CopyOpCode(self.op,
2092
                         disks=[[constants.DDM_ADD, -1,
2093
                                 {
2094
                                   constants.IDISK_SIZE: "invalid"
2095
                                 }]])
2096
    self.ExecOpCodeExpectException(
2097
      op, errors.TypeEnforcementError, "is not a valid size")
2098

  
2099
  def testAddDisk(self):
2100
    op = self.CopyOpCode(self.op,
2101
                         disks=[[constants.DDM_ADD, -1,
2102
                                 {
2103
                                   constants.IDISK_SIZE: 1024
2104
                                 }]])
2105
    self.ExecOpCode(op)
2106

  
2107
  def testAddDiskNoneName(self):
2108
    op = self.CopyOpCode(self.op,
2109
                         disks=[[constants.DDM_ADD, -1,
2110
                                 {
2111
                                   constants.IDISK_SIZE: 1024,
2112
                                   constants.IDISK_NAME: constants.VALUE_NONE
2113
                                 }]])
2114
    self.ExecOpCode(op)
2115

  
2116
  def testModifyDiskWithSize(self):
2117
    op = self.CopyOpCode(self.op,
2118
                         disks=[[constants.DDM_MODIFY, 0,
2119
                                 {
2120
                                   constants.IDISK_SIZE: 1024
2121
                                 }]])
2122
    self.ExecOpCodeExpectOpPrereqError(
2123
      op, "Disk size change not possible, use grow-disk")
2124

  
2125
  def testModifyDiskWithRandomParams(self):
2126
    op = self.CopyOpCode(self.op,
2127
                         disks=[[constants.DDM_MODIFY, 0,
2128
                                 {
2129
                                   constants.IDISK_METAVG: "new_meta_vg",
2130
                                   constants.IDISK_MODE: "invalid",
2131
                                   constants.IDISK_NAME: "new_name"
2132
                                 }]])
2133
    self.ExecOpCodeExpectOpPrereqError(
2134
      op, "Disk modification doesn't support additional arbitrary parameters")
2135

  
2136
  def testModifyDiskUnsetName(self):
2137
    op = self.CopyOpCode(self.op,
2138
                         disks=[[constants.DDM_MODIFY, 0,
2139
                                  {
2140
                                    constants.IDISK_NAME: constants.VALUE_NONE
2141
                                  }]])
2142
    self.ExecOpCode(op)
2143

  
2144
  def testSetOldDiskTemplate(self):
2145
    op = self.CopyOpCode(self.op,
2146
                         disk_template=self.inst.disk_template)
2147
    self.ExecOpCodeExpectOpPrereqError(
2148
      op, "Instance already has disk template")
2149

  
2150
  def testSetDisabledDiskTemplate(self):
2151
    self.cfg.SetEnabledDiskTemplates([self.inst.disk_template])
2152
    op = self.CopyOpCode(self.op,
2153
                         disk_template=constants.DT_EXT)
2154
    self.ExecOpCodeExpectOpPrereqError(
2155
      op, "Disk template .* is not enabled for this cluster")
2156

  
2157
  def testInvalidDiskTemplateConversion(self):
2158
    op = self.CopyOpCode(self.op,
2159
                         disk_template=constants.DT_EXT)
2160
    self.ExecOpCodeExpectOpPrereqError(
2161
      op, "Unsupported disk template conversion from .* to .*")
2162

  
2163
  def testConvertToDRBDWithSecondarySameAsPrimary(self):
2164
    op = self.CopyOpCode(self.op,
2165
                         disk_template=constants.DT_DRBD8,
2166
                         remote_node=self.master.name)
2167
    self.ExecOpCodeExpectOpPrereqError(
2168
      op, "Given new secondary node .* is the same as the primary node"
2169
          " of the instance")
2170

  
2171
  def testConvertPlainToDRBD(self):
2172
    self.rpc.call_blockdev_shutdown.return_value = \
2173
      self.RpcResultsBuilder() \
2174
        .CreateSuccessfulNodeResult(self.master, True)
2175
    self.rpc.call_blockdev_getmirrorstatus.return_value = \
2176
      self.RpcResultsBuilder() \
2177
        .CreateSuccessfulNodeResult(self.master, [objects.BlockDevStatus()])
2178

  
2179
    op = self.CopyOpCode(self.op,
2180
                         disk_template=constants.DT_DRBD8,
2181
                         remote_node=self.snode.name)
2182
    self.ExecOpCode(op)
2183

  
2184
  def testConvertDRBDToPlain(self):
2185
    self.inst.disks = [self.cfg.CreateDisk(dev_type=constants.DT_DRBD8,
2186
                                           primary_node=self.master,
2187
                                           secondary_node=self.snode)]
2188
    self.inst.disk_template = constants.DT_DRBD8
2189
    self.rpc.call_blockdev_shutdown.return_value = \
2190
      self.RpcResultsBuilder() \
2191
        .CreateSuccessfulNodeResult(self.master, True)
2192
    self.rpc.call_blockdev_remove.return_value = \
2193
      self.RpcResultsBuilder() \
2194
        .CreateSuccessfulNodeResult(self.master)
2195
    self.rpc.call_blockdev_getmirrorstatus.return_value = \
2196
      self.RpcResultsBuilder() \
2197
        .CreateSuccessfulNodeResult(self.master, [objects.BlockDevStatus()])
2198

  
2199
    op = self.CopyOpCode(self.op,
2200
                         disk_template=constants.DT_PLAIN)
2201
    self.ExecOpCode(op)
2202

  
2203

  
1716 2204
if __name__ == "__main__":
1717 2205
  testutils.GanetiTestProgram()
b/test/py/cmdlib/testsupport/config_mock.py
176 176
                     name=None,
177 177
                     primary_node=None,
178 178
                     os=None,
179
                     hypervisor=constants.HT_FAKE,
179
                     hypervisor=None,
180 180
                     hvparams=None,
181 181
                     beparams=None,
182 182
                     osparams=None,
......
208 208
    if os is None:
209 209
      os = self.GetDefaultOs().name + objects.OS.VARIANT_DELIM +\
210 210
           self.GetDefaultOs().supported_variants[0]
211
    if hypervisor is None:
212
      hypervisor = self.GetClusterInfo().enabled_hypervisors[0]
211 213
    if hvparams is None:
212 214
      hvparams = {}
213 215
    if beparams is None:
......
281 283
    if network is None:
282 284
      network = "192.168.123.0/24"
283 285
    if gateway is None:
284
      gateway = "192.168.123.1"
286
      if network[-3:] == "/24":
287
        gateway = network[:-4] + "1"
288
      else:
289
        gateway = "192.168.123.1"
285 290
    if network[-3:] == "/24" and gateway == network[:-4] + "1":
286 291
      if reservations is None:
287 292
        reservations = "0" * 256
......
503 508
      name = "mock_nic_%d" % nic_id
504 509
    if mac is None:
505 510
      mac = "aa:00:00:aa:%02x:%02x" % (nic_id / 0xff, nic_id % 0xff)
511
    if isinstance(network, objects.Network):
512
      network = network.uuid
506 513
    if nicparams is None:
507 514
      nicparams = {}
508 515

  
b/test/py/cmdlib/testsupport/netutils_mock.py
111 111
  netutils_mod.FormatAddress.side_effect = netutils.FormatAddress
112 112
  netutils_mod.Hostname.GetNormalizedName.side_effect = \
113 113
    netutils.Hostname.GetNormalizedName
114
  netutils_mod.IPAddress = netutils.IPAddress
115
  netutils_mod.IP4Address = netutils.IP4Address
116
  netutils_mod.IP6Address = netutils.IP6Address

Also available in: Unified diff