Example #1
0
    def test_compare_bucket_indep(self):
        origin = self.define_crushmap_10()

        # indep, mapping order does not matter
        c = Main().constructor([
            'compare',
            '--rule', 'indep',
            '--replication-count', '2',
            '--order-matters',
        ])

        c.set_origin_crushmap(origin)

        #
        # Swapping weights within a bucket, values stay
        # in the bucket but move between children
        #
        destination = copy.deepcopy(origin)
        host0 = destination['trees'][0]['children'][0]
        w0 = host0['children'][0]['weight']
        w1 = host0['children'][1]['weight']
        host0['children'][0]['weight'] = w1
        host0['children'][1]['weight'] = w0
        c.set_destination_crushmap(destination)

        c.args.values_count = 100
        (from_to, in_out) = c.compare_bucket(host0)
        assert from_to == {
            'device01': {'device00': 5}
        }
        assert in_out == {}

        #
        # Increasing the weight of the items it contains changes the
        # weight of the bucket and items move in/out of the bucket.
        #
        destination = copy.deepcopy(origin)
        host0 = destination['trees'][0]['children'][0]
        host0['children'][0]['weight'] *= 10
        c.set_destination_crushmap(destination)

        c.args.values_count = 30
        (from_to, in_out) = c.compare_bucket(host0)
        print("from_to " + str(from_to))
        print("in_out " + str(in_out))
        assert from_to == {
            'device01': {'device00': 1}
        }
        assert in_out == {
            'device01': {'device05': 1},
            'device04': {'device00': 1},
            'device05': {'device00': 2},
            'device09': {'device01': 1},
            'device13': {'device00': 1},
            'device17': {'device00': 1},
            'device19': {'device00': 1},
            'device00': {'device19': 1},
        }
Example #2
0
 def test_destination_weights(self):
     a = Main().constructor([
         "compare", "--rule", "replicated_ruleset",
         "--replication-count", "1",
         "--origin", "tests/weights-crushmap.json",
         "--destination", "tests/weights-crushmap.json",
         "--destination-weights", "tests/weights.json"])
     a.args.backward_compatibility = True
     a.run_compare()
Example #3
0
 def test_analyze_weights(self):
     a = Main().constructor([
         "analyze", "--rule", "replicated_ruleset", "--replication-count",
         "2", "--type", "device", "--crushmap", "tests/ceph/dump.json",
         "--weights", "tests/ceph/weights.json"
     ])
     a.args.backward_compatibility = True
     res = a.run()
     assert "-100.00" in str(res)  # One of the OSDs has a weight of 0.0
Example #4
0
    def verify_optimize(self, weights, expected_delta, values_count,
                        replication_count):
        crushmap = self.make_bucket(weights)
        rule = 'firstn'
        p = [
            '--values-count',
            str(values_count),
            '--replication-count',
            str(replication_count),
            '--rule',
            rule,
            '--choose-args',
            'optimize',
        ]
        o = Main().constructor(['--verbose', 'optimize'] + p)
        origin_crushmap = copy.deepcopy(crushmap)
        bucket = crushmap['trees'][0]
        previous_weight_set = []
        for position in range(replication_count):
            o.optimize_replica(p, origin_crushmap, crushmap, bucket,
                               replication_count, position)
            assert 1 == len(crushmap['choose_args']['optimize'])
            weight_set = copy.deepcopy(
                crushmap['choose_args']['optimize'][0]['weight_set'])
            assert weight_set[:len(previous_weight_set)] == previous_weight_set

        a = Main().constructor(['analyze', '--choose-args', 'optimize'] + p)
        r = a.analyze_crushmap(crushmap)
        delta = (r['~objects~'] - r['~expected~']).tolist()
        print("delta = " + str(delta))
        assert expected_delta == delta
Example #5
0
 def test_display(self):
     c1, c2 = self.define_crushmaps_1()
     c = Main().constructor([
         'compare',
         '--rule', 'indep',
         '--replication-count', '2',
         '--values-count', '10',
     ])
     c.set_origin(c1)
     c.set_destination(c2)
     c.compare()
     out = c.display()
     print(out)
     assert 'device04        0        0        1        1   10.00%' in out
     assert 'objects%   10.00%    5.00%    5.00%    5.00%   25.00%' in out
Example #6
0
 def test_compare_display(self):
     c = Main().constructor([
         'compare',
         '--rule', 'firstn',
         '--values-count', '1000',
     ])
     c1, c2 = self.define_crushmaps_2()
     c.set_origin(c2)
     c.set_destination(c1)
     c.args.replication_count = 1
     c.compare()
     out = c.display()
     print(out)
     assert "objects%   10.20%   12.70%   22.90%" in out
     c.args.replication_count = 3
     c.compare()
     out = c.display()
     print(out)
     assert ("objects%    0.17%    0.13%    0.97%    0.77%    0.77%"
             "    0.63%    0.73%    0.87%   12.30%   12.20%   29.53%") in out
Example #7
0
    def test_sanity_check_args(self):
        a = Main().constructor([
            'compare',
        ])
        with pytest.raises(Exception) as e:
            a.pre_sanity_check_args()
        assert 'missing --origin' in str(e.value)

        a = Main().constructor([
            'compare',
            '--origin', 'ORIGIN',
        ])
        with pytest.raises(Exception) as e:
            a.pre_sanity_check_args()
        assert 'missing --destination' in str(e.value)

        a = Main().constructor([
            'compare',
            '--origin', 'ORIGIN',
            '--destination', 'DESTINATION',
        ])
        a.pre_sanity_check_args()
        with pytest.raises(Exception) as e:
            a.post_sanity_check_args()
        assert 'missing --rule' in str(e.value)

        a = Main().constructor([
            'compare',
            '--origin', 'ORIGIN',
            '--destination', 'DESTINATION',
            '--rule', 'RULE',
            '--choose-args', 'CHOOSE ARGS',
        ])
        a.pre_sanity_check_args()
        a.post_sanity_check_args()
Example #8
0
    def test_compare(self):
        c1, c2 = self.define_crushmaps_1()

        # firstn, mapping order does not matter
        c = Main().constructor([
            'compare',
            '--rule', 'firstn',
            '--replication-count', '2',
            '--values-count', '10',
        ])

        # device05 is removed
        c.set_origin(c1)
        c.set_destination(c2)
        assert c.compare() == {
            'device04': {'device17': 1},
            'device05': {'device12': 1, 'device04': 2, 'device08': 1}
        }
        # device05 is added
        c.set_origin(c2)
        c.set_destination(c1)
        assert c.compare() == {
            'device12': {'device05': 1},
            'device17': {'device04': 1},
            'device04': {'device05': 2},
            'device08': {'device05': 1}
        }

        # indep, mapping order matters
        c = Main().constructor([
            'compare',
            '--rule', 'indep',
            '--replication-count', '2',
            '--values-count', '10',
            '--order-matters',
        ])
        # device05 is removed
        c.set_origin(c1)
        c.set_destination(c2)
        assert c.compare() == {
            'device04': {'device13': 1, 'device17': 1},
            'device05': {'device04': 2, 'device08': 1}
        }
        # device05 is added
        c.set_origin(c2)
        c.set_destination(c1)
        assert c.compare() == {
            'device13': {'device04': 1},
            'device17': {'device04': 1},
            'device04': {'device05': 2},
            'device08': {'device05': 1}
        }
Example #9
0
    def test_sanity_check_args(self):
        a = Main().constructor([
            'optimize',
        ])
        with pytest.raises(Exception) as e:
            a.pre_sanity_check_args()
        assert 'missing --crushmap' in str(e.value)

        a = Main().constructor([
            'optimize',
            '--crushmap',
            'CRUSHMAP',
        ])
        with pytest.raises(Exception) as e:
            a.pre_sanity_check_args()
        assert 'missing --out-path' in str(e.value)

        a = Main().constructor([
            'optimize',
            '--crushmap',
            'CRUSHMAP',
            '--out-path',
            'OUT PATH',
            '--no-forecast',
        ])
        with pytest.raises(Exception) as e:
            a.pre_sanity_check_args()
        assert 'only valid with --step' in str(e.value)

        a = Main().constructor([
            'optimize',
            '--crushmap',
            'CRUSHMAP',
            '--out-path',
            'OUT PATH',
        ])
        a.pre_sanity_check_args()
        with pytest.raises(Exception) as e:
            a.post_sanity_check_args()
        assert 'missing --rule' in str(e.value)

        a = Main().constructor([
            'optimize',
            '--crushmap',
            'CRUSHMAP',
            '--out-path',
            'OUT PATH',
            '--rule',
            'RULE',
        ])
        a.pre_sanity_check_args()
        with pytest.raises(Exception) as e:
            a.post_sanity_check_args()
        assert 'missing --choose-args' in str(e.value)

        a = Main().constructor([
            'optimize',
            '--crushmap',
            'CRUSHMAP',
            '--out-path',
            'OUT PATH',
            '--rule',
            'RULE',
            '--choose-args',
            'CHOOSE ARGS',
        ])
        a.pre_sanity_check_args()
        a.post_sanity_check_args()
Example #10
0
    def test_analyze(self):
        trees = [
            {
                "name": "dc1",
                "type": "root",
                "id": -1,
                'children': []
            },
        ]
        weights = (
            (10.0, 1.0, 5.0, 4.0),
            (10.0, 1.0, 5.0, 4.0),
            (10.0, 1.0, 5.0, 4.0),
            (10.0, 1.0, 5.0, 4.0),
            (1.0, 0.1, 0.5, 0.4),
        )
        trees[0]['children'].extend([{
            "type":
            "host",
            "id":
            -(i + 3),
            "name":
            "host%d" % i,
            "weight":
            weights[i][0],
            "children": [
                {
                    "id": (3 * i),
                    "name": "device%02d" % (3 * i),
                    "weight": weights[i][1]
                },
                {
                    "id": (3 * i + 1),
                    "name": "device%02d" % (3 * i + 1),
                    "weight": weights[i][2]
                },
                {
                    "id": (3 * i + 2),
                    "name": "device%02d" % (3 * i + 2),
                    "weight": weights[i][3]
                },
            ],
        } for i in range(5)])
        a = Main().constructor([
            'analyze',
            '--rule',
            'data',
            '--replication-count',
            '2',
            '--values-count',
            '10000',
        ])
        a.args.crushmap = {
            "trees": trees,
            "rules": {
                "data": [["take", "dc1"],
                         ["chooseleaf", "firstn", 0, "type", "host"], ["emit"]]
            }
        }
        d = a.analyze()
        expected = """\
        ~id~  ~weight~  ~objects~  ~over/under used %~
~name~                                                
host4     -7       1.0        541                10.91
host3     -6      10.0       4930                 1.07
host2     -5      10.0       4860                -0.37
host1     -4      10.0       4836                -0.86
host0     -3      10.0       4833                -0.92

Worst case scenario if a host fails:

        ~over used %~
~type~               
device          25.55
host            22.45
root             0.00\
""" # noqa trailing whitespaces are expected
        assert expected == str(d)