Merge "Add a glance module that allows uploading images"
This commit is contained in:
commit
a8fbbb60bd
38
os_cloud_config/cmd/tests/test_upload_kernel_ramdisk.py
Normal file
38
os_cloud_config/cmd/tests/test_upload_kernel_ramdisk.py
Normal file
@ -0,0 +1,38 @@
|
||||
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import sys
|
||||
|
||||
import mock
|
||||
|
||||
from os_cloud_config.cmd import upload_kernel_ramdisk
|
||||
from os_cloud_config.tests import base
|
||||
|
||||
|
||||
class UploadKernelRamdiskTest(base.TestCase):
|
||||
|
||||
@mock.patch('os_cloud_config.cmd.utils._clients.get_glance_client',
|
||||
return_value='glance_client_mock')
|
||||
@mock.patch('os_cloud_config.glance.create_or_find_kernel_and_ramdisk')
|
||||
@mock.patch.dict('os.environ', {'OS_USERNAME': 'a', 'OS_PASSWORD': 'a',
|
||||
'OS_TENANT_NAME': 'a', 'OS_AUTH_URL': 'a'})
|
||||
@mock.patch.object(sys, 'argv', ['upload_kernel_ramdisk', '-k',
|
||||
'bm-kernel', '-r', 'bm-ramdisk', '-l',
|
||||
'kernel-file', '-s', 'ramdisk-file'])
|
||||
def test_with_arguments(self, create_or_find_mock, glanceclient_mock):
|
||||
upload_kernel_ramdisk.main()
|
||||
create_or_find_mock.assert_called_once_with(
|
||||
'glance_client_mock', 'bm-kernel', 'bm-ramdisk',
|
||||
kernel_path='kernel-file', ramdisk_path='ramdisk-file')
|
56
os_cloud_config/cmd/upload_kernel_ramdisk.py
Normal file
56
os_cloud_config/cmd/upload_kernel_ramdisk.py
Normal file
@ -0,0 +1,56 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import textwrap
|
||||
|
||||
from os_cloud_config.cmd.utils import _clients as clients
|
||||
from os_cloud_config.cmd.utils import environment
|
||||
from os_cloud_config import glance
|
||||
|
||||
|
||||
def parse_args():
|
||||
description = textwrap.dedent("""
|
||||
Uploads the provided kernel and ramdisk to a Glance store.
|
||||
""")
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description=description,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
parser.add_argument('-k', '--kernel', dest='kernel',
|
||||
help='Name of the kernel image', required=True)
|
||||
parser.add_argument('-l' '--kernel-file', dest='kernel_file',
|
||||
help='Kernel to upload', required=True)
|
||||
parser.add_argument('-r', '--ramdisk', dest='ramdisk',
|
||||
help='Name of the ramdisk image', required=True)
|
||||
parser.add_argument('-s', '--ramdisk-file', dest='ramdisk_file',
|
||||
help='Ramdisk to upload', required=True)
|
||||
environment._add_logging_arguments(parser)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
environment._configure_logging(args)
|
||||
try:
|
||||
environment._ensure()
|
||||
client = clients.get_glance_client()
|
||||
glance.create_or_find_kernel_and_ramdisk(
|
||||
client, args.kernel, args.ramdisk, kernel_path=args.kernel_file,
|
||||
ramdisk_path=args.ramdisk_file)
|
||||
except Exception:
|
||||
logging.exception("Unexpected error during command execution")
|
||||
return 1
|
||||
return 0
|
61
os_cloud_config/glance.py
Normal file
61
os_cloud_config/glance.py
Normal file
@ -0,0 +1,61 @@
|
||||
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import logging
|
||||
|
||||
from glanceclient.openstack.common.apiclient import exceptions
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def create_or_find_kernel_and_ramdisk(glanceclient, kernel_name, ramdisk_name,
|
||||
kernel_path=None, ramdisk_path=None):
|
||||
"""Find or create a given kernel and ramdisk in Glance.
|
||||
|
||||
If either kernel_path or ramdisk_path is None, they will not be created,
|
||||
and an exception will be raised if it does not exist in Glance.
|
||||
|
||||
:param glanceclient: A client for Glance.
|
||||
:param kernel_name: Name to search for or create for the kernel.
|
||||
:param ramdisk_name: Name to search for or create for the ramdisk.
|
||||
:param kernel_path: Path to the kernel on disk.
|
||||
:param ramdisk_path: Path to the ramdisk on disk.
|
||||
|
||||
:returns: A dictionary mapping kernel or ramdisk to the ID in Glance.
|
||||
"""
|
||||
try:
|
||||
kernel_image = glanceclient.images.find(name=kernel_name,
|
||||
disk_format='aki')
|
||||
except exceptions.NotFound:
|
||||
if kernel_path:
|
||||
kernel_image = glanceclient.images.create(
|
||||
name=kernel_name, disk_format='aki', is_public=True,
|
||||
data=open(kernel_path, 'rb'))
|
||||
else:
|
||||
raise ValueError("Kernel image not found in Glance, and no path "
|
||||
"specified.")
|
||||
try:
|
||||
ramdisk_image = glanceclient.images.find(name=ramdisk_name,
|
||||
disk_format='ari')
|
||||
except exceptions.NotFound:
|
||||
if ramdisk_path:
|
||||
# public, type=ari
|
||||
ramdisk_image = glanceclient.images.create(
|
||||
name=ramdisk_name, disk_format='ari', is_public=True,
|
||||
data=open(ramdisk_path, 'rb'))
|
||||
else:
|
||||
raise ValueError("Ramdisk image not found in Glance, and no path "
|
||||
"specified.")
|
||||
return {'kernel': kernel_image.id, 'ramdisk': ramdisk_image.id}
|
74
os_cloud_config/tests/test_glance.py
Normal file
74
os_cloud_config/tests/test_glance.py
Normal file
@ -0,0 +1,74 @@
|
||||
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import collections
|
||||
import tempfile
|
||||
|
||||
from glanceclient.openstack.common.apiclient import exceptions
|
||||
import mock
|
||||
import testtools
|
||||
|
||||
from os_cloud_config import glance
|
||||
from os_cloud_config.tests import base
|
||||
|
||||
|
||||
class GlanceTest(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(GlanceTest, self).setUp()
|
||||
self.image = collections.namedtuple('image', ['id'])
|
||||
|
||||
def test_return_existing_kernel_and_ramdisk(self):
|
||||
client = mock.MagicMock()
|
||||
expected = {'kernel': 'aaa', 'ramdisk': 'zzz'}
|
||||
client.images.find.side_effect = (self.image('aaa'), self.image('zzz'))
|
||||
ids = glance.create_or_find_kernel_and_ramdisk(client, 'bm-kernel',
|
||||
'bm-ramdisk')
|
||||
client.images.create.assert_not_called()
|
||||
self.assertEqual(expected, ids)
|
||||
|
||||
def test_raise_exception_kernel(self):
|
||||
client = mock.MagicMock()
|
||||
client.images.find.side_effect = exceptions.NotFound
|
||||
message = "Kernel image not found in Glance, and no path specified."
|
||||
with testtools.ExpectedException(ValueError, message):
|
||||
glance.create_or_find_kernel_and_ramdisk(client, 'bm-kernel',
|
||||
None)
|
||||
|
||||
def test_raise_exception_ramdisk(self):
|
||||
client = mock.MagicMock()
|
||||
client.images.find.side_effect = (self.image('aaa'),
|
||||
exceptions.NotFound)
|
||||
message = "Ramdisk image not found in Glance, and no path specified."
|
||||
with testtools.ExpectedException(ValueError, message):
|
||||
glance.create_or_find_kernel_and_ramdisk(client, 'bm-kernel',
|
||||
'bm-ramdisk')
|
||||
|
||||
def test_create_kernel_and_ramdisk(self):
|
||||
client = mock.MagicMock()
|
||||
client.images.find.side_effect = exceptions.NotFound
|
||||
client.images.create.side_effect = (self.image('aaa'),
|
||||
self.image('zzz'))
|
||||
expected = {'kernel': 'aaa', 'ramdisk': 'zzz'}
|
||||
with tempfile.NamedTemporaryFile() as imagefile:
|
||||
ids = glance.create_or_find_kernel_and_ramdisk(
|
||||
client, 'bm-kernel', 'bm-ramdisk', kernel_path=imagefile.name,
|
||||
ramdisk_path=imagefile.name)
|
||||
kernel_create = mock.call(name='bm-kernel', disk_format='aki',
|
||||
is_public=True, data=mock.ANY)
|
||||
ramdisk_create = mock.call(name='bm-ramdisk', disk_format='ari',
|
||||
is_public=True, data=mock.ANY)
|
||||
client.images.create.assert_has_calls([kernel_create, ramdisk_create])
|
||||
self.assertEqual(expected, ids)
|
@ -32,6 +32,7 @@ console_scripts =
|
||||
setup-endpoints = os_cloud_config.cmd.setup_endpoints:main
|
||||
setup-flavors = os_cloud_config.cmd.setup_flavors:main
|
||||
setup-neutron = os_cloud_config.cmd.setup_neutron:main
|
||||
upload-kernel-ramdisk = os_cloud_config.cmd.upload_kernel_ramdisk:main
|
||||
|
||||
[build_sphinx]
|
||||
source-dir = doc/source
|
||||
|
Loading…
x
Reference in New Issue
Block a user