remove magic from decorator and fix function binding

This commit is contained in:
Jim Rollenhagen 2014-02-20 12:06:24 -08:00
parent 373b80bf52
commit 408bc793eb
4 changed files with 21 additions and 22 deletions

@ -101,8 +101,7 @@ class AsyncCommandResult(BaseCommandResult):
def run(self):
try:
result = self.execute_method(self.command_name,
**self.command_params)
result = self.execute_method(**self.command_params)
with self.command_state_lock:
self.command_result = result
self.command_status = AgentCommandStatus.SUCCEEDED

@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
"""
import functools
import inspect
from teeth_agent import base
@ -26,22 +25,18 @@ def async_command(validator=None):
"""
def async_decorator(func):
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
def wrapper(self, **command_params):
# Run a validator before passing everything off to async.
# validators should raise exceptions or return silently.
if validator:
validator(*args, **kwargs)
# Grab the variable names from the func definition.
command_names = inspect.getargspec(func)[0]
# Create dict {command_name: arg,...}
if command_names[0] == "self":
command_params = dict(zip(command_names[1:len(args)+1], args))
else:
command_params = dict(zip(command_names[:len(args)], args))
# Add all of kwargs
command_params = dict(command_params.items() + kwargs.items())
validator(**command_params)
# bind self to func so that AsyncCommandResult doesn't need to
# know about the mode
bound_func = functools.partial(func, self)
return base.AsyncCommandResult(func.__name__,
command_params,
func).start()
bound_func).start()
return wrapper
return async_decorator

@ -134,7 +134,9 @@ def _verify_image(image_info, image_location):
return False
def _validate_image_info(image_info, *args, **kwargs):
def _validate_image_info(image_info=None, **kwargs):
image_info = image_info or {}
for field in ['id', 'urls', 'hashes']:
if field not in image_info:
msg = 'Image is missing \'{}\' field.'.format(field)
@ -158,14 +160,14 @@ class StandbyMode(base.BaseAgentMode):
self.command_map['run_image'] = self.run_image
@decorators.async_command(_validate_image_info)
def cache_image(self, image_info):
def cache_image(self, image_info=None):
device = hardware.get_manager().get_os_install_device()
_download_image(image_info)
_write_image(image_info, device)
@decorators.async_command(_validate_image_info)
def prepare_image(self, image_info, metadata, files):
def prepare_image(self, image_info=None, metadata=None, files=None):
location = _configdrive_location()
device = hardware.get_manager().get_os_install_device()

@ -84,13 +84,14 @@ class TestStandbyMode(unittest.TestCase):
invalid_info)
def test_cache_image_success(self):
result = self.agent_mode.cache_image(self._build_fake_image_info())
result = self.agent_mode.cache_image(
image_info=self._build_fake_image_info())
result.join()
def test_cache_image_invalid_image_list(self):
self.assertRaises(errors.InvalidCommandParamsError,
self.agent_mode.cache_image,
{'foo': 'bar'})
image_info={'foo': 'bar'})
def test_image_location(self):
image_info = self._build_fake_image_info()
@ -221,7 +222,7 @@ class TestStandbyMode(unittest.TestCase):
image_info = self._build_fake_image_info()
download_mock.return_value = None
write_mock.return_value = None
async_result = self.agent_mode.cache_image(image_info)
async_result = self.agent_mode.cache_image(image_info=image_info)
async_result.join()
download_mock.assert_called_once_with(image_info)
write_mock.assert_called_once_with(image_info, None)
@ -251,7 +252,9 @@ class TestStandbyMode(unittest.TestCase):
configdrive_mock.return_value = None
configdrive_copy_mock.return_value = None
async_result = self.agent_mode.prepare_image(image_info, {}, [])
async_result = self.agent_mode.prepare_image(image_info=image_info,
metadata={},
files=[])
async_result.join()
download_mock.assert_called_once_with(image_info)