Revision ec996117 qa/qa_utils.py

b/qa/qa_utils.py
23 23

  
24 24
"""
25 25

  
26
import copy
26 27
import operator
27 28
import os
28 29
import random
......
779 780
    return path
780 781

  
781 782

  
782
def _GetParameterOptions(key, specs, old_specs):
783
def _GetParameterOptions(specs):
783 784
  """Helper to build policy options."""
784
  values = ["%s=%s" % (par, keyvals[key])
785
            for (par, keyvals) in specs.items()
786
            if key in keyvals]
787
  if old_specs:
788
    present_pars = frozenset(par
789
                             for (par, keyvals) in specs.items()
790
                             if key in keyvals)
791
    values.extend("%s=%s" % (par, keyvals[key])
792
                  for (par, keyvals) in old_specs.items()
793
                  if key in keyvals and par not in present_pars)
785
  values = ["%s=%s" % (par, val)
786
            for (par, val) in specs.items()]
794 787
  return ",".join(values)
795 788

  
796 789

  
797
def TestSetISpecs(new_specs, get_policy_fn=None, build_cmd_fn=None,
798
                  fail=False, old_values=None):
790
def TestSetISpecs(new_specs=None, diff_specs=None, get_policy_fn=None,
791
                  build_cmd_fn=None, fail=False, old_values=None):
799 792
  """Change instance specs for an object.
800 793

  
801
  @type new_specs: dict of dict
802
  @param new_specs: new_specs[par][key], where key is "min", "max", "std". It
803
      can be an empty dictionary.
794
  At most one of new_specs or diff_specs can be specified.
795

  
796
  @type new_specs: dict
797
  @param new_specs: new complete specs, in the same format returned by
798
      L{ParseIPolicy}.
799
  @type diff_specs: dict
800
  @param diff_specs: diff_specs[key][par], where key is "min", "max", "std". It
801
      can be an incomplete specifications or an empty dictionary.
804 802
  @type get_policy_fn: function
805 803
  @param get_policy_fn: function that returns the current policy as in
806
      L{qa_cluster._GetClusterIPolicy}
804
      L{ParseIPolicy}
807 805
  @type build_cmd_fn: function
808 806
  @param build_cmd_fn: function that return the full command line from the
809 807
      options alone
......
811 809
  @param fail: if the change is expected to fail
812 810
  @type old_values: tuple
813 811
  @param old_values: (old_policy, old_specs), as returned by
814
     L{qa_cluster._GetClusterIPolicy}
815
  @return: same as L{qa_cluster._GetClusterIPolicy}
812
     L{ParseIPolicy}
813
  @return: same as L{ParseIPolicy}
816 814

  
817 815
  """
818 816
  assert get_policy_fn is not None
819 817
  assert build_cmd_fn is not None
818
  assert new_specs is None or diff_specs is None
820 819

  
821 820
  if old_values:
822 821
    (old_policy, old_specs) = old_values
823 822
  else:
824 823
    (old_policy, old_specs) = get_policy_fn()
824

  
825
  if diff_specs:
826
    new_specs = copy.deepcopy(old_specs)
827
    for (key, parvals) in diff_specs.items():
828
      for (par, val) in parvals.items():
829
        new_specs[key][par] = val
830

  
825 831
  if new_specs:
826 832
    cmd = []
827
    if any(("min" in val or "max" in val) for val in new_specs.values()):
833
    if (diff_specs is None or
834
        ("min" in diff_specs or "max" in diff_specs)):
828 835
      minmax_opt_items = []
829 836
      for key in ["min", "max"]:
830
        keyopt = _GetParameterOptions(key, new_specs, old_specs)
837
        keyopt = _GetParameterOptions(new_specs[key])
831 838
        minmax_opt_items.append("%s:%s" % (key, keyopt))
832 839
      cmd.extend([
833 840
        "--ipolicy-bounds-specs",
834 841
        "/".join(minmax_opt_items)
835 842
        ])
836
    std_opt = _GetParameterOptions("std", new_specs, {})
843
    if diff_specs:
844
      std_source = diff_specs
845
    else:
846
      std_source = new_specs
847
    std_opt = _GetParameterOptions(std_source.get("std", {}))
837 848
    if std_opt:
838 849
      cmd.extend(["--ipolicy-std-specs", std_opt])
839 850
    AssertCommand(build_cmd_fn(cmd), fail=fail)
840 851

  
841
  # Check the new state
842
  (eff_policy, eff_specs) = get_policy_fn()
843
  AssertEqual(eff_policy, old_policy)
844
  if fail:
845
    AssertEqual(eff_specs, old_specs)
852
    # Check the new state
853
    (eff_policy, eff_specs) = get_policy_fn()
854
    AssertEqual(eff_policy, old_policy)
855
    if fail:
856
      AssertEqual(eff_specs, old_specs)
857
    else:
858
      AssertEqual(eff_specs, new_specs)
859

  
846 860
  else:
847
    for par in eff_specs:
848
      for key in eff_specs[par]:
849
        if par in new_specs and key in new_specs[par]:
850
          AssertEqual(int(eff_specs[par][key]), int(new_specs[par][key]))
851
        else:
852
          AssertEqual(int(eff_specs[par][key]), int(old_specs[par][key]))
861
    (eff_policy, eff_specs) = (old_policy, old_specs)
862

  
853 863
  return (eff_policy, eff_specs)
854 864

  
855 865

  
......
861 871
  @rtype: tuple
862 872
  @return: (policy, specs), where:
863 873
      - policy is a dictionary of the policy values, instance specs excluded
864
      - specs is dict of dict, specs[par][key] is a spec value, where key is
874
      - specs is dict of dict, specs[key][par] is a spec value, where key is
865 875
        "min", "max", or "std"
866 876

  
867 877
  """
......
870 880
  ispec_keys = constants.ISPECS_MINMAX_KEYS | frozenset([constants.ISPECS_STD])
871 881
  for (key, val) in policy.items():
872 882
    if key in ispec_keys:
873
      for (par, pval) in val.items():
874
        d = ret_specs.setdefault(par, {})
875
        d[key] = pval
883
      ret_specs[key] = val
876 884
    else:
877 885
      ret_policy[key] = val
878 886
  return (ret_policy, ret_specs)

Also available in: Unified diff