From e0f8429bfaae349381cd0a52f950c62b10d3f346 Mon Sep 17 00:00:00 2001 From: Konstantin Skaburskas Date: Wed, 7 Oct 2015 23:42:22 +0200 Subject: [PATCH 1/4] Provide size in the VM template. Take size from the image manifest. --- .../src/main/python/stratuslab/image/Image.py | 3 +++ .../python/stratuslab/vm_manager/Runner.py | 26 +++++++++++++------ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/api/code/src/main/python/stratuslab/image/Image.py b/api/code/src/main/python/stratuslab/image/Image.py index 925c8f4f..c1fb597f 100644 --- a/api/code/src/main/python/stratuslab/image/Image.py +++ b/api/code/src/main/python/stratuslab/image/Image.py @@ -68,6 +68,9 @@ def getImageDisksBusTypeByImageId(self, imageId): def getInboundPortsByImageId(self, imageId): return self._getImageElementValue('inboundports', imageId) + def get_image_size_by_image_id(self, image_id): + return self._getImageElementValue('bytes', image_id) + def _getImageElementValue(self, element, imageId): if Image.isImageId(imageId): return self.manifestDownloader.getImageElementValue(element, imageId) diff --git a/api/code/src/main/python/stratuslab/vm_manager/Runner.py b/api/code/src/main/python/stratuslab/vm_manager/Runner.py index 80cd7723..38b535b5 100644 --- a/api/code/src/main/python/stratuslab/vm_manager/Runner.py +++ b/api/code/src/main/python/stratuslab/vm_manager/Runner.py @@ -113,6 +113,7 @@ def __init__(self, image, configHolder): self._setCloudContext() self.createImageData = {self.CREATE_IMAGE_KEY_CREATOR_EMAIL: self.authorEmail, self.CREATE_IMAGE_KEY_NEWIMAGE_MARKETPLACE: self.marketplaceEndpointNewimage} + self._image = None self._initVmAttributes() self.instancesDetail = [] self.availableInstanceTypes = self._getAvailableInstanceTypes() @@ -146,6 +147,10 @@ def _initVmAttributes(self): self._initVmAttributesStatic() + if not self._image: + self._image = Image(self.configHolder) + + self._set_root_disk_size_entry() self._setMsgRecipients() self._setUserKeyIfDefined() self._setSaveDisk() @@ -177,6 +182,13 @@ def _initVmAttributesStatic(self): self.diskImageFormat = None self.disk_driver = None self.inbound_ports = '' + self.root_disk_size_entry = '' + + def _set_root_disk_size_entry(self): + if self.vm_image: + size_bytes = int(self._image.get_image_size_by_image_id(self.vm_image)) + size_MB = size_bytes / 1024 ** 2 + self.root_disk_size_entry = 'size = %s,' % size_MB def _setMsgRecipients(self): try: @@ -189,8 +201,7 @@ def _setDiskImageFormat(self): # if image ID was provided extract disk driver type from manifest if self.vm_image: if not useQcowDiskFormat and Image.isImageId(self.vm_image): - image = Image(self.configHolder) - self.disk_driver = image.getImageFormatByImageId(self.vm_image) + self.disk_driver = self._image.getImageFormatByImageId(self.vm_image) return self.disk_driver = (useQcowDiskFormat and 'qcow2') or 'raw' @@ -199,8 +210,7 @@ def _setDisksBusType(self): disks_bus = self.vmDisksBus else: if Image.isImageId(self.vm_image): - image = Image(self.configHolder) - disks_bus = image.getImageDisksBusTypeByImageId(self.vm_image) + disks_bus = self._image.getImageDisksBusTypeByImageId(self.vm_image) else: return @@ -261,9 +271,8 @@ def _setReadonlyDiskOptional(self): def _setInboundPorts(self): if Image.isImageId(self.vm_image): - image = Image(self.configHolder) try: - self.inboundPorts = image.getInboundPortsByImageId(self.vm_image) + self.inboundPorts = self._image.getInboundPortsByImageId(self.vm_image) except Exceptions.ExecutionException: pass @@ -637,8 +646,9 @@ def _checkImageExists(self, imageId): if self.noCheckImageUrl: printWarning('Image availability check is disabled.') return - imageObject = Image(self.configHolder) - imageObject.checkImageExists(imageId) + if not self._image: + self._image = Image(self.configHolder) + self._image.checkImageExists(imageId) def _prependMarketplaceUrlIfImageId(self, image): if Image.isImageId(image): From caea73a1579a2c22d680d166ad5634adc49c7209 Mon Sep 17 00:00:00 2001 From: Konstantin Skaburskas Date: Wed, 7 Oct 2015 23:44:14 +0200 Subject: [PATCH 2/4] Take into account hierarchy of DISK element of the VM template when building CloudInfo object. --- api/code/src/main/python/stratuslab/CloudInfo.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/api/code/src/main/python/stratuslab/CloudInfo.py b/api/code/src/main/python/stratuslab/CloudInfo.py index 64acef8c..29ff511a 100644 --- a/api/code/src/main/python/stratuslab/CloudInfo.py +++ b/api/code/src/main/python/stratuslab/CloudInfo.py @@ -35,9 +35,17 @@ def _populate(self, element, parentHierachy=[]): for child in children: self._populate(child, _parentHierachy) else: - # skip the root element - hierachy = parentHierachy[1:] + [element.tag] - attributeName = '_'.join(hierachy) + # root element is not included + if parentHierachy[-1].tag == 'DISK': + try: + disk_id = parentHierachy[-1].find('DISK_ID').text + except Exception: + disk_id = 'X' + hierachy = [e.tag for e in parentHierachy[1:]] + [disk_id, element.tag] + attributeName = '_'.join(hierachy) + else: + hierachy = parentHierachy[1:] + [element] + attributeName = '_'.join([e.tag for e in hierachy]) if isinstance(element.text, unicode): text = element.text.encode('utf-8') else: @@ -50,7 +58,7 @@ def _getChildren(self, parent): def _updateHierachy(self, element, parentHierachy): _parentHierachy = parentHierachy[:] - _parentHierachy.append(element.tag) + _parentHierachy.append(element) return _parentHierachy def getAttributes(self): From ccacf29816d458489ba9dc626dd61818d100b052 Mon Sep 17 00:00:00 2001 From: Konstantin Skaburskas Date: Wed, 7 Oct 2015 23:52:35 +0200 Subject: [PATCH 3/4] Take into account hierarchy of DISK element of the VM template when building CloudInfo object. --- api/code/src/main/resources/share/vm/schema.one | 1 + 1 file changed, 1 insertion(+) diff --git a/api/code/src/main/resources/share/vm/schema.one b/api/code/src/main/resources/share/vm/schema.one index db6ee84d..bf731cf8 100644 --- a/api/code/src/main/resources/share/vm/schema.one +++ b/api/code/src/main/resources/share/vm/schema.one @@ -12,6 +12,7 @@ source = "%(vm_image)s", target = "%(vm_disks_prefix)sa", save = %(save_disk)s, readonly = "no", +%(root_disk_size_entry)s driver = "%(disk_driver)s" ] DISK = [ From 5bebb94a008490116b21791cc3dbc544214e3bf0 Mon Sep 17 00:00:00 2001 From: Konstantin Skaburskas Date: Thu, 8 Oct 2015 00:19:17 +0200 Subject: [PATCH 4/4] Added unit tests. --- api/code/src/test/python/CloudInfoTest.py | 28 +++++++++++++++++++ .../src/test/python/vm_manager/RunnerTest.py | 6 ++++ 2 files changed, 34 insertions(+) diff --git a/api/code/src/test/python/CloudInfoTest.py b/api/code/src/test/python/CloudInfoTest.py index 8a31ffad..89fb5340 100644 --- a/api/code/src/test/python/CloudInfoTest.py +++ b/api/code/src/test/python/CloudInfoTest.py @@ -58,5 +58,33 @@ def testPopulate(self): self.assertEqual('ID3',info.level1_level2_level3_id3) self.assertEqual('ID4',info.level1_id4) + def test_disk_element(self): + xml = ''' + + + ID1 + + 0 + 123 + + + 456 + + + +''' + root = etree.fromstring(xml) + + info = CloudInfo() + info.populate(root) + + assert hasattr(info, 'level1_disk_0_disk_id') + assert hasattr(info, 'level1_disk_0_size') + assert hasattr(info, 'level1_disk_x_size') + assert '0' == info.level1_disk_0_disk_id + assert '123' == info.level1_disk_0_size + assert '456' == info.level1_disk_x_size + + if __name__ == "__main__": unittest.main() diff --git a/api/code/src/test/python/vm_manager/RunnerTest.py b/api/code/src/test/python/vm_manager/RunnerTest.py index a9f054b2..21a799e9 100644 --- a/api/code/src/test/python/vm_manager/RunnerTest.py +++ b/api/code/src/test/python/vm_manager/RunnerTest.py @@ -99,6 +99,12 @@ def setUp(self): def tearDown(self): reload(ConfigHolder) + def test_set_root_disk_size(self): + runner = self._getRunnerForManifest(self.MANIFEST_DISKS_BUS_VIRTIO, + 'MMZu9WvwKIro-rtBQfDk4PsKO7_') + vm_params = runner._vmParamDict() + self.failUnlessEqual('size = 0,', vm_params['root_disk_size_entry']) + def testDisksBusTypeVirtio(self): runner = self._getRunnerForManifest(self.MANIFEST_DISKS_BUS_VIRTIO, 'MMZu9WvwKIro-rtBQfDk4PsKO7_')