diff --git a/aerostat/app.py b/aerostat/app.py index faed328..1c29f15 100644 --- a/aerostat/app.py +++ b/aerostat/app.py @@ -37,13 +37,15 @@ def main(): cloud_config = config.get_one_cloud(options=parsed_options) cloud = shade.OpenStackCloud(cloud_config=cloud_config) - res = resolver.Resolver(cloud) + downloader = download.Downloader('.', cloud) + res = resolver.Resolver(cloud, downloader) tasks = [] # for server in cloud.list_servers(): # tasks.extend(res.server(server)) tasks.extend(res.server(cloud.get_server('dev1'))) + tasks.extend(res.image(cloud.get_image('testvol1-img1'))) playbook = [ {'hosts': 'localhost', @@ -54,10 +56,13 @@ def main(): print(yaml.dump(playbook, default_flow_style=False, explicit_start=True)) - print('downloading snapshot') - image = cloud.get_image('dev1-sn1') - with download.ProgressBarDownloader('dev1-sn1.dat', image.size) as out: - cloud.download_image('dev1-sn1', output_file=out) + downloader.start() + + # print('downloading volume snapshot') + # snapshot = cloud.get_volume_snapshot('testvol1-sn1') + # pprint.pprint(snapshot) + # # with download.ProgressBarDownloader('testvol1-sn1.dat', snapshot.size) as out: + # # cloud.download_image('dev1-sn1', output_file=out) # for volume in dev1.volumes: # vol = cloud.get_volume(volume.id) diff --git a/aerostat/download.py b/aerostat/download.py index 62f6055..3cdd66d 100644 --- a/aerostat/download.py +++ b/aerostat/download.py @@ -15,6 +15,8 @@ # License for the specific language governing permissions and limitations # under the License. +import os.path + import progressbar @@ -31,6 +33,7 @@ class ProgressBarDownloader: self.bar = progressbar.ProgressBar( widgets=[ progressbar.Percentage(), + ' ', progressbar.Bar(), progressbar.FileTransferSpeed(), ' ', @@ -51,3 +54,34 @@ class ProgressBarDownloader: self.fd.write(block) self.amt_read += len(block) self.bar.update(self.amt_read) + + +class Downloader: + + def __init__(self, output_dir, cloud): + self.output_dir = output_dir + self.cloud = cloud + self._tasks = [] + + def _add(self, resource_type, resource, output_path): + self._tasks.append((resource_type, resource, output_path)) + + def add_image(self, image): + base = image.name + '.dat' + output_path = os.path.join(self.output_dir, base) + self._add('image', image, output_path) + return base + + def start(self): + # FIXME(dhellmann): start downloads in a separate thread or process + for resource_type, resource, output_path in self._tasks: + if os.path.exists(output_path): + print('output file {} already exists, skipping download'.format(output_path)) + continue + if resource_type == 'image': + print('downloading image {} to {}'.format( + resource.name, + output_path, + )) + with ProgressBarDownloader(output_path, resource.size) as out: + self.cloud.download_image(resource.name, output_file=out) diff --git a/aerostat/resolver.py b/aerostat/resolver.py index ced462b..3bb827c 100644 --- a/aerostat/resolver.py +++ b/aerostat/resolver.py @@ -20,9 +20,10 @@ import pprint class Resolver: - def __init__(self, cloud): + def __init__(self, cloud, downloader): self.cloud = cloud self._memo = set() + self._downloader = downloader def security_group(self, group): if ('security_group', group.id) in self._memo: @@ -106,3 +107,20 @@ class Resolver: 'name': 'Creating server {}'.format(server.name), 'os_server': server_data, } + + def image(self, image): + filename = self._downloader.add_image(image) + image_data = { + 'name': image.name, + 'container_format': image.container_format, + 'disk_format': image.disk_format, + 'min_disk': image.min_disk, + 'min_ram': image.min_ram, + } + # FIXME(dhellmann): handle ramdisk property? + if filename: + image_data['filename'] = filename + yield { + 'name': 'Creating image {}'.format(image.name), + 'os_image': image_data, + }