image membership management works
This commit is contained in:
@@ -57,6 +57,8 @@ class HTTPClient(httplib2.Http):
|
||||
string_parts.append(header)
|
||||
|
||||
logger.debug("REQ: %s\n" % "".join(string_parts))
|
||||
if 'raw_body' in kwargs:
|
||||
logger.debug("REQ BODY (RAW): %s\n" % (kwargs['raw_body']))
|
||||
if 'body' in kwargs:
|
||||
logger.debug("REQ BODY: %s\n" % (kwargs['body']))
|
||||
logger.debug("RESP: %s\nRESP BODY: %s\n", resp, body)
|
||||
@@ -71,9 +73,14 @@ class HTTPClient(httplib2.Http):
|
||||
_kwargs = copy.copy(kwargs)
|
||||
_kwargs.setdefault('headers', kwargs.get('headers', {}))
|
||||
_kwargs['headers']['User-Agent'] = USER_AGENT
|
||||
if 'body' in kwargs and kwargs['body'] is not None:
|
||||
_kwargs['headers']['Content-Type'] = 'application/octet-stream'
|
||||
_kwargs['body'] = kwargs['body']
|
||||
if 'raw_body' in _kwargs:
|
||||
raw_body = _kwargs.pop('raw_body')
|
||||
if raw_body is not None:
|
||||
_kwargs['headers']['Content-Type'] = 'application/octet-stream'
|
||||
_kwargs['body'] = raw_body
|
||||
elif 'body' in kwargs and kwargs['body'] is not None:
|
||||
_kwargs['headers']['Content-Type'] = 'application/json'
|
||||
_kwargs['body'] = json.dumps(kwargs['body'])
|
||||
|
||||
resp, body = super(HTTPClient, self).request(url, method, **_kwargs)
|
||||
self.http_log((url, method,), _kwargs, resp, body)
|
||||
|
@@ -64,16 +64,14 @@ class ImageMemberManager(base.Manager):
|
||||
|
||||
def _list_by_member(self, member):
|
||||
member_id = base.getid(member)
|
||||
resp, body = self.api.get('/v1/shared_images/%s' % member_id)
|
||||
resp, body = self.api.get('/v1/shared-images/%s' % member_id)
|
||||
out = []
|
||||
for member in body['shared_images']:
|
||||
member['member_id'] = member_id
|
||||
out.append(ImageMember(self, member, loaded=True))
|
||||
return out
|
||||
|
||||
def delete(self, member):
|
||||
member_id = member.member_id
|
||||
image_id = member.image_id
|
||||
def delete(self, image_id, member_id):
|
||||
self._delete("/v1/images/%s/members/%s" % (image_id, member_id))
|
||||
|
||||
def create(self, image, member_id, can_share=False):
|
||||
|
@@ -140,7 +140,8 @@ class ImageManager(base.Manager):
|
||||
if copy_from is not None:
|
||||
hdrs['x-glance-api-copy-from'] = copy_from
|
||||
|
||||
resp, body = self.api.post('/v1/images', headers=hdrs, body=image_data)
|
||||
resp, body = self.api.post('/v1/images', headers=hdrs,
|
||||
raw_body=image_data)
|
||||
return Image(self, body['image'])
|
||||
|
||||
def update(self, image, **kwargs):
|
||||
@@ -171,5 +172,5 @@ class ImageManager(base.Manager):
|
||||
|
||||
image_id = base.getid(image)
|
||||
resp, body = self.api.put('/v1/images/%s' % image_id, headers=hdrs,
|
||||
body=image_data)
|
||||
raw_body=image_data)
|
||||
return Image(self, body['image'])
|
||||
|
@@ -47,18 +47,18 @@ def do_image_show(gc, args):
|
||||
help='ID of image to reserve.')
|
||||
@utils.arg('--name', metavar='<NAME>',
|
||||
help='Name of image.')
|
||||
@utils.arg('--disk_format', metavar='<CONTAINER_FORMAT>',
|
||||
@utils.arg('--disk-format', metavar='<CONTAINER_FORMAT>',
|
||||
help='Disk format of image.')
|
||||
@utils.arg('--container_format', metavar='<DISK_FORMAT>',
|
||||
@utils.arg('--container-format', metavar='<DISK_FORMAT>',
|
||||
help='Container format of image.')
|
||||
@utils.arg('--owner', metavar='<TENANT_ID>',
|
||||
help='Tenant who should own image.')
|
||||
@utils.arg('--size', metavar='<SIZE>',
|
||||
help=('Size of image data (in bytes). Only used with'
|
||||
' \'--location\' and \'--copy_from\'.'))
|
||||
@utils.arg('--min_disk', metavar='<DISK_GB>',
|
||||
@utils.arg('--min-disk', metavar='<DISK_GB>',
|
||||
help='Minimum size of disk needed to boot image (in gigabytes).')
|
||||
@utils.arg('--min_ram', metavar='<DISK_RAM>',
|
||||
@utils.arg('--min-ram', metavar='<DISK_RAM>',
|
||||
help='Minimum amount of ram needed to boot image (in megabytes).')
|
||||
@utils.arg('--location', metavar='<IMAGE_URL>',
|
||||
help=('URL where the data for this image already resides.'
|
||||
@@ -67,7 +67,7 @@ def do_image_show(gc, args):
|
||||
' you would specify \'file:///usr/share/image.tar.gz\'.'))
|
||||
@utils.arg('--checksum', metavar='<CHECKSUM>',
|
||||
help='Hash of image data used Glance can use for verification.')
|
||||
@utils.arg('--copy_from', metavar='<IMAGE_URL>',
|
||||
@utils.arg('--copy-from', metavar='<IMAGE_URL>',
|
||||
help=('Similar to \'--location\' in usage, but this indicates that'
|
||||
' the Glance server should immediately copy the data and'
|
||||
' store it in its configured image store.'))
|
||||
@@ -104,17 +104,17 @@ def do_image_create(gc, args):
|
||||
@utils.arg('id', metavar='<IMAGE_ID>', help='ID of image to modify.')
|
||||
@utils.arg('--name', metavar='<NAME>',
|
||||
help='Name of image.')
|
||||
@utils.arg('--disk_format', metavar='<CONTAINER_FORMAT>',
|
||||
@utils.arg('--disk-format', metavar='<CONTAINER_FORMAT>',
|
||||
help='Disk format of image.')
|
||||
@utils.arg('--container_format', metavar='<DISK_FORMAT>',
|
||||
@utils.arg('--container-format', metavar='<DISK_FORMAT>',
|
||||
help='Container format of image.')
|
||||
@utils.arg('--owner', metavar='<TENANT_ID>',
|
||||
help='Tenant who should own image.')
|
||||
@utils.arg('--size', metavar='<SIZE>',
|
||||
help='Size of image data (in bytes).')
|
||||
@utils.arg('--min_disk', metavar='<DISK_GB>',
|
||||
@utils.arg('--min-disk', metavar='<DISK_GB>',
|
||||
help='Minimum size of disk needed to boot image (in gigabytes).')
|
||||
@utils.arg('--min_ram', metavar='<DISK_RAM>',
|
||||
@utils.arg('--min-ram', metavar='<DISK_RAM>',
|
||||
help='Minimum amount of ram needed to boot image (in megabytes).')
|
||||
@utils.arg('--location', metavar='<IMAGE_URL>',
|
||||
help=('URL where the data for this image already resides.'
|
||||
@@ -123,13 +123,13 @@ def do_image_create(gc, args):
|
||||
' you would specify \'file:///usr/share/image.tar.gz\'.'))
|
||||
@utils.arg('--checksum', metavar='<CHECKSUM>',
|
||||
help='Hash of image data used Glance can use for verification.')
|
||||
@utils.arg('--copy_from', metavar='<IMAGE_URL>',
|
||||
@utils.arg('--copy-from', metavar='<IMAGE_URL>',
|
||||
help=('Similar to \'--location\' in usage, but this indicates that'
|
||||
' the Glance server should immediately copy the data and'
|
||||
' store it in its configured image store.'))
|
||||
@utils.arg('--is_public', type=bool,
|
||||
@utils.arg('--is-public', type=bool,
|
||||
help='Make image accessible to the public.')
|
||||
@utils.arg('--is_protected', type=bool,
|
||||
@utils.arg('--is-protected', type=bool,
|
||||
help='Prevent image from being deleted.')
|
||||
@utils.arg('--property', metavar="<key=value>", action='append', default=[],
|
||||
help=("Arbitrary property to associate with image. "
|
||||
@@ -161,3 +161,40 @@ def do_image_update(gc, args):
|
||||
def do_image_delete(gc, args):
|
||||
"""Delete a specific image."""
|
||||
gc.images.delete(args.id)
|
||||
|
||||
|
||||
@utils.arg('--image-id', metavar='<IMAGE_ID>',
|
||||
help='Filter results by an image ID.')
|
||||
@utils.arg('--tenant-id', metavar='<TENANT_ID>',
|
||||
help='Filter results by a tenant ID.')
|
||||
def do_member_list(gc, args):
|
||||
if args.image_id and args.tenant_id:
|
||||
print 'Unable to filter members by both --image-id and --tenant-id.'
|
||||
sys.exit(1)
|
||||
elif args.image_id:
|
||||
kwargs = {'image': args.image_id}
|
||||
elif args.tenant_id:
|
||||
kwargs = {'member': args.tenant_id}
|
||||
else:
|
||||
print 'Unable to list all members. Specify --image-id or --tenant-id'
|
||||
sys.exit(1)
|
||||
|
||||
members = gc.image_members.list(**kwargs)
|
||||
columns = ['Image ID', 'Member ID', 'Can Share']
|
||||
utils.print_list(members, columns)
|
||||
|
||||
@utils.arg('image_id', metavar='<IMAGE_ID>',
|
||||
help='Image to add member to.')
|
||||
@utils.arg('tenant_id', metavar='<TENANT_ID>',
|
||||
help='Tenant to add as member')
|
||||
@utils.arg('--can-share', action='store_true', default=False,
|
||||
help='Allow the specified tenant to share this image.')
|
||||
def do_member_create(gc, args):
|
||||
gc.image_members.create(args.image_id, args.tenant_id, args.can_share)
|
||||
|
||||
@utils.arg('image_id', metavar='<IMAGE_ID>',
|
||||
help='Image to add member to.')
|
||||
@utils.arg('tenant_id', metavar='<TENANT_ID>',
|
||||
help='Tenant to add as member')
|
||||
def do_member_delete(gc, args):
|
||||
gc.image_members.delete(args.image_id, args.tenant_id)
|
||||
|
@@ -25,7 +25,7 @@ class ImageMemberManagerTest(unittest.TestCase):
|
||||
|
||||
def test_list_by_member(self):
|
||||
members = self.mgr.list(member='1')
|
||||
expect = [('GET', '/v1/shared_images/1', {}, None)]
|
||||
expect = [('GET', '/v1/shared-images/1', {}, None)]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertEqual(len(members), 1)
|
||||
self.assertEqual(members[0].member_id, '1')
|
||||
@@ -41,12 +41,8 @@ class ImageMemberManagerTest(unittest.TestCase):
|
||||
self.assertEqual(member.can_share, False)
|
||||
|
||||
def test_delete(self):
|
||||
member = self.mgr.get(self.image, '1')
|
||||
self.mgr.delete(member)
|
||||
expect = [
|
||||
('GET', '/v1/images/1/members/1', {}, None),
|
||||
('DELETE', '/v1/images/1/members/1', {}, None),
|
||||
]
|
||||
self.mgr.delete('1', '1')
|
||||
expect = [('DELETE', '/v1/images/1/members/1', {}, None)]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
|
||||
def test_create(self):
|
||||
|
@@ -87,7 +87,7 @@ fixtures = {
|
||||
'PUT': ({}, None),
|
||||
'DELETE': ({}, None),
|
||||
},
|
||||
'/v1/shared_images/1': {
|
||||
'/v1/shared-images/1': {
|
||||
'GET': (
|
||||
{},
|
||||
{'shared_images': [
|
||||
@@ -116,11 +116,11 @@ class FakeAPI(object):
|
||||
def head(self, url):
|
||||
return self._request('HEAD', url)
|
||||
|
||||
def post(self, url, headers=None, body=None):
|
||||
return self._request('POST', url, headers, body)
|
||||
def post(self, url, headers=None, body=None, raw_body=None):
|
||||
return self._request('POST', url, headers, body or raw_body)
|
||||
|
||||
def put(self, url, headers=None, body=None):
|
||||
return self._request('PUT', url, headers, body)
|
||||
def put(self, url, headers=None, body=None, raw_body=None):
|
||||
return self._request('PUT', url, headers, body or raw_body)
|
||||
|
||||
def delete(self, url):
|
||||
return self._request('DELETE', url)
|
||||
|
Reference in New Issue
Block a user