Skip to content

Commit 6da61e0

Browse files
committed
Adds image create and delete functionality.
We use the V1 API for `create` since it does not yet exist in the V2 API in glanceclient. For blueprint glance-client. Change-Id: Ifa819c14f6a013f4530d16247a671e5a1c740a28
1 parent 95bf187 commit 6da61e0

6 files changed

Lines changed: 198 additions & 3 deletions

File tree

openstackclient/image/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
API_NAME = "image"
2424
API_VERSIONS = {
25-
"1.0": "glanceclient.v2.client.Client",
25+
"1": "glanceclient.v1.client.Client",
2626
"2": "glanceclient.v2.client.Client"
2727
}
2828

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Copyright 2013 OpenStack, LLC.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
#

openstackclient/image/v1/image.py

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# Copyright 2013 OpenStack, LLC.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
#
15+
16+
"""Image V1 Action Implementations"""
17+
18+
import logging
19+
import os
20+
import sys
21+
22+
if os.name == "nt":
23+
import msvcrt
24+
else:
25+
msvcrt = None
26+
27+
from cliff import show
28+
29+
30+
class CreateImage(show.ShowOne):
31+
"""Create image command"""
32+
33+
api = "image"
34+
log = logging.getLogger(__name__ + ".CreateImage")
35+
36+
def get_parser(self, prog_name):
37+
parser = super(CreateImage, self).get_parser(prog_name)
38+
parser.add_argument(
39+
"name",
40+
metavar="<name>",
41+
help="Name of image.")
42+
parser.add_argument(
43+
"--disk_format",
44+
default="raw",
45+
metavar="<disk_format>",
46+
help="Disk format of image.")
47+
parser.add_argument(
48+
"--id",
49+
metavar="<id>",
50+
help="ID of image to reserve.")
51+
parser.add_argument(
52+
"--store",
53+
metavar="<store>",
54+
help="Store to upload image to.")
55+
parser.add_argument(
56+
"--container-format",
57+
default="bare",
58+
metavar="<container_format>",
59+
help="Container format of image.")
60+
parser.add_argument(
61+
"--owner",
62+
metavar="<tenant_id>",
63+
help="Owner of the image.")
64+
parser.add_argument(
65+
"--size",
66+
metavar="<size>",
67+
help="Size of image in bytes. Only used with --location and"
68+
" --copy-from.")
69+
parser.add_argument(
70+
"--min-disk",
71+
metavar="<disk_gb>",
72+
help="Minimum size of disk needed to boot image in gigabytes.")
73+
parser.add_argument(
74+
"--min-ram",
75+
metavar="<disk_ram>",
76+
help="Minimum amount of ram needed to boot image in megabytes.")
77+
parser.add_argument(
78+
"--location",
79+
metavar="<image_url>",
80+
help="URL where the data for this image already resides.")
81+
parser.add_argument(
82+
"--file",
83+
metavar="<file>",
84+
help="Local file that contains disk image.")
85+
parser.add_argument(
86+
"--checksum",
87+
metavar="<checksum>",
88+
help="Hash of image data used for verification.")
89+
parser.add_argument(
90+
"--copy-from",
91+
metavar="<image_url>",
92+
help="Similar to --location, but this indicates that the image"
93+
" should immediately be copied from the data store.")
94+
parser.add_argument(
95+
"--metadata",
96+
metavar="<key=value>",
97+
default=[],
98+
action="append",
99+
help="Arbitrary metadata to associate with image.")
100+
protected_group = parser.add_mutually_exclusive_group()
101+
protected_group.add_argument(
102+
"--protected",
103+
dest="protected",
104+
action="store_true",
105+
help="Prevent image from being deleted (default: False).")
106+
protected_group.add_argument(
107+
"--unprotected",
108+
dest="protected",
109+
action="store_false",
110+
default=False,
111+
help="Allow images to be deleted (default: True).")
112+
public_group = parser.add_mutually_exclusive_group()
113+
public_group.add_argument(
114+
"--public",
115+
dest="is_public",
116+
action="store_true",
117+
default=True,
118+
help="Image is accessible to the public (default).")
119+
public_group.add_argument(
120+
"--private",
121+
dest="is_public",
122+
action="store_false",
123+
help="Image is inaccessible to the public.")
124+
return parser
125+
126+
def take_action(self, parsed_args):
127+
self.log.debug("take_action(%s)" % parsed_args)
128+
129+
# NOTE(jk0): Since create() takes kwargs, it's easiest to just make a
130+
# copy of parsed_args and remove what we don't need.
131+
args = vars(parsed_args)
132+
args = dict(filter(lambda x: x[1] is not None, args.items()))
133+
args.pop("columns")
134+
args.pop("formatter")
135+
args.pop("prefix")
136+
args.pop("variables")
137+
138+
args["properties"] = {}
139+
for _metadata in args.pop("metadata"):
140+
key, value = _metadata.split("=", 1)
141+
args["properties"][key] = value
142+
143+
if "location" not in args and "copy_from" not in args:
144+
if "file" in args:
145+
args["data"] = open(args.pop("file"), "rb")
146+
else:
147+
args["data"] = None
148+
if sys.stdin.isatty() is not True:
149+
if msvcrt:
150+
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
151+
args["data"] = sys.stdin
152+
153+
image_client = self.app.client_manager.image
154+
data = image_client.images.create(**args)._info.copy()
155+
156+
return zip(*sorted(data.iteritems()))

openstackclient/image/v2/image.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# under the License.
1414
#
1515

16-
"""Image Action Implementations"""
16+
"""Image V2 Action Implementations"""
1717

1818
import logging
1919

@@ -25,6 +25,27 @@
2525
from openstackclient.common import utils
2626

2727

28+
class DeleteImage(command.Command):
29+
"""Delete image command"""
30+
31+
api = "image"
32+
log = logging.getLogger(__name__ + ".DeleteImage")
33+
34+
def get_parser(self, prog_name):
35+
parser = super(DeleteImage, self).get_parser(prog_name)
36+
parser.add_argument(
37+
"id",
38+
metavar="<image_id>",
39+
help="ID of image to delete.")
40+
return parser
41+
42+
def take_action(self, parsed_args):
43+
self.log.debug("take_action(%s)" % parsed_args)
44+
45+
image_client = self.app.client_manager.image
46+
image_client.images.delete(parsed_args.id)
47+
48+
2849
class ListImage(lister.Lister):
2950
"""List image command"""
3051

setup.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,11 @@ def read(fname):
173173
'set_user=openstackclient.identity.v3.user:SetUser',
174174
'show_user=openstackclient.identity.v3.user:ShowUser',
175175
],
176+
'openstack.image.v1': [
177+
'create_image=openstackclient.image.v1.image:CreateImage',
178+
],
176179
'openstack.image.v2': [
180+
'delete_image=openstackclient.image.v2.image:DeleteImage',
177181
'list_image=openstackclient.image.v2.image:ListImage',
178182
'save_image=openstackclient.image.v2.image:SaveImage',
179183
'show_image=openstackclient.image.v2.image:ShowImage',

tools/pip-requires

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
cliff
22
keyring
33
pycrypto
4-
python-glanceclient>=0.5.1
4+
python-glanceclient>=0.9.0,<2
55
python-keystoneclient>=0.2,<1.0
66
python-novaclient>=2
77
python-cinderclient>=1

0 commit comments

Comments
 (0)