This mostly just removes unneeded whitespace at the end
of lines. It also updates the copyright headers on all of
the files that I touched.
Signed-off-by: Chris Lalancette <clalance(a)redhat.com>
---
imagefactory/ApplicationConfiguration.py | 17 +++----
imagefactory/builders/BaseBuilder.py | 68 +++++++++++++--------------
imagefactory/builders/FedoraBuilder.py | 13 +++---
imagefactory/builders/IBuilder.py | 9 ++--
imagefactory/builders/IBuilderDelegate.py | 15 +++---
imagefactory/builders/MockBuilder.py | 25 +++++-----
imagefactory/builders/RHELBuilder.py | 9 ++--
imagefactory/qmfagent/BuildAdaptor.py | 50 ++++++++++----------
imagefactory/qmfagent/ImageFactory.py | 17 +++----
imagefactory/qmfagent/ImageFactoryAgent.py | 29 ++++++------
imgfac.py | 46 +++++++++---------
tests/builders/testBaseBuilder.py | 38 ++++++++--------
tests/builders/testMockBuilder.py | 12 +++---
tests/qmfagent/testBuildAdaptor.py | 18 ++++----
tests/qmfagent/testImageFactory.py | 18 ++++----
tests/qmfagent/testImageFactoryAgent.py | 26 +++++-----
tests/testApplicationConfiguration.py | 12 +++---
17 files changed, 206 insertions(+), 216 deletions(-)
diff --git a/imagefactory/ApplicationConfiguration.py
b/imagefactory/ApplicationConfiguration.py
index 9a54398..5125b56 100644
--- a/imagefactory/ApplicationConfiguration.py
+++ b/imagefactory/ApplicationConfiguration.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# encoding: utf-8
-# Copyright (C) 2010 Red Hat, Inc.
+# Copyright (C) 2010-2011 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@ import json
class ApplicationConfiguration(object):
instance = None
-
+
def configuration():
doc = "The configuration property."
def fget(self):
@@ -36,7 +36,7 @@ class ApplicationConfiguration(object):
del self._configuration
return locals()
configuration = property(**configuration())
-
+
def arguments():
doc = "The arguments property."
def fget(self):
@@ -47,18 +47,18 @@ class ApplicationConfiguration(object):
del self._arguments
return locals()
arguments = property(**arguments())
-
-
+
+
def __new__(cls, *p, **k):
if cls.instance is None:
cls.instance = object.__new__(cls, *p, **k)
return cls.instance
-
+
def __init__(self):
super(ApplicationConfiguration, self).__init__()
self.configuration = {}
self.arguments = self.parse_arguments()
-
+
if (self.arguments):
config_file_path = self.arguments.config
if (os.path.isfile(config_file_path)):
@@ -70,7 +70,7 @@ class ApplicationConfiguration(object):
argdict = self.arguments.__dict__
for key in argdict.keys():
self.configuration[key] = argdict[key]
-
+
def parse_arguments(self):
argparser = argparse.ArgumentParser(description='System image creation
tool...', prog='imgfac')
argparser.add_argument('--version', action='version',
version='%(prog)s 0.1', help='Version info')
@@ -92,4 +92,3 @@ class ApplicationConfiguration(object):
# return argparser.parse_args(['--debug'])
else:
return argparser.parse_args([])
-
diff --git a/imagefactory/builders/BaseBuilder.py b/imagefactory/builders/BaseBuilder.py
index 1aba768..5c4d9a7 100644
--- a/imagefactory/builders/BaseBuilder.py
+++ b/imagefactory/builders/BaseBuilder.py
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2010 Red Hat, Inc.
+# Copyright (C) 2010-2011 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -30,7 +30,7 @@ class BaseBuilder(object):
"""BaseBuilder provides a starting point for builder classes
conforming to the IBuilder interface. Subclasses of BaseBuilder
can focus on the OS/Provider specific activity for creating and deploying
images."""
zope.interface.implements(IBuilder)
-
+
# Properties
def template():
doc = "The template property."
@@ -42,7 +42,7 @@ class BaseBuilder(object):
del self._template
return locals()
template = property(**template())
-
+
def target():
doc = "The target property."
def fget(self):
@@ -53,7 +53,7 @@ class BaseBuilder(object):
del self._target
return locals()
target = property(**target())
-
+
def target_id():
doc = "The target_id property."
def fget(self):
@@ -64,7 +64,7 @@ class BaseBuilder(object):
del self._target_id
return locals()
target_id = property(**target_id())
-
+
def provider():
doc = "The provider property."
def fget(self):
@@ -75,7 +75,7 @@ class BaseBuilder(object):
del self._provider
return locals()
provider = property(**provider())
-
+
def image_id():
doc = "The image_id property."
def fget(self):
@@ -86,7 +86,7 @@ class BaseBuilder(object):
del self._image_id
return locals()
image_id = property(**image_id())
-
+
def image():
doc = "The image property."
def fget(self):
@@ -97,12 +97,12 @@ class BaseBuilder(object):
del self._image
return locals()
image = property(**image())
-
+
def status():
doc = "The status property."
def fget(self):
return self._status
-
+
def fset(self, value):
if(self.delegate):
try: #check with the delegate if we should update
@@ -124,12 +124,12 @@ class BaseBuilder(object):
self._status = value
return locals()
status = property(**status())
-
+
def percent_complete():
doc = "The percent_complete property."
def fget(self):
return self._percent_complete
-
+
def fset(self, value):
if(self.delegate):
try: #check with the delegate if we should update
@@ -149,10 +149,10 @@ class BaseBuilder(object):
pass
else:
self._percent_complete = value
-
+
return locals()
percent_complete = property(**percent_complete())
-
+
def output_descriptor():
doc = "The output_descriptor property."
def fget(self):
@@ -163,7 +163,7 @@ class BaseBuilder(object):
del self._output_descriptor
return locals()
output_descriptor = property(**output_descriptor())
-
+
def delegate():
doc = "The delegate property."
def fget(self):
@@ -174,8 +174,8 @@ class BaseBuilder(object):
del self._delegate
return locals()
delegate = property(**delegate())
-
-
+
+
# Initializer
def __init__(self, template=None, target=None):
super(BaseBuilder, self).__init__()
@@ -190,39 +190,39 @@ class BaseBuilder(object):
self._percent_complete = 0
self.output_descriptor = "<icicle></icicle>"
self.delegate = None
-
+
# Make instances callable for passing to thread objects
def __call__(self, *args, **kwargs):
# the method that we want to call on self is in args... kwargs is the method
parameters, if there are any.
getattr(self, str().join(args))(**kwargs)
-
+
# Image actions
def build_image(self):
"""Build the image file. This method is implemented by subclasses
of BaseBuilder to handle OS specific build mechanics."""
raise NotImplementedError
-
+
def abort(self):
"""Stop building the image file. This method is implemented by
subclasses of BaseBuilder to handle OS specific build mechanics."""
raise NotImplementedError
-
+
def store_image(self, location, target_parameters=None):
"""Store the image in an instance of Image Warehouse specified by
'location'. Any provider specific
parameters needed for later deploying images are passed as an XML block in
'target_parameters'."""
-
+
http = httplib2.Http()
http_headers = {'content-type':'text/plain'}
-
+
# since there is no way to know if the bucket exists or not, do the put on the
base URL first since it seems to be non-destructive
try:
http.request(location, "PUT", headers=http_headers)
-
+
if (not location.endswith('/')):
location = "%s/" % (location, )
-
+
base_url = "%s%s" % (location, self.image_id)
self.log.debug("File (%s) to be stored at %s" % (self.image,
base_url))
image_file = open(self.image)
-
+
# Upload the image itself
image_size = os.path.getsize(self.image)
curl = pycurl.Curl()
@@ -234,28 +234,28 @@ class BaseBuilder(object):
curl.perform()
curl.close()
image_file.close()
-
+
metadata = dict(uuid=self.image_id, type="image",
template=self.template, target=self.target, target_parameters=target_parameters,
icicle=self.output_descriptor)
self.__set_storage_metadata(base_url, metadata)
except Exception, e:
self.log.exception("Image could not be stored... Check status of image
warehouse! \nCaught exception while trying to store image(%s):\n%s" %
(self.image_id, e))
-
-
+
+
def __set_storage_metadata(self, url, metadata):
http = httplib2.Http()
for item in metadata:
http.request("%s/%s" % (url, item), "PUT",
body=str(metadata[item]), headers={'content-type':'text/plain'})
-
+
def push_image(self, image_id, provider, credentials):
"""Prep the image for the provider and deploy. This method is
implemented by subclasses of the BaseBuilder to handle OS/Provider specific
mechanics."""
raise NotImplementedError
-
+
def __fetch_template(self, template_string):
if((not template_string) or (("<template>" in
template_string.lower()) and ("</template>" in
template_string.lower()))):
return template_string
-
+
template_url = None
-
+
try:
template_id = uuid.UUID(template_string)
template_url = "%s/%s/template" %
(ApplicationConfiguration().configuration['warehouse'], template_id)
@@ -268,9 +268,7 @@ class BaseBuilder(object):
else:
self.log.warning("Template (%s) is not XML, URL, or UUID! Returning
'None'..." % (template_string, ))
return None
-
+
http = httplib2.Http()
headers, template = http.request(template_url, "GET")
return template
-
-
diff --git a/imagefactory/builders/FedoraBuilder.py
b/imagefactory/builders/FedoraBuilder.py
index 692cbda..047e0c3 100644
--- a/imagefactory/builders/FedoraBuilder.py
+++ b/imagefactory/builders/FedoraBuilder.py
@@ -68,7 +68,7 @@ class FedoraBuilder(BaseBuilder):
#self.config.set('paths', 'data_dir',
self.app_config["output_dir"])
self.guest = oz.Fedora.get_class(oz.TDL.TDL(xmlstring=template), self.config, None)
# TODO: Should this be global?
- self.image_id = str(self.image_id)
+ self.image_id = str(self.image_id)
# May not be necessary to do both of these
self.guest.diskimage = self.app_config["output_dir"] +
"/base-image-" + self.image_id + ".dsk"
@@ -176,7 +176,7 @@ class FedoraBuilder(BaseBuilder):
self.log.debug("launch guestfs")
g.launch ()
-
+
# Do inspection here, as libguestfs prefers we do it before mounting anything
#inspection = g.inspect_os()
# This assumes, I think reasonably, only one OS on the disk image provided by Oz
@@ -229,7 +229,7 @@ class FedoraBuilder(BaseBuilder):
# Do inspection here, as libguestfs prefers we do it before mounting
anything
inspection = g.inspect_os()
# This should always be /dev/vda or /dev/sda but we do it anyway to be safe
- osroot = inspection[0]
+ osroot = inspection[0]
# eg "fedora"
distro = g.inspect_get_distro(osroot)
@@ -251,7 +251,7 @@ class FedoraBuilder(BaseBuilder):
# recreate initrd using scheme described below
# g.sh("yum -y remove kernel")
# g.sh("yum -y install kernel-xen")
- # recreate INITRD
+ # recreate INITRD
# BG - create_devices
# TODO: Why?
# TODO: MAKEDEV is no longer even a standard part of F14 - force it in
ks.cfg?
@@ -389,7 +389,7 @@ class FedoraBuilder(BaseBuilder):
ec2_secret_key =
ctxt.xpathEval("//provider_credentials/ec2_credentials/secret_access_key")[0].content
doc.freeDoc()
- ctxt.xpathFreeContext()
+ ctxt.xpathFreeContext()
# Shove certs into named temporary files
ec2_cert_file_object = NamedTemporaryFile()
@@ -520,7 +520,7 @@ class FedoraBuilder(BaseBuilder):
def abort(self):
pass
-
+
# This file content is tightly bound up with our mod code above
# I've inserted it as class variables for convenience
rc_local="""curl
http://169.254.169.254/2009-04-04/meta-data/public-keys/0/openssh-key 2>/dev/null
>/tmp/my-key
@@ -595,4 +595,3 @@ none /dev/shm tmpfs defaults 0 0
none /proc proc defaults 0 0
none /sys sysfs defaults 0 0
"""
-
diff --git a/imagefactory/builders/IBuilder.py b/imagefactory/builders/IBuilder.py
index b9d409e..4eabc3f 100644
--- a/imagefactory/builders/IBuilder.py
+++ b/imagefactory/builders/IBuilder.py
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2010 Red Hat, Inc.
+# Copyright (C) 2010-2011 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -63,13 +63,12 @@ class IBuilder(Interface):
# methods
def build_image():
"""Tell the builder to start building the
image."""
-
+
def abort():
"""Tell the builder to stop building the image."""
-
+
def store_image(location, target_parameters):
"""Upload the completed image to an image
warehouse."""
-
+
def push_image(image_id, provider, credentials):
"""Deploy an image to the cloud provider."""
-
diff --git a/imagefactory/builders/IBuilderDelegate.py
b/imagefactory/builders/IBuilderDelegate.py
index 7cdd927..b2e0123 100644
--- a/imagefactory/builders/IBuilderDelegate.py
+++ b/imagefactory/builders/IBuilderDelegate.py
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2010 Red Hat, Inc.
+# Copyright (C) 2010-2011 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -25,22 +25,21 @@ class IBuilderDelegate(Interface):
Subclasses of the BaseBuilder class will get this for free. Classes
that conform to the IBuilderDelegate interface can selectively
implement methods from this interface."""
-
+
def builder_will_update_status(self, builder, original_status, new_status):
"""The builder will update from original_status to
new_status."""
-
+
def builder_did_update_status(self, builder, original_status, new_status):
"""The builder updated the status from original_status to
new_status."""
-
+
def builder_should_update_status(self, builder, original_status, new_status):
"""Returns whether the builder should update the status from
original_status to new_status."""
-
+
def builder_will_update_percentage(self, builder, original_percentage, new_percentage):
"""The builder will update from original_percentage to
new_percentage."""
-
+
def builder_did_update_percentage(self, builder, original_percentage, new_percentage):
"""The builder updated from original_percentage to
new_percentage."""
-
+
def builder_should_update_percentage(self, builder, original_percentage,
new_percentage):
"""Returns whether the builder should update from original_percentage to
new_percentage."""
-
diff --git a/imagefactory/builders/MockBuilder.py b/imagefactory/builders/MockBuilder.py
index 88fc8b3..60f9081 100644
--- a/imagefactory/builders/MockBuilder.py
+++ b/imagefactory/builders/MockBuilder.py
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2010 Red Hat, Inc.
+# Copyright (C) 2010-2011 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -31,14 +31,14 @@ from imagefactory.ApplicationConfiguration import
ApplicationConfiguration
class MockBuilder(BaseBuilder):
"""docstring for MockBuilder"""
zope.interface.implements(IBuilder)
-
+
# Initializer
def __init__(self,
template='<template><name>Mock</name></template>',
target='mock'):
super(MockBuilder, self).__init__(template, target)
self.log = logging.getLogger('%s.%s' % (__name__,
self.__class__.__name__))
self.app_config = ApplicationConfiguration().configuration
self.warehouse_url = self.app_config['warehouse']
-
+
# Image actions
def build_image(self):
self.log.debug("build_image() called on MockBuilder...")
@@ -47,11 +47,11 @@ class MockBuilder(BaseBuilder):
self.status = "INITIALIZING"
self.log.debug("Initializing mock image...")
self.percent_complete = 0
-
+
directory = os.path.dirname(self.image)
if (not os.path.exists(directory)):
os.makedirs(directory)
-
+
with open(self.image, 'w') as image_file:
self.status = "BUILDING"
self.log.debug("Building mock image...")
@@ -68,7 +68,7 @@ class MockBuilder(BaseBuilder):
image_file.write(":created_by: %s\n" %
(sys.argv[0].rpartition('/')[2], ))
image_file.write(":created_on: %s\n" % (time.strftime("%a, %d
%b %Y %H:%M:%S +0000", time.gmtime()), ))
image_file.close()
-
+
self.percent_complete = 50
self.percent_complete = 75
self.percent_complete = 95
@@ -77,22 +77,22 @@ class MockBuilder(BaseBuilder):
self.percent_complete = 100
self.status = "COMPLETED"
self.log.debug("Completed mock image build...")
-
+
if(self.warehouse_url):
self.log.debug("Storing mock image at %s%s..." %
(self.warehouse_url, self.image_id))
self.store_image(self.warehouse_url)
else:
self.log.debug("No storage location specified, skipping this
step...")
-
+
def push_image(self, image_id, provider, credentials):
image_path = "%s/deltacloud-%s/%s/images/%s.yml" %
(self.app_config['output'], os.getlogin(), provider, self.image_id)
original_image_url = "%s/%s" % (self.warehouse_url, image_id)
this_image_url = "%s/%s" % (self.warehouse_url, self.image_id)
http_headers = {'content-type':'text/plain'}
http = httplib2.Http()
-
+
headers_response_image, image = http.request(original_image_url,
"GET")
-
+
self.log.debug("Storing mock image for %s at path: %s" % (provider,
image_path))
directory = os.path.dirname(image_path)
if (not os.path.exists(directory)):
@@ -100,12 +100,11 @@ class MockBuilder(BaseBuilder):
with open(image_path, 'w') as image_file:
image_file.write(image)
image_file.close()
-
+
http.request(this_image_url, "PUT", body=image, headers=http_headers)
metadata = dict(uuid=self.image_id, type="provider_image",
template=self.template, target=self.target, icicle=self.output_descriptor,
image=original_image_url, provider=provider, target_identifier=this_image_url)
self.__set_storage_metadata(this_image_url, metadata)
self.log.debug("MockBuilder instance %s pushed image with uuid %s to
warehouse location (%s) and set metadata: %s" % (id(self), image_id, this_image_url,
metadata))
-
+
def abort(self):
self.log.debug("Method abort() called on MockBuilder instance %s" %
(id(self), ))
-
diff --git a/imagefactory/builders/RHELBuilder.py b/imagefactory/builders/RHELBuilder.py
index 96d9159..3f8d1be 100644
--- a/imagefactory/builders/RHELBuilder.py
+++ b/imagefactory/builders/RHELBuilder.py
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2010 Red Hat, Inc.
+# Copyright (C) 2010-2011 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -24,15 +24,14 @@ from BaseBuilder import BaseBuilder
class RHELBuilder(BaseBuilder):
"""docstring for RHELBuilder"""
zope.interface.implements(IBuilder)
-
+
# Initializer
def __init__(self, template=None, target=None):
super(RHELBuilder, self).__init__(template, target)
-
+
# Image actions
def build_image(self):
pass
-
+
def abort(self):
pass
-
diff --git a/imagefactory/qmfagent/BuildAdaptor.py
b/imagefactory/qmfagent/BuildAdaptor.py
index d611b06..32d5b18 100644
--- a/imagefactory/qmfagent/BuildAdaptor.py
+++ b/imagefactory/qmfagent/BuildAdaptor.py
@@ -1,14 +1,14 @@
-# Copyright (C) 2010 Red Hat, Inc.
-#
+# Copyright (C) 2010-2011 Red Hat, Inc.
+#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
-#
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
@@ -36,7 +36,7 @@ class BuildAdaptor(object):
# _states_method = SchemaMethod("build_states", desc = "Returns a
representation of the build state transitions.")
# _states_method.addArgument(SchemaProperty("states", SCHEMA_DATA_MAP,
direction=DIR_IN_OUT))
# qmf_schema.addMethod(_states_method)
-
+
#QMF schema for status change event
qmf_event_schema_status = Schema(SCHEMA_TYPE_EVENT,
"com.redhat.imagefactory", "BuildAdaptorStatusEvent")
qmf_event_schema_status.addProperty(SchemaProperty("addr",
SCHEMA_DATA_MAP))
@@ -48,7 +48,7 @@ class BuildAdaptor(object):
qmf_event_schema_percentage.addProperty(SchemaProperty("addr",
SCHEMA_DATA_MAP))
qmf_event_schema_percentage.addProperty(SchemaProperty("event",
SCHEMA_DATA_STRING))
qmf_event_schema_percentage.addProperty(SchemaProperty("percent_complete",
SCHEMA_DATA_INT))
-
+
### Properties
def template():
doc = "The template property."
@@ -60,7 +60,7 @@ class BuildAdaptor(object):
del self._template
return locals()
template = property(**template())
-
+
def target():
doc = "The target property."
def fget(self):
@@ -71,7 +71,7 @@ class BuildAdaptor(object):
del self._target
return locals()
target = property(**target())
-
+
def status():
doc = "The status property."
def fget(self):
@@ -83,7 +83,7 @@ class BuildAdaptor(object):
del self._status
return locals()
status = property(**status())
-
+
def percent_complete():
doc = "The percent_complete property."
def fget(self):
@@ -95,7 +95,7 @@ class BuildAdaptor(object):
del self._percent_complete
return locals()
percent_complete = property(**percent_complete())
-
+
def image():
doc = "The image property."
def fget(self):
@@ -107,7 +107,7 @@ class BuildAdaptor(object):
del self._image
return locals()
image = property(**image())
-
+
def qmf_object():
doc = "The qmf_object property."
def fget(self):
@@ -118,22 +118,22 @@ class BuildAdaptor(object):
del self._qmf_object
return locals()
qmf_object = property(**qmf_object())
-
+
def __init__(self, template, target):
super(BuildAdaptor, self).__init__()
-
+
self.log = logging.getLogger('%s.%s' % (__name__,
self.__class__.__name__))
self.qmf_object = Data(BuildAdaptor.qmf_schema)
# FIXME: sloranz - I should be able to get the agent from the qmf_object this is
a workaround...
- self.agent = None
-
+ self.agent = None
+
self.template = template
self.target = target
self.status = "None"
self.percent_complete = 0
self.image = "None"
self.builder = None
-
+
builder_class = imagefactory.builders.MockBuilder.MockBuilder
if (self.target != "mock"): # If target is mock always run mock builder
regardless of template
parsed_doc = libxml2.parseDoc(template)
@@ -145,28 +145,28 @@ class BuildAdaptor(object):
builder_class = getattr(builder_module, class_name)
except AttributeError, e:
self.log.exception("CAUGHT EXCEPTION: %s \n Could not find builder
class for %s, returning MockBuilder!", e, os_name)
-
+
self.builder = builder_class(template, target)
# Register as a delegate to the builder
self.builder.delegate = self
self.image = str(self.builder.image_id)
-
+
def build_image(self):
thread_name = "%s.build_image()" % (self.builder.image_id, )
# using args to pass the method we want to call on the target object.
self._builder_thread = Thread(target = self.builder, name=thread_name,
args=('build_image'))
self._builder_thread.start()
-
+
def push_image(self, image_id, provider, credentials):
thread_name = "%s.push_image()" % (image_id, )
# using args to pass the method we want to call on the target object.
kwargs = dict(image_id=image_id, provider=provider, credentials=credentials)
self._builder_thread = Thread(target = self.builder, name=thread_name,
args=('push_image'), kwargs=kwargs)
self._builder_thread.start()
-
+
def abort(self):
self.builder.abort()
-
+
# Builder delegate methods
def builder_did_update_status(self, builder, old_status, new_status):
self.status = new_status
@@ -180,11 +180,11 @@ class BuildAdaptor(object):
event.new_status = str(new_status)
event.old_status = str(old_status)
agent.session.raiseEvent(data=event, severity=4)
-
+
if(new_status == "COMPLETED"):
agent.deregister(self.qmf_object)
-
-
+
+
def builder_did_update_percentage(self, builder, original_percentage,
new_percentage):
self.percent_complete = new_percentage
# FIXME: sloranz - I should be able to get the agent from the qmf_object this is
a workaround...
@@ -196,7 +196,7 @@ class BuildAdaptor(object):
event.event = "PERCENTAGE"
event.percent_complete = new_percentage
agent.session.raiseEvent(data=event, severity=4)
-
+
# if __name__ == '__main__':
# unittest.main()
diff --git a/imagefactory/qmfagent/ImageFactory.py
b/imagefactory/qmfagent/ImageFactory.py
index 7e0eab1..a9a2c71 100644
--- a/imagefactory/qmfagent/ImageFactory.py
+++ b/imagefactory/qmfagent/ImageFactory.py
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2010 Red Hat, Inc.
+# Copyright (C) 2010-2011 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -26,7 +26,7 @@ from imagefactory.ApplicationConfiguration import
ApplicationConfiguration
class ImageFactory(object):
instance = None
-
+
# QMF schema for ImageFactory
qmf_schema = Schema(SCHEMA_TYPE_DATA, "com.redhat.imagefactory",
"ImageFactory")
_build_image_method = SchemaMethod("build_image", desc="Build a new
image")
@@ -40,7 +40,7 @@ class ImageFactory(object):
_push_image_method.addArgument(SchemaProperty("credentials",
SCHEMA_DATA_STRING, direction=DIR_IN))
_push_image_method.addArgument(SchemaProperty("build_adaptor",
SCHEMA_DATA_MAP, direction=DIR_OUT))
qmf_schema.addMethod(_push_image_method)
-
+
## Properties
def qmf_object():
doc = "The qmf_object property."
@@ -52,21 +52,21 @@ class ImageFactory(object):
del self._qmf_object
return locals()
qmf_object = property(**qmf_object())
-
-
+
+
def __new__(cls, *p, **k):
if cls.instance is None:
cls.instance = object.__new__(cls, *p, **k)
return cls.instance
-
+
def __init__(self):
self.qmf_object = Data(ImageFactory.qmf_schema)
-
+
def build_image(self,template,target):
build_adaptor = BuildAdaptor.BuildAdaptor(template,target)
build_adaptor.build_image()
return build_adaptor
-
+
def push_image(self,image_id, provider, credentials):
base_url = ApplicationConfiguration().configuration['warehouse']
if (base_url):
@@ -81,4 +81,3 @@ class ImageFactory(object):
raise RuntimeError("Could not retrieve template (%s) or target (%s)
from %s/%s" % (template, target, base_url, image_id))
else:
raise RuntimeError("No image warehouse found!")
-
diff --git a/imagefactory/qmfagent/ImageFactoryAgent.py
b/imagefactory/qmfagent/ImageFactoryAgent.py
index bc4b501..fbb77e3 100644
--- a/imagefactory/qmfagent/ImageFactoryAgent.py
+++ b/imagefactory/qmfagent/ImageFactoryAgent.py
@@ -1,14 +1,14 @@
-# Copyright (C) 2010 Red Hat, Inc.
-#
+# Copyright (C) 2010-2011 Red Hat, Inc.
+#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
-#
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
@@ -34,7 +34,7 @@ class ImageFactoryAgent(AgentHandler):
del self._qmf_object
return locals()
qmf_object = property(**qmf_object())
-
+
def managedObjects():
doc = "The managedObjects property."
def fget(self):
@@ -45,8 +45,8 @@ class ImageFactoryAgent(AgentHandler):
# del self._managedObjects
return locals()
managedObjects = property(**managedObjects())
-
-
+
+
def __init__(self, url):
self.log = logging.getLogger('%s.%s' % (__name__,
self.__class__.__name__))
self._managedObjects = {}
@@ -71,25 +71,25 @@ class ImageFactoryAgent(AgentHandler):
self.image_factory = ImageFactory()
self.image_factory_addr = self.session.addData(self.image_factory.qmf_object,
"image_factory")
self.log.info("image_factory has qmf/qpid address: %s",
self.image_factory_addr)
-
+
## AgentHandler override
def method(self, handle, methodName, args, subtypes, addr, userId):
"""
Handle incoming method calls.
"""
self.log.debug("Method called: name = %s \n args = %s \n handle = %s \n addr
= %s \n subtypes = %s \n userId = %s", methodName, args, handle, addr, subtypes,
userId)
-
+
if (addr == self.image_factory_addr):
target_obj = self.image_factory
elif (repr(addr) in self.managedObjects):
target_obj = self.managedObjects[repr(addr)]
-
+
try:
result = getattr(target_obj, methodName)(**args)
except Exception, e:
self.log.exception(e)
self.session.raiseException(handle, "Exception: %s %s" % (repr(e),
str(e)))
-
+
if (addr == self.image_factory_addr):
build_adaptor_instance_name = "build_adaptor-%s" %
(result.builder.image_id, )
qmf_object_addr = self.session.addData(result.qmf_object,
build_adaptor_instance_name, persistent=True)
@@ -107,7 +107,7 @@ class ImageFactoryAgent(AgentHandler):
else:
handle.addReturnArgument("result", repr(result))
self.session.methodSuccess(handle)
-
+
def shutdown(self):
"""
Clean up the session and connection. Cancel the running thread.
@@ -120,7 +120,7 @@ class ImageFactoryAgent(AgentHandler):
except Exception, e:
self.log.exception(e)
return False
-
+
def deregister(self, managed_object):
"""
Remove an item from the agents collection of managed objects.
@@ -132,9 +132,8 @@ class ImageFactoryAgent(AgentHandler):
managed_object_key = repr(managed_object)
elif(managed_object.__class__ == str):
managed_object_key = managed_object
-
+
try:
del self.managedObjects[managed_object_key]
except KeyError:
self.log.error("Trying to remove object (%s) from managedObjects that
does not exist..." % (managed_object_key, ))
-
diff --git a/imgfac.py b/imgfac.py
index c3ccac0..6ae02d2 100755
--- a/imgfac.py
+++ b/imgfac.py
@@ -1,17 +1,17 @@
#!/usr/bin/env python
# encoding: utf-8
-# Copyright (C) 2010 Red Hat, Inc.
-#
+# Copyright (C) 2010-2011 Red Hat, Inc.
+#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
-#
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
@@ -27,7 +27,7 @@ from imagefactory.qmfagent.ImageFactoryAgent import *
class Application(object):
instance = None
-
+
def qmf_agent():
doc = "The qmf_agent property."
def fget(self):
@@ -38,26 +38,26 @@ class Application(object):
del self._qmf_agent
return locals()
qmf_agent = property(**qmf_agent())
-
-
+
+
def __new__(cls, *p, **k):
if cls.instance is None:
cls.instance = object.__new__(cls, *p, **k)
return cls.instance
-
+
def __init__(self):
- super(Application, self).__init__()
+ super(Application, self).__init__()
logging.basicConfig(level=logging.NOTSET, format='%(asctime)s %(levelname)s
%(name)s pid(%(process)d) Message: %(message)s',
filename='/var/log/imagefactory.log')
signal.signal(signal.SIGTERM, self.signal_handler)
self.app_config = ApplicationConfiguration().configuration
-
+
def setup_logging(self):
logging.basicConfig(level=logging.WARNING, format='%(asctime)s %(levelname)s
%(name)s pid(%(process)d) Message: %(message)s',
filename='/var/log/imagefactory.log')
if (self.app_config['debug']):
logging.getLogger('').setLevel(logging.DEBUG)
elif (self.app_config['verbose']):
logging.getLogger('').setLevel(logging.INFO)
-
+
def signal_handler(self, signum, stack):
"""docstring for sigterm_handler"""
if (signum == signal.SIGTERM):
@@ -65,19 +65,19 @@ class Application(object):
if (self.qmf_agent):
self.qmf_agent.shutdown()
sys.exit(0)
-
-
+
+
# TODO: (redmine 273) - add code here to set the user:group we're running as and
drop privileges
def daemonize(self): #based on Python recipe 278731
UMASK = 0
WORKING_DIRECTORY = '/'
IO_REDIRECT = os.devnull
-
+
try:
pid = os.fork()
except OSError, e:
raise Exception, "%s [%d]" % (e.strerror, e.errno)
-
+
if (pid == 0):
os.setsid()
signal.signal(signal.SIGHUP, signal.SIG_IGN)
@@ -85,7 +85,7 @@ class Application(object):
pid = os.fork()
except OSError, e:
raise Exception, "%s [%d]" % (e.strerror, e.errno)
-
+
if (pid == 0):
os.chdir(WORKING_DIRECTORY)
os.umask(UMASK)
@@ -93,30 +93,30 @@ class Application(object):
os._exit(0)
else:
os._exit(0)
-
+
for file_descriptor in range(0, 2): # close stdin, stdout, stderr
try:
os.close(file_descriptor)
except OSError:
pass # The file descriptor wasn't open to begin with, just ignore
-
+
os.open(IO_REDIRECT, os.O_RDWR)
os.dup2(0, 1)
os.dup2(0, 2)
-
+
return(True)
-
-
+
+
def main(self):
if (self.app_config['qmf']):
if (not self.app_config['foreground']):
self.daemonize()
self.setup_logging()
logging.info("Launching daemon...")
-
+
self.qmf_agent = ImageFactoryAgent(self.app_config['broker'])
self.qmf_agent.run()
-
+
if __name__ == "__main__":
diff --git a/tests/builders/testBaseBuilder.py b/tests/builders/testBaseBuilder.py
index b8e4061..d40a041 100644
--- a/tests/builders/testBaseBuilder.py
+++ b/tests/builders/testBaseBuilder.py
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2010 Red Hat, Inc.
+# Copyright (C) 2010-2011 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -31,100 +31,100 @@ class TestBaseBuilder(unittest.TestCase):
self.builder = BaseBuilder()
self.delegate = BuilderDelegate()
self.new_builder_status = "NEW_STATUS"
-
+
def tearDown(self):
del self.builder
del self.delegate
del self.new_builder_status
-
+
def testImplementsIBuilder(self):
self.assert_(IBuilder.implementedBy(BaseBuilder), 'BaseBuilder does not
implement the ImageBuilder interface.')
try:
IBuilder.validateInvariants(BaseBuilder())
except Invalid, e:
self.fail(e)
-
+
def testIsCallable(self):
self.assert_(callable(self.builder))
-
+
def testImageIdSet(self):
self.assert_(self.builder.image_id, 'Initilizer failed to set
\'image_id\'...')
-
+
def testDelegateAssignment(self):
self.builder.delegate = self.delegate
self.assertIs(self.builder.delegate, self.delegate)
-
+
def testShouldUpdateStatus(self):
self.builder.status = "UPDATE_ME"
self.builder.delegate = self.delegate
self.builder.status = self.new_builder_status
self.assertEqual(self.new_builder_status, self.builder.status)
self.builder.delegate = None
-
+
def testShouldNotUpdateStatus(self):
self.builder.status = "NO_UPDATE"
self.builder.delegate = self.delegate
self.builder.status = self.new_builder_status
self.assertEqual("NO_UPDATE", self.builder.status)
self.builder.delegate = None
-
+
def testModifyStatusUpdate(self):
self.builder.status = "INSERT_CHANGE"
self.builder.delegate = self.delegate
self.builder.status = self.new_builder_status
self.assertEqual("MODIFIED_STATUS_UPDATE", self.builder.status)
self.builder.delegate = None
-
+
def testModifyPercentageUpdate(self):
self.builder.percent_complete = None
self.builder.delegate = self.delegate
self.builder.percent_complete = 50
self.assertEqual(self.builder.percent_complete, 0)
self.builder.delegate = None
-
+
def testShouldUpdatePercentage(self):
self.builder.percent_complete = 50
self.builder.delegate = self.delegate
self.builder.percent_complete = 95
self.assertEqual(95, self.builder.percent_complete)
self.builder.delegate = None
-
+
def testShouldNotUpdatePercentage(self):
self.builder.percent_complete = 100
self.builder.delegate = self.delegate
self.builder.percent_complete = 52
self.assertEqual(100, self.builder.percent_complete)
self.builder.delegate = None
-
+
class BuilderDelegate(object):
zope.interface.implements(IBuilderDelegate)
-
+
def builder_should_update_status(self, builder, original_status, new_status):
if(original_status == "NO_UPDATE"):
return False
else:
return True
-
+
def builder_will_update_status(self, builder, original_status, new_status):
if(original_status == "INSERT_CHANGE"):
return "MODIFIED_STATUS_UPDATE"
else:
return new_status
-
+
def builder_will_update_percentage(self, builder, original_percentage,
new_percentage):
if(original_percentage >= 0):
return new_percentage
else:
return 0
-
+
def builder_should_update_percentage(self, builder, original_percentage,
new_percentage):
if(original_percentage == 100):
return False
else:
return True
-
+
if __name__ == '__main__':
- unittest.main()
\ No newline at end of file
+ unittest.main()
diff --git a/tests/builders/testMockBuilder.py b/tests/builders/testMockBuilder.py
index 7dc71d2..104bc5c 100644
--- a/tests/builders/testMockBuilder.py
+++ b/tests/builders/testMockBuilder.py
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2010 Red Hat, Inc.
+# Copyright (C) 2010-2011 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -30,24 +30,24 @@ class TestMockBuilder(unittest.TestCase):
self.template = "<template></template>"
self.target = "mock"
self.builder = MockBuilder(self.template, self.target)
-
+
def tearDown(self):
del self.builder
del self.template
del self.target
-
+
def testImplementsIBuilder(self):
self.assert_(IBuilder.implementedBy(MockBuilder), 'MockBuilder does not
implement the ImageBuilder interface...')
-
+
def testInit(self):
self.assertEqual(self.builder.template, self.template)
self.assertEqual(self.builder.target, self.target)
-
+
def testBuildImage(self):
self.builder.build_image()
self.assertEqual(self.builder.status, "COMPLETED")
self.assert_(os.path.exists(self.builder.image))
-
+
if __name__ == '__main__':
diff --git a/tests/qmfagent/testBuildAdaptor.py b/tests/qmfagent/testBuildAdaptor.py
index 01be57f..df75c9a 100644
--- a/tests/qmfagent/testBuildAdaptor.py
+++ b/tests/qmfagent/testBuildAdaptor.py
@@ -1,14 +1,14 @@
-# Copyright (C) 2010 Red Hat, Inc.
-#
+# Copyright (C) 2010-2011 Red Hat, Inc.
+#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
-#
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
@@ -38,10 +38,10 @@ class TestBuildAdaptor(unittest.TestCase):
<description>Fedora 14</description>
</template>
"""
-
+
def tearDown(self):
del self.tdl_string
-
+
def testQMFSchemaDefinition(self):
expected_schema_properties = ("status", "percent_complete",
"image")
expected_schema_methods = dict(abort=())
@@ -52,13 +52,13 @@ class TestBuildAdaptor(unittest.TestCase):
arguments = expected_schema_methods[schema_method.getName()]
for schema_property in schema_method.getArguments():
self.assertIn(schema_property.getName(), arguments)
-
+
def testInstantiateMockBuilder(self):
build_adaptor = BuildAdaptor(self.tdl_string, "mock")
self.assertIsInstance(build_adaptor.builder, MockBuilder.MockBuilder)
self.assertEqual(build_adaptor.template, self.tdl_string)
self.assertEqual(build_adaptor.target, "mock")
-
+
if __name__ == '__main__':
- unittest.main()
\ No newline at end of file
+ unittest.main()
diff --git a/tests/qmfagent/testImageFactory.py b/tests/qmfagent/testImageFactory.py
index af9d9b6..a9e36ad 100644
--- a/tests/qmfagent/testImageFactory.py
+++ b/tests/qmfagent/testImageFactory.py
@@ -1,14 +1,14 @@
-# Copyright (C) 2010 Red Hat, Inc.
-#
+# Copyright (C) 2010-2011 Red Hat, Inc.
+#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
-#
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
@@ -25,10 +25,10 @@ class TestImageFactory(unittest.TestCase):
def setUp(self):
# logging.basicConfig(level=logging.NOTSET, format='%(asctime)s %(levelname)s
%(name)s pid(%(process)d) Message: %(message)s')
pass
-
+
def tearDown(self):
pass
-
+
def testQMFSchemaDefinition(self):
expected_schema_methods = dict(build_image=("template",
"target", "build_adaptor"), push_image=("image_id",
"provider", "credentials", "build_adaptor"))
for schema_method in ImageFactory.qmf_schema.getMethods():
@@ -36,16 +36,16 @@ class TestImageFactory(unittest.TestCase):
arguments = expected_schema_methods[schema_method.getName()]
for schema_property in schema_method.getArguments():
self.assertIn(schema_property.getName(), arguments)
-
+
def testSingleton(self):
image_factory_one = ImageFactory()
image_factory_two = ImageFactory()
self.assertIs(image_factory_one, image_factory_two)
-
+
# def testClassDefinition(self):
# pass
#
if __name__ == '__main__':
- unittest.main()
\ No newline at end of file
+ unittest.main()
diff --git a/tests/qmfagent/testImageFactoryAgent.py
b/tests/qmfagent/testImageFactoryAgent.py
index 7345fa6..14e503e 100644
--- a/tests/qmfagent/testImageFactoryAgent.py
+++ b/tests/qmfagent/testImageFactoryAgent.py
@@ -1,14 +1,14 @@
-# Copyright (C) 2010 Red Hat, Inc.
-#
+# Copyright (C) 2010-2011 Red Hat, Inc.
+#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
-#
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
@@ -39,7 +39,7 @@ class TestImageFactoryAgent(unittest.TestCase):
self.console = MockConsole(self.console_session)
self.console.start()
time.sleep(5) # Give the agent some time to show up. raise this value testQueries
fails to find the agent.
-
+
def tearDown(self):
del self.expected_state_transitions
self.console.cancel()
@@ -50,7 +50,7 @@ class TestImageFactoryAgent(unittest.TestCase):
del self.connection
self.if_agent.shutdown()
del self.if_agent
-
+
def testImageFactoryAgent(self):
"""Test agent registration, method calls, and
events"""
# test that the agent registered and consoles can see it.
@@ -65,7 +65,7 @@ class TestImageFactoryAgent(unittest.TestCase):
self.assertIsNotNone(self.console.build_adaptor_addr_str)
except AttributeError:
self.fail("build_image did not return a DataAddr for
build_adaptor...")
-
+
# test that status changes in build adaptor create QMF events the consoles see.
agent_name = self.console.agent.getName()
self.assertGreater(self.console.event_count,
len(self.expected_state_transitions))
@@ -78,30 +78,30 @@ class TestImageFactoryAgent(unittest.TestCase):
self.assertEqual(self.console.build_adaptor_addr_str,
properties["addr"])
self.assertEqual(self.expected_state_transitions[index][0],properties["old_status"])
self.assertEqual(self.expected_state_transitions[index][1],properties["new_status"])
-
+
class MockConsole(ConsoleHandler):
def __init__(self, consoleSession):
super(MockConsole, self).__init__(consoleSession)
self.status_events = []
self.event_count = 0
-
+
def agentAdded(self, agent):
self.agent = agent
factories = agent.query("{class:ImageFactory,
package:'com.redhat.imagefactory'}")
response =
factories[0].build_image("<template></template>", "mock")
self.build_adaptor_addr_str = response["build_adaptor"]
-
+
def agentDeleted(self, agent, reason):
self.agent = None
self.reason_for_missing_agent = reason
-
+
def eventRaised(self, agent, data, timestamp, severity):
if(data.getProperties()["event"] == "STATUS"):
self.status_events.append(dict(agent=agent, data=data, timestamp=timestamp,
severity=severity))
self.event_count = self.event_count + 1
-
+
if __name__ == '__main__':
- unittest.main()
\ No newline at end of file
+ unittest.main()
diff --git a/tests/testApplicationConfiguration.py
b/tests/testApplicationConfiguration.py
index f87f93c..2f972c5 100644
--- a/tests/testApplicationConfiguration.py
+++ b/tests/testApplicationConfiguration.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# encoding: utf-8
-# Copyright (C) 2010 Red Hat, Inc.
+# Copyright (C) 2010-2011 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -28,24 +28,24 @@ class TestApplicationConfiguration(unittest.TestCase):
self.arguments = self.app_config.arguments
self.configuration = self.app_config.configuration
self.defaults = dict(verbose=False, debug=False, foreground=False,
config="/etc/imagefactory.conf", output="/tmp", qmf=False,
broker="localhost", warehouse=None, template=None)
-
+
def tearDown(self):
del self.app_config
del self.arguments
del self.configuration
del self.defaults
-
+
def testSingleton(self):
self.assertIs(ApplicationConfiguration(), self.app_config)
-
+
def testArgumentDefaults(self):
self.assertIsNotNone(self.arguments)
for key in self.defaults:
self.assertEqual(getattr(self.arguments, key), self.defaults[key])
-
+
def testConfigurationDictionaryDefaults(self):
self.assertIsNotNone(self.configuration)
self.assertDictContainsSubset(self.defaults, self.configuration)
if __name__ == '__main__':
- unittest.main()
\ No newline at end of file
+ unittest.main()
--
1.7.4