class testImageWarehouse(unittest.TestCase):
    def setUp(self):
        logging.basicConfig(level=logging.NOTSET, format='%(asctime)s %(levelname)s %(name)s pid(%(process)d) Message: %(message)s', filename='/tmp/imagefactory-unittests.log')
        self.warehouse = ImageWarehouse(ApplicationConfiguration().configuration["warehouse"])
        self.metadata = dict(key1="value1", key2="value2", key3="value3")

    def tearDown(self):
        del self.warehouse
        del self.metadata

    def testImageWarehouseMethods(self):
        """Tests CRUD operations on target images, templates, icicles, and metadata on those objects..."""
        # TARGET IMAGE
        # store a target image
        target_image_id = str(uuid.uuid4())
        file_content = "This is just to test storing a target image in warehouse.  There is not much to see here."
        file_path = "/tmp/testImageWarehouse_testStoreAndFetchTargetImage.%s" % (target_image_id, )
        with open(file_path, 'w') as test_file:
            test_file.write(file_content)
            test_file.close()
        self.warehouse.store_target_image(target_image_id, file_path, metadata=self.metadata)
        # now fetch that target image
        target_image, metadata = self.warehouse.target_image_with_id(target_image_id, metadata_keys=self.metadata.keys())
        # now make the assertions
        self.assertEqual(file_content, target_image)
        self.assertEqual(self.metadata, metadata)

        # TEMPLATE
        template_content = "<template>This is a test template. There is not much to see here.</template>"
        # store the template and let an id get assigned
        template_id = self.warehouse.store_template(template_content)
        self.assertTrue(template_id)
        # store the template with a specified id
        template_id_known = str(uuid.uuid4())
        template_id2 = self.warehouse.store_template(template_content, template_id_known)
        self.assertEqual(template_id_known, template_id2)
        # fetch the templates
        fetched_template_content, template_metadata1 = self.warehouse.template_with_id(template_id)
        self.assertEqual(template_content, fetched_template_content)
        fetched_template_content2, template_metadata2 = self.warehouse.template_with_id(template_id_known)
        self.assertEqual(template_content, fetched_template_content2)
        # set the template id for a target image and fetch it back
        self.warehouse.set_metadata_for_id_of_type(dict(template=template_id), target_image_id, "target_image")
        template_id3, fetched_template_content3, template_metadata3 = self.warehouse.template_for_target_image_id(target_image_id)
        self.assertEqual(template_id, template_id3)
        self.assertEqual(template_content, fetched_template_content3)

        # ICICLE
        icicle_content = "<icicle>This is a test icicle. There is not much to see here.</icicle>"
        # store the icicle and let an id get assigned
        icicle_id = self.warehouse.store_icicle(icicle_content)
        self.assertTrue(icicle_id)
        # store the icicle with a specified id
        icicle_id_known = str(uuid.uuid4())
        icicle_id2 = self.warehouse.store_icicle(icicle_content, icicle_id_known)
        self.assertEqual(icicle_id_known, icicle_id2)
        # fetch the icicles
        fetched_icicle_content, icicle_metadata1 = self.warehouse.icicle_with_id(icicle_id)
        self.assertEqual(icicle_content, fetched_icicle_content)
        fetched_icicle_content2, icicle_metadata2 = self.warehouse.icicle_with_id(icicle_id_known)
        self.assertEqual(icicle_content, fetched_icicle_content2)
        # set the icicle id for a target image and fetch it back
        self.warehouse.set_metadata_for_id_of_type(dict(icicle=icicle_id), target_image_id, "target_image")
        icicle_id3, fetched_icicle_content3, icicle_metadata3 = self.warehouse.icicle_for_target_image_id(target_image_id)
        self.assertEqual(icicle_id, icicle_id3)
        self.assertEqual(icicle_content, fetched_icicle_content3)

        self.assertTrue(self.warehouse.remove_target_image_with_id(target_image_id))
        self.assertTrue(self.warehouse.remove_template_with_id(template_id))
        self.assertTrue(self.warehouse.remove_template_with_id(template_id2))
        self.assertTrue(self.warehouse.remove_icicle_with_id(icicle_id))
        self.assertTrue(self.warehouse.remove_icicle_with_id(icicle_id2))

        os.remove(file_path)

    def testImageAndBuildMethods(self):
        """Tests CRUD operations on images, builds and metadata on those objects..."""
        image_xml = '<image/>'

        image_id = self.warehouse.store_image(None, image_xml, self.metadata)

        self.assertTrue(image_id)

        image_body, metadata = self.warehouse.object_with_id_of_type(image_id, 'image', self.metadata.keys())

        self.assertEqual(image_xml, image_body)
        self.assertEqual(self.metadata, metadata)

        build_id = self.warehouse.store_build(None, self.metadata)

        build_body, metadata = self.warehouse.object_with_id_of_type(build_id, 'build', self.metadata.keys())

        self.assertEqual('', build_body)
        self.assertEqual(self.metadata, metadata)

        ids = self.warehouse.query('build', '$object_type == "build" && $key1 == "value1"')

        self.assertTrue(build_id in ids)

    def testBucketCreation(self):
        # self.assert_(self.warehouse.create_bucket_at_url("%s/unittests-create_bucket/%s" % (self.warehouse.url, str(uuid.uuid4()))))
        self.warehouse.create_bucket_at_url("%s/unittests-create_bucket" % (self.warehouse.url, ))
        self.assert_(self.warehouse.create_bucket_at_url("%s/unittests-create_bucket/%s" % (self.warehouse.url, time.asctime().replace(' ', '-'))))
Example #2
0
class Template(object):
    uuid_pattern = '([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{12})'

    identifier = props.prop("_identifier", "The identifier property.")
    url = props.prop("_url", "The url property.")
    xml = props.prop("_xml", "The xml property.")
    @property
    def os_name(self):
        """The property os_name"""
        return self._content_at_path('/template/os/name')
    @property
    def os_version(self):
        """The property os_version"""
        return self._content_at_path('/template/os/version')
    @property
    def os_arch(self):
        """The property os_arch"""
        return self._content_at_path('/template/os/arch')

    def __repr__(self):
        if(self.xml):
            return self.xml
        else:
            return super(Template, self).__repr__

    def _content_at_path(self, path):
        try:
            return libxml2.parseDoc(self.xml).xpathEval(path)[0].content
        except Exception as e:
            self.log.exception('Could not parse document for path (%s):\n%s' % (path, e))
            return None

    def __init__(self, template=None, uuid=None, url=None, xml=None):
        self.log = logging.getLogger('%s.%s' % (__name__, self.__class__.__name__))
        self.warehouse = ImageWarehouse(ApplicationConfiguration().configuration["warehouse"])

        self.identifier = None
        self.url = None
        self.xml = None

        path = None
        if(template):
            template_string = str(template)
            template_string_type = self.__template_string_type(template_string)
            if(template_string_type == "UUID"):
                uuid = template_string
            elif(template_string_type == "URL"):
                url = template_string
            elif(template_string_type == "XML"):
                xml = template_string
            elif(template_string_type == "PATH"):
                path = template_string

        if(uuid):
            uuid_string = uuid
            self.identifier, self.xml = self.__fetch_template_for_uuid(uuid_string)
            if((not self.identifier) and (not self.xml)):
                raise RuntimeError("Could not create a template with the uuid %s" % (uuid, ))
        elif(url):
            self.url = url
            self.identifier, self.xml = self.__fetch_template_with_url(url)
        elif(xml):
            self.xml = xml
        elif(path):
            template_file = open(path, "r")
            file_content = template_file.read()
            template_file.close()
            if(self.__string_is_xml_template(file_content)):
                self.xml = file_content
            else:
                raise ValueError("File %s does not contain properly formatted template xml:\n%s" % (path, self.__abbreviated_template(file_content)))
        else:
            raise ValueError("'template' must be a UUID, URL, XML string or XML document path...")

    def __template_string_type(self, template_string):
        regex = re.compile(Template.uuid_pattern)
        match = regex.search(template_string)

        if(template_string.lower().startswith("http")):
            return "URL"
        elif(("<template" in template_string.lower()) and ("</template>" in template_string.lower())):
            return "XML"
        elif(match):
            return "UUID"
        elif(os.path.exists(template_string)):
            return "PATH"
        else:
            raise ValueError("'template_string' must be a UUID, URL, or XML document...\n--- TEMPLATE STRING ---\n%s\n-----------------" % (template_string, ))

    def __fetch_template_for_uuid(self, uuid_string):
        xml_string, metadata = self.warehouse.template_with_id(uuid_string)
        if(xml_string and self.__string_is_xml_template(xml_string)):
            return uuid_string, xml_string
        else:
            self.log.debug("Unable to fetch a valid template given template id %s:\n%s\nWill try fetching template id from a target image with this id..." % (uuid_string, self.__abbreviated_template(xml_string)))
            template_id, xml_string, metadata = self.warehouse.template_for_target_image_id(uuid_string)
            if(template_id and xml_string and self.__string_is_xml_template(xml_string)):
                return template_id, xml_string
            else:
                self.log.debug("Unable to fetch a valid template given a target image id %s:\n%s\n" % (uuid_string, self.__abbreviated_template(xml_string)))
                return None, None

    def __string_is_xml_template(self, text):
        return (("<template" in text.lower()) and ("</template>" in text.lower()))

    def __fetch_template_with_url(self, url):
        template_id = None
        regex = re.compile(Template.uuid_pattern)
        match = regex.search(url)

        if (match):
            template_id = match.group()

        if (not url.startswith(self.warehouse.url)):
            response_headers, response = httplib2.Http().request(url, "GET", headers={'content-type':'text/plain'})
        else:
            response_headers, response = self.warehouse.request(url, "GET")
        if(response and self.__string_is_xml_template(response)):
            return template_id, response
        else:
            raise RuntimeError("Recieved status %s fetching a template from %s!\n--- Response Headers:\n%s\n--- Response:\n%s" % (response_headers["status"], url, response_headers, response))

    def __abbreviated_template(self, template_string):
        lines = template_string.splitlines(True)
        if(len(lines) > 20):
            return "%s\n...\n...\n...\n%s" % ("".join(lines[0:10]), "".join(lines[-10:len(lines)]))
        else:
            return template_string