Esempio n. 1
0
    def test_load_errors(self):
        bad_file = os.path.join(self.tmpdir, 'bad_file.json')
        with self.assertRaises(IOError):
            CompositeRingBuilder.load(bad_file)

        def check_bad_content(content):
            with open(bad_file, 'wb') as fp:
                fp.write(content)
            try:
                with self.assertRaises(ValueError) as cm:
                    CompositeRingBuilder.load(bad_file)
                self.assertIn(
                    "File does not contain valid composite ring data",
                    cm.exception.message)
            except AssertionError as err:
                raise AssertionError('With content %r: %s' % (content, err))

        for content in ('', 'not json', json.dumps({}), json.dumps([])):
            check_bad_content(content)

        good_content = {
            'components': [
                {'version': 1, 'id': 'uuid_x', 'replicas': 12},
                {'version': 2, 'id': 'uuid_y', 'replicas': 12}
            ],
            'builder_files': {'uuid_x': '/path/to/file_x',
                              'uuid_y': '/path/to/file_y'},
            'version': 99}
        for missing in good_content:
            bad_content = dict(good_content)
            bad_content.pop(missing)
            check_bad_content(json.dumps(bad_content))
Esempio n. 2
0
 def check_bad_content(content):
     with open(bad_file, 'wb') as fp:
         fp.write(content)
     try:
         with self.assertRaises(ValueError) as cm:
             CompositeRingBuilder.load(bad_file)
         self.assertIn(
             "File does not contain valid composite ring data",
             cm.exception.message)
     except AssertionError as err:
         raise AssertionError('With content %r: %s' % (content, err))
Esempio n. 3
0
 def test_compose_override_component_builders(self):
     # check passing different builder files to the compose() method
     # overrides loaded builder files
     cb_file = os.path.join(self.tmpdir, 'test-composite-ring.json')
     builders = self.create_sample_ringbuilders(2)
     cb, builder_files = self._make_composite_builder(builders)
     # modify builders and save in different files
     self.add_dev_and_rebalance(builders[1])
     with self.assertRaises(ValueError):
         cb.compose(builder_files)  # sanity check - originals are unchanged
     other_files = self.save_builders(builders, prefix='other')
     cb.compose(other_files).save(self.output_ring)
     self.check_composite_ring(self.output_ring, builders)
     # check composite builder persists ok
     cb.save(cb_file)
     self.assertTrue(os.path.exists(cb_file))
     self.check_composite_meta(cb_file, other_files, version=2)
     # and reloads ok
     cb = CompositeRingBuilder.load(cb_file)
     # and composes ok after reload
     cb.compose(force=True).save(self.output_ring)
     self.check_composite_ring(self.output_ring, builders)
     # check composite builder persists ok again
     cb_file = os.path.join(self.tmpdir, 'test-composite-ring.json2')
     cb.save(cb_file)
     self.assertTrue(os.path.exists(cb_file))
     self.check_composite_meta(cb_file, other_files, version=3)
Esempio n. 4
0
 def test_compose_modified_component_builders(self):
     # check it's ok to compose again with same but modified builders
     cb_file = os.path.join(self.tmpdir, 'test-composite-ring.json')
     builders = self.create_sample_ringbuilders(2)
     cb, builder_files = self._make_composite_builder(builders)
     ring = Ring(self.output_ring)
     orig_devs = [dev for dev in ring.devs if dev]
     self.assertEqual(10, len(orig_devs))  # sanity check
     self.add_dev_and_rebalance(builders[1])
     builder_files = self.save_builders(builders)
     cb.compose().save(self.output_ring)
     self.check_composite_ring(self.output_ring, builders)
     ring = Ring(self.output_ring)
     modified_devs = [dev for dev in ring.devs if dev]
     self.assertEqual(len(orig_devs) + 1, len(modified_devs))
     # check composite builder persists ok
     cb.save(cb_file)
     self.assertTrue(os.path.exists(cb_file))
     self.check_composite_meta(cb_file, builder_files, version=2)
     # and reloads ok
     cb = CompositeRingBuilder.load(cb_file)
     # and composes ok after reload
     cb.compose(force=True).save(self.output_ring)
     self.check_composite_ring(self.output_ring, builders)
     # check composite builder persists ok again
     cb_file = os.path.join(self.tmpdir, 'test-composite-ring.json2')
     cb.save(cb_file)
     self.assertTrue(os.path.exists(cb_file))
     self.check_composite_meta(cb_file, builder_files, version=3)
Esempio n. 5
0
 def test_compose_ok(self):
     cb_file = os.path.join(self.tmpdir, 'test-composite-ring.json')
     builders = self.create_sample_ringbuilders(2)
     # make first version of composite ring
     cb, builder_files = self._make_composite_builder(builders)
     # check composite builder persists ok
     cb.save(cb_file)
     self.assertTrue(os.path.exists(cb_file))
     self.check_composite_meta(cb_file, builder_files)
     # and reloads ok
     cb = CompositeRingBuilder.load(cb_file)
     self.assertEqual(1, cb.version)
     # composes after with no component builder changes will fail...
     with self.assertRaises(ValueError) as cm:
         cb.compose()
     self.assertIn('None of the component builders has been modified',
                   cm.exception.message)
     self.assertEqual(1, cb.version)
     # ...unless we force it
     cb.compose(force=True).save(self.output_ring)
     self.check_composite_ring(self.output_ring, builders)
     self.assertEqual(2, cb.version)
     # check composite builder persists ok again
     cb_file = os.path.join(self.tmpdir, 'test-composite-ring.json2')
     cb.save(cb_file)
     self.assertTrue(os.path.exists(cb_file))
     self.check_composite_meta(cb_file, builder_files, version=2)
Esempio n. 6
0
    def test_compose_with_builder_files(self):
        cb_file = os.path.join(self.tmpdir, 'test-composite-ring.json')
        builders = self.create_sample_ringbuilders(2)
        cb, _ = self._make_composite_builder(builders)
        cb.save(cb_file)

        for i, b in enumerate(builders):
            self.add_dev_and_rebalance(b)
        self.save_builders(builders)
        cb = CompositeRingBuilder.load(cb_file)
        cb.compose().save(self.output_ring)
        self.check_composite_ring(self.output_ring, builders)
Esempio n. 7
0
def main(arguments=None):
    if arguments is not None:
        argv = arguments
    else:
        argv = sys.argv

    parser = argparse.ArgumentParser(description=DESCRIPTION)
    parser.add_argument(
        'composite_builder_file',
        metavar='composite_builder_file', type=str,
        help='Name of composite builder file')

    subparsers = parser.add_subparsers(
        help='subcommand help', title='subcommands')

    # show
    show_parser = subparsers.add_parser(
        'show', help='show composite ring builder metadata')
    show_parser.set_defaults(func=show)

    # compose
    compose_parser = subparsers.add_parser(
        'compose', help='compose composite ring',
        usage='%(prog)s [-h] '
              '[builder_file builder_file [builder_file ...] '
              '--output ring_file [--force]')
    bf_help = ('Paths to component ring builder files to include in composite '
               'ring')
    compose_parser.add_argument('builder_files', metavar='builder_file',
                                nargs='*', type=str, help=bf_help)
    compose_parser.add_argument('--output', metavar='output_file', type=str,
                                required=True, help='Name of output ring file')
    compose_parser.add_argument(
        '--force', action='store_true',
        help='Force new composite ring file to be written')
    compose_parser.set_defaults(func=compose)

    _print_to_stderr(WARNING)
    args = parser.parse_args(argv[1:])
    composite_builder = None
    if args.func != compose or os.path.exists(args.composite_builder_file):
        try:
            composite_builder = CompositeRingBuilder.load(
                args.composite_builder_file)
        except Exception as err:
            _print_err(
                'An error occurred while loading the composite builder file.',
                err)
            exit(EXIT_ERROR)

    exit(args.func(composite_builder, args))