ACK
On Jun 15, 2011, at 7:02 AM, Mark McLoughlin wrote:
e.g.
$> imgfac.py --target-image ami-669f680f --image-desc '<image><name>My Image</name></image>' --target ec2 --provider ec2-us-east-1
imports the specified AMI metadata into IWHD as a provider image.
imagefactory/ApplicationConfiguration.py | 4 ++ imagefactory/BuildDispatcher.py | 65 +++++++++++++++++++++++++---- imagefactory/ImageWarehouse.py | 19 ++++++++- imgfac.py | 11 +++++- 4 files changed, 87 insertions(+), 12 deletions(-)
diff --git a/imagefactory/ApplicationConfiguration.py b/imagefactory/ApplicationConfiguration.py index 3b121b8..989f2bb 100644 --- a/imagefactory/ApplicationConfiguration.py +++ b/imagefactory/ApplicationConfiguration.py @@ -70,6 +70,10 @@ class ApplicationConfiguration(Singleton): group_push.add_argument('--provider', action='append', help='Cloud service providers to push the image (e.g. ec2-us-east-1, rackspace, etc.)') group_push.add_argument('--credentials', help='Cloud provider credentials XML (i.e. <provider_credentials/> document)')
group_build = argparser.add_argument_group(title='Image importing', description=cli_build_description)
group_build.add_argument('--target-image', help='Target specific identifier for the image to import.')
group_build.add_argument('--image-desc', help='XML document describing the imported image.')
group_warehouse = argparser.add_argument_group(title='Image Warehouse', description=warehouse_description) group_warehouse.add_argument('--warehouse', default='http://localhost:9090/', help='URL of the warehouse location to store images. (default: %(default)s)') group_warehouse.add_argument('--image_bucket', help='Name of warehouse bucket to look in images. (default: %(default)s)')
diff --git a/imagefactory/BuildDispatcher.py b/imagefactory/BuildDispatcher.py index 5e1ac4b..2bc0014 100644 --- a/imagefactory/BuildDispatcher.py +++ b/imagefactory/BuildDispatcher.py @@ -30,13 +30,24 @@ class BuildDispatcher(Singleton): def _singleton_init(self): self.warehouse = ImageWarehouse(ApplicationConfiguration().configuration['warehouse'])
def import_image(self, image_id, build_id, target_identifier, image_desc, target, provider):
image_id = self._ensure_image(image_id, image_desc)
build_id = self._ensure_build(image_id, build_id)
target_image_id = self._ensure_target_image(build_id, target)
provider_image_id = self._ensure_provider_image(target_image_id, provider, target_identifier)
self._commit_build(image_id, build_id)
return (image_id, build_id, target_image_id, provider_image_id)
def build_image_for_targets(self, image_id, build_id, template, targets, job_cls = BuildJob, *args, **kwargs): if image_id and not targets: targets = self._targets_for_image_id(image_id)
template = self._load_template(image_id, build_id, template)
image_id = self._ensure_image(image_id, template)
image_id = self._ensure_image_with_template(image_id, template) build_id = self._ensure_build(image_id, build_id) watcher = BuildWatcher(image_id, build_id, len(targets), self.warehouse)
@@ -75,23 +86,39 @@ class BuildDispatcher(Singleton): return None return nodes[0].content
- def _ensure_image(self, image_id, template):
if image_id:
return image_id
- def _ensure_image_with_template(self, image_id, template): name = self._xml_node(template.xml, '/template/name') if name:
image_xml = '<image><name>%s</name></image>' % name
image_desc = '<image><name>%s</name></image>' % name else:
image_xml = '</image>'
image_desc = '</image>'
return self._ensure_image(image_id, image_desc)
return self.warehouse.store_image(None, image_xml)
def _ensure_image(self, image_id, image_desc):
if image_id:
return image_id
else:
return self.warehouse.store_image(None, image_desc)
def _ensure_build(self, image_id, build_id): if build_id: return build_id return self.warehouse.store_build(None, dict(image = image_id))
def _ensure_target_image(self, build_id, target):
target_image_id = self._target_image_for_build_and_target(build_id, target)
if target_image_id:
return target_image_id
return self.warehouse.store_target_image(None, None, dict(build=build_id, target=target))
def _ensure_provider_image(self, target_image_id, provider, target_identifier):
provider_image_id = self._provider_image_for_target_image_and_provider(target_image_id, provider)
if provider_image_id:
self._set_provider_image_attr(provider_image_id, 'target_identifier', target_identifier)
else:
metadata = dict(target_image=target_image_id, provider=provider, target_identifier=target_identifier)
return self.warehouse.create_provider_image(None, None, metadata)
def _load_template(self, image_id, build_id, template): if not template: if build_id:
@@ -100,12 +127,24 @@ class BuildDispatcher(Singleton): template = self._template_for_image_id(image_id) return Template(template)
def _commit_build(self, image_id, build_id):
parent_id = self._latest_build(image_id)
if parent_id:
self._set_build_parent(build_id, parent_id)
self._set_latest_build(image_id, build_id)
def _latest_build(self, image_id): return self.warehouse.metadata_for_id_of_type(['latest_build'], image_id, 'image')['latest_build']
def _latest_unpushed(self, image_id): return self.warehouse.metadata_for_id_of_type(['latest_unpushed'], image_id, 'image')['latest_unpushed']
def _set_latest_build(self, image_id, build_id):
self.warehouse.set_metadata_for_id_of_type({'latest_build' : build_id}, image_id, 'image')
def _set_build_parent(self, build_id, parent_id):
self.warehouse.set_metadata_for_id_of_type({'parent' : parent_id}, build_id, 'build')
def _targets_for_build_id(self, build_id): targets = [] for target_image_id in self._target_images_for_build(build_id):
@@ -122,7 +161,15 @@ class BuildDispatcher(Singleton): return self.warehouse.query("target_image", "$build == "%s"" % (build_id,))
def _target_image_for_build_and_target(self, build_id, target):
return self.warehouse.query("target_image", "$build == \"%s\" && $target == \"%s\"" % (build_id, target))[0]
results = self.warehouse.query("target_image", "$build == \"%s\" && $target == \"%s\"" % (build_id, target))
return results[0] if results else None
def _provider_image_for_target_image_and_provider(self, target_image_id, provider):
results = self.warehouse.query("provider_image", "$target_image == \"%s\" && $provider == \"%s\"" % (target_image_id, provider))
return results[0] if results else None
def _set_provider_image_attr(provider_image_id, attr, value):
self.warehouse.set_metadata_for_id_of_type({attr : value}, provider_image_id, "provider_image")
def _template_for_target_image_id(self, target_image_id): return self.warehouse.metadata_for_id_of_type(['template'], target_image_id, 'target_image')['template']
diff --git a/imagefactory/ImageWarehouse.py b/imagefactory/ImageWarehouse.py index 9fbd110..02504cd 100644 --- a/imagefactory/ImageWarehouse.py +++ b/imagefactory/ImageWarehouse.py @@ -193,8 +193,7 @@ class ImageWarehouse(object):
return build_id
- def store_target_image(self, target_image_id, image_file_path, metadata=None):
object_url = self.__url_for_id_of_type(target_image_id, "target_image")
- def _upload_image_file(self, object_url, image_file_path): try: image_file = open(image_file_path)
@@ -212,12 +211,26 @@ class ImageWarehouse(object): except Exception, e: raise WarehouseError("Problem encountered trying to reach image warehouse. Please check that iwhd is running and reachable.\nException text: %s" % (e, ))
def store_target_image(self, target_image_id, image_file_path, metadata=None):
if(not target_image_id):
target_image_id = str(uuid.uuid4())
object_url = self.__url_for_id_of_type(target_image_id, "target_image")
if image_file_path:
self._upload_image_file(object_url, image_file_path)
else:
self._http_put(object_url)
meta_data = dict(uuid=target_image_id, object_type="target_image") if(metadata): meta_data.update(metadata) self.set_metadata_for_object_at_url(meta_data, object_url)
return target_image_id
def create_provider_image(self, image_id, txt=None, metadata=None):
if(not image_id):
image_id = str(uuid.uuid4()) object_url = self.__url_for_id_of_type(image_id, object_type="provider_image") if(not txt): if(metadata):
@@ -232,6 +245,8 @@ class ImageWarehouse(object): meta_data.update(metadata) self.set_metadata_for_object_at_url(meta_data, object_url)
return image_id
- def store_template(self, template, template_id=None, metadata=None): if(not template_id): template_id = str(uuid.uuid4())
diff --git a/imgfac.py b/imgfac.py index daa6e71..2a8f1dd 100755 --- a/imgfac.py +++ b/imgfac.py @@ -147,7 +147,16 @@ class Application(Singleton): self.app_config['foreground'] = True self.setup_logging()
if (self.app_config['template'] and self.app_config['target']) or (self.app_config['image'] and not self.app_config['provider']):
if self.app_config['target_image'] and self.app_config['target'] and self.app_config['provider']:
if len(self.app_config['target']) != 1:
print("Expect a single target, but '%s' supplied" % (self.app_config['target'],))
sys.exit(1)
if len(self.app_config['provider']) != 1:
print("Expect a single provider, but '%s' supplied" % (self.app_config['provider'],))
sys.exit(1)
image_ids = BuildDispatcher().import_image(self.app_config['image'], None, self.app_config['target_image'], self.app_config['image_desc'], self.app_config['target'][0], self.app_config['provider'][0])
print("Imported target image ID %s as image %s" % (self.app_config['target_image'], image_ids[0]))
elif (self.app_config['template'] and self.app_config['target']) or (self.app_config['image'] and not self.app_config['provider']): dispatchers = BuildDispatcher().build_image_for_targets(self.app_config['image'], None, self.app_config['template'], self.app_config['target']) for dispatcher in dispatchers: print("Building build %s of image %s to target %s" % (dispatcher.build_id, dispatcher.image_id, dispatcher.target))
-- 1.7.4.4