Skip to content

Commit 563b237

Browse files
Merge pull request softlayer#641 from sudorandom/image-export
Adds image export and improves image import docs
2 parents 961978c + 5f10f74 commit 563b237

8 files changed

Lines changed: 98 additions & 36 deletions

File tree

SoftLayer/CLI/image/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
MASK = ('id,accountId,name,globalIdentifier,parentId,publicFlag,flexImageFlag,'
77
'imageType')
88
DETAIL_MASK = MASK + (',children[id,blockDevicesDiskSpaceTotal,datacenter],'
9-
'note,createDate,status')
9+
'note,createDate,status,transaction')
1010
PUBLIC_TYPE = formatting.FormattedItem('PUBLIC', 'Public')
1111
PRIVATE_TYPE = formatting.FormattedItem('PRIVATE', 'Private')

SoftLayer/CLI/image/detail.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ def cli(env, identifier):
4040
utils.lookup(image, 'status', 'keyname'),
4141
utils.lookup(image, 'status', 'name'),
4242
)])
43+
table.add_row([
44+
'active_transaction',
45+
formatting.transaction_status(image.get('transaction')),
46+
])
4347
table.add_row(['account', image.get('accountId', formatting.blank())])
4448
table.add_row(['visibility',
4549
image_mod.PUBLIC_TYPE if image['publicFlag']

SoftLayer/CLI/image/export.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""Export an image."""
2+
# :license: MIT, see LICENSE for more details.
3+
4+
import SoftLayer
5+
from SoftLayer.CLI import environment
6+
from SoftLayer.CLI import exceptions
7+
from SoftLayer.CLI import helpers
8+
9+
10+
import click
11+
12+
13+
@click.command()
14+
@click.argument('identifier')
15+
@click.argument('uri')
16+
@environment.pass_env
17+
def cli(env, identifier, uri):
18+
"""Export an image to object storage.
19+
20+
The URI for an object storage object (.vhd/.iso file) of the format:
21+
swift://<objectStorageAccount>@<cluster>/<container>/<objectPath>
22+
"""
23+
24+
image_mgr = SoftLayer.ImageManager(env.client)
25+
image_id = helpers.resolve_id(image_mgr.resolve_ids, identifier, 'image')
26+
result = image_mgr.export_image_to_uri(image_id, uri)
27+
28+
if not result:
29+
raise exceptions.CLIAbort("Failed to export Image")

SoftLayer/CLI/image/import.py

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,24 @@
1515
@click.argument('uri')
1616
@click.option('--note', default="",
1717
help="The note to be applied to the imported template")
18-
@click.option('--osrefcode', default="",
18+
@click.option('--os-code', default="",
1919
help="The referenceCode of the operating system software"
2020
" description for the imported VHD")
2121
@environment.pass_env
22-
def cli(env, name, note, osrefcode, uri):
23-
"""Import an image."""
22+
def cli(env, name, note, os_code, uri):
23+
"""Import an image.
24+
25+
The URI for an object storage object (.vhd/.iso file) of the format:
26+
swift://<objectStorageAccount>@<cluster>/<container>/<objectPath>
27+
"""
2428

2529
image_mgr = SoftLayer.ImageManager(env.client)
26-
data = {}
27-
output = []
28-
if name:
29-
data['name'] = name
30-
if note:
31-
data['note'] = note
32-
if osrefcode:
33-
data['operatingSystemReferenceCode'] = osrefcode
34-
if uri:
35-
data['uri'] = uri
36-
37-
# not sure if u should validate here or not
38-
# if uri.endswith(".vhd") and osrefcode == "":
39-
# raise exceptions.CLIAbort("Please specify osrefcode for .vhdImage")
40-
41-
result = image_mgr.import_image_from_uri(data)
30+
result = image_mgr.import_image_from_uri(
31+
name=name,
32+
note=note,
33+
os_code=os_code,
34+
uri=uri,
35+
)
4236

4337
if not result:
4438
raise exceptions.CLIAbort("Failed to import Image")
@@ -50,5 +44,4 @@ def cli(env, name, note, osrefcode, uri):
5044
table.add_row(['id', result['id']])
5145
table.add_row(['created', result['createDate']])
5246
table.add_row(['guid', result['globalIdentifier']])
53-
output.append(table)
54-
env.fout(output)
47+
env.fout(table)

SoftLayer/CLI/routes.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
('image:edit', 'SoftLayer.CLI.image.edit:cli'),
7878
('image:list', 'SoftLayer.CLI.image.list:cli'),
7979
('image:import', 'SoftLayer.CLI.image.import:cli'),
80+
('image:export', 'SoftLayer.CLI.image.export:cli'),
8081

8182
('iscsi', 'SoftLayer.CLI.iscsi'),
8283
('iscsi:cancel', 'SoftLayer.CLI.iscsi.cancel:cli'),

SoftLayer/fixtures/SoftLayer_Virtual_Guest_Block_Device_Template_Group.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,5 @@
2727
'id': 100,
2828
'name': 'test_image',
2929
}]
30+
31+
copyToExternalSource = True

SoftLayer/managers/image.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from SoftLayer import utils
1010

1111
IMAGE_MASK = ('id,accountId,name,globalIdentifier,blockDevices,parentId,'
12-
'createDate')
12+
'createDate,transaction')
1313

1414

1515
class ImageManager(utils.IdentifierMixin, object):
@@ -119,7 +119,28 @@ def edit(self, image_id, name=None, note=None, tag=None):
119119
else:
120120
return False
121121

122-
def import_image_from_uri(self, data):
123-
"""Import images which match the given uri."""
124-
result = self.vgbdtg.createFromExternalSource(data)
125-
return result
122+
def import_image_from_uri(self, name, uri, os_code=None, note=None):
123+
"""Import a new image from object storage.
124+
125+
:param string name: Name of the new image
126+
:param string uri: The URI for an object storage object
127+
(.vhd/.iso file) of the format:
128+
swift://<objectStorageAccount>@<cluster>/<container>/<objectPath>
129+
:param string os_code: The reference code of the operating system
130+
:param string note: Note to add to the image
131+
"""
132+
return self.vgbdtg.createFromExternalSource({
133+
'name': name,
134+
'note': note,
135+
'operatingSystemReferenceCode': os_code,
136+
'uri': uri,
137+
})
138+
139+
def export_image_to_uri(self, image_id, uri):
140+
"""Export image into the given object storage
141+
142+
:param int image_id: The ID of the image
143+
:param string uri: The URI for object storage of the format
144+
swift://<objectStorageAccount>@<cluster>/<container>/<objectPath>
145+
"""
146+
return self.vgbdtg.copyToExternalSource({'uri': uri}, id=image_id)

tests/managers/image_tests.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,24 @@ def test_edit_full(self):
132132
args=({'name': 'abc', 'note': 'xyz'},))
133133

134134
def test_import_image(self):
135-
# Test import image
136-
self.image.import_image_from_uri({'name': 'test_image',
137-
'note': 'testimage',
138-
'uri': 'invaliduri'})
139-
140-
self.assert_called_with(IMAGE_SERVICE, 'createFromExternalSource',
141-
args=({'name': 'test_image',
142-
'note': 'testimage',
143-
'uri': 'invaliduri'},))
135+
self.image.import_image_from_uri(name='test_image',
136+
note='testimage',
137+
uri='someuri',
138+
os_code='UBUNTU_LATEST')
139+
140+
self.assert_called_with(
141+
IMAGE_SERVICE,
142+
'createFromExternalSource',
143+
args=({'name': 'test_image',
144+
'note': 'testimage',
145+
'uri': 'someuri',
146+
'operatingSystemReferenceCode': 'UBUNTU_LATEST'},))
147+
148+
def test_export_image(self):
149+
self.image.export_image_to_uri(1234, 'someuri')
150+
151+
self.assert_called_with(
152+
IMAGE_SERVICE,
153+
'copyToExternalSource',
154+
args=({'uri': 'someuri'},),
155+
identifier=1234)

0 commit comments

Comments
 (0)