Example #1
0
class RunnableTestCase(TestCase):

    def setUp(self):
        clear_doms()
        self.guid = uuid.uuid4()
        self.run_dir = tempfile.mkdtemp()
        self.net_dir = os.path.join(self.run_dir, 'etc', 'net.d')
        os.makedirs(self.net_dir)
        self.cont_dir = os.path.join(self.run_dir, 'containers')
        os.makedirs(self.cont_dir)
        self.exes = FakeCommands()
        self.svdsm = FakeSuperVdsm(self.exes)
        self.patch = Patch([
            (vdsm.virt.containers.xmlfile,
                'STATE_DIR', os.path.join(self.run_dir, 'containers')),
            (vdsm.virt.containers.command,
                'supervdsm', self.svdsm),
            (vdsm.virt.containers.command,
                '_SYSTEMCTL', self.exes.systemctl),
            (vdsm.virt.containers.docker,
                '_DOCKER', self.exes.docker),
        ])
        self.patch.apply()
        vdsm.virt.containers.docker.setup_network(
            'test', 'brtest', 'eth1', '192.168.0.1', '192.168.0.0', '24'
        )

    def tearDown(self):
        self.patch.revert()
        shutil.rmtree(self.run_dir)
Example #2
0
    def setUp(self):
        """
        Prepares a workdir and set of files for the TestCase.
        Avoid requiring root privileges for os.chown call
        by mkimage._commonCleanFs.
        Avoid errors creating _P_PAYLOAD_IMAGES
        """
        self.tempdir = mkdtemp(prefix="vdsm-mkimage-tests")
        self.workdir = os.path.join(self.tempdir, "work")
        os.mkdir(self.workdir)
        self.img_dir = os.path.join(self.tempdir, "images")
        os.mkdir(self.img_dir)
        self.files = {}
        self.expected_results = {}
        self.subdir = os.path.join('a', 'subdirectory', 'for', 'testing')
        for i in range(5):
            content = os.urandom(1024)
            filename = "test_%d" % i
            longpath = os.path.join(self.subdir, filename)
            self.expected_results[filename] = content
            self.files[filename] = b64encode(content)
            self.expected_results[longpath] = content
            self.files[longpath] = b64encode(content)

        self.patch = Patch([
            (mkimage, "DISKIMAGE_USER", -1),
            (mkimage, "DISKIMAGE_GROUP", -1),
            (mkimage, "_P_PAYLOAD_IMAGES", self.img_dir),
        ])

        # Must be last; if setUp fails, tearDown is not invoked
        self.patch.apply()
Example #3
0
class CgroupTestCase(TestCase):

    def setUp(self):
        self.pid = 0
        testdir = os.path.dirname(os.path.abspath(__file__))
        self.root = os.path.join(testdir, 'fake')

        self.procfsroot = os.path.join(
            self.root, vdsm.virt.containers.cgroups.PROCFS
        )
        self.cgroupfsroot = os.path.join(
            self.root, vdsm.virt.containers.cgroups.CGROUPFS
        )

        with move_into(self.root):
            cgroupsdata = os.path.join(self.root, 'cgroups.tgz')
            with gzip.GzipFile(cgroupsdata) as gz:
                tar = tarfile.TarFile(fileobj=gz)
                tar.extractall()

        self.patch = Patch([
            (vdsm.virt.containers.cgroups,
                '_PROCBASE', self.procfsroot),
            (vdsm.virt.containers.cgroups,
                '_CGROUPBASE', self.cgroupfsroot),
        ])
        self.patch.apply()

    def tearDown(self):
        self.patch.revert()
        shutil.rmtree(self.procfsroot)
        shutil.rmtree(self.cgroupfsroot)
Example #4
0
class CgroupTestCase(TestCase):
    def setUp(self):
        self.pid = 0
        testdir = os.path.dirname(os.path.abspath(__file__))
        self.root = os.path.join(testdir, 'fake')

        self.procfsroot = os.path.join(self.root,
                                       vdsm.virt.containers.cgroups.PROCFS)
        self.cgroupfsroot = os.path.join(self.root,
                                         vdsm.virt.containers.cgroups.CGROUPFS)

        with move_into(self.root):
            cgroupsdata = os.path.join(self.root, 'cgroups.tgz')
            with gzip.GzipFile(cgroupsdata) as gz:
                tar = tarfile.TarFile(fileobj=gz)
                tar.extractall()

        self.patch = Patch([
            (vdsm.virt.containers.cgroups, '_PROCBASE', self.procfsroot),
            (vdsm.virt.containers.cgroups, '_CGROUPBASE', self.cgroupfsroot),
        ])
        self.patch.apply()

    def tearDown(self):
        self.patch.revert()
        shutil.rmtree(self.procfsroot)
        shutil.rmtree(self.cgroupfsroot)
Example #5
0
class RunnableTestCase(TestCase):
    def setUp(self):
        clear_doms()
        self.guid = uuid.uuid4()
        self.run_dir = tempfile.mkdtemp()
        self.net_dir = os.path.join(self.run_dir, 'etc', 'net.d')
        os.makedirs(self.net_dir)
        self.cont_dir = os.path.join(self.run_dir, 'containers')
        os.makedirs(self.cont_dir)
        self.exes = FakeCommands()
        self.svdsm = FakeSuperVdsm(self.exes)
        self.patch = Patch([
            (vdsm.virt.containers.xmlfile, 'STATE_DIR',
             os.path.join(self.run_dir, 'containers')),
            (vdsm.virt.containers.command, 'supervdsm', self.svdsm),
            (vdsm.virt.containers.command, '_SYSTEMCTL', self.exes.systemctl),
            (vdsm.virt.containers.docker, '_DOCKER', self.exes.docker),
        ])
        self.patch.apply()
        vdsm.virt.containers.docker.setup_network('test', 'brtest', 'eth1',
                                                  '192.168.0.1', '192.168.0.0',
                                                  '24')

    def tearDown(self):
        self.patch.revert()
        shutil.rmtree(self.run_dir)
Example #6
0
 def __init__(self, now):
     self.now = now
     self.patch = Patch([
         (vdsm.common.time, 'monotonic_time', self.monotonic_time),
         (vdsm.common.function, 'monotonic_time', self.monotonic_time),
         (time, 'sleep', self.sleep),
     ])
Example #7
0
    def setUp(self):
        self.cif = fake.ClientIF()
        self.conn = FakeConnection()

        self.patch = Patch([
            (containersconnection, 'recovery', lambda *args: []),
            (libvirtconnection, 'get', lambda *args, **kwargs: self.conn),
        ])
        self.patch.apply()
Example #8
0
    def setUp(self):
        self.vm_uuids = ('a', 'b',)
        self.vm_is_ext = [False] * len(self.vm_uuids)
        self.cif = fake.ClientIF()
        self.conn = FakeConnection()

        self.patch = Patch([
            (libvirtconnection, 'get', lambda *args, **kwargs: self.conn),
        ])
        self.patch.apply()

        # must be after patch.apply()
        self.conn.domains = _make_domains_collection(
            list(zip(self.vm_uuids, self.vm_is_ext))
        )
Example #9
0
    def setUp(self):
        """
        Prepares a workdir and set of files for the TestCase.
        Avoid requiring root privileges for os.chown call
        by mkimage._commonCleanFs.
        Avoid errors creating _P_PAYLOAD_IMAGES
        """
        self.tempdir = mkdtemp(prefix="vdsm-mkimage-tests")
        self.workdir = os.path.join(self.tempdir, "work")
        os.mkdir(self.workdir)
        self.img_dir = os.path.join(self.tempdir, "images")
        os.mkdir(self.img_dir)
        self.files = {}
        self.expected_results = {}
        self.subdir = os.path.join('a', 'subdirectory', 'for', 'testing')
        for i in range(5):
            content = os.urandom(1024)
            filename = "test_%d" % i
            longpath = os.path.join(self.subdir, filename)
            self.expected_results[filename] = content
            self.files[filename] = b64encode(content)
            self.expected_results[longpath] = content
            self.files[longpath] = b64encode(content)

        self.patch = Patch([
            (mkimage, "DISKIMAGE_USER", -1),
            (mkimage, "DISKIMAGE_GROUP", -1),
            (mkimage, "_P_PAYLOAD_IMAGES", self.img_dir),
        ])

        # Must be last; if setUp fails, tearDown is not invoked
        self.patch.apply()
Example #10
0
class FakeMonotonicTime(object):
    def __init__(self, now):
        self.now = now
        self.patch = Patch([
            (utils, 'monotonic_time', self.monotonic_time),
            (time, 'sleep', self.sleep),
        ])

    def monotonic_time(self):
        return self.now

    def sleep(self, seconds):
        self.now += seconds

    def __enter__(self):
        self.patch.apply()
        return self

    def __exit__(self, *_):
        self.patch.revert()
Example #11
0
class VdsmTestCase(unittest.TestCase):

    _patch_arch = Patch([
        (platform, "machine", _vdsm_machine),
    ])

    def __init__(self, *args, **kwargs):
        unittest.TestCase.__init__(self, *args, **kwargs)
        self.log = logging.getLogger(self.__class__.__name__)
        self.maxDiff = None  # disable truncating diff in assert error messages

    @classmethod
    def setUpClass(cls):
        cls._patch_arch.apply()

    @classmethod
    def tearDownClass(cls):
        cls._patch_arch.revert()

    def retryAssert(self, *args, **kwargs):
        '''Keep retrying an assertion if AssertionError is raised.
           See function utils.retry for the meaning of the arguments.
        '''
        # the utils module only can be imported correctly after
        # hackVdsmModule() is called. Do not import it at the
        # module level.
        from vdsm.common.function import retry
        return retry(expectedException=AssertionError, *args, **kwargs)

    def assertNotRaises(self, callableObj=None, *args, **kwargs):
        # This is required when any exception raised during the call should be
        # considered as a test failure.
        context = not_raises(self)
        if callableObj is None:
            return context
        with context:
            callableObj(*args, **kwargs)

    @contextmanager
    def assertElapsed(self, expected, tolerance=0.5):
        start = vdsm.common.time.monotonic_time()

        yield

        elapsed = vdsm.common.time.monotonic_time() - start

        if abs(elapsed - expected) > tolerance:
            raise AssertionError("Operation time: %s" % elapsed)

    def assertEquals(self, *args, **kwargs):
        raise RuntimeError(
            "assertEquals is deprecated, please use assertEqual\n"
            "See https://docs.python.org/2/library/unittest.html"
            "#deprecated-aliases")
Example #12
0
class FakeMonotonicTime(object):

    def __init__(self, now):
        self.now = now
        self.patch = Patch([
            (utils, 'monotonic_time', self.monotonic_time),
            (time, 'sleep', self.sleep),
        ])

    def monotonic_time(self):
        return self.now

    def sleep(self, seconds):
        self.now += seconds

    def __enter__(self):
        self.patch.apply()
        return self

    def __exit__(self, *_):
        self.patch.revert()
Example #13
0
 def __init__(self, now):
     self.now = now
     self.patch = Patch([
         (utils, 'monotonic_time', self.monotonic_time),
         (time, 'sleep', self.sleep),
     ])
Example #14
0
class MkimageTestCase(VdsmTestCase):
    """
    Tests for mkimage module.
    """

    # pylint: disable=R0904

    def setUp(self):
        """
        Prepares a workdir and set of files for the TestCase.
        Avoid requiring root privileges for os.chown call
        by mkimage._commonCleanFs.
        Avoid errors creating _P_PAYLOAD_IMAGES
        """
        self.tempdir = mkdtemp(prefix="vdsm-mkimage-tests")
        self.workdir = os.path.join(self.tempdir, "work")
        os.mkdir(self.workdir)
        self.img_dir = os.path.join(self.tempdir, "images")
        os.mkdir(self.img_dir)
        self.files = {}
        self.expected_results = {}
        self.subdir = os.path.join('a', 'subdirectory', 'for', 'testing')
        for i in range(5):
            content = os.urandom(1024)
            filename = "test_%d" % i
            longpath = os.path.join(self.subdir, filename)
            self.expected_results[filename] = content
            self.files[filename] = b64encode(content)
            self.expected_results[longpath] = content
            self.files[longpath] = b64encode(content)

        self.patch = Patch([
            (mkimage, "DISKIMAGE_USER", -1),
            (mkimage, "DISKIMAGE_GROUP", -1),
            (mkimage, "_P_PAYLOAD_IMAGES", self.img_dir),
        ])

        # Must be last; if setUp fails, tearDown is not invoked
        self.patch.apply()

    def tearDown(self):
        """
        Removes the workdir and its content when finished.
        Restore original values of mkimage constants.
        """
        self.patch.revert()
        rmtree(self.tempdir)

    def _check_permissions(self, filepath, permsMask):
        """
        Ensure the file at `filepath' has the permissions coherent
        with the given mask.
        The mask may specifiy the required presence, or absence, of a
        permission bit.
        """
        data = os.stat(filepath)
        if stat.S_ISREG(data.st_mode):
            for perm, expected in permsMask:
                self.assertEqual(bool(data.st_mode & perm), expected,
                                 '%s: %s' % (filepath, oct(data.st_mode)))

    def _check_content(self, checkPerms=True):
        """
        Ensure that the workdir contains what we want
        """
        out_dir = os.listdir(self.workdir)
        out_subdir = os.listdir(os.path.join(self.workdir, self.subdir))
        self.assertEqual(len(out_dir) - 1, len(self.expected_results) / 2)
        self.assertEqual(len(out_subdir), len(self.expected_results) / 2)
        for filename in self.expected_results:
            if os.path.basename(filename) == filename:
                self.assertIn(filename, out_dir)
            else:
                self.assertIn(os.path.basename(filename), out_subdir)
            filepath = os.path.join(self.workdir, filename)
            if checkPerms:
                self._check_permissions(filepath, ((stat.S_IRUSR, True),
                                                   (stat.S_IWUSR, True),
                                                   (stat.S_IXUSR, False)))
                self._check_permissions(filepath, ((stat.S_IRGRP, True),
                                                   (stat.S_IWGRP, False),
                                                   (stat.S_IXGRP, False)))
                self._check_permissions(filepath, ((stat.S_IROTH, False),
                                                   (stat.S_IWOTH, False),
                                                   (stat.S_IXOTH, False)))
            with open(filepath, "r") as fd:
                content = fd.read()
                self.assertEqual(content, self.expected_results[filename])

    def _check_label(self, imgPath, label):
        """
        Ensures filesystem contains the desired label
        """
        if label is None:
            return
        cmd = ['blkid', '-s', 'LABEL', imgPath]
        try:
            (ret, out, err) = execCmd(cmd, raw=True)
        except OSError:
            raise SkipTest("cannot execute blkid")

        self.assertEqual(ret, 0)
        partitions = out.rpartition('LABEL=')
        self.assertEqual(len(partitions), 3)
        self.assertEqual(partitions[2].strip(), '"' + label + '"')

    def test__decodeFilesIntoDir(self):
        """
        Tests mkimage._decodeFilesIntoDir
        """
        # pylint: disable=W0212
        mkimage._decodeFilesIntoDir(self.files, self.workdir)
        self._check_content()

    @ValidateRunningAsRoot
    @permutations([['vfat'], ['auto']])
    def test_injectFilesToFs(self, fstype):
        """
        Tests mkimage.injectFilesToFs creating an image and checking its
        content. Requires root permissions for writing into the floppy image.
        """
        floppy = mkimage.getFileName("vmId_inject", self.files)
        command = [EXT_MKFS_MSDOS, '-C', floppy, '1440']
        try:
            rc, out, err = execCmd(command, raw=True)

            mkimage.injectFilesToFs(floppy, self.files, fstype)

            self.assertTrue(os.path.exists(floppy))
            m = mount.Mount(floppy, self.workdir)
            m.mount(mntOpts='loop')
            try:
                self._check_content(checkPerms=False)
            finally:
                m.umount()
        finally:
            rm_file(floppy)

    @ValidateRunningAsRoot
    def test_injectFilesToFs_wrongfs(self):
        """
        Tests for failure mkimage.injectFilesToFs when wrong fstype is
        specified. Requires root permissions for mounting the image.
        """
        floppy = mkimage.getFileName("vmId_inject", self.files)
        command = [EXT_MKFS_MSDOS, '-C', floppy, '1440']
        try:
            rc, out, err = execCmd(command, raw=True)

            with self.assertRaises(MountError):
                mkimage.injectFilesToFs(floppy, self.files, 'ext3')
        finally:
            rm_file(floppy)

    @ValidateRunningAsRoot
    @permutations([[None], ['FSLABEL']])
    def test_mkFloppyFs(self, label):
        """
        Tests mkimage.mkFloppyFs creating an image and checking its content.
        Requires root permissions for writing into the floppy image.
        """
        floppy = mkimage.mkFloppyFs("vmId_floppy", self.files, label)
        self.assertTrue(os.path.exists(floppy))
        m = mount.Mount(floppy, self.workdir)
        m.mount(mntOpts='loop')
        try:
            self._check_content(checkPerms=False)
            self._check_label(floppy, label)
        finally:
            m.umount()

    @ValidateRunningAsRoot
    @permutations([[None], ['fslabel']])
    def test_mkIsoFs(self, label):
        """
        Tests mkimage.mkIsoFs creating an image and checking its content
        """
        iso_img = mkimage.mkIsoFs("vmId_iso", self.files, label)
        self.assertTrue(os.path.exists(iso_img))
        m = mount.Mount(iso_img, self.workdir)
        try:
            m.mount(mntOpts='loop')
        except mount.MountError as e:
            raise SkipTest("Error mounting iso image: %s" % e)
        try:
            self._check_content()
            self._check_label(iso_img, label)
        finally:
            m.umount()

    def test_removeFs(self):
        """
        Tests mkimage.removeFs creating an image and removing it.
        Check also that removeFs doesn't remove anything
        outside mkimage._P_PAYLOAD_IMAGES
        """
        checkSudo(["mount", "-o", "loop", "somefile", "target"])
        checkSudo(["umount", "target"])
        iso_img = mkimage.mkIsoFs("vmId_iso", self.files)
        self.assertTrue(os.path.exists(iso_img))
        mkimage.removeFs(iso_img)
        self.assertFalse(os.path.exists(iso_img))
        self.assertRaises(Exception, mkimage.removeFs, self.workdir)
Example #15
0
class MkimageTestCase(VdsmTestCase):
    """
    Tests for mkimage module.
    """
    # pylint: disable=R0904

    def setUp(self):
        """
        Prepares a workdir and set of files for the TestCase.
        Avoid requiring root privileges for os.chown call
        by mkimage._commonCleanFs.
        Avoid errors creating _P_PAYLOAD_IMAGES
        """
        self.tempdir = mkdtemp(prefix="vdsm-mkimage-tests")
        self.workdir = os.path.join(self.tempdir, "work")
        os.mkdir(self.workdir)
        self.img_dir = os.path.join(self.tempdir, "images")
        os.mkdir(self.img_dir)
        self.files = {}
        self.expected_results = {}
        self.subdir = os.path.join('a', 'subdirectory', 'for', 'testing')
        for i in range(5):
            content = os.urandom(1024)
            filename = "test_%d" % i
            longpath = os.path.join(self.subdir, filename)
            self.expected_results[filename] = content
            self.files[filename] = b64encode(content)
            self.expected_results[longpath] = content
            self.files[longpath] = b64encode(content)

        self.patch = Patch([
            (mkimage, "DISKIMAGE_USER", -1),
            (mkimage, "DISKIMAGE_GROUP", -1),
            (mkimage, "_P_PAYLOAD_IMAGES", self.img_dir),
        ])

        # Must be last; if setUp fails, tearDown is not invoked
        self.patch.apply()

    def tearDown(self):
        """
        Removes the workdir and its content when finished.
        Restore original values of mkimage constants.
        """
        self.patch.revert()
        rmtree(self.tempdir)

    def _check_permissions(self, filepath, permsMask):
        """
        Ensure the file at `filepath' has the permissions coherent
        with the given mask.
        The mask may specifiy the required presence, or absence, of a
        permission bit.
        """
        data = os.stat(filepath)
        if stat.S_ISREG(data.st_mode):
            for perm, expected in permsMask:
                self.assertEqual(bool(data.st_mode & perm), expected,
                                 '%s: %s' % (filepath, oct(data.st_mode)))

    def _check_content(self, checkPerms=True):
        """
        Ensure that the workdir contains what we want
        """
        out_dir = os.listdir(self.workdir)
        out_subdir = os.listdir(os.path.join(self.workdir, self.subdir))
        self.assertEqual(len(out_dir) - 1, len(self.expected_results) / 2)
        self.assertEqual(len(out_subdir), len(self.expected_results) / 2)
        for filename in self.expected_results:
            if os.path.basename(filename) == filename:
                self.assertIn(filename, out_dir)
            else:
                self.assertIn(os.path.basename(filename), out_subdir)
            filepath = os.path.join(self.workdir, filename)
            if checkPerms:
                self._check_permissions(filepath,
                                        ((stat.S_IRUSR, True),
                                         (stat.S_IWUSR, True),
                                         (stat.S_IXUSR, False)))
                self._check_permissions(filepath,
                                        ((stat.S_IRGRP, True),
                                         (stat.S_IWGRP, False),
                                         (stat.S_IXGRP, False)))
                self._check_permissions(filepath,
                                        ((stat.S_IROTH, False),
                                         (stat.S_IWOTH, False),
                                         (stat.S_IXOTH, False)))
            with open(filepath, "r") as fd:
                content = fd.read()
                self.assertEqual(content, self.expected_results[filename])

    def _check_label(self, imgPath, label):
        """
        Ensures filesystem contains the desired label
        """
        if label is None:
            return
        cmd = ['blkid', '-s', 'LABEL', imgPath]
        try:
            (ret, out, err) = execCmd(cmd, raw=True)
        except OSError:
            raise SkipTest("cannot execute blkid")

        self.assertEqual(ret, 0)
        partitions = out.rpartition('LABEL=')
        self.assertEqual(len(partitions), 3)
        self.assertEqual(partitions[2].strip(), '"' + label + '"')

    def test__decodeFilesIntoDir(self):
        """
        Tests mkimage._decodeFilesIntoDir
        """
        # pylint: disable=W0212
        mkimage._decodeFilesIntoDir(self.files, self.workdir)
        self._check_content()

    @ValidateRunningAsRoot
    @permutations([[None], ['FSLABEL']])
    def test_mkFloppyFs(self, label):
        """
        Tests mkimage.mkFloppyFs creating an image and checking its content.
        Requires root permissions for writing into the floppy image.
        """
        floppy = mkimage.mkFloppyFs("vmId_floppy", self.files, label)
        self.assertTrue(os.path.exists(floppy))
        m = mount.Mount(floppy, self.workdir)
        m.mount(mntOpts='loop')
        try:
            self._check_content(checkPerms=False)
            self._check_label(floppy, label)
        finally:
            m.umount()

    @ValidateRunningAsRoot
    @permutations([[None], ['fslabel']])
    def test_mkIsoFs(self, label):
        """
        Tests mkimage.mkIsoFs creating an image and checking its content
        """
        iso_img = mkimage.mkIsoFs("vmId_iso", self.files, label)
        self.assertTrue(os.path.exists(iso_img))
        m = mount.Mount(iso_img, self.workdir)
        try:
            m.mount(mntOpts='loop')
        except mount.MountError as e:
            raise SkipTest("Error mounting iso image: %s" % e)
        try:
            self._check_content()
            self._check_label(iso_img, label)
        finally:
            m.umount()

    def test_removeFs(self):
        """
        Tests mkimage.removeFs creating an image and removing it.
        Check also that removeFs doesn't remove anything
        outside mkimage._P_PAYLOAD_IMAGES
        """
        checkSudo(["mount", "-o", "loop", "somefile", "target"])
        checkSudo(["umount", "target"])
        iso_img = mkimage.mkIsoFs("vmId_iso", self.files)
        self.assertTrue(os.path.exists(iso_img))
        mkimage.removeFs(iso_img)
        self.assertFalse(os.path.exists(iso_img))
        self.assertRaises(Exception, mkimage.removeFs, self.workdir)
Example #16
0
class TestAllDomains(TestCaseBase):
    def setUp(self):
        self.vm_uuids = (
            'a',
            'b',
        )
        self.vm_is_ext = [False] * len(self.vm_uuids)
        self.cif = fake.ClientIF()
        self.conn = FakeConnection()

        self.patch = Patch([
            (libvirtconnection, 'get', lambda *args, **kwargs: self.conn),
        ])
        self.patch.apply()

        # must be after patch.apply()
        self.conn.domains = _make_domains_collection(
            list(zip(self.vm_uuids, self.vm_is_ext)))

    def tearDown(self):
        self.patch.revert()

    def test_recover_no_domains(self):
        self.conn.domains = {}
        recovery.all_domains(self.cif)
        assert self.cif.vmRequests == {}

    def test_recover_few_domains(self):
        recovery.all_domains(self.cif)
        assert set(self.cif.vmRequests.keys()) == \
            set(self.vm_uuids)
        assert self.vm_is_ext == \
            [conf['external'] for conf, _ in self.cif.vmRequests.values()]

    @permutations([
        # create_fn
        (
            _raise, ),
        (_error, ),
    ])
    def test_recover_failures(self, create_fn):
        """
        We find VMs to recover through libvirt, but Vdsm fail to create
        its Vm objects. We should then destroy those VMs.
        """
        with MonkeyPatchScope([(self.cif, 'createVm', create_fn)]):
            recovery.all_domains(self.cif)
        assert self.cif.vmRequests == \
            {}
        assert all(vm.destroyed for vm in self.conn.domains.values())

    def test_domain_error(self):
        """
        We find VMs to recover through libvirt, but we get a failure trying
        to identify (UUIDString, XMLDesc) a domain being recovered
        """
        self.conn.domains['a'].XMLDesc = _raise
        recovery.all_domains(self.cif)
        assert set(self.cif.vmRequests.keys()) == \
            set(('b',))

    def test_recover_and_destroy_failure(self):
        """
        We find VMs to recover through libvirt, but Vdsm fail to create
        its Vm objects. We should then destroy those VMs, but one of
        the domains can't complete that. We should handle this case
        gracefully
        """
        self.conn.domains['b'].destroy = _raise
        with MonkeyPatchScope([(self.cif, 'createVm', _error)]):
            recovery.all_domains(self.cif)
        assert self.cif.vmRequests == \
            {}
        assert self.conn.domains['a'].destroyed
        assert not self.conn.domains['b'].destroyed

    def test_external_vm(self):
        vm_infos = (
            ('a', True),
            ('b', False),
        )
        self.conn.domains = _make_domains_collection(vm_infos)
        recovery.all_domains(self.cif)
        assert set(self.cif.vmRequests.keys()) == \
            set(vm_id for vm_id, _ in vm_infos)

        for vm_id, vm_is_ext in vm_infos:
            conf, _ = self.cif.vmRequests[vm_id]
            assert vm_is_ext == conf['external']

    def test_recover_external_vm_down(self):
        vm_is_ext = [True] * len(self.vm_uuids)
        self.conn.domains = _make_domains_collection(
            list(zip(self.vm_uuids, vm_is_ext)))
        for dom in self.conn.domains.values():
            dom.domState = libvirt.VIR_DOMAIN_SHUTOFF

        recovery.all_domains(self.cif)
        assert self.cif.vmRequests == {}

    def test_recover_external_vm_error(self):
        """
        handle gracefully error while getting the state of external VM
        """
        vm_is_ext = [True] * len(self.vm_uuids)
        self.conn.domains = _make_domains_collection(
            list(zip(self.vm_uuids, vm_is_ext)))
        for dom in self.conn.domains.values():
            dom.state = _raise

        recovery.all_domains(self.cif)
        assert self.cif.vmRequests == {}

    def test_external_vm_failure(self):
        """
        We find *external* VMs to recover through libvirt,
        but Vdsm fail to create its Vm objects.
        We should then destroy the non-external VMs.
        """
        vm_infos = (
            ('a', True),
            ('b', False),
        )
        self.conn.domains = _make_domains_collection(vm_infos)
        with MonkeyPatchScope([(self.cif, 'createVm', _error)]):
            recovery.all_domains(self.cif)
        assert self.cif.vmRequests == \
            {}
        for vm_id, vm_is_ext in vm_infos:
            vm_obj = self.conn.domains[vm_id]
            expect_destroy = not vm_is_ext
            assert vm_obj.destroyed == expect_destroy

    def test_lookup_external_vms(self):
        vm_ext = [True] * len(self.vm_uuids)
        self.conn.domains = _make_domains_collection(
            list(zip(self.vm_uuids, vm_ext)))
        self.cif.unknown_vm_ids = list(self.vm_uuids)
        recovery.lookup_external_vms(self.cif)
        assert set(self.cif.vmRequests.keys()) == \
            set(self.vm_uuids)
        assert vm_ext == \
            [conf['external'] for conf, _ in self.cif.vmRequests.values()]

    def test_lookup_external_vms_fails(self):
        """
        Failure to get the XML of an external VM while trying lookup
        """
        vm_ext = [True] * len(self.vm_uuids)
        self.conn.domains = _make_domains_collection(
            list(zip(self.vm_uuids, vm_ext)))
        self.conn.domains['a'].XMLDesc = _raise
        self.cif.unknown_vm_ids = list(self.vm_uuids)
        recovery.lookup_external_vms(self.cif)
        assert set(self.cif.vmRequests.keys()) == \
            set(('b',))
Example #17
0
 def setUp(self):
     self.connection = vmfakecon.Connection()
     self.patch = Patch([
         (libvirtconnection, 'get', lambda: self.connection)
     ])
     self.patch.apply()
Example #18
0
class APITests(VdsmTestCase):

    def setUp(self):
        self.connection = vmfakecon.Connection()
        self.patch = Patch([
            (libvirtconnection, 'get', lambda: self.connection)
        ])
        self.patch.apply()

    def tearDown(self):
        self.patch.revert()
        libvirtconnection._clear()

    def test_clear(self):
        self.connection.secrets = {
            "uuid1": vmfakecon.Secret(self.connection, "uuid1", "ceph",
                                      "ovirt/name1", None),
            "uuid2": vmfakecon.Secret(self.connection, "uuid2", "ceph",
                                      "name2", None),
        }
        secret.clear()
        self.assertNotIn("uuid1", self.connection.secrets)
        self.assertIn("uuid2", self.connection.secrets)

    def test_clear_skip_failed(self):
        def fail():
            raise vmfakecon.Error(libvirt.VIR_ERR_INTERNAL_ERROR)
        self.connection.secrets = {
            "uuid1": vmfakecon.Secret(self.connection, "uuid1", "ceph",
                                      "ovirt/name1", None),
            "uuid2": vmfakecon.Secret(self.connection, "uuid2", "ceph",
                                      "ovirt/name2", None),
        }
        self.connection.secrets["uuid1"].undefine = fail
        secret.clear()
        self.assertNotIn("uuid2", self.connection.secrets)

    def test_register_validation(self):
        res = secret.register([{"invalid": "secret"}])
        self.assertEqual(res, response.error("secretBadRequestErr"))

    def test_register_new(self):
        sec1 = make_secret(password="******")
        sec2 = make_secret(password="******")
        res = secret.register([sec1, sec2])
        self.assertEqual(res, response.success())
        virsec1 = self.connection.secrets[sec1["uuid"]]
        self.assertEqual("sec1 password", virsec1.value)
        virsec2 = self.connection.secrets[sec2["uuid"]]
        self.assertEqual("sec2 password", virsec2.value)

    def test_register_replace(self):
        # Register 2 secrets
        sec1 = make_secret(password="******")
        sec2 = make_secret(password="******")
        secret.register([sec1, sec2])
        # Replace existing secret value
        sec2["password"] = make_password("sec2 new password")
        res = secret.register([sec2])
        self.assertEqual(res, response.success())
        virsec1 = self.connection.secrets[sec1["uuid"]]
        self.assertEqual("sec1 password", virsec1.value)
        virsec2 = self.connection.secrets[sec2["uuid"]]
        self.assertEqual("sec2 new password", virsec2.value)

    def test_register_change_usage_id(self):
        sec = make_secret(usage_id="ovirt/provider_uuid/secert_uuid")
        secret.register([sec])
        # Change usage id
        sec["usageID"] = "ovirt/domain_uuid/secret_uuid"
        res = secret.register([sec])
        self.assertEqual(res, response.success())
        virsec = self.connection.secrets[sec["uuid"]]
        self.assertEqual("ovirt/domain_uuid/secret_uuid", virsec.usage_id)

    def test_register_clear(self):
        self.connection.secrets = {
            "uuid1": vmfakecon.Secret(self.connection, "uuid1", "ceph",
                                      "ovirt/name1", None),
            "uuid2": vmfakecon.Secret(self.connection, "uuid2", "ceph",
                                      "name2", None),
        }
        sec = make_secret()
        res = secret.register([sec], clear=True)
        # Should succeed
        self.assertEqual(res, response.success())
        # Should remove existing ovirt secrets
        self.assertNotIn("uuid1", self.connection.secrets)
        # Should keep non-ovirt secrets
        self.assertIn("uuid2", self.connection.secrets)
        # Should register new secret
        virsec = self.connection.secrets[sec["uuid"]]
        self.assertEqual(sec["password"].value, virsec.value)

    def test_register_libvirt_error(self):
        def fail(xml):
            raise vmfakecon.Error(libvirt.VIR_ERR_INTERNAL_ERROR)
        self.connection.secretDefineXML = fail
        res = secret.register([make_secret()])
        self.assertEqual(res, response.error("secretRegisterErr"))

    def test_register_unexpected_error(self):
        def fail(xml):
            raise Unexpected
        self.connection.secretDefineXML = fail
        self.assertRaises(Unexpected, secret.register, [make_secret()])

    def test_unregister_validation(self):
        res = secret.unregister(["this-is-not-a-uuid"])
        self.assertEqual(res, response.error("secretBadRequestErr"))

    def test_unregister_existing(self):
        sec1 = make_secret(password="******")
        sec2 = make_secret(password="******")
        secret.register([sec1, sec2])
        res = secret.unregister([sec1["uuid"]])
        self.assertEqual(res, response.success())
        self.assertNotIn(sec1["uuid"], self.connection.secrets)
        self.assertIn(sec2["uuid"], self.connection.secrets)

    def test_unregister_missing(self):
        existing_sec = make_secret()
        secret.register([existing_sec])
        missing_sec = make_secret()
        res = secret.unregister([missing_sec["uuid"], existing_sec["uuid"]])
        self.assertEqual(res, response.success())
        self.assertEqual({}, self.connection.secrets)

    def test_unregister_libvirt_error(self):
        def fail(uuid):
            raise vmfakecon.Error(libvirt.VIR_ERR_INTERNAL_ERROR)
        self.connection.secretLookupByUUIDString = fail
        res = secret.unregister([str(uuid.uuid4())])
        self.assertEqual(res, response.error("secretUnregisterErr"))

    def test_unregister_unexpected_error(self):
        def fail(uuid):
            raise Unexpected
        self.connection.secretLookupByUUIDString = fail
        self.assertRaises(Unexpected, secret.unregister, [str(uuid.uuid4())])
Example #19
0
 def __init__(self, now):
     self.now = now
     self.patch = Patch([
         (utils, 'monotonic_time', self.monotonic_time),
         (time, 'sleep', self.sleep),
     ])
Example #20
0
class TestAllDomains(TestCaseBase):

    def setUp(self):
        self.vm_uuids = ('a', 'b',)
        self.vm_is_ext = [False] * len(self.vm_uuids)
        self.cif = fake.ClientIF()
        self.conn = FakeConnection()

        self.patch = Patch([
            (libvirtconnection, 'get', lambda *args, **kwargs: self.conn),
        ])
        self.patch.apply()

        # must be after patch.apply()
        self.conn.domains = _make_domains_collection(
            list(zip(self.vm_uuids, self.vm_is_ext))
        )

    def tearDown(self):
        self.patch.revert()

    def test_recover_no_domains(self):
        self.conn.domains = {}
        recovery.all_domains(self.cif)
        self.assertEqual(self.cif.vmRequests, {})

    def test_recover_few_domains(self):
        recovery.all_domains(self.cif)
        self.assertEqual(
            set(self.cif.vmRequests.keys()),
            set(self.vm_uuids)
        )
        self.assertEqual(
            self.vm_is_ext,
            [conf['external'] for conf, _ in self.cif.vmRequests.values()]
        )

    @permutations([
        # create_fn
        (_raise,),
        (_error,),
    ])
    def test_recover_failures(self, create_fn):
        """
        We find VMs to recover through libvirt, but Vdsm fail to create
        its Vm objects. We should then destroy those VMs.
        """
        with MonkeyPatchScope([
            (self.cif, 'createVm', create_fn)
        ]):
            recovery.all_domains(self.cif)
        self.assertEqual(
            self.cif.vmRequests,
            {}
        )
        self.assertTrue(all(
            vm.destroyed for vm in self.conn.domains.values()
        ))

    def test_domain_error(self):
        """
        We find VMs to recover through libvirt, but we get a failure trying
        to identify (UUIDString, XMLDesc) a domain being recovered
        """
        self.conn.domains['a'].XMLDesc = _raise
        recovery.all_domains(self.cif)
        self.assertEqual(
            set(self.cif.vmRequests.keys()),
            set(('b',))
        )

    def test_recover_and_destroy_failure(self):
        """
        We find VMs to recover through libvirt, but Vdsm fail to create
        its Vm objects. We should then destroy those VMs, but one of
        the domains can't complete that. We should handle this case
        gracefully
        """
        self.conn.domains['b'].destroy = _raise
        with MonkeyPatchScope([
            (self.cif, 'createVm', _error)
        ]):
            recovery.all_domains(self.cif)
        self.assertEqual(
            self.cif.vmRequests,
            {}
        )
        self.assertTrue(self.conn.domains['a'].destroyed)
        self.assertFalse(self.conn.domains['b'].destroyed)

    def test_external_vm(self):
        vm_infos = (('a', True), ('b', False),)
        self.conn.domains = _make_domains_collection(vm_infos)
        recovery.all_domains(self.cif)
        self.assertEqual(
            set(self.cif.vmRequests.keys()),
            set(vm_id for vm_id, _ in vm_infos)
        )

        for vm_id, vm_is_ext in vm_infos:
            conf, _ = self.cif.vmRequests[vm_id]
            self.assertEqual(vm_is_ext, conf['external'])

    def test_recover_external_vm_down(self):
        vm_is_ext = [True] * len(self.vm_uuids)
        self.conn.domains = _make_domains_collection(
            list(zip(self.vm_uuids, vm_is_ext))
        )
        for dom in self.conn.domains.values():
            dom.domState = libvirt.VIR_DOMAIN_SHUTOFF

        recovery.all_domains(self.cif)
        self.assertEqual(self.cif.vmRequests, {})

    def test_recover_external_vm_error(self):
        """
        handle gracefully error while getting the state of external VM
        """
        vm_is_ext = [True] * len(self.vm_uuids)
        self.conn.domains = _make_domains_collection(
            list(zip(self.vm_uuids, vm_is_ext))
        )
        for dom in self.conn.domains.values():
            dom.state = _raise

        recovery.all_domains(self.cif)
        self.assertEqual(self.cif.vmRequests, {})

    def test_external_vm_failure(self):
        """
        We find *external* VMs to recover through libvirt,
        but Vdsm fail to create its Vm objects.
        We should then destroy the non-external VMs.
        """
        vm_infos = (('a', True), ('b', False),)
        self.conn.domains = _make_domains_collection(vm_infos)
        with MonkeyPatchScope([
            (self.cif, 'createVm', _error)
        ]):
            recovery.all_domains(self.cif)
        self.assertEqual(
            self.cif.vmRequests,
            {}
        )
        for vm_id, vm_is_ext in vm_infos:
            vm_obj = self.conn.domains[vm_id]
            expect_destroy = not vm_is_ext
            self.assertEqual(vm_obj.destroyed, expect_destroy)

    def test_lookup_external_vms(self):
        vm_ext = [True] * len(self.vm_uuids)
        self.conn.domains = _make_domains_collection(
            list(zip(self.vm_uuids, vm_ext)))
        self.cif.unknown_vm_ids = list(self.vm_uuids)
        recovery.lookup_external_vms(self.cif)
        self.assertEqual(
            set(self.cif.vmRequests.keys()),
            set(self.vm_uuids)
        )
        self.assertEqual(
            vm_ext,
            [conf['external'] for conf, _ in self.cif.vmRequests.values()]
        )

    def test_lookup_external_vms_fails(self):
        """
        Failure to get the XML of an external VM while trying lookup
        """
        vm_ext = [True] * len(self.vm_uuids)
        self.conn.domains = _make_domains_collection(
            list(zip(self.vm_uuids, vm_ext)))
        self.conn.domains['a'].XMLDesc = _raise
        self.cif.unknown_vm_ids = list(self.vm_uuids)
        recovery.lookup_external_vms(self.cif)
        self.assertEqual(
            set(self.cif.vmRequests.keys()),
            set(('b',))
        )