Revision 919db916

b/lib/cli.py
189 189
  "SPECS_DISK_SIZE_OPT",
190 190
  "SPECS_MEM_SIZE_OPT",
191 191
  "SPECS_NIC_COUNT_OPT",
192
  "SPLIT_ISPECS_OPTS",
192 193
  "IPOLICY_STD_SPECS_OPT",
193 194
  "IPOLICY_DISK_TEMPLATES",
194 195
  "IPOLICY_VCPU_RATIO",
......
1657 1658

  
1658 1659
# common instance policy options
1659 1660
INSTANCE_POLICY_OPTS = [
1661
  IPOLICY_BOUNDS_SPECS_OPT,
1662
  IPOLICY_DISK_TEMPLATES,
1663
  IPOLICY_VCPU_RATIO,
1664
  IPOLICY_SPINDLE_RATIO,
1665
  ]
1666

  
1667
# instance policy split specs options
1668
SPLIT_ISPECS_OPTS = [
1660 1669
  SPECS_CPU_COUNT_OPT,
1661 1670
  SPECS_DISK_COUNT_OPT,
1662 1671
  SPECS_DISK_SIZE_OPT,
1663 1672
  SPECS_MEM_SIZE_OPT,
1664 1673
  SPECS_NIC_COUNT_OPT,
1665
  IPOLICY_BOUNDS_SPECS_OPT,
1666
  IPOLICY_DISK_TEMPLATES,
1667
  IPOLICY_VCPU_RATIO,
1668
  IPOLICY_SPINDLE_RATIO,
1669 1674
  ]
1670 1675

  
1671 1676

  
......
3846 3851

  
3847 3852
def _InitISpecsFromSplitOpts(ipolicy, ispecs_mem_size, ispecs_cpu_count,
3848 3853
                             ispecs_disk_count, ispecs_disk_size,
3849
                             ispecs_nic_count, group_ipolicy, allowed_values):
3854
                             ispecs_nic_count, group_ipolicy, fill_all):
3850 3855
  try:
3851 3856
    if ispecs_mem_size:
3852 3857
      ispecs_mem_size = _MaybeParseUnit(ispecs_mem_size)
......
3874 3879
    forced_type = TISPECS_CLUSTER_TYPES
3875 3880
  for specs in ispecs_transposed.values():
3876 3881
    assert type(specs) is dict
3877
    utils.ForceDictType(specs, forced_type, allowed_values=allowed_values)
3882
    utils.ForceDictType(specs, forced_type)
3878 3883

  
3879 3884
  # then transpose
3880 3885
  ispecs = {
......
3887 3892
    for key, val in specs.items(): # {min: .. ,max: .., std: ..}
3888 3893
      assert key in ispecs
3889 3894
      ispecs[key][name] = val
3895
  ipolicy[constants.ISPECS_MINMAX] = {}
3890 3896
  for key in constants.ISPECS_MINMAX_KEYS:
3891
    ipolicy[constants.ISPECS_MINMAX][key] = ispecs[key]
3892
  ipolicy[constants.ISPECS_STD] = ispecs[constants.ISPECS_STD]
3897
    if fill_all:
3898
      ipolicy[constants.ISPECS_MINMAX][key] = \
3899
        objects.FillDict(constants.ISPECS_MINMAX_DEFAULTS[key], ispecs[key])
3900
    else:
3901
      ipolicy[constants.ISPECS_MINMAX][key] = ispecs[key]
3902
  if fill_all:
3903
    ipolicy[constants.ISPECS_STD] = \
3904
        objects.FillDict(constants.IPOLICY_DEFAULTS[constants.ISPECS_STD],
3905
                         ispecs[constants.ISPECS_STD])
3906
  else:
3907
    ipolicy[constants.ISPECS_STD] = ispecs[constants.ISPECS_STD]
3893 3908

  
3894 3909

  
3895 3910
def _ParseSpecUnit(spec, keyname):
3896 3911
  ret = spec.copy()
3897 3912
  for k in [constants.ISPEC_DISK_SIZE, constants.ISPEC_MEM_SIZE]:
3898
    if k in ret and ret[k] != constants.VALUE_DEFAULT:
3913
    if k in ret:
3899 3914
      try:
3900 3915
        ret[k] = utils.ParseUnit(ret[k])
3901 3916
      except (TypeError, ValueError, errors.UnitParseError), err:
......
3905 3920
  return ret
3906 3921

  
3907 3922

  
3908
def _ParseISpec(spec, keyname, allowed_values):
3923
def _ParseISpec(spec, keyname, required):
3909 3924
  ret = _ParseSpecUnit(spec, keyname)
3910
  utils.ForceDictType(ret, constants.ISPECS_PARAMETER_TYPES,
3911
                      allowed_values=allowed_values)
3925
  utils.ForceDictType(ret, constants.ISPECS_PARAMETER_TYPES)
3926
  missing = constants.ISPECS_PARAMETERS - frozenset(ret.keys())
3927
  if required and missing:
3928
    raise errors.OpPrereqError("Missing parameters in ipolicy spec %s: %s" %
3929
                               (keyname, utils.CommaJoin(missing)),
3930
                               errors.ECODE_INVAL)
3931
  return ret
3932

  
3933

  
3934
def _GetISpecsInAllowedValues(minmax_ispecs, allowed_values):
3935
  ret = None
3936
  if minmax_ispecs and allowed_values and len(minmax_ispecs) == 1:
3937
    for (key, spec) in minmax_ispecs.items():
3938
      # This loop is executed exactly once
3939
      if key in allowed_values and not spec:
3940
        ret = key
3912 3941
  return ret
3913 3942

  
3914 3943

  
3915 3944
def _InitISpecsFromFullOpts(ipolicy_out, minmax_ispecs, std_ispecs,
3916 3945
                            group_ipolicy, allowed_values):
3917
  if minmax_ispecs is not None:
3946
  found_allowed = _GetISpecsInAllowedValues(minmax_ispecs, allowed_values)
3947
  if found_allowed is not None:
3948
    ipolicy_out[constants.ISPECS_MINMAX] = found_allowed
3949
  elif minmax_ispecs is not None:
3918 3950
    minmax_out = {}
3919 3951
    for (key, spec) in minmax_ispecs.items():
3920 3952
      if key not in constants.ISPECS_MINMAX_KEYS:
3921 3953
        msg = "Invalid key in bounds instance specifications: %s" % key
3922 3954
        raise errors.OpPrereqError(msg, errors.ECODE_INVAL)
3923
      minmax_out[key] = _ParseISpec(spec, key, allowed_values)
3955
      minmax_out[key] = _ParseISpec(spec, key, True)
3924 3956
    ipolicy_out[constants.ISPECS_MINMAX] = minmax_out
3925 3957
  if std_ispecs is not None:
3926 3958
    assert not group_ipolicy # This is not an option for gnt-group
3927
    ipolicy_out[constants.ISPECS_STD] = _ParseISpec(std_ispecs, "std",
3928
                                                    allowed_values)
3959
    ipolicy_out[constants.ISPECS_STD] = _ParseISpec(std_ispecs, "std", False)
3929 3960

  
3930 3961

  
3931 3962
def CreateIPolicyFromOpts(ispecs_mem_size=None,
......
3946 3977
  @param fill_all: whether for cluster policies we should ensure that
3947 3978
    all values are filled
3948 3979

  
3949

  
3950 3980
  """
3951
  if ((ispecs_mem_size or ispecs_cpu_count or ispecs_disk_count or
3952
       ispecs_disk_size or ispecs_nic_count) and
3953
      (minmax_ispecs is not None or std_ispecs is not None)):
3981
  assert not (fill_all and allowed_values)
3982

  
3983
  split_specs = (ispecs_mem_size or ispecs_cpu_count or ispecs_disk_count or
3984
                 ispecs_disk_size or ispecs_nic_count)
3985
  if (split_specs and (minmax_ispecs is not None or std_ispecs is not None)):
3954 3986
    raise errors.OpPrereqError("A --specs-xxx option cannot be specified"
3955 3987
                               " together with any --ipolicy-xxx-specs option",
3956 3988
                               errors.ECODE_INVAL)
3957 3989

  
3958 3990
  ipolicy_out = objects.MakeEmptyIPolicy()
3959
  if minmax_ispecs is None and std_ispecs is None:
3991
  if split_specs:
3992
    assert fill_all
3960 3993
    _InitISpecsFromSplitOpts(ipolicy_out, ispecs_mem_size, ispecs_cpu_count,
3961 3994
                             ispecs_disk_count, ispecs_disk_size,
3962
                             ispecs_nic_count, group_ipolicy, allowed_values)
3963
  else:
3995
                             ispecs_nic_count, group_ipolicy, fill_all)
3996
  elif (minmax_ispecs is not None or std_ispecs is not None):
3964 3997
    _InitISpecsFromFullOpts(ipolicy_out, minmax_ispecs, std_ispecs,
3965 3998
                            group_ipolicy, allowed_values)
3966 3999

  
b/lib/client/gnt_cluster.py
967 967
          opts.hv_state or
968 968
          opts.enabled_disk_templates or
969 969
          opts.disk_state or
970
          opts.ispecs_mem_size or
971
          opts.ispecs_cpu_count or
972
          opts.ispecs_disk_count or
973
          opts.ispecs_disk_size or
974
          opts.ispecs_nic_count or
975 970
          opts.ipolicy_bounds_specs is not None or
976 971
          opts.ipolicy_std_specs is not None or
977 972
          opts.ipolicy_disk_templates is not None or
......
1025 1020
    utils.ForceDictType(ndparams, constants.NDS_PARAMETER_TYPES)
1026 1021

  
1027 1022
  ipolicy = CreateIPolicyFromOpts(
1028
    ispecs_mem_size=opts.ispecs_mem_size,
1029
    ispecs_cpu_count=opts.ispecs_cpu_count,
1030
    ispecs_disk_count=opts.ispecs_disk_count,
1031
    ispecs_disk_size=opts.ispecs_disk_size,
1032
    ispecs_nic_count=opts.ispecs_nic_count,
1033 1023
    minmax_ispecs=opts.ipolicy_bounds_specs,
1034 1024
    std_ispecs=opts.ipolicy_std_specs,
1035 1025
    ipolicy_disk_templates=opts.ipolicy_disk_templates,
......
1523 1513
     DEFAULT_IALLOCATOR_OPT, PRIMARY_IP_VERSION_OPT, PREALLOC_WIPE_DISKS_OPT,
1524 1514
     NODE_PARAMS_OPT, GLOBAL_SHARED_FILEDIR_OPT, USE_EXTERNAL_MIP_SCRIPT,
1525 1515
     DISK_PARAMS_OPT, HV_STATE_OPT, DISK_STATE_OPT, ENABLED_DISK_TEMPLATES_OPT,
1526
     IPOLICY_STD_SPECS_OPT] + INSTANCE_POLICY_OPTS,
1516
     IPOLICY_STD_SPECS_OPT] + INSTANCE_POLICY_OPTS + SPLIT_ISPECS_OPTS,
1527 1517
    "[opts...] <cluster_name>", "Initialises a new cluster configuration"),
1528 1518
  "destroy": (
1529 1519
    DestroyCluster, ARGS_NONE, [YES_DOIT_OPT],
b/lib/client/gnt_group.py
50 50

  
51 51
  """
52 52
  ipolicy = CreateIPolicyFromOpts(
53
    ispecs_mem_size=opts.ispecs_mem_size,
54
    ispecs_cpu_count=opts.ispecs_cpu_count,
55
    ispecs_disk_count=opts.ispecs_disk_count,
56
    ispecs_disk_size=opts.ispecs_disk_size,
57
    ispecs_nic_count=opts.ispecs_nic_count,
58 53
    minmax_ispecs=opts.ipolicy_bounds_specs,
59 54
    ipolicy_vcpu_ratio=opts.ipolicy_vcpu_ratio,
60 55
    ipolicy_spindle_ratio=opts.ipolicy_spindle_ratio,
......
162 157

  
163 158
  """
164 159
  allmods = [opts.ndparams, opts.alloc_policy, opts.diskparams, opts.hv_state,
165
             opts.disk_state, opts.ispecs_mem_size, opts.ispecs_cpu_count,
166
             opts.ispecs_disk_count, opts.ispecs_disk_size,
167
             opts.ispecs_nic_count, opts.ipolicy_bounds_specs,
160
             opts.disk_state, opts.ipolicy_bounds_specs,
168 161
             opts.ipolicy_vcpu_ratio, opts.ipolicy_spindle_ratio,
169 162
             opts.diskparams]
170 163
  if allmods.count(None) == len(allmods):
......
180 173

  
181 174
  diskparams = dict(opts.diskparams)
182 175

  
183
  # set the default values
184
  to_ipolicy = [
185
    opts.ispecs_mem_size,
186
    opts.ispecs_cpu_count,
187
    opts.ispecs_disk_count,
188
    opts.ispecs_disk_size,
189
    opts.ispecs_nic_count,
190
    ]
191
  for ispec in to_ipolicy:
192
    for param in ispec:
193
      if isinstance(ispec[param], basestring):
194
        if ispec[param].lower() == "default":
195
          ispec[param] = constants.VALUE_DEFAULT
196 176
  # create ipolicy object
197 177
  ipolicy = CreateIPolicyFromOpts(
198
    ispecs_mem_size=opts.ispecs_mem_size,
199
    ispecs_cpu_count=opts.ispecs_cpu_count,
200
    ispecs_disk_count=opts.ispecs_disk_count,
201
    ispecs_disk_size=opts.ispecs_disk_size,
202
    ispecs_nic_count=opts.ispecs_nic_count,
203 178
    minmax_ispecs=opts.ipolicy_bounds_specs,
204 179
    ipolicy_disk_templates=opts.ipolicy_disk_templates,
205 180
    ipolicy_vcpu_ratio=opts.ipolicy_vcpu_ratio,
b/man/gnt-cluster.rst
536 536
- ``--ipolicy-spindle-ratio`` limits the instances-spindles ratio
537 537
- ``--ipolicy-vcpu-ratio`` limits the vcpu-cpu ratio
538 538

  
539
All the instance policy elements can be overridden at group level. Group
540
level overrides can be removed by specifying ``default`` as the value of
541
an item.
542

  
539 543
For details about how to use ``--hypervisor-state`` and ``--disk-state``
540 544
have a look at **ganeti**\(7).
541 545

  
......
607 611
| [\--use-external-mip-script {yes \| no}]
608 612
| [\--hypervisor-state *hvstate*]
609 613
| [\--disk-state *diskstate*]
610
| [\--specs-cpu-count *spec-param*=*value* [,*spec-param*=*value*...]]
611
| [\--specs-disk-count *spec-param*=*value* [,*spec-param*=*value*...]]
612
| [\--specs-disk-size *spec-param*=*value* [,*spec-param*=*value*...]]
613
| [\--specs-mem-size *spec-param*=*value* [,*spec-param*=*value*...]]
614
| [\--specs-nic-count *spec-param*=*value* [,*spec-param*=*value*...]]
615 614
| [\--ipolicy-std-specs *spec*=*value* [,*spec*=*value*...]]
616 615
| [\--ipolicy-bounds-specs *bounds_ispecs*]
617 616
| [\--ipolicy-disk-templates *template* [,*template*...]]
......
654 653
command. To clear the default iallocator, just pass an empty string
655 654
('').
656 655

  
657
The ``--specs-...`` and ``--ipolicy-...`` options are described in the
658
**init** command.
656
The ``--ipolicy-...`` options are described in the **init** command.
659 657

  
660 658
See **ganeti**\(7) for a description of ``--submit`` and other common
661 659
options.
b/man/gnt-group.rst
27 27
| [\--node-parameters=*NDPARAMS*]
28 28
| [\--alloc-policy=*POLICY*]
29 29
| [{-D|\--disk-parameters} *disk-template*:*disk-param*=*value*[,*disk-param*=*value*...]]
30
| [\--specs-cpu-count *spec-param*=*value* [,*spec-param*=*value*...]]
31
| [\--specs-disk-count *spec-param*=*value* [,*spec-param*=*value*...]]
32
| [\--specs-disk-size *spec-param*=*value* [,*spec-param*=*value*...]]
33
| [\--specs-mem-size *spec-param*=*value* [,*spec-param*=*value*...]]
34
| [\--specs-nic-count *spec-param*=*value* [,*spec-param*=*value*...]]
35 30
| [\--ipolicy-bounds-specs *bound_ispecs*]
36 31
| [\--ipolicy-disk-templates *template* [,*template*...]]
37 32
| [\--ipolicy-spindle-ratio *ratio*]
......
70 65
**gnt-cluster add** in **gnt-cluster**\(8) for more information about
71 66
disk parameters
72 67

  
73
The ``--specs-...`` and ``--ipolicy-...`` options specify instance
74
policies on the node group, and are documented in the
75
**gnt-cluster**\(8) man page.
68
The ``--ipolicy-...`` options specify instance policies on the node
69
group, and are documented in the **gnt-cluster**\(8) man page.
76 70

  
77 71
See **ganeti**\(7) for a description of ``--submit`` and other common
78 72
options.
......
105 99
| [\--hypervisor-state *hvstate*]
106 100
| [{-D|\--disk-parameters} *disk-template*:*disk-param*=*value*[,*disk-param*=*value*...]]
107 101
| [\--disk-state *diskstate*]
108
| [\--specs-cpu-count *spec-param*=*value* [,*spec-param*=*value*...]]
109
| [\--specs-disk-count *spec-param*=*value* [,*spec-param*=*value*...]]
110
| [\--specs-disk-size *spec-param*=*value* [,*spec-param*=*value*...]]
111
| [\--specs-mem-size *spec-param*=*value* [,*spec-param*=*value*...]]
112
| [\--specs-nic-count *spec-param*=*value* [,*spec-param*=*value*...]]
113 102
| [\--ipolicy-bounds-specs *bound_ispecs*]
114 103
| [\--ipolicy-disk-templates *template* [,*template*...]]
115 104
| [\--ipolicy-spindle-ratio *ratio*]
......
126 115
(--disk-parameters)`` options are documented in the **add** command
127 116
above.
128 117

  
129
The ``--specs-...`` and ``--ipolicy-...`` options specify instance
130
policies on the node group, and are documented in the
131
**gnt-cluster**\(8) man page.
118
The ``--ipolicy-...`` options specify instance policies on the node
119
group, and are documented in the **gnt-cluster**\(8) man page.
132 120

  
133 121
See **ganeti**\(7) for a description of ``--submit`` and other common
134 122
options.
b/test/py/ganeti.cli_unittest.py
21 21

  
22 22
"""Script for unittesting the cli module"""
23 23

  
24
import unittest
24
import copy
25
import testutils
25 26
import time
27
import unittest
26 28
from cStringIO import StringIO
27 29

  
28
import ganeti
29
import testutils
30

  
31 30
from ganeti import constants
32 31
from ganeti import cli
33 32
from ganeti import errors
......
1181 1180

  
1182 1181
class TestCreateIPolicyFromOpts(unittest.TestCase):
1183 1182
  """Test case for cli.CreateIPolicyFromOpts."""
1183
  def setUp(self):
1184
    # Policies are big, and we want to see the difference in case of an error
1185
    self.maxDiff = None
1186

  
1184 1187
  def _RecursiveCheckMergedDicts(self, default_pol, diff_pol, merged_pol):
1185 1188
    self.assertTrue(type(default_pol) is dict)
1186 1189
    self.assertTrue(type(diff_pol) is dict)
......
1197 1200
        self.assertEqual(val, default_pol[key])
1198 1201

  
1199 1202
  def testClusterPolicy(self):
1200
    exp_pol0 = {
1201
      constants.ISPECS_MINMAX: {
1202
        constants.ISPECS_MIN: {},
1203
        constants.ISPECS_MAX: {},
1204
        },
1205
      constants.ISPECS_STD: {},
1206
      }
1203
    pol0 = cli.CreateIPolicyFromOpts(
1204
      ispecs_mem_size={},
1205
      ispecs_cpu_count={},
1206
      ispecs_disk_count={},
1207
      ispecs_disk_size={},
1208
      ispecs_nic_count={},
1209
      ipolicy_disk_templates=None,
1210
      ipolicy_vcpu_ratio=None,
1211
      ipolicy_spindle_ratio=None,
1212
      fill_all=True
1213
      )
1214
    self.assertEqual(pol0, constants.IPOLICY_DEFAULTS)
1215

  
1207 1216
    exp_pol1 = {
1208 1217
      constants.ISPECS_MINMAX: {
1209 1218
        constants.ISPECS_MIN: {
......
1221 1230
        },
1222 1231
      constants.IPOLICY_VCPU_RATIO: 3.1,
1223 1232
      }
1233
    pol1 = cli.CreateIPolicyFromOpts(
1234
      ispecs_mem_size={"max": "12g"},
1235
      ispecs_cpu_count={"min": 2, "std": 2},
1236
      ispecs_disk_count={"min": 1, "max": 2, "std": 2},
1237
      ispecs_disk_size={},
1238
      ispecs_nic_count={},
1239
      ipolicy_disk_templates=None,
1240
      ipolicy_vcpu_ratio=3.1,
1241
      ipolicy_spindle_ratio=None,
1242
      fill_all=True
1243
      )
1244
    self._RecursiveCheckMergedDicts(constants.IPOLICY_DEFAULTS,
1245
                                    exp_pol1, pol1)
1246

  
1224 1247
    exp_pol2 = {
1225 1248
      constants.ISPECS_MINMAX: {
1226 1249
        constants.ISPECS_MIN: {
......
1238 1261
      constants.IPOLICY_SPINDLE_RATIO: 1.3,
1239 1262
      constants.IPOLICY_DTS: ["templates"],
1240 1263
      }
1241
    for fillall in [False, True]:
1242
      pol0 = cli.CreateIPolicyFromOpts(
1243
        ispecs_mem_size={},
1244
        ispecs_cpu_count={},
1245
        ispecs_disk_count={},
1246
        ispecs_disk_size={},
1247
        ispecs_nic_count={},
1264
    pol2 = cli.CreateIPolicyFromOpts(
1265
      ispecs_mem_size={},
1266
      ispecs_cpu_count={"std": 2},
1267
      ispecs_disk_count={},
1268
      ispecs_disk_size={"min": "0.5g"},
1269
      ispecs_nic_count={"min": 2, "max": 3, "std": 3},
1270
      ipolicy_disk_templates=["templates"],
1271
      ipolicy_vcpu_ratio=None,
1272
      ipolicy_spindle_ratio=1.3,
1273
      fill_all=True
1274
      )
1275
    self._RecursiveCheckMergedDicts(constants.IPOLICY_DEFAULTS,
1276
                                      exp_pol2, pol2)
1277

  
1278
    for fill_all in [False, True]:
1279
      exp_pol3 = {
1280
        constants.ISPECS_STD: {
1281
          constants.ISPEC_CPU_COUNT: 2,
1282
          constants.ISPEC_NIC_COUNT: 3,
1283
          },
1284
        }
1285
      pol3 = cli.CreateIPolicyFromOpts(
1286
        std_ispecs={
1287
          constants.ISPEC_CPU_COUNT: "2",
1288
          constants.ISPEC_NIC_COUNT: "3",
1289
          },
1248 1290
        ipolicy_disk_templates=None,
1249 1291
        ipolicy_vcpu_ratio=None,
1250 1292
        ipolicy_spindle_ratio=None,
1251
        fill_all=fillall
1252
        )
1253
      if fillall:
1254
        self.assertEqual(pol0, constants.IPOLICY_DEFAULTS)
1255
      else:
1256
        self.assertEqual(pol0, exp_pol0)
1257
      pol1 = cli.CreateIPolicyFromOpts(
1258
        ispecs_mem_size={"max": "12g"},
1259
        ispecs_cpu_count={"min": 2, "std": 2},
1260
        ispecs_disk_count={"min": 1, "max": 2, "std": 2},
1261
        ispecs_disk_size={},
1262
        ispecs_nic_count={},
1263
        ipolicy_disk_templates=None,
1264
        ipolicy_vcpu_ratio=3.1,
1265
        ipolicy_spindle_ratio=None,
1266
        fill_all=fillall
1293
        fill_all=fill_all
1267 1294
        )
1268
      if fillall:
1295
      if fill_all:
1269 1296
        self._RecursiveCheckMergedDicts(constants.IPOLICY_DEFAULTS,
1270
                                        exp_pol1, pol1)
1297
                                        exp_pol3, pol3)
1271 1298
      else:
1272
        self.assertEqual(pol1, exp_pol1)
1273
      pol2 = cli.CreateIPolicyFromOpts(
1274
        ispecs_mem_size={},
1275
        ispecs_cpu_count={"std": 2},
1276
        ispecs_disk_count={},
1277
        ispecs_disk_size={"min": "0.5g"},
1278
        ispecs_nic_count={"min": 2, "max": 3, "std": 3},
1279
        ipolicy_disk_templates=["templates"],
1280
        ipolicy_vcpu_ratio=None,
1281
        ipolicy_spindle_ratio=1.3,
1282
        fill_all=fillall
1283
        )
1284
      if fillall:
1285
        self._RecursiveCheckMergedDicts(constants.IPOLICY_DEFAULTS,
1286
                                        exp_pol2, pol2)
1299
        self.assertEqual(pol3, exp_pol3)
1300

  
1301
  def testPartialPolicy(self):
1302
    exp_pol0 = objects.MakeEmptyIPolicy()
1303
    pol0 = cli.CreateIPolicyFromOpts(
1304
      minmax_ispecs=None,
1305
      std_ispecs=None,
1306
      ipolicy_disk_templates=None,
1307
      ipolicy_vcpu_ratio=None,
1308
      ipolicy_spindle_ratio=None,
1309
      fill_all=False
1310
      )
1311
    self.assertEqual(pol0, exp_pol0)
1312

  
1313
    exp_pol1 = {
1314
      constants.IPOLICY_VCPU_RATIO: 3.1,
1315
      }
1316
    pol1 = cli.CreateIPolicyFromOpts(
1317
      minmax_ispecs=None,
1318
      std_ispecs=None,
1319
      ipolicy_disk_templates=None,
1320
      ipolicy_vcpu_ratio=3.1,
1321
      ipolicy_spindle_ratio=None,
1322
      fill_all=False
1323
      )
1324
    self.assertEqual(pol1, exp_pol1)
1325

  
1326
    exp_pol2 = {
1327
      constants.IPOLICY_SPINDLE_RATIO: 1.3,
1328
      constants.IPOLICY_DTS: ["templates"],
1329
      }
1330
    pol2 = cli.CreateIPolicyFromOpts(
1331
      minmax_ispecs=None,
1332
      std_ispecs=None,
1333
      ipolicy_disk_templates=["templates"],
1334
      ipolicy_vcpu_ratio=None,
1335
      ipolicy_spindle_ratio=1.3,
1336
      fill_all=False
1337
      )
1338
    self.assertEqual(pol2, exp_pol2)
1339

  
1340
  def _TestInvalidISpecs(self, minmax_ispecs, std_ispecs, fail=True):
1341
    for fill_all in [False, True]:
1342
      if fail:
1343
        self.assertRaises((errors.OpPrereqError,
1344
                           errors.UnitParseError,
1345
                           errors.TypeEnforcementError),
1346
                          cli.CreateIPolicyFromOpts,
1347
                          minmax_ispecs=minmax_ispecs,
1348
                          std_ispecs=std_ispecs,
1349
                          fill_all=fill_all)
1287 1350
      else:
1288
        self.assertEqual(pol2, exp_pol2)
1351
        cli.CreateIPolicyFromOpts(minmax_ispecs=minmax_ispecs,
1352
                                  std_ispecs=std_ispecs,
1353
                                  fill_all=fill_all)
1289 1354

  
1290 1355
  def testInvalidPolicies(self):
1291
    self.assertRaises(errors.TypeEnforcementError, cli.CreateIPolicyFromOpts,
1292
                      ispecs_mem_size={}, ispecs_cpu_count={},
1293
                      ispecs_disk_count={}, ispecs_disk_size={"std": 1},
1294
                      ispecs_nic_count={}, ipolicy_disk_templates=None,
1295
                      ipolicy_vcpu_ratio=None, ipolicy_spindle_ratio=None,
1296
                      group_ipolicy=True)
1356
    self.assertRaises(AssertionError, cli.CreateIPolicyFromOpts,
1357
                      std_ispecs={constants.ISPEC_MEM_SIZE: 1024},
1358
                      ipolicy_disk_templates=None, ipolicy_vcpu_ratio=None,
1359
                      ipolicy_spindle_ratio=None, group_ipolicy=True)
1297 1360
    self.assertRaises(errors.OpPrereqError, cli.CreateIPolicyFromOpts,
1298 1361
                      ispecs_mem_size={"wrong": "x"}, ispecs_cpu_count={},
1299 1362
                      ispecs_disk_count={}, ispecs_disk_size={},
1300 1363
                      ispecs_nic_count={}, ipolicy_disk_templates=None,
1301
                      ipolicy_vcpu_ratio=None, ipolicy_spindle_ratio=None)
1364
                      ipolicy_vcpu_ratio=None, ipolicy_spindle_ratio=None,
1365
                      fill_all=True)
1302 1366
    self.assertRaises(errors.TypeEnforcementError, cli.CreateIPolicyFromOpts,
1303 1367
                      ispecs_mem_size={}, ispecs_cpu_count={"min": "default"},
1304 1368
                      ispecs_disk_count={}, ispecs_disk_size={},
1305 1369
                      ispecs_nic_count={}, ipolicy_disk_templates=None,
1306
                      ipolicy_vcpu_ratio=None, ipolicy_spindle_ratio=None)
1370
                      ipolicy_vcpu_ratio=None, ipolicy_spindle_ratio=None,
1371
                      fill_all=True)
1372

  
1373
    good_mmspecs = constants.ISPECS_MINMAX_DEFAULTS
1374
    self._TestInvalidISpecs(good_mmspecs, None, fail=False)
1375
    broken_mmspecs = copy.deepcopy(good_mmspecs)
1376
    for key in constants.ISPECS_MINMAX_KEYS:
1377
      for par in constants.ISPECS_PARAMETERS:
1378
        old = broken_mmspecs[key][par]
1379
        del broken_mmspecs[key][par]
1380
        self._TestInvalidISpecs(broken_mmspecs, None)
1381
        broken_mmspecs[key][par] = "invalid"
1382
        self._TestInvalidISpecs(broken_mmspecs, None)
1383
        broken_mmspecs[key][par] = old
1384
      broken_mmspecs[key]["invalid_key"] = None
1385
      self._TestInvalidISpecs(broken_mmspecs, None)
1386
      del broken_mmspecs[key]["invalid_key"]
1387
    assert broken_mmspecs == good_mmspecs
1388

  
1389
    good_stdspecs = constants.IPOLICY_DEFAULTS[constants.ISPECS_STD]
1390
    self._TestInvalidISpecs(None, good_stdspecs, fail=False)
1391
    broken_stdspecs = copy.deepcopy(good_stdspecs)
1392
    for par in constants.ISPECS_PARAMETERS:
1393
      old = broken_stdspecs[par]
1394
      broken_stdspecs[par] = "invalid"
1395
      self._TestInvalidISpecs(None, broken_stdspecs)
1396
      broken_stdspecs[par] = old
1397
    broken_stdspecs["invalid_key"] = None
1398
    self._TestInvalidISpecs(None, broken_stdspecs)
1399
    del broken_stdspecs["invalid_key"]
1400
    assert broken_stdspecs == good_stdspecs
1307 1401

  
1308 1402
  def testAllowedValues(self):
1309 1403
    allowedv = "blah"
1310 1404
    exp_pol1 = {
1311
      constants.ISPECS_MINMAX: {
1312
        constants.ISPECS_MIN: {
1313
          constants.ISPEC_CPU_COUNT: allowedv,
1314
          },
1315
        constants.ISPECS_MAX: {
1316
          },
1317
        },
1318
      constants.ISPECS_STD: {
1319
        },
1405
      constants.ISPECS_MINMAX: allowedv,
1320 1406
      constants.IPOLICY_DTS: allowedv,
1321 1407
      constants.IPOLICY_VCPU_RATIO: allowedv,
1322 1408
      constants.IPOLICY_SPINDLE_RATIO: allowedv,
1323 1409
      }
1324
    pol1 = cli.CreateIPolicyFromOpts(ispecs_mem_size={},
1325
                                     ispecs_cpu_count={"min": allowedv},
1326
                                     ispecs_disk_count={},
1327
                                     ispecs_disk_size={},
1328
                                     ispecs_nic_count={},
1410
    pol1 = cli.CreateIPolicyFromOpts(minmax_ispecs={allowedv: {}},
1411
                                     std_ispecs=None,
1329 1412
                                     ipolicy_disk_templates=allowedv,
1330 1413
                                     ipolicy_vcpu_ratio=allowedv,
1331 1414
                                     ipolicy_spindle_ratio=allowedv,
......
1357 1440
      exp_ipol[constants.ISPECS_MINMAX] = exp_minmax
1358 1441
    else:
1359 1442
      minmax_ispecs = None
1360
      if constants.ISPECS_MINMAX not in exp_ipol:
1361
        empty_minmax = dict((k, {}) for k in constants.ISPECS_MINMAX_KEYS)
1362
        exp_ipol[constants.ISPECS_MINMAX] = empty_minmax
1363 1443
    if exp_std is not None:
1364 1444
      std_ispecs = self._ConvertSpecToStrings(exp_std)
1365 1445
      exp_ipol[constants.ISPECS_STD] = exp_std
1366 1446
    else:
1367 1447
      std_ispecs = None
1368
      if constants.ISPECS_STD not in exp_ipol:
1369
        exp_ipol[constants.ISPECS_STD] = {}
1370 1448

  
1371 1449
    self._CheckNewStyleSpecsCall(exp_ipol, minmax_ispecs, std_ispecs,
1372 1450
                                 group_ipolicy, fill_all)

Also available in: Unified diff