Stop requiring root size for whole disk images
This requirement has been fixed in newer versions of ironic.
Change-Id: I4460755ee66b4aa0b8a651b6bd142c769d669ee2
(cherry picked from commit 2d801e2526
)
This commit is contained in:
parent
749d403c19
commit
0afed7462d
|
@ -388,7 +388,7 @@ class Provisioner(object):
|
||||||
try:
|
try:
|
||||||
root_size_gb = _utils.get_root_disk(root_size_gb, node)
|
root_size_gb = _utils.get_root_disk(root_size_gb, node)
|
||||||
|
|
||||||
image._validate(self.connection)
|
image._validate(self.connection, root_size_gb)
|
||||||
|
|
||||||
nics.validate()
|
nics.validate()
|
||||||
|
|
||||||
|
@ -405,7 +405,8 @@ class Provisioner(object):
|
||||||
capabilities['boot_option'] = 'netboot' if netboot else 'local'
|
capabilities['boot_option'] = 'netboot' if netboot else 'local'
|
||||||
|
|
||||||
instance_info = self._clean_instance_info(node.instance_info)
|
instance_info = self._clean_instance_info(node.instance_info)
|
||||||
instance_info['root_gb'] = root_size_gb
|
if root_size_gb is not None:
|
||||||
|
instance_info['root_gb'] = root_size_gb
|
||||||
instance_info['capabilities'] = capabilities
|
instance_info['capabilities'] = capabilities
|
||||||
if hostname:
|
if hostname:
|
||||||
instance_info['display_name'] = hostname
|
instance_info['display_name'] = hostname
|
||||||
|
|
|
@ -56,9 +56,9 @@ def get_root_disk(root_size_gb, node):
|
||||||
try:
|
try:
|
||||||
assert int(node.properties['local_gb']) > 0
|
assert int(node.properties['local_gb']) > 0
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise exceptions.UnknownRootDiskSize(
|
LOG.debug('No local_gb for node %s and no root partition size '
|
||||||
'No local_gb for node %s and no root partition size '
|
'specified', log_res(node))
|
||||||
'specified' % log_res(node))
|
return
|
||||||
except (TypeError, ValueError, AssertionError):
|
except (TypeError, ValueError, AssertionError):
|
||||||
raise exceptions.UnknownRootDiskSize(
|
raise exceptions.UnknownRootDiskSize(
|
||||||
'The local_gb for node %(node)s is invalid: '
|
'The local_gb for node %(node)s is invalid: '
|
||||||
|
|
|
@ -34,7 +34,7 @@ LOG = logging.getLogger(__name__)
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
class _Source(object):
|
class _Source(object):
|
||||||
|
|
||||||
def _validate(self, connection):
|
def _validate(self, connection, root_size_gb):
|
||||||
"""Validate the source."""
|
"""Validate the source."""
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
|
@ -53,7 +53,7 @@ class GlanceImage(_Source):
|
||||||
self.image = image
|
self.image = image
|
||||||
self._image_obj = None
|
self._image_obj = None
|
||||||
|
|
||||||
def _validate(self, connection):
|
def _validate(self, connection, root_size_gb):
|
||||||
if self._image_obj is not None:
|
if self._image_obj is not None:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
|
@ -64,8 +64,13 @@ class GlanceImage(_Source):
|
||||||
'Cannot find image %(image)s: %(error)s' %
|
'Cannot find image %(image)s: %(error)s' %
|
||||||
{'image': self.image, 'error': exc})
|
{'image': self.image, 'error': exc})
|
||||||
|
|
||||||
|
if (root_size_gb is None and
|
||||||
|
any(getattr(self._image_obj, x, None) is not None
|
||||||
|
for x in ('kernel_id', 'ramdisk_id'))):
|
||||||
|
raise exceptions.UnknownRootDiskSize(
|
||||||
|
'Partition images require root partition size')
|
||||||
|
|
||||||
def _node_updates(self, connection):
|
def _node_updates(self, connection):
|
||||||
self._validate(connection)
|
|
||||||
LOG.debug('Image: %s', self._image_obj)
|
LOG.debug('Image: %s', self._image_obj)
|
||||||
|
|
||||||
updates = {
|
updates = {
|
||||||
|
@ -108,7 +113,7 @@ class HttpWholeDiskImage(_Source):
|
||||||
self.checksum = checksum
|
self.checksum = checksum
|
||||||
self.checksum_url = checksum_url
|
self.checksum_url = checksum_url
|
||||||
|
|
||||||
def _validate(self, connection):
|
def _validate(self, connection, root_size_gb):
|
||||||
# TODO(dtantsur): should we validate image URLs here? Ironic will do it
|
# TODO(dtantsur): should we validate image URLs here? Ironic will do it
|
||||||
# as well, and images do not have to be accessible from where
|
# as well, and images do not have to be accessible from where
|
||||||
# metalsmith is running.
|
# metalsmith is running.
|
||||||
|
@ -140,7 +145,6 @@ class HttpWholeDiskImage(_Source):
|
||||||
{'fname': fname, 'url': self.checksum_url})
|
{'fname': fname, 'url': self.checksum_url})
|
||||||
|
|
||||||
def _node_updates(self, connection):
|
def _node_updates(self, connection):
|
||||||
self._validate(connection)
|
|
||||||
LOG.debug('Image: %(image)s, checksum %(checksum)s',
|
LOG.debug('Image: %(image)s, checksum %(checksum)s',
|
||||||
{'image': self.url, 'checksum': self.checksum})
|
{'image': self.url, 'checksum': self.checksum})
|
||||||
return {
|
return {
|
||||||
|
@ -170,6 +174,12 @@ class HttpPartitionImage(HttpWholeDiskImage):
|
||||||
self.kernel_url = kernel_url
|
self.kernel_url = kernel_url
|
||||||
self.ramdisk_url = ramdisk_url
|
self.ramdisk_url = ramdisk_url
|
||||||
|
|
||||||
|
def _validate(self, connection, root_size_gb):
|
||||||
|
super(HttpPartitionImage, self)._validate(connection, root_size_gb)
|
||||||
|
if root_size_gb is None:
|
||||||
|
raise exceptions.UnknownRootDiskSize(
|
||||||
|
'Partition images require root partition size')
|
||||||
|
|
||||||
def _node_updates(self, connection):
|
def _node_updates(self, connection):
|
||||||
updates = super(HttpPartitionImage, self)._node_updates(connection)
|
updates = super(HttpPartitionImage, self)._node_updates(connection)
|
||||||
updates['kernel'] = self.kernel_url
|
updates['kernel'] = self.kernel_url
|
||||||
|
@ -237,6 +247,12 @@ class FilePartitionImage(FileWholeDiskImage):
|
||||||
self.kernel_location = kernel_location
|
self.kernel_location = kernel_location
|
||||||
self.ramdisk_location = ramdisk_location
|
self.ramdisk_location = ramdisk_location
|
||||||
|
|
||||||
|
def _validate(self, connection, root_size_gb):
|
||||||
|
super(FilePartitionImage, self)._validate(connection, root_size_gb)
|
||||||
|
if root_size_gb is None:
|
||||||
|
raise exceptions.UnknownRootDiskSize(
|
||||||
|
'Partition images require root partition size')
|
||||||
|
|
||||||
def _node_updates(self, connection):
|
def _node_updates(self, connection):
|
||||||
updates = super(FilePartitionImage, self)._node_updates(connection)
|
updates = super(FilePartitionImage, self)._node_updates(connection)
|
||||||
updates['kernel'] = self.kernel_location
|
updates['kernel'] = self.kernel_location
|
||||||
|
|
|
@ -13,18 +13,49 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
|
from metalsmith import exceptions
|
||||||
from metalsmith import sources
|
from metalsmith import sources
|
||||||
|
|
||||||
|
|
||||||
class TestDetect(testtools.TestCase):
|
class TestDetect(testtools.TestCase):
|
||||||
|
|
||||||
def test_glance(self):
|
def test_glance_whole_disk(self):
|
||||||
source = sources.detect('foobar')
|
source = sources.detect('foobar')
|
||||||
self.assertIsInstance(source, sources.GlanceImage)
|
self.assertIsInstance(source, sources.GlanceImage)
|
||||||
self.assertEqual(source.image, 'foobar')
|
self.assertEqual(source.image, 'foobar')
|
||||||
|
|
||||||
|
conn = mock.Mock(spec=['image'])
|
||||||
|
conn.image.find_image.return_value = mock.Mock(
|
||||||
|
id=42, kernel_id=None, ramdisk_id=None)
|
||||||
|
source._validate(conn, None)
|
||||||
|
self.assertEqual({'image_source': 42}, source._node_updates(conn))
|
||||||
|
|
||||||
|
def test_glance_partition(self):
|
||||||
|
source = sources.detect('foobar')
|
||||||
|
self.assertIsInstance(source, sources.GlanceImage)
|
||||||
|
self.assertEqual(source.image, 'foobar')
|
||||||
|
|
||||||
|
conn = mock.Mock(spec=['image'])
|
||||||
|
conn.image.find_image.return_value = mock.Mock(
|
||||||
|
id=42, kernel_id=1, ramdisk_id=2)
|
||||||
|
source._validate(conn, 9)
|
||||||
|
self.assertEqual({'image_source': 42, 'kernel': 1, 'ramdisk': 2},
|
||||||
|
source._node_updates(conn))
|
||||||
|
|
||||||
|
def test_glance_partition_missing_root(self):
|
||||||
|
source = sources.detect('foobar')
|
||||||
|
self.assertIsInstance(source, sources.GlanceImage)
|
||||||
|
self.assertEqual(source.image, 'foobar')
|
||||||
|
|
||||||
|
conn = mock.Mock(spec=['image'])
|
||||||
|
conn.image.find_image.return_value = mock.Mock(
|
||||||
|
id=42, kernel_id=1, ramdisk_id=2)
|
||||||
|
self.assertRaises(exceptions.UnknownRootDiskSize,
|
||||||
|
source._validate, conn, None)
|
||||||
|
|
||||||
def test_glance_invalid_arguments(self):
|
def test_glance_invalid_arguments(self):
|
||||||
for kwargs in [{'kernel': 'foo'},
|
for kwargs in [{'kernel': 'foo'},
|
||||||
{'ramdisk': 'foo'},
|
{'ramdisk': 'foo'},
|
||||||
|
@ -43,6 +74,8 @@ class TestDetect(testtools.TestCase):
|
||||||
self.assertEqual(source.location, 'file:///image')
|
self.assertEqual(source.location, 'file:///image')
|
||||||
self.assertEqual(source.checksum, 'abcd')
|
self.assertEqual(source.checksum, 'abcd')
|
||||||
|
|
||||||
|
source._validate(mock.Mock(), None)
|
||||||
|
|
||||||
def test_file_partition_disk(self):
|
def test_file_partition_disk(self):
|
||||||
source = sources.detect('file:///image', checksum='abcd',
|
source = sources.detect('file:///image', checksum='abcd',
|
||||||
kernel='file:///kernel',
|
kernel='file:///kernel',
|
||||||
|
@ -53,6 +86,15 @@ class TestDetect(testtools.TestCase):
|
||||||
self.assertEqual(source.kernel_location, 'file:///kernel')
|
self.assertEqual(source.kernel_location, 'file:///kernel')
|
||||||
self.assertEqual(source.ramdisk_location, 'file:///ramdisk')
|
self.assertEqual(source.ramdisk_location, 'file:///ramdisk')
|
||||||
|
|
||||||
|
source._validate(mock.Mock(), 9)
|
||||||
|
|
||||||
|
def test_file_partition_disk_missing_root(self):
|
||||||
|
source = sources.detect('file:///image', checksum='abcd',
|
||||||
|
kernel='file:///kernel',
|
||||||
|
ramdisk='file:///ramdisk')
|
||||||
|
self.assertRaises(exceptions.UnknownRootDiskSize,
|
||||||
|
source._validate, mock.Mock(), None)
|
||||||
|
|
||||||
def test_file_partition_inconsistency(self):
|
def test_file_partition_inconsistency(self):
|
||||||
for kwargs in [{'kernel': 'foo'},
|
for kwargs in [{'kernel': 'foo'},
|
||||||
{'ramdisk': 'foo'},
|
{'ramdisk': 'foo'},
|
||||||
|
@ -69,12 +111,16 @@ class TestDetect(testtools.TestCase):
|
||||||
self.assertEqual(source.url, 'http:///image')
|
self.assertEqual(source.url, 'http:///image')
|
||||||
self.assertEqual(source.checksum, 'abcd')
|
self.assertEqual(source.checksum, 'abcd')
|
||||||
|
|
||||||
|
source._validate(mock.Mock(), None)
|
||||||
|
|
||||||
def test_https_whole_disk(self):
|
def test_https_whole_disk(self):
|
||||||
source = sources.detect('https:///image', checksum='abcd')
|
source = sources.detect('https:///image', checksum='abcd')
|
||||||
self.assertIs(source.__class__, sources.HttpWholeDiskImage)
|
self.assertIs(source.__class__, sources.HttpWholeDiskImage)
|
||||||
self.assertEqual(source.url, 'https:///image')
|
self.assertEqual(source.url, 'https:///image')
|
||||||
self.assertEqual(source.checksum, 'abcd')
|
self.assertEqual(source.checksum, 'abcd')
|
||||||
|
|
||||||
|
source._validate(mock.Mock(), None)
|
||||||
|
|
||||||
def test_https_whole_disk_checksum(self):
|
def test_https_whole_disk_checksum(self):
|
||||||
source = sources.detect('https:///image',
|
source = sources.detect('https:///image',
|
||||||
checksum='https://checksum')
|
checksum='https://checksum')
|
||||||
|
@ -92,6 +138,15 @@ class TestDetect(testtools.TestCase):
|
||||||
self.assertEqual(source.kernel_url, 'http:///kernel')
|
self.assertEqual(source.kernel_url, 'http:///kernel')
|
||||||
self.assertEqual(source.ramdisk_url, 'http:///ramdisk')
|
self.assertEqual(source.ramdisk_url, 'http:///ramdisk')
|
||||||
|
|
||||||
|
source._validate(mock.Mock(), 9)
|
||||||
|
|
||||||
|
def test_http_partition_disk_missing_root(self):
|
||||||
|
source = sources.detect('http:///image', checksum='abcd',
|
||||||
|
kernel='http:///kernel',
|
||||||
|
ramdisk='http:///ramdisk')
|
||||||
|
self.assertRaises(exceptions.UnknownRootDiskSize,
|
||||||
|
source._validate, mock.Mock(), None)
|
||||||
|
|
||||||
def test_https_partition_disk(self):
|
def test_https_partition_disk(self):
|
||||||
source = sources.detect('https:///image', checksum='abcd',
|
source = sources.detect('https:///image', checksum='abcd',
|
||||||
# Can mix HTTP and HTTPs
|
# Can mix HTTP and HTTPs
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
vars:
|
vars:
|
||||||
metalsmith_image: "{{ metalsmith_whole_disk_image }}"
|
metalsmith_image: "{{ metalsmith_whole_disk_image }}"
|
||||||
metalsmith_image_checksum: "{{ metalsmith_whole_disk_checksum | default('') }}"
|
metalsmith_image_checksum: "{{ metalsmith_whole_disk_checksum | default('') }}"
|
||||||
|
metalsmith_root_size:
|
||||||
# NOTE(dtantsur): cannot specify swap with whole disk images
|
# NOTE(dtantsur): cannot specify swap with whole disk images
|
||||||
metalsmith_swap_size:
|
metalsmith_swap_size:
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
No longer requires root size for whole disk images. This requirement has
|
||||||
|
been removed from ironic.
|
Loading…
Reference in New Issue