ACK
The main thing we were trying to do here was maintain a separation between the QMF
interface and the builders in order to have the option of adding alternate interfaces
(CLI, REST, etc). I think this does clean that up a bit. Maybe it makes sense for
BuildAdaptor to become QMFDispatcher? I never like the BuildAdaptor name anyway...
On Jun 1, 2011, at 6:22 AM, Mark McLoughlin wrote:
Move the functionality into the BuildDispatcher class.
Also, rename methods to get_builder() and start_builder_thread().
---
imagefactory/BuildDispatcher.py | 45 ++++++++++-----------------
imagefactory/qmfagent/BuildAdaptor.py | 4 +-
imagefactory/qmfagent/ImageFactoryAgent.py | 2 +-
imgfac.py | 14 ++++----
tests/qmfagent/testBuildAdaptor.py | 24 +--------------
tests/testBuildDispatcher.py | 41 +++++++++++++++++++++++++
6 files changed, 69 insertions(+), 61 deletions(-)
create mode 100644 tests/testBuildDispatcher.py
diff --git a/imagefactory/BuildDispatcher.py b/imagefactory/BuildDispatcher.py
index a49c956..d6e72cd 100644
--- a/imagefactory/BuildDispatcher.py
+++ b/imagefactory/BuildDispatcher.py
@@ -23,7 +23,7 @@ from threading import Thread, Lock
from imagefactory.builders import *
from imagefactory.Template import Template
-class BaseAdaptor(object):
+class BuildDispatcher(object):
template = props.prop("_template", "The template property.")
target = props.prop("_target", "The target property.")
@@ -32,7 +32,7 @@ class BaseAdaptor(object):
image_id = props.prop("_image_id" "The image property.")
def __init__(self, template, target):
- super(BaseAdaptor, self).__init__()
+ super(BuildDispatcher, self).__init__()
self.log = logging.getLogger('%s.%s' % (__name__,
self.__class__.__name__))
@@ -42,19 +42,19 @@ class BaseAdaptor(object):
self.percent_complete = 0
self.image_id = "None"
- self.builder =
BuildDispatcher.builder_for_target_with_template(template=template, target=target)
- self.builder.delegate = self
- self.image_id = self.builder.image_id
+ self._builder = self._get_builder()
+ self._builder.delegate = self
+ self.image_id = self._builder.image_id
def build_image(self):
- BuildDispatcher.builder_thread_with_method(builder=self.builder,
method_name="build_image")
+ self._start_builder_thread("build_image")
def push_image(self, image_id, provider, credentials):
kwargs = dict(image_id=image_id, provider=provider, credentials=credentials)
- BuildDispatcher.builder_thread_with_method(builder=self.builder,
method_name="push_image", arg_dict=kwargs)
+ self._start_builder_thread("push_image", arg_dict=kwargs)
def abort(self):
- self.builder.abort()
+ self._builder.abort()
def builder_did_update_status(self, builder, old_status, new_status):
self.status = new_status
@@ -65,16 +65,11 @@ class BaseAdaptor(object):
def builder_did_fail(self, builder, failure_type, failure_info):
pass
-class BuildDispatcher(object):
-
- @classmethod
- def builder_for_target_with_template(cls, target, template):
- log = logging.getLogger('%s.%s' % (__name__, cls.__name__))
-
- template_object = Template(template)
+ def _get_builder(self):
+ template_object = Template(self.template)
builder_class = MockBuilder.MockBuilder
- if (target != "mock"): # If target is mock always run mock builder
regardless of template
+ if (self.target != "mock"): # If target is mock always run mock
builder regardless of template
parsed_doc = libxml2.parseDoc(template_object.xml)
node = parsed_doc.xpathEval('/template/os/name')
os_name = node[0].content
@@ -84,18 +79,12 @@ class BuildDispatcher(object):
__import__(module_name)
builder_class = getattr(sys.modules[module_name], class_name)
except AttributeError, e:
- log.exception("CAUGHT EXCEPTION: %s \n Could not find builder class
for %s, returning MockBuilder!", e, os_name)
-
- return builder_class(template_object, target)
+ self.log.exception("CAUGHT EXCEPTION: %s \n Could not find builder
class for %s, returning MockBuilder!", e, os_name)
- @classmethod
- def builder_thread_with_method(cls, builder, method_name, arg_dict={},
autostart=True):
- log = logging.getLogger('%s.%s' % (__name__, cls.__name__))
+ return builder_class(template_object, self.target)
- thread_name = "%s.%s()" % (builder.image_id, method_name)
+ def _start_builder_thread(self, method_name, arg_dict={}):
+ thread_name = "%s.%s()" % (self.image_id, method_name)
# using args to pass the method we want to call on the target object.
- builder_thread = Thread(target = builder, name=thread_name, args=(method_name),
kwargs=arg_dict)
- if(autostart):
- builder_thread.start()
-
- return builder_thread
+ builder_thread = Thread(target = self._builder, name=thread_name,
args=(method_name), kwargs=arg_dict)
+ builder_thread.start()
diff --git a/imagefactory/qmfagent/BuildAdaptor.py
b/imagefactory/qmfagent/BuildAdaptor.py
index 8526fae..751d1ef 100644
--- a/imagefactory/qmfagent/BuildAdaptor.py
+++ b/imagefactory/qmfagent/BuildAdaptor.py
@@ -23,9 +23,9 @@ from qmf2 import *
from threading import Thread, Lock
from imagefactory import props
from imagefactory.builders import *
-from imagefactory.BuildDispatcher import BaseAdaptor
+from imagefactory.BuildDispatcher import BuildDispatcher
-class BuildAdaptor(BaseAdaptor):
+class BuildAdaptor(BuildDispatcher):
# QMF schema for BuildAdaptor
qmf_schema = Schema(SCHEMA_TYPE_DATA, "com.redhat.imagefactory",
"BuildAdaptor")
qmf_schema.addProperty(SchemaProperty("status", SCHEMA_DATA_STRING,
desc="string representing the status (see instance_states() on ImageFactory)"))
diff --git a/imagefactory/qmfagent/ImageFactoryAgent.py
b/imagefactory/qmfagent/ImageFactoryAgent.py
index 9502361..3b838ac 100644
--- a/imagefactory/qmfagent/ImageFactoryAgent.py
+++ b/imagefactory/qmfagent/ImageFactoryAgent.py
@@ -80,7 +80,7 @@ class ImageFactoryAgent(AgentHandler):
result = getattr(target_obj, methodName)(**args)
if ((addr == self.image_factory_addr) and (methodName in ("image",
"provider_image"))):
- build_adaptor_instance_name = "build_adaptor:%s:%s" %
(methodName, result.builder.image_id)
+ build_adaptor_instance_name = "build_adaptor:%s:%s" %
(methodName, result.image_id)
qmf_object_addr = self.session.addData(result.qmf_object,
build_adaptor_instance_name, persistent=True)
self.managedObjects[repr(qmf_object_addr)] = result
handle.addReturnArgument("build_adaptor",
qmf_object_addr.asMap())
diff --git a/imgfac.py b/imgfac.py
index b020778..3b24067 100755
--- a/imgfac.py
+++ b/imgfac.py
@@ -25,7 +25,7 @@ import signal
import logging
from imagefactory.ApplicationConfiguration import ApplicationConfiguration
from imagefactory.qmfagent.ImageFactoryAgent import *
-from imagefactory.BuildDispatcher import BaseAdaptor
+from imagefactory.BuildDispatcher import BuildDispatcher
from imagefactory.ImageWarehouse import ImageWarehouse
class Application(object):
@@ -156,9 +156,9 @@ class Application(object):
self.setup_logging()
if (self.app_config['template'] and
self.app_config['target']):
- self.adaptor = BaseAdaptor(self.app_config['target'],
self.app_config['template'])
- self.adaptor.build_image()
- print("Image created with id: %s" % (self.adaptor.image_id,
))
+ self.dispatcher = BuildDispatcher(self.app_config['target'],
self.app_config['template'])
+ self.dispatcher.build_image()
+ print("Image created with id: %s" % (self.dispatcher.image_id,
))
elif (self.app_config['image'] and
self.app_config['provider'] and self.app_config['credentials']):
credentials = self.app_config['credentials']
@@ -175,9 +175,9 @@ class Application(object):
warehouse = ImageWarehouse(self.app_config['warehouse'])
metadata = warehouse.metadata_for_id_of_type(('template',
'target'), self.app_config['image'], object_type='image')
- self.adaptor = BaseAdaptor(metadata['target'],
metadata['template'])
- self.adaptor.push_image(self.app_config['image'],
self.app_config['provider'], credentials)
- print("Image instance created with id: %s" %
(self.adaptor.image_id, ))
+ self.dispatcher = BuildDispatcher(metadata['target'],
metadata['template'])
+ self.dispatcher.push_image(self.app_config['image'],
self.app_config['provider'], credentials)
+ print("Image instance created with id: %s" %
(self.dispatcher.image_id, ))
if __name__ == "__main__":
diff --git a/tests/qmfagent/testBuildAdaptor.py b/tests/qmfagent/testBuildAdaptor.py
index 026923e..49ebb7b 100644
--- a/tests/qmfagent/testBuildAdaptor.py
+++ b/tests/qmfagent/testBuildAdaptor.py
@@ -18,29 +18,14 @@
import unittest
import logging
-from imagefactory.builders import *
from imagefactory.qmfagent.BuildAdaptor import BuildAdaptor
class TestBuildAdaptor(unittest.TestCase):
def setUp(self):
logging.basicConfig(level=logging.NOTSET, format='%(asctime)s %(levelname)s
%(name)s pid(%(process)d) Message: %(message)s',
filename='/tmp/imagefactory-unittests.log')
- self.tdl_string = """
- <template>
- <name>f14jeos</name>
- <os>
- <name>Fedora</name>
- <version>14</version>
- <arch>x86_64</arch>
- <install type='url'>
-
<
url>http://download.fedoraproject.org/pub/fedora/linux/releases/14/Fed...
- </install>
- </os>
- <description>Fedora 14</description>
- </template>
- """
def tearDown(self):
- del self.tdl_string
+ pass
def testQMFSchemaDefinition(self):
expected_schema_properties = ("status", "percent_complete",
"image_id")
@@ -53,12 +38,5 @@ class TestBuildAdaptor(unittest.TestCase):
for schema_property in schema_method.getArguments():
self.assertIn(schema_property.getName(), arguments)
- def testInstantiateMockBuilder(self):
- build_adaptor = BuildAdaptor(template=self.tdl_string, target="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()
diff --git a/tests/testBuildDispatcher.py b/tests/testBuildDispatcher.py
new file mode 100644
index 0000000..411d51d
--- /dev/null
+++ b/tests/testBuildDispatcher.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+# encoding: utf-8
+
+# 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,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at
http://www.gnu.org/copyleft/gpl.html.
+
+import unittest
+import logging
+from imagefactory import BuildDispatcher
+from imagefactory.builders import MockBuilder
+
+class testBuildDispatcher(unittest.TestCase):
+ def setUp(self):
+ logging.basicConfig(level=logging.NOTSET, format='%(asctime)s %(levelname)s
%(name)s pid(%(process)d) Message: %(message)s',
filename='/tmp/imagefactory-unittests.log')
+
+ def tearDown(self):
+ pass
+
+ def testInstantiateMockBuilder(self):
+ template_xml =
"<template><name>f14jeos</name><os><name>Fedora</name></os></template>"
+ dispatcher = BuildDispatcher.BuildDispatcher(template_xml, "mock")
+ self.assertIsInstance(dispatcher._builder, MockBuilder.MockBuilder)
+ self.assertEqual(dispatcher.template, template_xml)
+ self.assertEqual(dispatcher.target, "mock")
+
+if __name__ == '__main__':
+ unittest.main()
--
1.7.4.4