Beispiel #1
0
class TestDeprovision(TestCase):
    """
    Same as above, but calls deprovision in the test (Test is same as previous)
    """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert(PROJECT, NETWORK)

        self.good_bmi = BMI(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD,
                            PROJECT)
        self.good_bmi.import_ceph_image(EXIST_IMG_NAME)
        self.good_bmi.provision(NODE_NAME, EXIST_IMG_NAME, NETWORK, NIC)
        time.sleep(constants.HIL_CALL_TIMEOUT)

    def runTest(self):
        response = self.good_bmi.deprovision(NODE_NAME, NETWORK, NIC)
        self.assertEqual(response[constants.STATUS_CODE_KEY], 200)
        time.sleep(constants.HIL_CALL_TIMEOUT)

    def tearDown(self):
        self.good_bmi.remove_image(EXIST_IMG_NAME)
        self.db.project.delete_with_name(PROJECT)
        self.db.close()
        self.good_bmi.shutdown()
Beispiel #2
0
class TestCopyImage(TestCase):
    """
    Creating a flatten copy of an image
    """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert(PROJECT)

        self.good_bmi = BMI(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD,
                            PROJECT)
        self.good_bmi.import_ceph_image(EXIST_IMG_NAME)

    def runTest(self):
        response = self.good_bmi.copy_image(EXIST_IMG_NAME, PROJECT, IMG2)
        self.assertEqual(response[constants.STATUS_CODE_KEY], 200)
        images = self.db.image.fetch_images_from_project(PROJECT)
        exists_image = False
        for image in images:
            if IMG2 == image:
                exists_image = True
                break
        self.assertTrue(exists_image)
        with ceph.RBD(_cfg.fs, _cfg.iscsi.password) as fs:
            img_id = self.good_bmi.get_ceph_image_name_from_project(
                IMG2, PROJECT)
            fs.get_image(img_id)

    def tearDown(self):
        self.good_bmi.remove_image(IMG2)
        self.good_bmi.remove_image(EXIST_IMG_NAME)
        self.db.project.delete_with_name(PROJECT)
        self.db.close()
        self.good_bmi.shutdown()
Beispiel #3
0
class TestListImages(TestCase):
    """
    Imports an import image and calls the list images rest call
    """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert(PROJECT)
        self.good_bmi = BMI(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD,
                            PROJECT)
        self.good_bmi.import_ceph_image(EXIST_IMG_NAME)

    def runTest(self):
        data = {constants.PROJECT_PARAMETER: PROJECT}
        res = requests.post(PICASSO_URL + "list_images/",
                            data=data,
                            auth=(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD))
        js = res.json()
        self.assertEqual(res.status_code, 200)
        self.assertEqual(js[0], EXIST_IMG_NAME)

    def tearDown(self):
        self.good_bmi.remove_image(EXIST_IMG_NAME)
        self.db.project.delete_with_name(PROJECT)
        self.db.close()
        self.good_bmi.shutdown()
Beispiel #4
0
class TestListSnapshots(TestCase):
    """
    Does the same steps as previous test and calls list snapshots rest call
    """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert(PROJECT)
        self.good_bmi = BMI(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD,
                            PROJECT)
        self.good_bmi.import_ceph_image(EXIST_IMG_NAME)
        self.good_bmi.create_disk(NEW_DISK, EXIST_IMG_NAME)

        self.good_bmi.create_snapshot(NEW_DISK, NEW_SNAP_NAME)

    def runTest(self):
        data = {constants.PROJECT_PARAMETER: PROJECT}
        res = requests.post(PICASSO_URL + "list_snapshots/",
                            data=data,
                            auth=(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD))
        self.assertEqual(res.status_code, 200)
        js = res.json()
        self.assertEqual(res.status_code, 200)
        self.assertEqual(js[0][0], NEW_SNAP_NAME)

    def tearDown(self):
        self.good_bmi.delete_disk(NEW_DISK)
        self.good_bmi.remove_image(NEW_SNAP_NAME)
        self.good_bmi.remove_image(EXIST_IMG_NAME)
        self.db.project.delete_with_name(PROJECT)
        self.db.close()
        self.good_bmi.shutdown()
        time.sleep(constants.HIL_CALL_TIMEOUT)
Beispiel #5
0
class TestRemoveImage(TestCase):
    """
    Imports an Image and calls the remove image rest call
    """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert(PROJECT)
        self.good_bmi = BMI(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD,
                            PROJECT)
        self.good_bmi.import_ceph_image(EXIST_IMG_NAME)

    def runTest(self):
        data = {
            constants.PROJECT_PARAMETER: PROJECT,
            constants.IMAGE_NAME_PARAMETER: EXIST_IMG_NAME
        }
        res = requests.delete(PICASSO_URL + "remove_image/",
                              data=data,
                              auth=(CORRECT_HIL_USERNAME,
                                    CORRECT_HIL_PASSWORD))
        self.assertEqual(res.status_code, 200)

    def tearDown(self):
        self.db.project.delete_with_name(PROJECT)
        self.db.close()
        self.good_bmi.shutdown()
Beispiel #6
0
class TestProvision(TestCase):
    """
    Tests Rest Provision call by importing an image and calling provision
    """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert(PROJECT)
        self.good_bmi = BMI(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD,
                            PROJECT)
        self.good_bmi.import_ceph_image(EXIST_IMG_NAME)
        self.good_bmi.create_disk(NEW_DISK, EXIST_IMG_NAME)

    def runTest(self):
        data = {
            constants.PROJECT_PARAMETER: PROJECT,
            constants.NODE_NAME_PARAMETER: NODE_NAME,
            constants.DISK_NAME_PARAMETER: NEW_DISK,
            constants.NIC_PARAMETER: NIC
        }
        res = requests.put(PICASSO_URL + "provision/",
                           data=data,
                           auth=(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD))
        self.assertEqual(res.status_code, 200)
        time.sleep(constants.HIL_CALL_TIMEOUT)

    def tearDown(self):
        self.good_bmi.delete_disk(NEW_DISK)
        self.good_bmi.deprovision(NODE_NAME, NIC)
        self.good_bmi.remove_image(EXIST_IMG_NAME)
        self.db.project.delete_with_name(PROJECT)
        self.db.close()
        self.good_bmi.shutdown()
        time.sleep(constants.HIL_CALL_TIMEOUT)
class TestDeprovision(TestCase):
    """
    Same as above, but calls deprovision in the test (Test is same as previous)
    """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert(PROJECT, NETWORK)

        self.good_bmi = BMI(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD,
                            PROJECT)
        self.good_bmi.import_ceph_image(EXIST_IMG_NAME)
        self.good_bmi.provision(NODE_NAME, EXIST_IMG_NAME, NETWORK, NIC)
        time.sleep(constants.HIL_CALL_TIMEOUT)

    def runTest(self):
        response = self.good_bmi.deprovision(NODE_NAME, NETWORK, NIC)
        self.assertEqual(response[constants.STATUS_CODE_KEY], 200)
        time.sleep(constants.HIL_CALL_TIMEOUT)

    def tearDown(self):
        self.good_bmi.remove_image(EXIST_IMG_NAME)
        self.db.project.delete_with_name(PROJECT)
        self.db.close()
        self.good_bmi.shutdown()
Beispiel #8
0
class TestInsert(TestCase):
    """ Creates a project and tests inserting images """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert('project 1')

    def runTest(self):
        self.db.image.insert('image 1', 1)
        self.db.image.insert('image 2', 1, is_public=True)
        self.db.image.insert('image 3', 1, parent_id=1)
        self.db.image.insert('image 4', 1, is_snapshot=True, parent_id=1)

        images = self.db.image.fetch_images_from_project('project 1')
        self.assertTrue('image 1' in images and 'image 2' in images)

        images = self.db.image.fetch_clones_from_project('project 1')
        self.assertTrue('image 3' in [img[0] for img in images])

        snapshots = self.db.image.fetch_snapshots_from_project('project 1')
        self.assertTrue('image 4' in [snapshot[0] for snapshot in snapshots])

        images = self.db.image.fetch_names_with_public()
        self.assertTrue('image 2' in images)

    def tearDown(self):
        self.db.project.delete_with_name('project 1')
        self.db.close()
class TestListSnapshots(TestCase):
    """
    Creates snapshot like previous and calls list snapshots
    """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert(PROJECT, NETWORK)

        self.good_bmi = BMI(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD,
                            PROJECT)
        self.good_bmi.import_ceph_image(EXIST_IMG_NAME)
        self.good_bmi.provision(NODE_NAME, EXIST_IMG_NAME, NETWORK, NIC)
        time.sleep(constants.HIL_CALL_TIMEOUT)

        self.good_bmi.create_snapshot(NODE_NAME, NEW_SNAP_NAME)

    def runTest(self):
        response = self.good_bmi.list_snapshots()
        self.assertEqual(response[constants.STATUS_CODE_KEY], 200)
        self.assertEqual(response[constants.RETURN_VALUE_KEY][0][0],
                         NEW_SNAP_NAME)

    def tearDown(self):
        self.good_bmi.deprovision(NODE_NAME, NETWORK, NIC)
        self.good_bmi.remove_image(NEW_SNAP_NAME)
        self.good_bmi.remove_image(EXIST_IMG_NAME)
        self.db.project.delete_with_name(PROJECT)
        self.db.close()
        self.good_bmi.shutdown()
        time.sleep(constants.HIL_CALL_TIMEOUT)
Beispiel #10
0
class TestMove(TestCase):
    """ Inserts images and tries moving them """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert('project 1')
        self.db.project.insert('project 2')
        self.db.image.insert('image 1', 1)
        self.db.image.insert('image 2', 1, is_snapshot=True, parent_id=1)

    def runTest(self):
        self.db.image.move_image('project 1', 'image 1', 2, None)
        self.db.image.move_image('project 1', 'image 2', 1, 'image 3')

        images = self.db.image.fetch_images_from_project('project 2')
        images1 = self.db.image.fetch_images_from_project('project 1')
        self.assertTrue('image 1' in images and 'image 1' not in images1)

        snaps = self.db.image.fetch_snapshots_from_project('project 1')
        self.assertTrue(('image 3' in [s[0] for s in snaps])
                        and not ('image 2' in [s[0] for s in snaps]))

    def tearDown(self):
        self.db.project.delete_with_name('project 1')
        self.db.project.delete_with_name('project 2')
        self.db.close()
Beispiel #11
0
class TestMove(TestCase):
    """ Inserts images and tries moving them """

    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert('project 1', 'network 1')
        self.db.project.insert('project 2', 'network 2')
        self.db.image.insert('image 1', 1)
        self.db.image.insert('image 2', 1, is_snapshot=True, parent_id=1)

    def runTest(self):
        self.db.image.move_image('project 1', 'image 1', 2, None)
        self.db.image.move_image('project 1', 'image 2', 1, 'image 3')

        images = self.db.image.fetch_images_from_project('project 2')
        images1 = self.db.image.fetch_images_from_project('project 1')
        self.assertTrue('image 1' in images and 'image 1' not in images1)

        snaps = self.db.image.fetch_snapshots_from_project('project 1')
        self.assertTrue(('image 3' in [s[0] for s in snaps]) and
                        not ('image 2' in [s[0] for s in snaps]))

    def tearDown(self):
        self.db.project.delete_with_name('project 1')
        self.db.project.delete_with_name('project 2')
        self.db.close()
Beispiel #12
0
class TestInsert(TestCase):
    """ Creates a project and tests inserting images """

    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert('project 1', 'network 1')

    def runTest(self):
        self.db.image.insert('image 1', 1)
        self.db.image.insert('image 2', 1, is_public=True)
        self.db.image.insert('image 3', 1, parent_id=1)
        self.db.image.insert('image 4', 1, is_snapshot=True, parent_id=1)

        images = self.db.image.fetch_images_from_project('project 1')
        self.assertTrue('image 1' in images and 'image 2' in images)

        images = self.db.image.fetch_clones_from_project('project 1')
        self.assertTrue('image 3' in [img[0] for img in images])

        snapshots = self.db.image.fetch_snapshots_from_project('project 1')
        self.assertTrue('image 4' in [snapshot[0] for snapshot in snapshots])

        images = self.db.image.fetch_names_with_public()
        self.assertTrue('image 2' in images)

    def tearDown(self):
        self.db.project.delete_with_name('project 1')
        self.db.close()
Beispiel #13
0
class TestListSnapshots(TestCase):
    """
    Creates snapshot like previous and calls list snapshots
    """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert(PROJECT)

        self.good_bmi = BMI(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD,
                            PROJECT)
        self.good_bmi.import_ceph_image(EXIST_IMG_NAME)
        self.good_bmi.create_disk(NEW_DISK, EXIST_IMG_NAME)
        time.sleep(constants.HIL_CALL_TIMEOUT)

        self.good_bmi.create_snapshot(NEW_DISK, NEW_SNAP_NAME)

    def runTest(self):
        response = self.good_bmi.list_snapshots()
        self.assertEqual(response[constants.STATUS_CODE_KEY], 200)
        self.assertEqual(response[constants.RETURN_VALUE_KEY][0][0],
                         NEW_SNAP_NAME)

    def tearDown(self):
        self.good_bmi.delete_disk(NEW_DISK)
        self.good_bmi.remove_image(NEW_SNAP_NAME)
        self.good_bmi.remove_image(EXIST_IMG_NAME)
        self.db.project.delete_with_name(PROJECT)
        self.db.close()
        self.good_bmi.shutdown()
        time.sleep(constants.HIL_CALL_TIMEOUT)
Beispiel #14
0
class TestDelete(TestCase):
    """ Inserts and Deletes Project """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert('project 1', 'network 1')

    def runTest(self):
        self.db.project.delete_with_name('project 1')
        projects = self.db.project.fetch_projects()
        self.assertFalse('project 1' in projects)

    def tearDown(self):
        self.db.close()
Beispiel #15
0
class TestFetch(TestCase):
    """ Inserts several images and tests all fetch calls """

    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert('project 1', 'network 1')
        self.db.image.insert('image 1', 1)
        self.db.image.insert('image 2', 1, is_public=True)
        self.db.image.insert('image 3', 1, parent_id=1)
        self.db.image.insert('image 4', 1, is_snapshot=True, parent_id=1)

    def test_image_fetch(self):
        images = self.db.image.fetch_images_from_project('project 1')
        self.assertTrue('image 1' in images and 'image 2' in images)

        images = self.db.image.fetch_clones_from_project('project 1')
        self.assertTrue('image 3' in [img[0] for img in images])

        snapshots = self.db.image.fetch_snapshots_from_project('project 1')
        self.assertTrue('image 4' in [snapshot[0] for snapshot in snapshots])

        images = self.db.image.fetch_names_with_public()
        self.assertTrue('image 2' in images)

        name = self.db.image.fetch_name_with_id(1)
        self.assertEqual(name, 'image 1')

        img_id = self.db.image.fetch_id_with_name_from_project('image 2',
                                                               'project 1')
        self.assertEqual(img_id, 2)

        images = self.db.image.fetch_all_images()
        self.assertEqual(images.__len__(), 4)
        self.assertEqual([image[1] for image in images],
                         ['image 1', 'image 2', 'image 3', 'image 4'])

    def test_nonexistent_image_fetch(self):
        """
        Tries to retrieve the image id of an image that doesn't
        exist in the db. Should raise an error
        """

        with self.assertRaises(db_exceptions.ImageNotFoundException):
            img_id = self.db.image.fetch_id_with_name_from_project(
                'nonexistent_image', 'project 1')

    def tearDown(self):
        self.db.project.delete_with_name('project 1')
        self.db.close()
Beispiel #16
0
class TestFetch(TestCase):
    """ Inserts several images and tests all fetch calls """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert('project 1')
        self.db.image.insert('image 1', 1)
        self.db.image.insert('image 2', 1, is_public=True)
        self.db.image.insert('image 3', 1, parent_id=1)
        self.db.image.insert('image 4', 1, is_snapshot=True, parent_id=1)

    def test_image_fetch(self):
        images = self.db.image.fetch_images_from_project('project 1')
        self.assertTrue('image 1' in images and 'image 2' in images)

        images = self.db.image.fetch_clones_from_project('project 1')
        self.assertTrue('image 3' in [img[0] for img in images])

        snapshots = self.db.image.fetch_snapshots_from_project('project 1')
        self.assertTrue('image 4' in [snapshot[0] for snapshot in snapshots])

        images = self.db.image.fetch_names_with_public()
        self.assertTrue('image 2' in images)

        name = self.db.image.fetch_name_with_id(1)
        self.assertEqual(name, 'image 1')

        img_id = self.db.image.fetch_id_with_name_from_project(
            'image 2', 'project 1')
        self.assertEqual(img_id, 2)

        images = self.db.image.fetch_all_images()
        self.assertEqual(images.__len__(), 4)
        self.assertEqual([image[1] for image in images],
                         ['image 1', 'image 2', 'image 3', 'image 4'])

    def test_nonexistent_image_fetch(self):
        """
        Tries to retrieve the image id of an image that doesn't
        exist in the db. Should raise an error
        """

        with self.assertRaises(db_exceptions.ImageNotFoundException):
            img_id = self.db.image.fetch_id_with_name_from_project(
                'nonexistent_image', 'project 1')

    def tearDown(self):
        self.db.project.delete_with_name('project 1')
        self.db.close()
Beispiel #17
0
class TestDelete(TestCase):
    """ Inserts and Deletes Project """

    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert('project 1', 'network 1')

    def runTest(self):
        self.db.project.delete_with_name('project 1')
        projects = self.db.project.fetch_projects()
        self.assertFalse('project 1' in projects)

    def tearDown(self):
        self.db.close()
Beispiel #18
0
class TestDelete(TestCase):
    """ Inserts image and deletes it """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert('project 1')
        self.db.image.insert('image 1', 1)

    def runTest(self):
        self.db.image.delete_with_name_from_project('image 1', 'project 1')
        images = self.db.image.fetch_images_from_project('project 1')
        self.assertFalse('image 1' in images)

    def tearDown(self):
        self.db.project.delete_with_name('project 1')
        self.db.close()
Beispiel #19
0
class TestInsert(TestCase):
    """ Inserts Project """
    @trace
    def setUp(self):
        self.db = Database()

    def runTest(self):
        self.db.project.insert('project 1', 'network 1')

        projects = self.db.project.fetch_projects()

        self.assertEqual('project 1', projects[0][1])

    def tearDown(self):
        self.db.project.delete_with_name('project 1')
        self.db.close()
Beispiel #20
0
class TestDelete(TestCase):
    """ Inserts image and deletes it """

    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert('project 1', 'network 1')
        self.db.image.insert('image 1', 1)

    def runTest(self):
        self.db.image.delete_with_name_from_project('image 1', 'project 1')
        images = self.db.image.fetch_images_from_project('project 1')
        self.assertFalse('image 1' in images)

    def tearDown(self):
        self.db.project.delete_with_name('project 1')
        self.db.close()
Beispiel #21
0
class TestInsert(TestCase):
    """ Inserts Project """

    @trace
    def setUp(self):
        self.db = Database()

    def runTest(self):
        self.db.project.insert('project 1', 'network 1')

        projects = self.db.project.fetch_projects()

        self.assertEqual('project 1', projects[0][1])

    def tearDown(self):
        self.db.project.delete_with_name('project 1')
        self.db.close()
Beispiel #22
0
class TestFetch(TestCase):
    """ Inserts and Fetches Projects """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert('project 1', 'network 1')

    def runTest(self):
        projects = self.db.project.fetch_projects()
        self.assertTrue('project 1' in projects[0])

        pid = self.db.project.fetch_id_with_name('project 1')
        self.assertEqual(pid, 1)

    def tearDown(self):
        self.db.project.delete_with_name('project 1')
        self.db.close()
Beispiel #23
0
class TestFetch(TestCase):
    """ Inserts and Fetches Projects """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert('project 1', 'network 1')

    def runTest(self):
        projects = self.db.project.fetch_projects()
        self.assertTrue('project 1' in projects[0])

        pid = self.db.project.fetch_id_with_name('project 1')
        self.assertEqual(pid, 1)

    def tearDown(self):
        self.db.project.delete_with_name('project 1')
        self.db.close()
Beispiel #24
0
class TestCreateSnapshot(TestCase):
    """
    Calls provision like TestProvision then creates a snapshot using rest call
    """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert(PROJECT)
        self.good_bmi = BMI(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD,
                            PROJECT)
        self.good_bmi.import_ceph_image(EXIST_IMG_NAME)
        self.good_bmi.create_disk(NEW_DISK, EXIST_IMG_NAME)
        time.sleep(constants.HIL_CALL_TIMEOUT)

    def runTest(self):
        data = {
            constants.PROJECT_PARAMETER: PROJECT,
            constants.DISK_NAME_PARAMETER: NEW_DISK,
            constants.SNAP_NAME_PARAMETER: NEW_SNAP_NAME
        }
        res = requests.put(PICASSO_URL + "create_snapshot/",
                           data=data,
                           auth=(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD))
        self.assertEqual(res.status_code, 200)

        snaps = self.db.image.fetch_snapshots_from_project(PROJECT)
        has_image = False
        for snapshot in snaps:
            if NEW_SNAP_NAME == snapshot[0]:
                has_image = True
        self.assertTrue(has_image)

        with ceph.RBD(_cfg.fs, _cfg.iscsi.password) as fs:
            img_id = self.good_bmi.get_ceph_image_name_from_project(
                NEW_SNAP_NAME, PROJECT)
            fs.get_image(img_id)

    def tearDown(self):
        self.good_bmi.delete_disk(NEW_DISK)
        self.good_bmi.remove_image(NEW_SNAP_NAME)
        self.good_bmi.remove_image(EXIST_IMG_NAME)
        self.db.project.delete_with_name(PROJECT)
        self.db.close()
        self.good_bmi.shutdown()
        time.sleep(constants.HIL_CALL_TIMEOUT)
class TestRemoveImage(TestCase):
    """
    Imports an image and calls remove image
    """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert(PROJECT, NETWORK)
        self.good_bmi = BMI(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD,
                            PROJECT)
        self.good_bmi.import_ceph_image(EXIST_IMG_NAME)

    def runTest(self):
        response = self.good_bmi.remove_image(EXIST_IMG_NAME)
        self.assertEqual(response[constants.STATUS_CODE_KEY], 200)

    def tearDown(self):
        self.db.project.delete_with_name(PROJECT)
        self.db.close()
        self.good_bmi.shutdown()
Beispiel #26
0
class TestRemoveImage(TestCase):
    """
    Imports an image and calls remove image
    """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert(PROJECT)
        self.good_bmi = BMI(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD,
                            PROJECT)
        self.good_bmi.import_ceph_image(EXIST_IMG_NAME)

    def runTest(self):
        response = self.good_bmi.remove_image(EXIST_IMG_NAME)
        self.assertEqual(response[constants.STATUS_CODE_KEY], 200)

    def tearDown(self):
        self.db.project.delete_with_name(PROJECT)
        self.db.close()
        self.good_bmi.shutdown()
Beispiel #27
0
class TestCreateSnapshot(TestCase):
    """
    Provisions an imported image and creates snapshot
    """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert(PROJECT, NETWORK)

        self.good_bmi = BMI(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD,
                            PROJECT)
        self.good_bmi.import_ceph_image(EXIST_IMG_NAME)
        self.good_bmi.provision(NODE_NAME, EXIST_IMG_NAME, NETWORK, NIC)
        time.sleep(constants.HIL_CALL_TIMEOUT)

    def runTest(self):
        response = self.good_bmi.create_snapshot(NODE_NAME, NEW_SNAP_NAME)
        self.assertEqual(response[constants.STATUS_CODE_KEY], 200)

        snaps = self.db.image.fetch_snapshots_from_project(PROJECT)
        has_image = False
        for snapshot in snaps:
            if NEW_SNAP_NAME == snapshot[0]:
                has_image = True
        self.assertTrue(has_image)

        with ceph.RBD(_cfg.fs,
                      _cfg.iscsi.password) as fs:
            img_id = self.good_bmi.get_ceph_image_name_from_project(
                NEW_SNAP_NAME, PROJECT)
            fs.get_image(img_id)

    def tearDown(self):
        self.good_bmi.deprovision(NODE_NAME, NETWORK, NIC)
        self.good_bmi.remove_image(NEW_SNAP_NAME)
        self.good_bmi.remove_image(EXIST_IMG_NAME)
        self.db.project.delete_with_name(PROJECT)
        self.db.close()
        self.good_bmi.shutdown()
        time.sleep(constants.HIL_CALL_TIMEOUT)
class TestCreateSnapshot(TestCase):
    """
    Provisions an imported image and creates snapshot
    """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert(PROJECT, NETWORK)

        self.good_bmi = BMI(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD,
                            PROJECT)
        self.good_bmi.import_ceph_image(EXIST_IMG_NAME)
        self.good_bmi.provision(NODE_NAME, EXIST_IMG_NAME, NETWORK, NIC)
        time.sleep(constants.HIL_CALL_TIMEOUT)

    def runTest(self):
        response = self.good_bmi.create_snapshot(NODE_NAME, NEW_SNAP_NAME)
        self.assertEqual(response[constants.STATUS_CODE_KEY], 200)

        snaps = self.db.image.fetch_snapshots_from_project(PROJECT)
        has_image = False
        for snapshot in snaps:
            if NEW_SNAP_NAME == snapshot[0]:
                has_image = True
        self.assertTrue(has_image)

        with ceph.RBD(_cfg.fs,
                      _cfg.iscsi.password) as fs:
            img_id = self.good_bmi.get_ceph_image_name_from_project(
                NEW_SNAP_NAME, PROJECT)
            fs.get_image(img_id)

    def tearDown(self):
        self.good_bmi.deprovision(NODE_NAME, NETWORK, NIC)
        self.good_bmi.remove_image(NEW_SNAP_NAME)
        self.good_bmi.remove_image(EXIST_IMG_NAME)
        self.db.project.delete_with_name(PROJECT)
        self.db.close()
        self.good_bmi.shutdown()
        time.sleep(constants.HIL_CALL_TIMEOUT)
Beispiel #29
0
class TestProvisionDeprovision(TestCase):
    """
    This tests multiple things. It creates an image, then provisions
    from it and then deprovisions the node and delete the image.
    """
    @trace
    def setUp(self):
        self.db = Database()
        self.db.project.insert(PROJECT)

        self.good_bmi = BMI(CORRECT_HIL_USERNAME, CORRECT_HIL_PASSWORD,
                            PROJECT)
        self.good_bmi.import_ceph_image(EXIST_IMG_NAME)

    def runTest(self):
        # First create a disk
        response = self.good_bmi.create_disk(NEW_DISK, EXIST_IMG_NAME)
        self.assertEqual(response[constants.STATUS_CODE_KEY], 200)

        # Then provision a node from that disk
        response = self.good_bmi.provision(NODE_NAME, NEW_DISK, NIC)
        self.assertEqual(response[constants.STATUS_CODE_KEY], 200)

        # Then deprovision that node
        response = self.good_bmi.deprovision(NODE_NAME, NIC)
        self.assertEqual(response[constants.STATUS_CODE_KEY], 200)

        # Delete the disk
        response = self.good_bmi.delete_disk(NEW_DISK)
        self.assertEqual(response[constants.STATUS_CODE_KEY], 200)

    def tearDown(self):
        self.good_bmi.remove_image(EXIST_IMG_NAME)
        self.db.project.delete_with_name(PROJECT)
        self.db.close()
        self.good_bmi.shutdown()
        time.sleep(constants.HIL_CALL_TIMEOUT)
Beispiel #30
0
class BMI:
    @log
    def __init__(self, *args):
        if args.__len__() == 1:
            credentials = args[0]
            self.cfg = config.get()
            self.db = Database()
            self.__process_credentials(credentials)
            self.hil = HIL(base_url=self.cfg.net_isolator.url,
                           usr=self.username,
                           passwd=self.password)
            self.fs = RBD(self.cfg.fs, self.cfg.iscsi.password)
            self.dhcp = DNSMasq()
            # self.iscsi = IET(self.fs, self.config.iscsi_update_password)
            # Need to make this generic by passing specific config
            self.iscsi = TGT(self.cfg.fs.conf_file, self.cfg.fs.id,
                             self.cfg.fs.pool)
        elif args.__len__() == 3:
            username, password, project = args
            self.cfg = config.get()
            self.username = username
            self.password = password
            self.proj = project
            self.db = Database()
            self.pid = self.__does_project_exist(self.proj)
            self.is_admin = self.__check_admin()
            self.hil = HIL(base_url=self.cfg.net_isolator.url,
                           usr=self.username,
                           passwd=self.password)
            self.fs = RBD(self.cfg.fs, self.cfg.iscsi.password)
            logger.debug("Username is %s and Password is %s", self.username,
                         self.password)
            self.dhcp = DNSMasq()
            # self.iscsi = IET(self.fs, self.config.iscsi_update_password)
            self.iscsi = TGT(self.cfg.fs.conf_file, self.cfg.fs.id,
                             self.cfg.fs.pool)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.shutdown()

    @trace
    def __does_project_exist(self, project):
        pid = self.db.project.fetch_id_with_name(project)
        # None as a query result implies that the project does not exist.
        if pid is None:
            logger.info("Raising Project Not Found Exception for %s", project)
            raise db_exceptions.ProjectNotFoundException(project)

        return pid

    # this method will determine whether user is admin (still unclear on doing
    # it properly)
    def __check_admin(self):
        return True

    @trace
    def __get_ceph_image_name(self, name):
        img_id = self.db.image.fetch_id_with_name_from_project(name, self.proj)
        return str(self.cfg.bmi.uid) + "img" + str(img_id)

    def get_ceph_image_name_from_project(self, name, project_name):
        img_id = self.db.image.fetch_id_with_name_from_project(
            name, project_name)
        if img_id is None:
            logger.info("Raising Image Not Found Exception for %s", name)
            raise db_exceptions.ImageNotFoundException(name)

        return str(self.cfg.bmi.uid) + "img" + str(img_id)

    @trace
    def __extract_id(self, ceph_img_name):
        start_index = ceph_img_name.find("img")
        start_index += 3
        img_id = ceph_img_name[start_index:]
        return img_id

    @trace
    def __process_credentials(self, credentials):
        base64_str, self.proj = credentials
        self.pid = self.__does_project_exist(self.proj)
        self.username, self.password = tuple(
            base64.b64decode(base64_str).split(':'))
        logger.debug("Username is %s and Password is %s", self.username,
                     self.password)
        self.is_admin = self.__check_admin()

    @log
    def __register(self, node_name, img_name, target_name, mac_addr):
        logger.debug("The Mac Addr File name is %s", mac_addr)
        self.__generate_ipxe_file(node_name, target_name)
        self.__generate_mac_addr_file(img_name, node_name, mac_addr)

    @log
    def __unregister(self, node_name, mac_addr):
        logger.debug("The Mac Addr File name is %s", mac_addr)
        self.__delete_ipxe_file(node_name)
        self.__delete_mac_addr_file(mac_addr)

    @log
    def __delete_ipxe_file(self, node_name):
        """Delete the ipxe file"""
        ipxe_file = self.cfg.tftp.ipxe_path + node_name + ".ipxe"
        self.__delete_file(ipxe_file)

    @log
    def __delete_mac_addr_file(self, mac_addr):
        """Delete the mac_addr file"""
        mac_addr_file = self.cfg.tftp.pxelinux_path + mac_addr
        self.__delete_file(mac_addr_file)

    @log
    def __delete_file(self, file_path):
        """Helper function to delete a file.
        If the file does not exist, consider it a success.
        """
        # FIXME: This method doesn't need to be on the class at all.
        # Moving it out of the class breaks logging for this function,
        # which is weird.
        try:
            os.remove(file_path)
        except OSError as e:
            if e.errno == errno.ENOENT:
                logger.info("mac_addr file does not exist")
                return
            raise RegistrationFailedException(node_name, e.strerror)

    @log
    def __generate_ipxe_file(self, node_name, target_name):
        template_loc = os.path.abspath(
            os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
        logger.debug("Template LOC = %s", template_loc)
        path = self.cfg.tftp.ipxe_path + node_name + ".ipxe"
        logger.debug("The Path for ipxe file is %s", path)
        try:
            with open(path, 'w') as ipxe:
                for line in open(template_loc + "/ipxe.temp", 'r'):
                    line = line.replace(constants.IPXE_TARGET_NAME,
                                        target_name)
                    line = line.replace(constants.IPXE_ISCSI_IP,
                                        self.cfg.iscsi.ip)
                    ipxe.write(line)
            logger.info("Generated ipxe file")
            os.chmod(path, 0755)
            logger.info("Changed permissions to 755")
        except (OSError, IOError) as e:
            logger.info("Raising Registration Failed Exception for %s",
                        node_name)
            raise RegistrationFailedException(node_name, e.message)

    @log
    def __generate_mac_addr_file(self, img_name, node_name, mac_addr):
        template_loc = os.path.abspath(
            os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
        logger.debug("Template LOC = %s", template_loc)
        path = self.cfg.tftp.pxelinux_path + mac_addr
        logger.debug("The Path for mac addr file is %s", path)
        try:
            with open(path, 'w') as mac:
                for line in open(template_loc + "/mac.temp", 'r'):
                    line = line.replace(constants.MAC_IMG_NAME, img_name)
                    line = line.replace(constants.MAC_IPXE_NAME,
                                        node_name + ".ipxe")
                    mac.write(line)
            logger.info("Generated mac addr file")
            os.chmod(path, 0644)
            logger.debug("Changed permissions to 644")
        except (OSError, IOError) as e:
            logger.info("Raising Registration Failed Exception for %s",
                        node_name)
            raise RegistrationFailedException(node_name, e.message)

    # Parses the Exception and returns the dict that should be returned to user
    @log
    def __return_error(self, ex):

        # Replaces the image name with id in error string
        @log
        def swap_id_with_name(err_str):
            parts = err_str.split(" ")
            start_index = parts[0].find("img")
            if start_index != -1:
                start_index += 3
                img_id = parts[0][start_index:]
                name = self.db.image.fetch_name_with_id(img_id)
                if name is not None:
                    parts[0] = name
            return " ".join(parts)

        logger.debug("Checking if FileSystemException")
        if FileSystemException in ex.__class__.__bases__:
            logger.debug("It is FileSystemException")
            return {
                constants.STATUS_CODE_KEY: ex.status_code,
                constants.MESSAGE_KEY: swap_id_with_name(str(ex))
            }

        return {
            constants.STATUS_CODE_KEY: ex.status_code,
            constants.MESSAGE_KEY: str(ex)
        }

    # A custom function which is wrapper around only success code that
    # we are creating.
    @log
    def __return_success(self, obj):
        return {
            constants.STATUS_CODE_KEY: 200,
            constants.RETURN_VALUE_KEY: obj
        }

    @log
    def shutdown(self):
        self.fs.tear_down()
        self.db.close()

    # Provisions from HIL and Boots the given node with given image

    @log
    def create_disk(self, disk_name, img_name):
        """
        Creates a new image named <disk_name> from <img_name>,
        and then creates an iscsi endpoint for <disk_name>.
        Returns the disk image name (which also happens to be the iscsi target
        name)
        Note: The name of the iscsi target and the name of disk in ceph is same
        """
        # Database Operations
        try:
            # Find the image id by using the image name, and then create a new
            # entry for the new disk image.
            parent_id = self.db.image.fetch_id_with_name_from_project(
                img_name, self.proj)
            self.db.image.insert(disk_name, self.pid, parent_id)

            # This generates the name that BMI *must* have used when it created
            # the copy in ceph of img_name
            ceph_img_name = self.__get_ceph_image_name(img_name)

            # Prepare the ceph image name to be used.
            clone_ceph_name = self.__get_ceph_image_name(disk_name)
        except db_exceptions.ORMException as e:
            clone_ceph_name = self.__get_ceph_image_name(disk_name)
            return {
                constants.STATUS_CODE_KEY: 409,
                constants.MESSAGE_KEY:
                "Disk exists. Endpoint:" + clone_ceph_name
            }
        except DBException as e:
            logger.exception('')
            return self.__return_error(e)

        # Storage Operations
        try:
            self.fs.clone(ceph_img_name, self.cfg.bmi.snapshot,
                          clone_ceph_name)
        except FileSystemException as e:
            logger.exception('')
            self.db.image.delete_with_name_from_project(disk_name, self.proj)

        # iSCSI Operations
        try:
            self.iscsi.add_target(clone_ceph_name)
        except ISCSIException as e:
            logger.exception('')
            self.fs.remove(clone_ceph_name)
            self.db.image.delete_with_name_from_project(disk_name, self.proj)

        logger.info("The create_disk command was executed successfully")

        # This will be changed to return a list of all targets, with each
        # target including the endpoint, port and target name.
        return self.__return_success(clone_ceph_name)

    @log
    def delete_disk(self, disk_name):
        """
        Deletes the disk image <disk_name>. Also deletes the iSCSI target
        pointing to that image.
        """
        try:
            # Get the ceph image name.
            ceph_img_name = self.__get_ceph_image_name(disk_name)
        except DBException as e:
            logger.exception('')
            return self.__return_error(e)

        try:
            self.iscsi.remove_target(ceph_img_name)
        except ISCSIException as e:
            logger.exception('')
            return self.__return_error(e)

        try:
            ret = self.fs.remove(str(ceph_img_name).encode("utf-8"))
        except FileSystemException as e:
            # what if this fails? Also, we should check if it doesnt exists
            # in ceph then continue, otherwise raise an error.
            self.isci.add_target(ceph_img_name)
            return self.__return_error(e)

        # If __get_ceph_image_name(disk_name) passes, then it confirms that
        # existence of disk_name, and then this delete from db command should
        # succeed. Will think more if I need to wrap this up in a try except
        # block.
        self.db.image.delete_with_name_from_project(disk_name, self.proj)
        return self.__return_success(ret)

    @log
    def provision(self, node_name, disk_name, nic):
        """
        This takes in the name of the disk, and then creates the ipxe
        and macaddress file for <node> with <nic>
        """
        try:
            mac_addr = "01-" + self.hil.get_node_mac_addr(node_name, nic). \
                replace(":", "-")
            clone_ceph_name = self.__get_ceph_image_name(disk_name)
            self.__register(node_name, disk_name, clone_ceph_name, mac_addr)
            return self.__return_success(True)

        except (RegistrationFailedException, DBException, HILException) as e:
            # Message is being handled by custom formatter
            logger.exception('')
            return self.__return_error(e)

    @log
    def deprovision(self, node_name, nic):
        """
        This takes in the name of the node and nic to deprovision.
        This method deletes the ipxe file and the bootfile.
        """
        try:
            mac_addr = "01-" + self.hil.get_node_mac_addr(node_name, nic). \
                replace(":", "-")
            self.__unregister(node_name, mac_addr)
            return self.__return_success(True)

        except (RegistrationFailedException, HILException) as e:
            # Message is being handled by custom formatter
            logger.exception('')
            return self.__return_error(e)

    # Creates snapshot for the given image with snap_name as given name
    # fs_obj will be populated by decorator
    @log
    def create_snapshot(self, disk_name, snap_name):
        try:
            self.hil.validate_project(self.proj)

            ceph_img_name = self.__get_ceph_image_name(disk_name)

            self.fs.snap_image(ceph_img_name, self.cfg.bmi.snapshot)
            self.fs.snap_protect(ceph_img_name, self.cfg.bmi.snapshot)
            parent_id = self.db.image.fetch_parent_id(self.proj, disk_name)
            self.db.image.insert(snap_name,
                                 self.pid,
                                 parent_id,
                                 is_snapshot=True)
            snap_ceph_name = self.__get_ceph_image_name(snap_name)
            self.fs.clone(ceph_img_name, self.cfg.bmi.snapshot, snap_ceph_name)
            self.fs.flatten(snap_ceph_name)
            self.fs.snap_image(snap_ceph_name, self.cfg.bmi.snapshot)
            self.fs.snap_protect(snap_ceph_name, self.cfg.bmi.snapshot)
            self.fs.snap_unprotect(ceph_img_name, self.cfg.bmi.snapshot)
            self.fs.remove_snapshot(ceph_img_name, self.cfg.bmi.snapshot)
            return self.__return_success(True)

        except (HILException, DBException, FileSystemException) as e:
            logger.exception('')
            return self.__return_error(e)

    # Lists snapshot for the given image img_name
    # URL's have to be read from BMI config file
    # fs_obj will be populated by decorator
    @log
    def list_snapshots(self):
        try:
            self.hil.validate_project(self.proj)
            snapshots = self.db.image.fetch_snapshots_from_project(self.proj)
            return self.__return_success(snapshots)

        except (HILException, DBException, FileSystemException) as e:
            logger.exception('')
            return self.__return_error(e)

    # Removes snapshot snap_name for the given image img_name
    # fs_obj will be populated by decorator
    @log
    def remove_image(self, img_name):
        try:
            self.hil.validate_project(self.proj)
            ceph_img_name = self.__get_ceph_image_name(img_name)

            self.fs.snap_unprotect(ceph_img_name, self.cfg.bmi.snapshot)
            self.fs.remove_snapshot(ceph_img_name, self.cfg.bmi.snapshot)
            self.fs.remove(ceph_img_name)
            self.db.image.delete_with_name_from_project(img_name, self.proj)
            return self.__return_success(True)
        except (HILException, DBException, FileSystemException) as e:
            logger.exception('')
            return self.__return_error(e)

    # Lists the images for the project which includes the snapshot
    @log
    def list_images(self):
        try:
            self.hil.validate_project(self.proj)
            names = self.db.image.fetch_images_from_project(self.proj)
            return self.__return_success(names)

        except (HILException, DBException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def list_disks(self):
        """Show all disks that belong to <project>."""

        try:
            clones = self.db.image.fetch_clones_from_project(self.proj)
            return self.__return_success(clones)
        except DBException as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def list_all_images(self):
        try:
            images = self.db.image.fetch_all_images()
            new_images = []
            for image in images:
                image.insert(
                    3,
                    self.get_ceph_image_name_from_project(image[1], image[2]))
                new_images.append(image)
            return self.__return_success(new_images)
        except DBException as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def import_ceph_image(self, img):
        """
        Import an image from ceph to be used by BMI

        Clone an image in ceph to be used by BMI.

        : param img: Name of image in ceph
        : return: True on successful completion
        """

        try:
            ceph_img_name = str(img)

            # create a snapshot of the golden image and protect it
            # this is needed because, in ceph, you can only create clones from
            # snapshots.
            self.fs.snap_image(ceph_img_name, self.cfg.bmi.snapshot)
            self.fs.snap_protect(ceph_img_name, self.cfg.bmi.snapshot)

            # insert golden image name into bmi db
            self.db.image.insert(ceph_img_name, self.pid)

            # get a name for our copy of the golden image. For instance an
            # image in ceph called centos6.7, after cloning, will be a given
            # a name like 4img1 based on the UID in config and image id in db
            snap_ceph_name = self.__get_ceph_image_name(ceph_img_name)

            # clone the snapshot of the golden image and then flatten it
            self.fs.clone(ceph_img_name, self.cfg.bmi.snapshot, snap_ceph_name)
            self.fs.flatten(snap_ceph_name)

            # create a snapshot of our newly created golden image so that when
            # we provision, we can easily make clones from this readily
            # available snapshot.
            self.fs.snap_image(snap_ceph_name, self.cfg.bmi.snapshot)
            self.fs.snap_protect(snap_ceph_name, self.cfg.bmi.snapshot)

            # unprotect and delete the snapshot of the original golden because
            # we no longer need it.
            self.fs.snap_unprotect(ceph_img_name, self.cfg.bmi.snapshot)
            self.fs.remove_snapshot(ceph_img_name, self.cfg.bmi.snapshot)
            return self.__return_success(True)
        except (DBException, FileSystemException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def import_ceph_snapshot(self, img, snap_name, protect):
        """
        Import a snapshot from ceph to be used by BMI

        Clone a snapshot in ceph to be used by BMI. Similar to
        import_ceph_image except we can directly start the cloning process
        because it is already a snapshot.

        : param img: Name of snapshot in ceph
        : return: True on successful completion
        """
        try:
            ceph_img_name = str(img)

            if protect:
                self.fs.snap_protect(ceph_img_name, snap_name)
            self.db.image.insert(ceph_img_name, self.pid)
            snap_ceph_name = self.__get_ceph_image_name(ceph_img_name)
            self.fs.clone(ceph_img_name, snap_name, snap_ceph_name)
            self.fs.flatten(snap_ceph_name)
            self.fs.snap_image(snap_ceph_name, self.cfg.bmi.snapshot)
            self.fs.snap_protect(snap_ceph_name, self.cfg.bmi.snapshot)
            return self.__return_success(True)
        except (DBException, FileSystemException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def export_ceph_image(self, img, name):
        try:
            ceph_img_name = self.__get_ceph_image_name(img)
            self.fs.clone(ceph_img_name, self.cfg.bmi.snapshot, name)
            self.fs.flatten(name)
            return self.__return_success(True)
        except FileSystemException as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def delete_image(self, project, img):
        try:
            if not self.is_admin:
                raise AuthorizationFailedException()
            self.db.image.delete_with_name_from_project(img, project)
            return self.__return_success(True)
        except (DBException, AuthorizationFailedException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def add_image(self, project, img, id, snap, parent, public):
        try:
            if not self.is_admin:
                raise AuthorizationFailedException()
            parent_id = None
            if parent is not None:
                parent_id = self.db.image.fetch_id_with_name_from_project(
                    parent, project)
            pid = self.__does_project_exist(project)
            self.db.image.insert(img, pid, parent_id, public, snap, id)
            return self.__return_success(True)
        except (DBException, AuthorizationFailedException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def get_node_ip(self, node_name):
        try:
            mac_addr = self.hil.get_node_mac_addr(node_name)
            return self.__return_success(self.dhcp.get_ip(mac_addr))
        except (HILException, DHCPException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def copy_image(self, img1, dest_project, img2=None):
        """
        Create a deep copy of src image

        : param img1: Name of src image
        : param dest_project: Name of the project where des image will be
        created
        : param img2: Name of des image
        : return: True on successful completion
        """
        try:
            if not self.is_admin and (self.proj != dest_project):
                raise AuthorizationFailedException()
            dest_pid = self.__does_project_exist(dest_project)
            self.db.image.copy_image(self.proj, img1, dest_pid, img2)
            if img2 is not None:
                ceph_name = self.get_ceph_image_name_from_project(
                    img2, dest_project)
            else:
                ceph_name = self.get_ceph_image_name_from_project(
                    img1, dest_project)
            self.fs.clone(
                self.get_ceph_image_name_from_project(img1, self.proj),
                self.cfg.bmi.snapshot, ceph_name)

            self.fs.flatten(ceph_name)
            self.fs.snap_image(ceph_name, self.cfg.bmi.snapshot)
            self.fs.snap_protect(ceph_name, self.cfg.bmi.snapshot)

            return self.__return_success(True)
        except (DBException, FileSystemException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def move_image(self, img1, dest_project, img2):
        try:
            if not self.is_admin and (self.proj != dest_project):
                raise AuthorizationFailedException()
            dest_pid = self.__does_project_exist(dest_project)
            self.db.image.move_image(self.proj, img1, dest_pid, img2)
            return self.__return_success(True)
        except DBException as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def add_project(self, project, id):
        try:
            if not self.is_admin:
                raise AuthorizationFailedException()
            self.db.project.insert(project, id)
            return self.__return_success(True)
        except (DBException, AuthorizationFailedException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def delete_project(self, project):
        try:
            if not self.is_admin:
                raise AuthorizationFailedException()
            self.db.project.delete_with_name(project)
            return self.__return_success(True)
        except (DBException, AuthorizationFailedException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def list_projects(self):
        try:
            if not self.is_admin:
                raise AuthorizationFailedException()
            projects = self.db.project.fetch_projects()
            return self.__return_success(projects)
        except (DBException, AuthorizationFailedException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def mount_image(self, img):
        try:
            if not self.is_admin:
                raise AuthorizationFailedException()
            ceph_img_name = self.__get_ceph_image_name(img)
            self.iscsi.add_target(ceph_img_name)
            return self.__return_success(True)
        except (ISCSIException, DBException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def umount_image(self, img):
        try:
            if not self.is_admin:
                raise AuthorizationFailedException()
            ceph_img_name = self.__get_ceph_image_name(img)
            self.iscsi.remove_target(ceph_img_name)
            return self.__return_success(True)
        except (ISCSIException, DBException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def show_mounted(self):
        try:
            if not self.is_admin:
                raise AuthorizationFailedException()
            mappings = self.iscsi.list_targets()
            swapped_mappings = {}
            for k, v in mappings.iteritems():
                img_id = self.__extract_id(k)
                if self.proj == self.db.image.fetch_project_with_id(img_id):
                    swapped_mappings[self.db.image.fetch_name_with_id(
                        img_id)] = v
            return self.__return_success(swapped_mappings)
        except (ISCSIException, DBException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def remake_mappings(self):
        try:
            self.iscsi.persist_targets()
        except (FileSystemException, ISCSIException) as e:
            logger.exception('')
        except NotImplementedError:
            pass
Beispiel #31
0
class BMI:
    @log
    def __init__(self, *args):
        if args.__len__() == 1:
            credentials = args[0]
            self.cfg = config.get()
            self.db = Database()
            self.__process_credentials(credentials)
            self.hil = HIL(base_url=self.cfg.net_isolator.url,
                           usr=self.username,
                           passwd=self.password)
            self.fs = RBD(self.cfg.fs, self.cfg.iscsi.password)
            self.dhcp = DNSMasq()
            # self.iscsi = IET(self.fs, self.config.iscsi_update_password)
            # Need to make this generic by passing specific config
            self.iscsi = TGT(self.cfg.fs.conf_file, self.cfg.fs.id,
                             self.cfg.fs.pool)
        elif args.__len__() == 3:
            username, password, project = args
            self.cfg = config.get()
            self.username = username
            self.password = password
            self.proj = project
            self.db = Database()
            self.pid = self.__does_project_exist(self.proj)
            self.is_admin = self.__check_admin()
            self.hil = HIL(base_url=self.cfg.net_isolator.url,
                           usr=self.username,
                           passwd=self.password)
            self.fs = RBD(self.cfg.fs, self.cfg.iscsi.password)
            logger.debug("Username is %s and Password is %s", self.username,
                         self.password)
            self.dhcp = DNSMasq()
            # self.iscsi = IET(self.fs, self.config.iscsi_update_password)
            self.iscsi = TGT(self.cfg.fs.conf_file, self.cfg.fs.id,
                             self.cfg.fs.pool)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.shutdown()

    @trace
    def __does_project_exist(self, project):
        pid = self.db.project.fetch_id_with_name(project)
        # None as a query result implies that the project does not exist.
        if pid is None:
            logger.info("Raising Project Not Found Exception for %s", project)
            raise db_exceptions.ProjectNotFoundException(project)

        return pid

    # this method will determine whether user is admin (still unclear on doing
    # it properly)
    def __check_admin(self):
        return True

    @trace
    def __get_ceph_image_name(self, name):
        img_id = self.db.image.fetch_id_with_name_from_project(name, self.proj)
        if img_id is None:
            logger.info("Raising Image Not Found Exception for %s", name)
            raise db_exceptions.ImageNotFoundException(name)

        return str(self.cfg.bmi.uid) + "img" + str(img_id)

    def get_ceph_image_name_from_project(self, name, project_name):
        img_id = self.db.image.fetch_id_with_name_from_project(
            name, project_name)
        if img_id is None:
            logger.info("Raising Image Not Found Exception for %s", name)
            raise db_exceptions.ImageNotFoundException(name)

        return str(self.cfg.bmi.uid) + "img" + str(img_id)

    @trace
    def __extract_id(self, ceph_img_name):
        start_index = ceph_img_name.find("img")
        start_index += 3
        img_id = ceph_img_name[start_index:]
        return img_id

    @trace
    def __process_credentials(self, credentials):
        base64_str, self.proj = credentials
        self.pid = self.__does_project_exist(self.proj)
        self.username, self.password = tuple(
            base64.b64decode(base64_str).split(':'))
        logger.debug("Username is %s and Password is %s", self.username,
                     self.password)
        self.is_admin = self.__check_admin()

    @log
    def __register(self, node_name, img_name, target_name, mac_addr):
        logger.debug("The Mac Addr File name is %s", mac_addr)
        self.__generate_ipxe_file(node_name, target_name)
        self.__generate_mac_addr_file(img_name, node_name, mac_addr)

    @log
    def __generate_ipxe_file(self, node_name, target_name):
        template_loc = os.path.abspath(
            os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
        logger.debug("Template LOC = %s", template_loc)
        path = self.cfg.tftp.ipxe_path + node_name + ".ipxe"
        logger.debug("The Path for ipxe file is %s", path)
        try:
            with open(path, 'w') as ipxe:
                for line in open(template_loc + "/ipxe.temp", 'r'):
                    line = line.replace(constants.IPXE_TARGET_NAME,
                                        target_name)
                    line = line.replace(constants.IPXE_ISCSI_IP,
                                        self.cfg.iscsi.ip)
                    ipxe.write(line)
            logger.info("Generated ipxe file")
            os.chmod(path, 0755)
            logger.info("Changed permissions to 755")
        except (OSError, IOError) as e:
            logger.info("Raising Registration Failed Exception for %s",
                        node_name)
            raise RegistrationFailedException(node_name, e.message)

    @log
    def __generate_mac_addr_file(self, img_name, node_name, mac_addr):
        template_loc = os.path.abspath(
            os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
        logger.debug("Template LOC = %s", template_loc)
        path = self.cfg.tftp.pxelinux_path + mac_addr
        logger.debug("The Path for mac addr file is %s", path)
        try:
            with open(path, 'w') as mac:
                for line in open(template_loc + "/mac.temp", 'r'):
                    line = line.replace(constants.MAC_IMG_NAME, img_name)
                    line = line.replace(constants.MAC_IPXE_NAME,
                                        node_name + ".ipxe")
                    mac.write(line)
            logger.info("Generated mac addr file")
            os.chmod(path, 0644)
            logger.debug("Changed permissions to 644")
        except (OSError, IOError) as e:
            logger.info("Raising Registration Failed Exception for %s",
                        node_name)
            raise RegistrationFailedException(node_name, e.message)

    # Parses the Exception and returns the dict that should be returned to user
    @log
    def __return_error(self, ex):

        # Replaces the image name with id in error string
        @log
        def swap_id_with_name(err_str):
            parts = err_str.split(" ")
            start_index = parts[0].find("img")
            if start_index != -1:
                start_index += 3
                img_id = parts[0][start_index:]
                name = self.db.image.fetch_name_with_id(img_id)
                if name is not None:
                    parts[0] = name
            return " ".join(parts)

        logger.debug("Checking if FileSystemException")
        if FileSystemException in ex.__class__.__bases__:
            logger.debug("It is FileSystemException")
            return {
                constants.STATUS_CODE_KEY: ex.status_code,
                constants.MESSAGE_KEY: swap_id_with_name(str(ex))
            }

        return {
            constants.STATUS_CODE_KEY: ex.status_code,
            constants.MESSAGE_KEY: str(ex)
        }

    # A custom function which is wrapper around only success code that
    # we are creating.
    @log
    def __return_success(self, obj):
        return {
            constants.STATUS_CODE_KEY: 200,
            constants.RETURN_VALUE_KEY: obj
        }

    @log
    def shutdown(self):
        self.fs.tear_down()
        self.db.close()

    # Provisions from HIL and Boots the given node with given image
    @log
    def provision(self, node_name, img_name, network, nic):
        try:
            mac_addr = "01-" + self.hil.get_node_mac_addr(node_name). \
                replace(":", "-")
            self.hil.attach_node_to_project_network(node_name, network, nic)

            parent_id = self.db.image.fetch_id_with_name_from_project(
                img_name, self.proj)
            self.db.image.insert(node_name, self.pid, parent_id)
            clone_ceph_name = self.__get_ceph_image_name(node_name)
            ceph_img_name = self.__get_ceph_image_name(img_name)
            self.fs.clone(ceph_img_name, constants.DEFAULT_SNAPSHOT_NAME,
                          clone_ceph_name)
            ceph_config = self.cfg.fs
            logger.debug("Contents of ceph_config = %s", str(ceph_config))
            self.iscsi.add_target(clone_ceph_name)
            logger.info("The create command was executed successfully")
            self.__register(node_name, img_name, clone_ceph_name, mac_addr)
            return self.__return_success(True)

        except RegistrationFailedException as e:
            # Message is being handled by custom formatter
            # TODO: add a deployment and a unit test for this case.
            logger.exception('')
            clone_ceph_name = self.__get_ceph_image_name(node_name)
            self.iscsi.remove_target(clone_ceph_name)
            self.fs.remove(clone_ceph_name)
            self.db.image.delete_with_name_from_project(node_name, self.proj)
            time.sleep(constants.HIL_CALL_TIMEOUT)
            self.hil.detach_node_from_project_network(node_name, network, nic)
            return self.__return_error(e)

        except ISCSIException as e:
            # Message is being handled by custom formatter
            logger.exception('')
            clone_ceph_name = self.__get_ceph_image_name(node_name)
            self.fs.remove(clone_ceph_name)
            self.db.image.delete_with_name_from_project(node_name, self.proj)
            time.sleep(constants.HIL_CALL_TIMEOUT)
            self.hil.detach_node_from_project_network(node_name, network, nic)
            return self.__return_error(e)

        except FileSystemException as e:
            # Message is being handled by custom formatter
            logger.exception('')
            self.db.image.delete_with_name_from_project(node_name, self.proj)
            time.sleep(constants.HIL_CALL_TIMEOUT)
            self.hil.detach_node_from_project_network(node_name, network, nic)
            return self.__return_error(e)
        except DBException as e:
            # Message is being handled by custom formatter
            logger.exception('')
            time.sleep(constants.HIL_CALL_TIMEOUT)
            self.hil.detach_node_from_project_network(node_name, network, nic)
            return self.__return_error(e)
        except HILException as e:
            # Message is being handled by custom formatter
            logger.exception('')
            return self.__return_error(e)

    # This is for detach a node and removing it from iscsi
    # and destroying its image
    @log
    def deprovision(self, node_name, network, nic):
        ceph_img_name = None
        try:
            self.hil.detach_node_from_project_network(node_name, network, nic)
            ceph_img_name = self.__get_ceph_image_name(node_name)
            self.db.image.delete_with_name_from_project(node_name, self.proj)
            ceph_config = self.cfg.fs
            logger.debug("Contents of ceph+config = %s", str(ceph_config))
            self.iscsi.remove_target(ceph_img_name)
            logger.info("The delete command was executed successfully")
            ret = self.fs.remove(str(ceph_img_name).encode("utf-8"))
            return self.__return_success(ret)

        except FileSystemException as e:
            logger.exception('')
            self.iscsi.add_target(ceph_img_name)
            parent_name = self.fs.get_parent_info(ceph_img_name)[1]

            parent_id = self.db.image.fetch_id_with_name_from_project(
                parent_name, self.proj)
            self.db.image.insert(node_name,
                                 self.pid,
                                 parent_id,
                                 id=self.__extract_id(ceph_img_name))
            time.sleep(constants.HIL_CALL_TIMEOUT)
            self.hil.attach_node_to_project_network(node_name, network, nic)
            return self.__return_error(e)
        except ISCSIException as e:
            logger.exception('')
            parent_name = self.fs.get_parent_info(ceph_img_name)[1]
            parent_id = self.db.image.fetch_id_with_name_from_project(
                parent_name, self.proj)
            self.db.image.insert(node_name,
                                 self.pid,
                                 parent_id,
                                 id=self.__extract_id(ceph_img_name))
            time.sleep(constants.HIL_CALL_TIMEOUT)
            self.hil.attach_node_to_project_network(node_name, network, nic)
            return self.__return_error(e)
        except DBException as e:
            logger.exception('')
            time.sleep(constants.HIL_CALL_TIMEOUT)
            self.hil.attach_node_to_project_network(node_name, network, nic)
            return self.__return_error(e)
        except HILException as e:
            logger.exception('')
            return self.__return_error(e)

    # Creates snapshot for the given image with snap_name as given name
    # fs_obj will be populated by decorator
    @log
    def create_snapshot(self, node_name, snap_name):
        try:
            self.hil.validate_project(self.proj)

            ceph_img_name = self.__get_ceph_image_name(node_name)

            self.fs.snap_image(ceph_img_name, constants.DEFAULT_SNAPSHOT_NAME)
            self.fs.snap_protect(ceph_img_name,
                                 constants.DEFAULT_SNAPSHOT_NAME)
            parent_id = self.db.image.fetch_parent_id(self.proj, node_name)
            self.db.image.insert(snap_name,
                                 self.pid,
                                 parent_id,
                                 is_snapshot=True)
            snap_ceph_name = self.__get_ceph_image_name(snap_name)
            self.fs.clone(ceph_img_name, constants.DEFAULT_SNAPSHOT_NAME,
                          snap_ceph_name)
            self.fs.flatten(snap_ceph_name)
            self.fs.snap_image(snap_ceph_name, constants.DEFAULT_SNAPSHOT_NAME)
            self.fs.snap_protect(snap_ceph_name,
                                 constants.DEFAULT_SNAPSHOT_NAME)
            self.fs.snap_unprotect(ceph_img_name,
                                   constants.DEFAULT_SNAPSHOT_NAME)
            self.fs.remove_snapshot(ceph_img_name,
                                    constants.DEFAULT_SNAPSHOT_NAME)
            return self.__return_success(True)

        except (HILException, DBException, FileSystemException) as e:
            logger.exception('')
            return self.__return_error(e)

    # Lists snapshot for the given image img_name
    # URL's have to be read from BMI config file
    # fs_obj will be populated by decorator
    @log
    def list_snapshots(self):
        try:
            self.hil.validate_project(self.proj)
            snapshots = self.db.image.fetch_snapshots_from_project(self.proj)
            return self.__return_success(snapshots)

        except (HILException, DBException, FileSystemException) as e:
            logger.exception('')
            return self.__return_error(e)

    # Removes snapshot snap_name for the given image img_name
    # fs_obj will be populated by decorator
    @log
    def remove_image(self, img_name):
        try:
            self.hil.validate_project(self.proj)
            ceph_img_name = self.__get_ceph_image_name(img_name)

            self.fs.snap_unprotect(ceph_img_name,
                                   constants.DEFAULT_SNAPSHOT_NAME)
            self.fs.remove_snapshot(ceph_img_name,
                                    constants.DEFAULT_SNAPSHOT_NAME)
            self.fs.remove(ceph_img_name)
            self.db.image.delete_with_name_from_project(img_name, self.proj)
            return self.__return_success(True)
        except (HILException, DBException, FileSystemException) as e:
            logger.exception('')
            return self.__return_error(e)

    # Lists the images for the project which includes the snapshot
    @log
    def list_images(self):
        try:
            self.hil.validate_project(self.proj)
            names = self.db.image.fetch_images_from_project(self.proj)
            return self.__return_success(names)

        except (HILException, DBException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def list_provisioned_nodes(self):
        try:
            clones = self.db.image.fetch_clones_from_project(self.proj)
            return self.__return_success(clones)
        except DBException as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def list_all_images(self):
        try:
            images = self.db.image.fetch_all_images()
            new_images = []
            for image in images:
                image.insert(
                    3,
                    self.get_ceph_image_name_from_project(image[1], image[2]))
                new_images.append(image)
            return self.__return_success(new_images)
        except DBException as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def import_ceph_image(self, img):
        """
        Import an image from ceph to be used by BMI

        Clone an image in ceph to be used by BMI.

        :param img: Name of image in ceph
        :return: True on successful completion
        """

        try:
            ceph_img_name = str(img)

            # create a snapshot of the golden image and protect it
            # this is needed because, in ceph, you can only create clones from
            # snapshots.
            self.fs.snap_image(ceph_img_name, constants.DEFAULT_SNAPSHOT_NAME)
            self.fs.snap_protect(ceph_img_name,
                                 constants.DEFAULT_SNAPSHOT_NAME)

            # insert golden image name into bmi db
            self.db.image.insert(ceph_img_name, self.pid)

            # get a name for our copy of the golden image. For instance an
            # image in ceph called centos6.7, after cloning, will be a given
            # a name like 4img1 based on the UID in config and image id in db
            snap_ceph_name = self.__get_ceph_image_name(ceph_img_name)

            # clone the snapshot of the golden image and then flatten it
            self.fs.clone(ceph_img_name, constants.DEFAULT_SNAPSHOT_NAME,
                          snap_ceph_name)
            self.fs.flatten(snap_ceph_name)

            # create a snapshot of our newly created golden image so that when
            # we provision, we can easily make clones from this readily
            # available snapshot.
            self.fs.snap_image(snap_ceph_name, constants.DEFAULT_SNAPSHOT_NAME)
            self.fs.snap_protect(snap_ceph_name,
                                 constants.DEFAULT_SNAPSHOT_NAME)

            # unprotect and delete the snapshot of the original golden because
            # we no longer need it.
            self.fs.snap_unprotect(ceph_img_name,
                                   constants.DEFAULT_SNAPSHOT_NAME)
            self.fs.remove_snapshot(ceph_img_name,
                                    constants.DEFAULT_SNAPSHOT_NAME)
            return self.__return_success(True)
        except (DBException, FileSystemException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def import_ceph_snapshot(self, img, snap_name, protect):
        """
        Import a snapshot from ceph to be used by BMI

        Clone a snapshot in ceph to be used by BMI. Similar to
        import_ceph_image except we can directly start the cloning process
        because it is already a snapshot.

        :param img: Name of snapshot in ceph
        :return: True on successful completion
        """
        try:
            ceph_img_name = str(img)

            if protect:
                self.fs.snap_protect(ceph_img_name, snap_name)
            self.db.image.insert(ceph_img_name, self.pid)
            snap_ceph_name = self.__get_ceph_image_name(ceph_img_name)
            self.fs.clone(ceph_img_name, snap_name, snap_ceph_name)
            self.fs.flatten(snap_ceph_name)
            self.fs.snap_image(snap_ceph_name, constants.DEFAULT_SNAPSHOT_NAME)
            self.fs.snap_protect(snap_ceph_name,
                                 constants.DEFAULT_SNAPSHOT_NAME)
            return self.__return_success(True)
        except (DBException, FileSystemException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def export_ceph_image(self, img, name):
        try:
            ceph_img_name = self.__get_ceph_image_name(img)
            self.fs.clone(ceph_img_name, constants.DEFAULT_SNAPSHOT_NAME, name)
            self.fs.flatten(name)
            return self.__return_success(True)
        except FileSystemException as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def delete_image(self, project, img):
        try:
            if not self.is_admin:
                raise AuthorizationFailedException()
            self.db.image.delete_with_name_from_project(img, project)
            return self.__return_success(True)
        except (DBException, AuthorizationFailedException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def add_image(self, project, img, id, snap, parent, public):
        try:
            if not self.is_admin:
                raise AuthorizationFailedException()
            parent_id = None
            if parent is not None:
                parent_id = self.db.image.fetch_id_with_name_from_project(
                    parent, project)
            pid = self.__does_project_exist(project)
            self.db.image.insert(img, pid, parent_id, public, snap, id)
            return self.__return_success(True)
        except (DBException, AuthorizationFailedException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def get_node_ip(self, node_name):
        try:
            mac_addr = self.hil.get_node_mac_addr(node_name)
            return self.__return_success(self.dhcp.get_ip(mac_addr))
        except (HILException, DHCPException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def copy_image(self, img1, dest_project, img2=None):
        """
        Create a deep copy of src image

        :param img1: Name of src image
        :param dest_project: Name of the project where des image will be
        created
        :param img2: Name of des image
        :return: True on successful completion
        """
        try:
            if not self.is_admin and (self.proj != dest_project):
                raise AuthorizationFailedException()
            dest_pid = self.__does_project_exist(dest_project)
            self.db.image.copy_image(self.proj, img1, dest_pid, img2)
            if img2 is not None:
                ceph_name = self.get_ceph_image_name_from_project(
                    img2, dest_project)
            else:
                ceph_name = self.get_ceph_image_name_from_project(
                    img1, dest_project)
            self.fs.clone(
                self.get_ceph_image_name_from_project(img1, self.proj),
                constants.DEFAULT_SNAPSHOT_NAME, ceph_name)

            self.fs.flatten(ceph_name)
            self.fs.snap_image(ceph_name, constants.DEFAULT_SNAPSHOT_NAME)
            self.fs.snap_protect(ceph_name, constants.DEFAULT_SNAPSHOT_NAME)

            return self.__return_success(True)
        except (DBException, FileSystemException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def move_image(self, img1, dest_project, img2):
        try:
            if not self.is_admin and (self.proj != dest_project):
                raise AuthorizationFailedException()
            dest_pid = self.__does_project_exist(dest_project)
            self.db.image.move_image(self.proj, img1, dest_pid, img2)
            return self.__return_success(True)
        except DBException as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def add_project(self, project, network, id):
        try:
            if not self.is_admin:
                raise AuthorizationFailedException()
            self.db.project.insert(project, network, id)
            return self.__return_success(True)
        except (DBException, AuthorizationFailedException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def delete_project(self, project):
        try:
            if not self.is_admin:
                raise AuthorizationFailedException()
            self.db.project.delete_with_name(project)
            return self.__return_success(True)
        except (DBException, AuthorizationFailedException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def list_projects(self):
        try:
            if not self.is_admin:
                raise AuthorizationFailedException()
            projects = self.db.project.fetch_projects()
            return self.__return_success(projects)
        except (DBException, AuthorizationFailedException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def mount_image(self, img):
        try:
            if not self.is_admin:
                raise AuthorizationFailedException()
            ceph_img_name = self.__get_ceph_image_name(img)
            self.iscsi.add_target(ceph_img_name)
            return self.__return_success(True)
        except (ISCSIException, DBException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def umount_image(self, img):
        try:
            if not self.is_admin:
                raise AuthorizationFailedException()
            ceph_img_name = self.__get_ceph_image_name(img)
            self.iscsi.remove_target(ceph_img_name)
            return self.__return_success(True)
        except (ISCSIException, DBException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def show_mounted(self):
        try:
            if not self.is_admin:
                raise AuthorizationFailedException()
            mappings = self.iscsi.list_targets()
            swapped_mappings = {}
            for k, v in mappings.iteritems():
                img_id = self.__extract_id(k)
                if self.proj == self.db.image.fetch_project_with_id(img_id):
                    swapped_mappings[self.db.image.fetch_name_with_id(
                        img_id)] = v
            return self.__return_success(swapped_mappings)
        except (ISCSIException, DBException) as e:
            logger.exception('')
            return self.__return_error(e)

    @log
    def remake_mappings(self):
        try:
            self.iscsi.persist_targets()
        except (FileSystemException, ISCSIException) as e:
            logger.exception('')
        except NotImplementedError:
            pass