Ejemplo n.º 1
0
    def test_upgrade_None_to_last_phantom_share_path(self):
        """Upgrade from version 'None' (possibly a clean start) with a root
        with missing path.

        """
        old_root = os.path.join(self.root_dir, 'My Files')
        old_shares = os.path.join(self.root_dir, 'Shared With Me')
        self.main = FakeMain(self.root_dir, self.shares_dir,
                             self.data_dir, self.partials_dir)
        self.main.shutdown()
        self.rmtree(self.vm_data_dir)
        os.makedirs(self.vm_data_dir)
        self.set_md_version('')
        shares = LegacyShareFileShelf(self.share_md_dir)
        root_share = _Share(path=self.root_dir)
        root_share.access_level = ACCESS_LEVEL_RW
        # set None to the share path
        root_share.path = None
        shares[request.ROOT] = root_share

        if self.md_version_None:
            self.set_md_version('')
        # check that it's all OK
        self.main = FakeMain(self.root_dir, self.shares_dir,
                             self.data_dir, self.partials_dir)
        self.assertFalse(os.path.exists(old_root))
        self.assertTrue(os.path.exists(self.root_dir))
        self.assertTrue(os.path.exists(self.shares_dir))
        self.assertTrue(os.path.islink(old_shares))
        self.assertEqual(old_shares, self.main.shares_dir_link)
        self.check_version()
Ejemplo n.º 2
0
 def test_broken_symlink_latest_metadata(self):
     """Test vm startup with latest metadata and a broken symlink."""
     self._build_layout_version_4()
     os.unlink(self.shares_dir_link)
     # create a broken link
     os.symlink('foo', self.shares_dir_link)
     self.main = FakeMain(self.root_dir, self.shares_dir,
                          self.data_dir, self.partials_dir)
     self.check_version()
Ejemplo n.º 3
0
 def test_upgrade_None_to_last(self):
     """Upgrade from version 'None' (possibly a clean start)."""
     old_root = os.path.join(self.root_dir, 'My Files')
     old_shares = os.path.join(self.root_dir, 'Shared With Me')
     # start and check that everything is ok
     self.main = FakeMain(self.root_dir, self.shares_dir,
                          self.data_dir, self.partials_dir)
     self.assertFalse(os.path.exists(old_root))
     self.assertTrue(os.path.exists(self.root_dir))
     self.assertTrue(os.path.exists(old_shares))
     self.assertTrue(os.path.islink(old_shares))
     self.assertEqual(old_shares, self.main.shares_dir_link)
     self.check_version()
Ejemplo n.º 4
0
    def test_upgrade_4(self):
        """Test migration from 4 to 5 (broken symlink in the root)."""
        self._build_layout_version_4()
        self.set_md_version('4')
        # break the symlink
        if os.path.exists(self.shares_dir_link):
            os.unlink(self.shares_dir_link)
        os.symlink(self.shares_dir_link, self.shares_dir_link)

        if self.md_version_None:
            self.set_md_version('')
        self.main = FakeMain(self.root_dir, self.shares_dir,
                             self.data_dir, self.partials_dir)
        self.assertEqual(
            self.main.shares_dir, os.readlink(self.main.shares_dir_link))
        self.check_version()
Ejemplo n.º 5
0
    def test_upgrade_6(self):
        """Test the migration from version 6."""
        # build a fake version 5 state
        self._build_layout_version_4()
        self.set_md_version('6')
        self.udfs_md_dir = os.path.join(self.vm_data_dir, 'udfs')
        # create some old shares and shared metadata
        legacy_shares = VMFileShelf(self.share_md_dir)
        root = Root(path=self.root_dir)
        legacy_shares[request.ROOT] = root
        for idx, name in enumerate(['share'] * 10):
            sid = str(uuid.uuid4())
            share_name = name + '_' + str(idx)
            share = Share(
                path=os.path.join(self.shares_dir, share_name),
                volume_id=sid, name=share_name, node_id=str(uuid.uuid4()),
                other_username='******' + str(idx),
                other_visible_name='visible name ' + str(idx))
            if idx % 2:
                share.access_level = ACCESS_LEVEL_RW
            else:
                share.access_level = ACCESS_LEVEL_RO
            legacy_shares[sid] = share

        # create shared shares
        legacy_shared = VMFileShelf(self.shared_md_dir)
        for idx, name in enumerate(['dir'] * 5):
            sid = str(uuid.uuid4())
            share_name = name + '_' + str(idx)
            share = Shared(path=os.path.join(self.root_dir, share_name),
                           volume_id=sid, node_id=str(uuid.uuid4()),
                           name=share_name, other_username='******',
                           other_visible_name='hola')
            if idx % 2:
                share.access_level = ACCESS_LEVEL_RW
            else:
                share.access_level = ACCESS_LEVEL_RO
            legacy_shared[sid] = share

        # create some udfs
        legacy_udfs = VMFileShelf(self.udfs_md_dir)
        for idx, name in enumerate(['dir'] * 5):
            udf_id = str(uuid.uuid4())
            udf_name = name + '_' + str(idx)
            udf = UDF(
                udf_id, str(uuid.uuid4()), u'~/' + udf_name.decode('utf-8'),
                os.path.join(self.home_dir, udf_name))
            if idx % 2:
                udf.subscribed = True
            else:
                udf.subscribed = False
            legacy_udfs[sid] = udf

        # keep a copy of the current shares and shared metadata to check
        # the upgrade went ok
        legacy_shares = dict(legacy_shares.items())
        legacy_shared = dict(legacy_shared.items())
        legacy_udfs = dict(legacy_udfs.items())

        if self.md_version_None:
            self.set_md_version('')
        # upgrade it!
        self.main = FakeMain(self.root_dir, self.shares_dir,
                             self.data_dir, self.partials_dir)
        vm = self.main.vm

        for sid in vm.shares:
            old_share = legacy_shares[sid]
            share = vm.shares[sid]
            self.assertTrue(
                isinstance(share, Share) or isinstance(share, Root))
            self.assertEqual(share.__dict__, old_share.__dict__)

        for sid in vm.shared:
            old_share = legacy_shared[sid]
            share = vm.shared[sid]
            self.assertTrue(isinstance(share, Shared))
            self.assertEqual(share.__dict__, old_share.__dict__)

        for udf_id in vm.udfs:
            old_udf = legacy_udfs[udf_id]
            udf = vm.udfs[udf_id]
            self.assertTrue(isinstance(udf, UDF))
            self.assertEqual(udf.__dict__, old_udf.__dict__)
Ejemplo n.º 6
0
    def test_upgrade_5_partial_upgrade(self):
        """Test migration from version 5 with upgrade to 6 unfinished."""
        # build a fake version 5 state
        self._build_layout_version_4()
        self.set_md_version('5')
        self.udfs_md_dir = os.path.join(self.vm_data_dir, 'udfs')
        # create some old shares and shared metadata
        legacy_shares = LegacyShareFileShelf(self.share_md_dir)
        root_share = _Share(path=self.root_dir, share_id=request.ROOT,
                            access_level=ACCESS_LEVEL_RW, node_id=str(
                                uuid.uuid4()))
        legacy_shares[request.ROOT] = root_share
        for idx, name in enumerate(['share'] * 3):
            sid = str(uuid.uuid4())
            share_name = name + '_' + str(idx)
            share = _Share(path=os.path.join(self.shares_dir, share_name),
                           share_id=sid, name=share_name,
                           node_id=str(uuid.uuid4()),
                           other_username='******' + str(idx),
                           other_visible_name='visible name ' + str(idx))
            if idx == 0:
                share.access_level = ACCESS_LEVEL_RW
                legacy_shares[sid] = share
            elif idx == 1:
                share.access_level = ACCESS_LEVEL_RO
                legacy_shares[sid] = share
            else:
                # add a 'new' Share dict to the shelf
                share.access_level = ACCESS_LEVEL_RW
                share = Share(
                    path=share.path, volume_id=share.id, name=share.name,
                    access_level=share.access_level,
                    other_username=share.other_username,
                    other_visible_name=share.other_visible_name,
                    node_id=share.subtree)
                legacy_shares[sid] = share.__dict__

        # create shared shares
        legacy_shared = LegacyShareFileShelf(self.shared_md_dir)
        for idx, name in enumerate(['dir'] * 3):
            sid = str(uuid.uuid4())
            share_name = name + '_' + str(idx)
            share = _Share(path=os.path.join(self.root_dir, share_name),
                           share_id=sid, node_id=str(uuid.uuid4()),
                           name=share_name, other_username='******',
                           other_visible_name='hola')
            if idx == 0:
                share.access_level = ACCESS_LEVEL_RW
                legacy_shares[sid] = share
            elif idx == 1:
                share.access_level = ACCESS_LEVEL_RO
                legacy_shares[sid] = share
            else:
                # add a 'new' Shared dict to the shelf
                share.access_level = ACCESS_LEVEL_RW
                share = Shared(path=share.path,
                               volume_id=share.id, name=share.name,
                               access_level=share.access_level,
                               other_username=share.other_username,
                               other_visible_name=share.other_visible_name,
                               node_id=share.subtree)
                legacy_shares[sid] = share.__dict__

        # keep a copy of the current shares and shared metadata to check
        # the upgrade went ok
        legacy_shares = dict(legacy_shares.items())
        legacy_shared = dict(legacy_shared.items())

        if self.md_version_None:
            self.set_md_version('')
        # upgrade it!
        self.main = FakeMain(self.root_dir, self.shares_dir,
                             self.data_dir, self.partials_dir)
        vm = self.main.vm

        def compare_share(share, old_share):
            """Compare two shares, new and old"""
            old_id = getattr(old_share, 'id', None)
            if old_id is None:
                old_id = old_share['volume_id']
            self.assertEqual(share.volume_id, old_id)
            self.assertEqual(
                share.path,
                getattr(old_share, 'path', None) or old_share['path'])
            self.assertEqual(
                share.node_id,
                getattr(old_share, 'subtree', None) or old_share['node_id'])
            if not isinstance(share, Root):
                self.assertEqual(
                    share.name,
                    getattr(old_share, 'name', None) or old_share['name'])
                username = (getattr(old_share, 'other_username', None) or
                            old_share['other_username'])
                self.assertEqual(share.other_username, username)
                name = (getattr(old_share, 'other_visible_name', None) or
                        old_share['other_visible_name'])
                self.assertEqual(share.other_visible_name, name)
                level = (getattr(old_share, 'access_level', None) or
                         old_share['access_level'])
                self.assertEqual(share.access_level, level)

        for sid in vm.shares:
            old_share = legacy_shares[sid]
            share = vm.shares[sid]
            self.assertTrue(
                isinstance(share, Share) or isinstance(share, Root))
            compare_share(share, old_share)

        for sid in vm.shared:
            old_share = legacy_shared[sid]
            share = vm.shared[sid]
            self.assertTrue(isinstance(share, Shared))
            compare_share(share, old_share)
Ejemplo n.º 7
0
    def test_upgrade_5_with_udfs(self):
        """Test the migration from version 5 with old UDFs."""
        # build a fake version 5 state
        self._build_layout_version_4()
        self.set_md_version('5')
        self.udfs_md_dir = os.path.join(self.vm_data_dir, 'udfs')
        # create some old shares and shared metadata
        legacy_shares = LegacyShareFileShelf(self.share_md_dir)
        root_share = _Share(path=self.root_dir, share_id=request.ROOT,
                            access_level=ACCESS_LEVEL_RW)
        legacy_shares[request.ROOT] = root_share
        for idx, name in enumerate(['share'] * 10):
            sid = str(uuid.uuid4())
            share_name = name + '_' + str(idx)
            share = _Share(path=os.path.join(self.shares_dir, share_name),
                           share_id=sid, name=share_name,
                           node_id=str(uuid.uuid4()),
                           other_username='******' + str(idx),
                           other_visible_name='visible name ' + str(idx))
            if idx % 2:
                share.access_level = ACCESS_LEVEL_RW
            else:
                share.access_level = ACCESS_LEVEL_RO
            legacy_shares[sid] = share

        # create shared shares
        legacy_shared = LegacyShareFileShelf(self.shared_md_dir)
        for idx, name in enumerate(['dir'] * 5):
            sid = str(uuid.uuid4())
            share_name = name + '_' + str(idx)
            share = _Share(path=os.path.join(self.root_dir, share_name),
                           share_id=sid, node_id=str(uuid.uuid4()),
                           name=share_name, other_username='******',
                           other_visible_name='hola')
            if idx % 2:
                share.access_level = ACCESS_LEVEL_RW
            else:
                share.access_level = ACCESS_LEVEL_RO
            legacy_shared[sid] = share

        # create some udfs
        legacy_udfs = LegacyShareFileShelf(self.udfs_md_dir)
        for idx, name in enumerate(['dir'] * 5):
            udf_id = str(uuid.uuid4())
            udf_name = name + '_' + str(idx)
            udf = _UDF(
                udf_id, str(uuid.uuid4()), u'~/' + udf_name.decode('utf-8'),
                os.path.join(self.home_dir, udf_name))
            if idx % 2:
                udf.subscribed = True
            else:
                udf.subscribed = False
            legacy_udfs[sid] = udf

        # keep a copy of the current shares and shared metadata to check
        # the upgrade went ok
        legacy_shares = dict(legacy_shares.items())
        legacy_shared = dict(legacy_shared.items())
        legacy_udfs = dict(legacy_udfs.items())

        if self.md_version_None:
            self.set_md_version('')
        # upgrade it!
        self.main = FakeMain(self.root_dir, self.shares_dir,
                             self.data_dir, self.partials_dir)
        vm = self.main.vm

        def compare_share(share, old_share):
            """Compare two shares, new and old"""
            self.assertEqual(share.volume_id, old_share.id)
            self.assertEqual(share.path, old_share.path)
            self.assertEqual(share.node_id, old_share.subtree)
            if not isinstance(share, Root):
                self.assertEqual(share.name, old_share.name)
                self.assertEqual(
                    share.other_username, old_share.other_username)
                self.assertEqual(
                    share.other_visible_name, old_share.other_visible_name)
                self.assertEqual(share.access_level, old_share.access_level)

        for sid in vm.shares:
            old_share = legacy_shares[sid]
            share = vm.shares[sid]
            self.assertTrue(
                isinstance(share, Share) or isinstance(share, Root))
            compare_share(share, old_share)

        for sid in vm.shared:
            old_share = legacy_shared[sid]
            share = vm.shared[sid]
            self.assertTrue(isinstance(share, Shared))
            compare_share(share, old_share)

        for udf_id in vm.udfs:
            old_udf = legacy_udfs[udf_id]
            udf = vm.udfs[udf_id]
            self.assertTrue(isinstance(udf, UDF))
            self.assertEqual(udf.volume_id, old_udf.id)
            self.assertEqual(udf.path, old_udf.path)
            self.assertEqual(udf.node_id, old_udf.node_id)
            self.assertEqual(udf.suggested_path, old_udf.suggested_path)
            self.assertEqual(
                type(udf.suggested_path), type(old_udf.suggested_path))
            self.assertEqual(udf.subscribed, old_udf.subscribed)
Ejemplo n.º 8
0
class MetadataNewLayoutTests(MetadataTestCase):
    """Test for 'new' layout and metadata upgrade."""

    @defer.inlineCallbacks
    def setUp(self):
        yield super(MetadataNewLayoutTests, self).setUp()
        # We need to define home_dir here to add 'home' to the path
        # and avoid crashes between existing paths.
        self.home_dir = os.path.join(self.tmpdir, 'home', 'ubuntuonehacker')
        self.share_md_dir = os.path.join(self.vm_data_dir, 'shares')
        self.shared_md_dir = os.path.join(self.vm_data_dir, 'shared')
        self.u1_dir = os.path.join(
            self.home_dir, os.path.split(self.u1_dir)[1])
        self.root_dir = self.u1_dir
        self.shares_dir = os.path.join(self.tmpdir, 'shares')
        self.shares_dir_link = os.path.join(self.u1_dir, 'Shared With Me')

    def _build_layout_version_4(self):
        """Build the directory structure to mimic md v.4/5."""
        os.makedirs(self.share_md_dir)
        os.makedirs(self.shared_md_dir)
        os.makedirs(self.root_dir)
        os.makedirs(self.shares_dir)
        os.symlink(self.shares_dir, self.shares_dir_link)

    def _fix_permissions(self):
        """Fix shares dir permissions, making it read-only."""
        os.chmod(self.shares_dir, 0500)

    def test_upgrade_None_to_last(self):
        """Upgrade from version 'None' (possibly a clean start)."""
        old_root = os.path.join(self.root_dir, 'My Files')
        old_shares = os.path.join(self.root_dir, 'Shared With Me')
        # start and check that everything is ok
        self.main = FakeMain(self.root_dir, self.shares_dir,
                             self.data_dir, self.partials_dir)
        self.assertFalse(os.path.exists(old_root))
        self.assertTrue(os.path.exists(self.root_dir))
        self.assertTrue(os.path.exists(old_shares))
        self.assertTrue(os.path.islink(old_shares))
        self.assertEqual(old_shares, self.main.shares_dir_link)
        self.check_version()

    def test_upgrade_None_to_last_phantom_share_path(self):
        """Upgrade from version 'None' (possibly a clean start) with a root
        with missing path.

        """
        old_root = os.path.join(self.root_dir, 'My Files')
        old_shares = os.path.join(self.root_dir, 'Shared With Me')
        self.main = FakeMain(self.root_dir, self.shares_dir,
                             self.data_dir, self.partials_dir)
        self.main.shutdown()
        self.rmtree(self.vm_data_dir)
        os.makedirs(self.vm_data_dir)
        self.set_md_version('')
        shares = LegacyShareFileShelf(self.share_md_dir)
        root_share = _Share(path=self.root_dir)
        root_share.access_level = ACCESS_LEVEL_RW
        # set None to the share path
        root_share.path = None
        shares[request.ROOT] = root_share

        if self.md_version_None:
            self.set_md_version('')
        # check that it's all OK
        self.main = FakeMain(self.root_dir, self.shares_dir,
                             self.data_dir, self.partials_dir)
        self.assertFalse(os.path.exists(old_root))
        self.assertTrue(os.path.exists(self.root_dir))
        self.assertTrue(os.path.exists(self.shares_dir))
        self.assertTrue(os.path.islink(old_shares))
        self.assertEqual(old_shares, self.main.shares_dir_link)
        self.check_version()

    def test_upgrade_4(self):
        """Test migration from 4 to 5 (broken symlink in the root)."""
        self._build_layout_version_4()
        self.set_md_version('4')
        # break the symlink
        if os.path.exists(self.shares_dir_link):
            os.unlink(self.shares_dir_link)
        os.symlink(self.shares_dir_link, self.shares_dir_link)

        if self.md_version_None:
            self.set_md_version('')
        self.main = FakeMain(self.root_dir, self.shares_dir,
                             self.data_dir, self.partials_dir)
        self.assertEqual(
            self.main.shares_dir, os.readlink(self.main.shares_dir_link))
        self.check_version()

    def test_upgrade_5(self):
        """Test the migration from version 5."""
        # build a fake version 5 state
        self._build_layout_version_4()
        self.set_md_version('5')
        # create some old shares and shared metadata
        legacy_shares = LegacyShareFileShelf(self.share_md_dir)
        root_share = _Share(path=self.root_dir, share_id=request.ROOT,
                            access_level=ACCESS_LEVEL_RW)
        legacy_shares[request.ROOT] = root_share
        for idx, name in enumerate(['share'] * 10):
            sid = str(uuid.uuid4())
            share_name = name + '_' + str(idx)
            share = _Share(path=os.path.join(self.shares_dir, share_name),
                           share_id=sid, name=share_name,
                           node_id=str(uuid.uuid4()),
                           other_username='******' + str(idx),
                           other_visible_name='visible name ' + str(idx))
            if idx % 2:
                share.access_level = ACCESS_LEVEL_RW
            else:
                share.access_level = ACCESS_LEVEL_RO
            legacy_shares[sid] = share

        # create shared shares
        legacy_shared = LegacyShareFileShelf(self.shared_md_dir)
        for idx, name in enumerate(['dir'] * 5):
            sid = str(uuid.uuid4())
            share_name = name + '_' + str(idx)
            share = _Share(path=os.path.join(self.root_dir, share_name),
                           share_id=sid, node_id=str(uuid.uuid4()),
                           name=share_name, other_username='******',
                           other_visible_name='hola')
            if idx % 2:
                share.access_level = ACCESS_LEVEL_RW
            else:
                share.access_level = ACCESS_LEVEL_RO
            legacy_shared[sid] = share

        # keep a copy of the current shares and shared metadata to check
        # the upgrade went ok
        legacy_shares = dict(legacy_shares.items())
        legacy_shared = dict(legacy_shared.items())

        if self.md_version_None:
            self.set_md_version('')
        # upgrade it!
        self.main = FakeMain(self.root_dir, self.shares_dir,
                             self.data_dir, self.partials_dir)
        vm = self.main.vm

        def compare_share(share, old_share):
            """Compare two shares, new and old"""
            self.assertEqual(share.volume_id, old_share.id)
            self.assertEqual(share.path, old_share.path)
            self.assertEqual(share.node_id, old_share.subtree)
            if not isinstance(share, Root):
                self.assertEqual(share.name, old_share.name)
                self.assertEqual(
                    share.other_username, old_share.other_username)
                self.assertEqual(
                    share.other_visible_name, old_share.other_visible_name)
                self.assertEqual(share.access_level, old_share.access_level)

        for sid in vm.shares:
            old_share = legacy_shares[sid]
            share = vm.shares[sid]
            self.assertTrue(
                isinstance(share, Share) or isinstance(share, Root))
            compare_share(share, old_share)

        for sid in vm.shared:
            old_share = legacy_shared[sid]
            share = vm.shared[sid]
            self.assertTrue(isinstance(share, Shared))
            compare_share(share, old_share)

    def test_upgrade_5_with_udfs(self):
        """Test the migration from version 5 with old UDFs."""
        # build a fake version 5 state
        self._build_layout_version_4()
        self.set_md_version('5')
        self.udfs_md_dir = os.path.join(self.vm_data_dir, 'udfs')
        # create some old shares and shared metadata
        legacy_shares = LegacyShareFileShelf(self.share_md_dir)
        root_share = _Share(path=self.root_dir, share_id=request.ROOT,
                            access_level=ACCESS_LEVEL_RW)
        legacy_shares[request.ROOT] = root_share
        for idx, name in enumerate(['share'] * 10):
            sid = str(uuid.uuid4())
            share_name = name + '_' + str(idx)
            share = _Share(path=os.path.join(self.shares_dir, share_name),
                           share_id=sid, name=share_name,
                           node_id=str(uuid.uuid4()),
                           other_username='******' + str(idx),
                           other_visible_name='visible name ' + str(idx))
            if idx % 2:
                share.access_level = ACCESS_LEVEL_RW
            else:
                share.access_level = ACCESS_LEVEL_RO
            legacy_shares[sid] = share

        # create shared shares
        legacy_shared = LegacyShareFileShelf(self.shared_md_dir)
        for idx, name in enumerate(['dir'] * 5):
            sid = str(uuid.uuid4())
            share_name = name + '_' + str(idx)
            share = _Share(path=os.path.join(self.root_dir, share_name),
                           share_id=sid, node_id=str(uuid.uuid4()),
                           name=share_name, other_username='******',
                           other_visible_name='hola')
            if idx % 2:
                share.access_level = ACCESS_LEVEL_RW
            else:
                share.access_level = ACCESS_LEVEL_RO
            legacy_shared[sid] = share

        # create some udfs
        legacy_udfs = LegacyShareFileShelf(self.udfs_md_dir)
        for idx, name in enumerate(['dir'] * 5):
            udf_id = str(uuid.uuid4())
            udf_name = name + '_' + str(idx)
            udf = _UDF(
                udf_id, str(uuid.uuid4()), u'~/' + udf_name.decode('utf-8'),
                os.path.join(self.home_dir, udf_name))
            if idx % 2:
                udf.subscribed = True
            else:
                udf.subscribed = False
            legacy_udfs[sid] = udf

        # keep a copy of the current shares and shared metadata to check
        # the upgrade went ok
        legacy_shares = dict(legacy_shares.items())
        legacy_shared = dict(legacy_shared.items())
        legacy_udfs = dict(legacy_udfs.items())

        if self.md_version_None:
            self.set_md_version('')
        # upgrade it!
        self.main = FakeMain(self.root_dir, self.shares_dir,
                             self.data_dir, self.partials_dir)
        vm = self.main.vm

        def compare_share(share, old_share):
            """Compare two shares, new and old"""
            self.assertEqual(share.volume_id, old_share.id)
            self.assertEqual(share.path, old_share.path)
            self.assertEqual(share.node_id, old_share.subtree)
            if not isinstance(share, Root):
                self.assertEqual(share.name, old_share.name)
                self.assertEqual(
                    share.other_username, old_share.other_username)
                self.assertEqual(
                    share.other_visible_name, old_share.other_visible_name)
                self.assertEqual(share.access_level, old_share.access_level)

        for sid in vm.shares:
            old_share = legacy_shares[sid]
            share = vm.shares[sid]
            self.assertTrue(
                isinstance(share, Share) or isinstance(share, Root))
            compare_share(share, old_share)

        for sid in vm.shared:
            old_share = legacy_shared[sid]
            share = vm.shared[sid]
            self.assertTrue(isinstance(share, Shared))
            compare_share(share, old_share)

        for udf_id in vm.udfs:
            old_udf = legacy_udfs[udf_id]
            udf = vm.udfs[udf_id]
            self.assertTrue(isinstance(udf, UDF))
            self.assertEqual(udf.volume_id, old_udf.id)
            self.assertEqual(udf.path, old_udf.path)
            self.assertEqual(udf.node_id, old_udf.node_id)
            self.assertEqual(udf.suggested_path, old_udf.suggested_path)
            self.assertEqual(
                type(udf.suggested_path), type(old_udf.suggested_path))
            self.assertEqual(udf.subscribed, old_udf.subscribed)

    def test_upgrade_5_partial_upgrade(self):
        """Test migration from version 5 with upgrade to 6 unfinished."""
        # build a fake version 5 state
        self._build_layout_version_4()
        self.set_md_version('5')
        self.udfs_md_dir = os.path.join(self.vm_data_dir, 'udfs')
        # create some old shares and shared metadata
        legacy_shares = LegacyShareFileShelf(self.share_md_dir)
        root_share = _Share(path=self.root_dir, share_id=request.ROOT,
                            access_level=ACCESS_LEVEL_RW, node_id=str(
                                uuid.uuid4()))
        legacy_shares[request.ROOT] = root_share
        for idx, name in enumerate(['share'] * 3):
            sid = str(uuid.uuid4())
            share_name = name + '_' + str(idx)
            share = _Share(path=os.path.join(self.shares_dir, share_name),
                           share_id=sid, name=share_name,
                           node_id=str(uuid.uuid4()),
                           other_username='******' + str(idx),
                           other_visible_name='visible name ' + str(idx))
            if idx == 0:
                share.access_level = ACCESS_LEVEL_RW
                legacy_shares[sid] = share
            elif idx == 1:
                share.access_level = ACCESS_LEVEL_RO
                legacy_shares[sid] = share
            else:
                # add a 'new' Share dict to the shelf
                share.access_level = ACCESS_LEVEL_RW
                share = Share(
                    path=share.path, volume_id=share.id, name=share.name,
                    access_level=share.access_level,
                    other_username=share.other_username,
                    other_visible_name=share.other_visible_name,
                    node_id=share.subtree)
                legacy_shares[sid] = share.__dict__

        # create shared shares
        legacy_shared = LegacyShareFileShelf(self.shared_md_dir)
        for idx, name in enumerate(['dir'] * 3):
            sid = str(uuid.uuid4())
            share_name = name + '_' + str(idx)
            share = _Share(path=os.path.join(self.root_dir, share_name),
                           share_id=sid, node_id=str(uuid.uuid4()),
                           name=share_name, other_username='******',
                           other_visible_name='hola')
            if idx == 0:
                share.access_level = ACCESS_LEVEL_RW
                legacy_shares[sid] = share
            elif idx == 1:
                share.access_level = ACCESS_LEVEL_RO
                legacy_shares[sid] = share
            else:
                # add a 'new' Shared dict to the shelf
                share.access_level = ACCESS_LEVEL_RW
                share = Shared(path=share.path,
                               volume_id=share.id, name=share.name,
                               access_level=share.access_level,
                               other_username=share.other_username,
                               other_visible_name=share.other_visible_name,
                               node_id=share.subtree)
                legacy_shares[sid] = share.__dict__

        # keep a copy of the current shares and shared metadata to check
        # the upgrade went ok
        legacy_shares = dict(legacy_shares.items())
        legacy_shared = dict(legacy_shared.items())

        if self.md_version_None:
            self.set_md_version('')
        # upgrade it!
        self.main = FakeMain(self.root_dir, self.shares_dir,
                             self.data_dir, self.partials_dir)
        vm = self.main.vm

        def compare_share(share, old_share):
            """Compare two shares, new and old"""
            old_id = getattr(old_share, 'id', None)
            if old_id is None:
                old_id = old_share['volume_id']
            self.assertEqual(share.volume_id, old_id)
            self.assertEqual(
                share.path,
                getattr(old_share, 'path', None) or old_share['path'])
            self.assertEqual(
                share.node_id,
                getattr(old_share, 'subtree', None) or old_share['node_id'])
            if not isinstance(share, Root):
                self.assertEqual(
                    share.name,
                    getattr(old_share, 'name', None) or old_share['name'])
                username = (getattr(old_share, 'other_username', None) or
                            old_share['other_username'])
                self.assertEqual(share.other_username, username)
                name = (getattr(old_share, 'other_visible_name', None) or
                        old_share['other_visible_name'])
                self.assertEqual(share.other_visible_name, name)
                level = (getattr(old_share, 'access_level', None) or
                         old_share['access_level'])
                self.assertEqual(share.access_level, level)

        for sid in vm.shares:
            old_share = legacy_shares[sid]
            share = vm.shares[sid]
            self.assertTrue(
                isinstance(share, Share) or isinstance(share, Root))
            compare_share(share, old_share)

        for sid in vm.shared:
            old_share = legacy_shared[sid]
            share = vm.shared[sid]
            self.assertTrue(isinstance(share, Shared))
            compare_share(share, old_share)

    def test_upgrade_5_critical_error(self):
        """Test the migration from version 5 with a critical error."""
        # build a fake version 5 state
        self._build_layout_version_4()
        self.set_md_version('5')
        # create some old shares and shared metadata
        legacy_shares = LegacyShareFileShelf(self.share_md_dir)
        root_share = _Share(path=self.root_dir, share_id=request.ROOT,
                            access_level=ACCESS_LEVEL_RW)
        legacy_shares[request.ROOT] = root_share
        for idx, name in enumerate(['share'] * 10):
            sid = str(uuid.uuid4())
            share_name = name + '_' + str(idx)
            share = _Share(path=os.path.join(self.shares_dir, share_name),
                           share_id=sid, name=share_name,
                           node_id=str(uuid.uuid4()),
                           other_username='******' + str(idx),
                           other_visible_name='visible name ' + str(idx))
            if idx % 2:
                share.access_level = ACCESS_LEVEL_RW
            else:
                share.access_level = ACCESS_LEVEL_RO
            legacy_shares[sid] = share
        # create shared shares
        legacy_shared = LegacyShareFileShelf(self.shared_md_dir)
        for idx, name in enumerate(['dir'] * 5):
            sid = str(uuid.uuid4())
            share_name = name + '_' + str(idx)
            share = _Share(path=os.path.join(self.root_dir, share_name),
                           share_id=sid, node_id=str(uuid.uuid4()),
                           name=share_name, other_username='******',
                           other_visible_name='hola')
            if idx % 2:
                share.access_level = ACCESS_LEVEL_RW
            else:
                share.access_level = ACCESS_LEVEL_RO
            legacy_shared[sid] = share

        # keep a copy of the current shares and shared metadata to check
        # the upgrade went ok
        legacy_shares = dict(legacy_shares.items())
        legacy_shared = dict(legacy_shared.items())

        if self.md_version_None:
            self.set_md_version('')
        # upgrade it!
        old_upgrade_share_to_volume = MetadataUpgrader._upgrade_share_to_volume

        def upgrade_share_to_volume(share, shared=False):
            raise ValueError('FAIL!')
        MetadataUpgrader._upgrade_share_to_volume = upgrade_share_to_volume
        try:
            self.assertRaises(ValueError, FakeMain, self.root_dir,
                              self.shares_dir, self.data_dir,
                              self.partials_dir)
        finally:
            MetadataUpgrader._upgrade_share_to_volume = \
                    old_upgrade_share_to_volume

        shares = LegacyShareFileShelf(self.share_md_dir)
        self.assertEqual(len(list(shares.keys())), len(legacy_shares.keys()))
        for sid, share in shares.iteritems():
            old_share = legacy_shares[sid]
            self.assertTrue(isinstance(share, _Share))
            self.assertTrue(isinstance(old_share, _Share))
        shared = LegacyShareFileShelf(self.shared_md_dir)
        self.assertEqual(len(list(shared.keys())), len(legacy_shared.keys()))
        for sid, share in shared.iteritems():
            old_share = legacy_shared[sid]
            self.assertTrue(isinstance(share, _Share))
            self.assertTrue(isinstance(old_share, _Share))

    def test_broken_symlink_latest_metadata(self):
        """Test vm startup with latest metadata and a broken symlink."""
        self._build_layout_version_4()
        os.unlink(self.shares_dir_link)
        # create a broken link
        os.symlink('foo', self.shares_dir_link)
        self.main = FakeMain(self.root_dir, self.shares_dir,
                             self.data_dir, self.partials_dir)
        self.check_version()

    def test_upgrade_6(self):
        """Test the migration from version 6."""
        # build a fake version 5 state
        self._build_layout_version_4()
        self.set_md_version('6')
        self.udfs_md_dir = os.path.join(self.vm_data_dir, 'udfs')
        # create some old shares and shared metadata
        legacy_shares = VMFileShelf(self.share_md_dir)
        root = Root(path=self.root_dir)
        legacy_shares[request.ROOT] = root
        for idx, name in enumerate(['share'] * 10):
            sid = str(uuid.uuid4())
            share_name = name + '_' + str(idx)
            share = Share(
                path=os.path.join(self.shares_dir, share_name),
                volume_id=sid, name=share_name, node_id=str(uuid.uuid4()),
                other_username='******' + str(idx),
                other_visible_name='visible name ' + str(idx))
            if idx % 2:
                share.access_level = ACCESS_LEVEL_RW
            else:
                share.access_level = ACCESS_LEVEL_RO
            legacy_shares[sid] = share

        # create shared shares
        legacy_shared = VMFileShelf(self.shared_md_dir)
        for idx, name in enumerate(['dir'] * 5):
            sid = str(uuid.uuid4())
            share_name = name + '_' + str(idx)
            share = Shared(path=os.path.join(self.root_dir, share_name),
                           volume_id=sid, node_id=str(uuid.uuid4()),
                           name=share_name, other_username='******',
                           other_visible_name='hola')
            if idx % 2:
                share.access_level = ACCESS_LEVEL_RW
            else:
                share.access_level = ACCESS_LEVEL_RO
            legacy_shared[sid] = share

        # create some udfs
        legacy_udfs = VMFileShelf(self.udfs_md_dir)
        for idx, name in enumerate(['dir'] * 5):
            udf_id = str(uuid.uuid4())
            udf_name = name + '_' + str(idx)
            udf = UDF(
                udf_id, str(uuid.uuid4()), u'~/' + udf_name.decode('utf-8'),
                os.path.join(self.home_dir, udf_name))
            if idx % 2:
                udf.subscribed = True
            else:
                udf.subscribed = False
            legacy_udfs[sid] = udf

        # keep a copy of the current shares and shared metadata to check
        # the upgrade went ok
        legacy_shares = dict(legacy_shares.items())
        legacy_shared = dict(legacy_shared.items())
        legacy_udfs = dict(legacy_udfs.items())

        if self.md_version_None:
            self.set_md_version('')
        # upgrade it!
        self.main = FakeMain(self.root_dir, self.shares_dir,
                             self.data_dir, self.partials_dir)
        vm = self.main.vm

        for sid in vm.shares:
            old_share = legacy_shares[sid]
            share = vm.shares[sid]
            self.assertTrue(
                isinstance(share, Share) or isinstance(share, Root))
            self.assertEqual(share.__dict__, old_share.__dict__)

        for sid in vm.shared:
            old_share = legacy_shared[sid]
            share = vm.shared[sid]
            self.assertTrue(isinstance(share, Shared))
            self.assertEqual(share.__dict__, old_share.__dict__)

        for udf_id in vm.udfs:
            old_udf = legacy_udfs[udf_id]
            udf = vm.udfs[udf_id]
            self.assertTrue(isinstance(udf, UDF))
            self.assertEqual(udf.__dict__, old_udf.__dict__)