Replacing teeth/overlord with ipa/ironic
This commit is contained in:
parent
b30d345c2e
commit
5914e36b30
@ -1,4 +1,4 @@
|
||||
[DEFAULT]
|
||||
test_command=OS_STDOUT_CAPTURE=1 OS_STDERR_CAPTURE=1 OS_TEST_TIMEOUT=60 ${PYTHON:-python} -m subunit.run discover -s teeth_agent/tests/ -p "*.py" $LISTOPT $IDOPTION
|
||||
test_command=OS_STDOUT_CAPTURE=1 OS_STDERR_CAPTURE=1 OS_TEST_TIMEOUT=60 ${PYTHON:-python} -m subunit.run discover -s ironic_python_agent/tests/ -p "*.py" $LISTOPT $IDOPTION
|
||||
test_id_option=--load-list $IDFILE
|
||||
test_list_option=--list
|
||||
|
@ -1,5 +1,7 @@
|
||||
FROM jayofdoom/docker-ubuntu-14.04
|
||||
|
||||
#TODO(pcsforeducation) ask Jay what we can change here
|
||||
|
||||
# The add is before the RUN to ensure we get the latest version of packages
|
||||
# Docker will cache RUN commands, but because the SHA1 of the dir will be
|
||||
# different it will not cache this layer
|
||||
|
@ -1,5 +1,5 @@
|
||||
# teeth-agent
|
||||
# ironic-python-agent
|
||||
|
||||
[![Build Status](https://travis-ci.org/rackerlabs/teeth-agent.png?branch=master)](https://travis-ci.org/rackerlabs/teeth-agent)
|
||||
|
||||
An agent for rebuilding and controlling Teeth chassis.
|
||||
An agent for rebuilding and controlling Ironic nodes.
|
||||
|
@ -18,26 +18,26 @@ import random
|
||||
import threading
|
||||
import time
|
||||
|
||||
from ironic_python_agent.api import app
|
||||
from ironic_python_agent import base
|
||||
from ironic_python_agent import encoding
|
||||
from ironic_python_agent import errors
|
||||
from ironic_python_agent import hardware
|
||||
from ironic_python_agent import ironic_api_client
|
||||
from ironic_python_agent.openstack.common import log
|
||||
from ironic_python_agent import utils
|
||||
|
||||
import pkg_resources
|
||||
from stevedore import driver
|
||||
from wsgiref import simple_server
|
||||
|
||||
from teeth_agent.api import app
|
||||
from teeth_agent import base
|
||||
from teeth_agent import encoding
|
||||
from teeth_agent import errors
|
||||
from teeth_agent import hardware
|
||||
from teeth_agent.openstack.common import log
|
||||
from teeth_agent import overlord_agent_api
|
||||
from teeth_agent import utils
|
||||
|
||||
|
||||
def _time():
|
||||
"""Wraps time.time() for simpler testing."""
|
||||
return time.time()
|
||||
|
||||
|
||||
class TeethAgentStatus(encoding.Serializable):
|
||||
class IronicPythonAgentStatus(encoding.Serializable):
|
||||
def __init__(self, mode, started_at, version):
|
||||
self.mode = mode
|
||||
self.started_at = started_at
|
||||
@ -52,7 +52,7 @@ class TeethAgentStatus(encoding.Serializable):
|
||||
])
|
||||
|
||||
|
||||
class TeethAgentHeartbeater(threading.Thread):
|
||||
class IronicPythonAgentHeartbeater(threading.Thread):
|
||||
# If we could wait at most N seconds between heartbeats (or in case of an
|
||||
# error) we will instead wait r x N seconds, where r is a random value
|
||||
# between these multipliers.
|
||||
@ -67,10 +67,10 @@ class TeethAgentHeartbeater(threading.Thread):
|
||||
backoff_factor = 2.7
|
||||
|
||||
def __init__(self, agent):
|
||||
super(TeethAgentHeartbeater, self).__init__()
|
||||
super(IronicPythonAgentHeartbeater, self).__init__()
|
||||
self.agent = agent
|
||||
self.hardware = hardware.get_manager()
|
||||
self.api = overlord_agent_api.APIClient(agent.api_url)
|
||||
self.api = ironic_api_client.APIClient(agent.api_url)
|
||||
self.log = log.getLogger(__name__)
|
||||
self.stop_event = threading.Event()
|
||||
self.error_delay = self.initial_delay
|
||||
@ -111,17 +111,18 @@ class TeethAgentHeartbeater(threading.Thread):
|
||||
return self.join()
|
||||
|
||||
|
||||
class TeethAgent(object):
|
||||
class IronicPythonAgent(object):
|
||||
def __init__(self, api_url, advertise_address, listen_address):
|
||||
self.api_url = api_url
|
||||
self.api_client = overlord_agent_api.APIClient(self.api_url)
|
||||
self.api_client = ironic_api_client.APIClient(self.api_url)
|
||||
self.listen_address = listen_address
|
||||
self.advertise_address = advertise_address
|
||||
self.mode_implementation = None
|
||||
self.version = pkg_resources.get_distribution('teeth-agent').version
|
||||
self.version = pkg_resources.get_distribution('ironic-python-agent')\
|
||||
.version
|
||||
self.api = app.VersionSelectorApplication(self)
|
||||
self.command_results = utils.get_ordereddict()
|
||||
self.heartbeater = TeethAgentHeartbeater(self)
|
||||
self.heartbeater = IronicPythonAgentHeartbeater(self)
|
||||
self.hardware = hardware.get_manager()
|
||||
self.command_lock = threading.Lock()
|
||||
self.log = log.getLogger(__name__)
|
||||
@ -136,7 +137,7 @@ class TeethAgent(object):
|
||||
|
||||
def get_status(self):
|
||||
"""Retrieve a serializable status."""
|
||||
return TeethAgentStatus(
|
||||
return IronicPythonAgentStatus(
|
||||
mode=self.get_mode_name(),
|
||||
started_at=self.started_at,
|
||||
version=self.version
|
||||
@ -209,7 +210,7 @@ class TeethAgent(object):
|
||||
return result
|
||||
|
||||
def run(self):
|
||||
"""Run the Teeth Agent."""
|
||||
"""Run the Ironic Python Agent."""
|
||||
self.started_at = _time()
|
||||
# Get the UUID so we can heartbeat to Ironic
|
||||
self.node = self.api_client.lookup_node(
|
||||
@ -232,7 +233,7 @@ class TeethAgent(object):
|
||||
|
||||
def _load_mode_implementation(mode_name):
|
||||
mgr = driver.DriverManager(
|
||||
namespace='teeth_agent.modes',
|
||||
namespace='ironic_python_agent.modes',
|
||||
name=mode_name.lower(),
|
||||
invoke_on_load=True,
|
||||
invoke_args=[],
|
||||
@ -246,6 +247,6 @@ def build_agent(api_url,
|
||||
listen_host,
|
||||
listen_port):
|
||||
|
||||
return TeethAgent(api_url,
|
||||
(advertise_host, advertise_port),
|
||||
(listen_host, listen_port))
|
||||
return IronicPythonAgent(api_url,
|
||||
(advertise_host, advertise_port),
|
||||
(listen_host, listen_port))
|
||||
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||
import pecan
|
||||
from pecan import hooks
|
||||
|
||||
from teeth_agent.api import config
|
||||
from ironic_python_agent.api import config
|
||||
|
||||
|
||||
class AgentHook(hooks.PecanHook):
|
||||
|
@ -24,8 +24,8 @@ server = {
|
||||
# Pecan Application Configurations
|
||||
# See https://pecan.readthedocs.org/en/latest/configuration.html#application-configuration # noqa
|
||||
app = {
|
||||
'root': 'teeth_agent.api.controllers.root.RootController',
|
||||
'modules': ['teeth_agent.api'],
|
||||
'root': 'ironic_python_agent.api.controllers.root.RootController',
|
||||
'modules': ['ironic_python_agent.api'],
|
||||
'static_root': '%(confdir)s/public',
|
||||
'debug': False,
|
||||
'enable_acl': True,
|
||||
|
@ -18,9 +18,9 @@ from pecan import rest
|
||||
from wsme import types as wtypes
|
||||
import wsmeext.pecan as wsme_pecan
|
||||
|
||||
from teeth_agent.api.controllers import v1
|
||||
from teeth_agent.api.controllers.v1 import base
|
||||
from teeth_agent.api.controllers.v1 import link
|
||||
from ironic_python_agent.api.controllers import v1
|
||||
from ironic_python_agent.api.controllers.v1 import base
|
||||
from ironic_python_agent.api.controllers.v1 import link
|
||||
|
||||
|
||||
class Version(base.APIBase):
|
||||
|
@ -22,10 +22,10 @@ from pecan import rest
|
||||
from wsme import types as wtypes
|
||||
import wsmeext.pecan as wsme_pecan
|
||||
|
||||
from teeth_agent.api.controllers.v1 import base
|
||||
from teeth_agent.api.controllers.v1 import command
|
||||
from teeth_agent.api.controllers.v1 import link
|
||||
from teeth_agent.api.controllers.v1 import status
|
||||
from ironic_python_agent.api.controllers.v1 import base
|
||||
from ironic_python_agent.api.controllers.v1 import command
|
||||
from ironic_python_agent.api.controllers.v1 import link
|
||||
from ironic_python_agent.api.controllers.v1 import status
|
||||
|
||||
|
||||
class MediaType(base.APIBase):
|
||||
|
@ -18,7 +18,7 @@ from pecan import rest
|
||||
from wsme import types
|
||||
from wsmeext import pecan as wsme_pecan
|
||||
|
||||
from teeth_agent.api.controllers.v1 import base
|
||||
from ironic_python_agent.api.controllers.v1 import base
|
||||
|
||||
|
||||
class CommandResult(base.APIBase):
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
from wsme import types as wtypes
|
||||
|
||||
from teeth_agent.api.controllers.v1 import base
|
||||
from ironic_python_agent.api.controllers.v1 import base
|
||||
|
||||
|
||||
class Link(base.APIBase):
|
||||
|
@ -18,7 +18,7 @@ from pecan import rest
|
||||
from wsme import types
|
||||
from wsmeext import pecan as wsme_pecan
|
||||
|
||||
from teeth_agent.api.controllers.v1 import base
|
||||
from ironic_python_agent.api.controllers.v1 import base
|
||||
|
||||
|
||||
class AgentStatus(base.APIBase):
|
||||
|
@ -18,9 +18,9 @@ import threading
|
||||
import uuid
|
||||
|
||||
|
||||
from teeth_agent import encoding
|
||||
from teeth_agent import errors
|
||||
from teeth_agent.openstack.common import log
|
||||
from ironic_python_agent import encoding
|
||||
from ironic_python_agent import errors
|
||||
from ironic_python_agent.openstack.common import log
|
||||
|
||||
|
||||
class AgentCommandStatus(object):
|
||||
|
@ -16,17 +16,17 @@ limitations under the License.
|
||||
|
||||
import argparse
|
||||
|
||||
from teeth_agent import agent
|
||||
from ironic_python_agent import agent
|
||||
|
||||
|
||||
def run():
|
||||
parser = argparse.ArgumentParser(
|
||||
description=('An agent that handles decomissioning and provisioning'
|
||||
' on behalf of teeth-overlord.'))
|
||||
' on behalf of Ironic.'))
|
||||
|
||||
parser.add_argument('--api-url',
|
||||
required=True,
|
||||
help='URL of the Teeth agent API')
|
||||
help='URL of the Ironic API')
|
||||
|
||||
parser.add_argument('--listen-host',
|
||||
default='0.0.0.0',
|
||||
|
@ -15,9 +15,11 @@ limitations under the License.
|
||||
"""
|
||||
|
||||
import base64
|
||||
|
||||
from ironic_python_agent import utils
|
||||
|
||||
import json
|
||||
import os
|
||||
from teeth_agent import utils
|
||||
|
||||
|
||||
class ConfigDriveWriter(object):
|
||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from teeth_agent import base
|
||||
from ironic_python_agent import base
|
||||
|
||||
|
||||
class DecomMode(base.BaseAgentMode):
|
||||
|
@ -15,7 +15,7 @@ limitations under the License.
|
||||
"""
|
||||
import functools
|
||||
|
||||
from teeth_agent import base
|
||||
from ironic_python_agent import base
|
||||
|
||||
|
||||
def async_command(validator=None):
|
||||
|
@ -14,12 +14,12 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from teeth_agent import encoding
|
||||
from teeth_agent import utils
|
||||
from ironic_python_agent import encoding
|
||||
from ironic_python_agent import utils
|
||||
|
||||
|
||||
class RESTError(Exception, encoding.Serializable):
|
||||
"""Base class for errors generated in teeth."""
|
||||
"""Base class for errors generated in ironic-python-client."""
|
||||
message = 'An error occurred'
|
||||
details = 'An unexpected error occurred. Please try back later.'
|
||||
status_code = 500
|
||||
@ -91,17 +91,17 @@ class RequestedObjectNotFoundError(NotFound):
|
||||
self.details = details
|
||||
|
||||
|
||||
class OverlordAPIError(RESTError):
|
||||
class IronicAPIError(RESTError):
|
||||
"""Error raised when a call to the agent API fails."""
|
||||
|
||||
message = 'Error in call to teeth-agent-api.'
|
||||
message = 'Error in call to ironic-api.'
|
||||
|
||||
def __init__(self, details):
|
||||
super(OverlordAPIError, self).__init__(details)
|
||||
super(IronicAPIError, self).__init__(details)
|
||||
self.details = details
|
||||
|
||||
|
||||
class HeartbeatError(OverlordAPIError):
|
||||
class HeartbeatError(IronicAPIError):
|
||||
"""Error raised when a heartbeat to the agent API fails."""
|
||||
|
||||
message = 'Error heartbeating to agent API.'
|
||||
@ -110,7 +110,7 @@ class HeartbeatError(OverlordAPIError):
|
||||
super(HeartbeatError, self).__init__(details)
|
||||
|
||||
|
||||
class LookupNodeError(OverlordAPIError):
|
||||
class LookupNodeError(IronicAPIError):
|
||||
"""Error raised when the node configuration lookup to the Ironic API
|
||||
fails.
|
||||
"""
|
||||
|
@ -20,9 +20,9 @@ import subprocess
|
||||
|
||||
import stevedore
|
||||
|
||||
from teeth_agent import encoding
|
||||
from teeth_agent.openstack.common import log
|
||||
from teeth_agent import utils
|
||||
from ironic_python_agent import encoding
|
||||
from ironic_python_agent.openstack.common import log
|
||||
from ironic_python_agent import utils
|
||||
|
||||
_global_manager = None
|
||||
|
||||
@ -30,9 +30,9 @@ _global_manager = None
|
||||
class HardwareSupport(object):
|
||||
"""These are just guidelines to suggest values that might be returned by
|
||||
calls to `evaluate_hardware_support`. No HardwareManager in mainline
|
||||
teeth-agent will ever offer a value greater than `MAINLINE`. Service
|
||||
Providers should feel free to return values greater than SERVICE_PROVIDER
|
||||
to distinguish between additional levels of support.
|
||||
ironic-python-agent will ever offer a value greater than `MAINLINE`.
|
||||
Service Providers should feel free to return values greater than
|
||||
SERVICE_PROVIDER to distinguish between additional levels of support.
|
||||
"""
|
||||
NONE = 0
|
||||
GENERIC = 1
|
||||
@ -164,7 +164,7 @@ def get_manager():
|
||||
if not _global_manager:
|
||||
LOG = log.getLogger()
|
||||
extension_manager = stevedore.ExtensionManager(
|
||||
namespace='teeth_agent.hardware_managers',
|
||||
namespace='ironic_python_agent.hardware_managers',
|
||||
invoke_on_load=True)
|
||||
|
||||
# There will always be at least one extension available (the
|
||||
|
@ -18,8 +18,8 @@ import json
|
||||
|
||||
import requests
|
||||
|
||||
from teeth_agent import encoding
|
||||
from teeth_agent import errors
|
||||
from ironic_python_agent import encoding
|
||||
from ironic_python_agent import errors
|
||||
|
||||
|
||||
class APIClient(object):
|
@ -19,7 +19,7 @@ gettext for openstack-common modules.
|
||||
|
||||
Usual usage in an openstack.common module:
|
||||
|
||||
from teeth_agent.openstack.common.gettextutils import _
|
||||
from ironic_python_agent.openstack.common.gettextutils import _
|
||||
"""
|
||||
|
||||
import copy
|
||||
@ -32,15 +32,15 @@ import os
|
||||
from babel import localedata
|
||||
import six
|
||||
|
||||
_localedir = os.environ.get('teeth_agent'.upper() + '_LOCALEDIR')
|
||||
_t = gettext.translation('teeth_agent', localedir=_localedir, fallback=True)
|
||||
_localedir = os.environ.get('ironic_python_agent'.upper() + '_LOCALEDIR')
|
||||
_t = gettext.translation('ironic_python_agent', localedir=_localedir, fallback=True)
|
||||
|
||||
# We use separate translation catalogs for each log level, so set up a
|
||||
# mapping between the log level name and the translator. The domain
|
||||
# for the log level is project_name + "-log-" + log_level so messages
|
||||
# for each level end up in their own catalog.
|
||||
_t_log_levels = dict(
|
||||
(level, gettext.translation('teeth_agent' + '-log-' + level,
|
||||
(level, gettext.translation('ironic_python_agent' + '-log-' + level,
|
||||
localedir=_localedir,
|
||||
fallback=True))
|
||||
for level in ['info', 'warning', 'error', 'critical']
|
||||
@ -64,7 +64,7 @@ def enable_lazy():
|
||||
|
||||
def _(msg):
|
||||
if USE_LAZY:
|
||||
return Message(msg, domain='teeth_agent')
|
||||
return Message(msg, domain='ironic_python_agent')
|
||||
else:
|
||||
if six.PY3:
|
||||
return _t.gettext(msg)
|
||||
@ -75,7 +75,7 @@ def _log_translation(msg, level):
|
||||
"""Build a single translation of a log message
|
||||
"""
|
||||
if USE_LAZY:
|
||||
return Message(msg, domain='teeth_agent' + '-log-' + level)
|
||||
return Message(msg, domain='ironic_python_agent' + '-log-' + level)
|
||||
else:
|
||||
translator = _t_log_levels[level]
|
||||
if six.PY3:
|
||||
@ -152,7 +152,7 @@ class Message(six.text_type):
|
||||
"""
|
||||
|
||||
def __new__(cls, msgid, msgtext=None, params=None,
|
||||
domain='teeth_agent', *args):
|
||||
domain='ironic_python_agent', *args):
|
||||
"""Create a new Message object.
|
||||
|
||||
In order for translation to work gettext requires a message ID, this
|
||||
|
@ -59,7 +59,7 @@ def import_module(import_str):
|
||||
|
||||
|
||||
def import_versioned_module(version, submodule=None):
|
||||
module = 'teeth_agent.v%s' % version
|
||||
module = 'ironic_python_agent.v%s' % version
|
||||
if submodule:
|
||||
module = '.'.join((module, submodule))
|
||||
return import_module(module)
|
||||
|
@ -40,9 +40,9 @@ import json
|
||||
import six
|
||||
import six.moves.xmlrpc_client as xmlrpclib
|
||||
|
||||
from teeth_agent.openstack.common import gettextutils
|
||||
from teeth_agent.openstack.common import importutils
|
||||
from teeth_agent.openstack.common import timeutils
|
||||
from ironic_python_agent.openstack.common import gettextutils
|
||||
from ironic_python_agent.openstack.common import importutils
|
||||
from ironic_python_agent.openstack.common import timeutils
|
||||
|
||||
netaddr = importutils.try_import("netaddr")
|
||||
|
||||
|
@ -41,10 +41,10 @@ from oslo.config import cfg
|
||||
import six
|
||||
from six import moves
|
||||
|
||||
from teeth_agent.openstack.common.gettextutils import _
|
||||
from teeth_agent.openstack.common import importutils
|
||||
from teeth_agent.openstack.common import jsonutils
|
||||
from teeth_agent.openstack.common import local
|
||||
from ironic_python_agent.openstack.common.gettextutils import _
|
||||
from ironic_python_agent.openstack.common import importutils
|
||||
from ironic_python_agent.openstack.common import jsonutils
|
||||
from ironic_python_agent.openstack.common import local
|
||||
|
||||
|
||||
_DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
|
||||
@ -537,7 +537,7 @@ def _setup_logging_from_conf(project, version):
|
||||
|
||||
if CONF.publish_errors:
|
||||
handler = importutils.import_object(
|
||||
"teeth_agent.openstack.common.log_handler.PublishErrorsHandler",
|
||||
"ironic_python_agent.openstack.common.log_handler.PublishErrorsHandler",
|
||||
logging.ERROR)
|
||||
log_root.addHandler(handler)
|
||||
|
||||
|
@ -37,7 +37,7 @@ genisoimage \
|
||||
-allow-lowercase \
|
||||
-allow-multidot \
|
||||
-l \
|
||||
-publisher "teeth" \
|
||||
-publisher "ironic" \
|
||||
-J \
|
||||
-r \
|
||||
-V 'config-2' \
|
||||
|
@ -20,12 +20,12 @@ import requests
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
from teeth_agent import base
|
||||
from teeth_agent import configdrive
|
||||
from teeth_agent import decorators
|
||||
from teeth_agent import errors
|
||||
from teeth_agent import hardware
|
||||
from teeth_agent.openstack.common import log
|
||||
from ironic_python_agent import base
|
||||
from ironic_python_agent import configdrive
|
||||
from ironic_python_agent import decorators
|
||||
from ironic_python_agent import errors
|
||||
from ironic_python_agent import hardware
|
||||
from ironic_python_agent.openstack.common import log
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
@ -18,17 +18,16 @@ import json
|
||||
import time
|
||||
import unittest
|
||||
|
||||
from ironic_python_agent import agent
|
||||
from ironic_python_agent import base
|
||||
from ironic_python_agent import encoding
|
||||
from ironic_python_agent import errors
|
||||
from ironic_python_agent import hardware
|
||||
|
||||
import mock
|
||||
import pkg_resources
|
||||
from wsgiref import simple_server
|
||||
|
||||
|
||||
from teeth_agent import agent
|
||||
from teeth_agent import base
|
||||
from teeth_agent import encoding
|
||||
from teeth_agent import errors
|
||||
from teeth_agent import hardware
|
||||
|
||||
EXPECTED_ERROR = RuntimeError('command execution failed')
|
||||
|
||||
|
||||
@ -47,13 +46,13 @@ class FakeMode(base.BaseAgentMode):
|
||||
class TestHeartbeater(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.mock_agent = mock.Mock()
|
||||
self.heartbeater = agent.TeethAgentHeartbeater(self.mock_agent)
|
||||
self.heartbeater = agent.IronicPythonAgentHeartbeater(self.mock_agent)
|
||||
self.heartbeater.api = mock.Mock()
|
||||
self.heartbeater.hardware = mock.create_autospec(
|
||||
hardware.HardwareManager)
|
||||
self.heartbeater.stop_event = mock.Mock()
|
||||
|
||||
@mock.patch('teeth_agent.agent._time')
|
||||
@mock.patch('ironic_python_agent.agent._time')
|
||||
@mock.patch('random.uniform')
|
||||
def test_heartbeat(self, mocked_uniform, mocked_time):
|
||||
time_responses = []
|
||||
@ -119,9 +118,10 @@ class TestHeartbeater(unittest.TestCase):
|
||||
class TestBaseAgent(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.encoder = encoding.RESTJSONEncoder(indent=4)
|
||||
self.agent = agent.TeethAgent('https://fake_api.example.org:8081/',
|
||||
('203.0.113.1', 9990),
|
||||
('192.0.2.1', 9999))
|
||||
self.agent = agent.IronicPythonAgent('https://fake_api.example.'
|
||||
'org:8081/',
|
||||
('203.0.113.1', 9990),
|
||||
('192.0.2.1', 9999))
|
||||
|
||||
def assertEqualEncoded(self, a, b):
|
||||
# Evidently JSONEncoder.default() can't handle None (??) so we have to
|
||||
@ -136,10 +136,11 @@ class TestBaseAgent(unittest.TestCase):
|
||||
self.agent.started_at = started_at
|
||||
|
||||
status = self.agent.get_status()
|
||||
self.assertTrue(isinstance(status, agent.TeethAgentStatus))
|
||||
self.assertTrue(isinstance(status, agent.IronicPythonAgentStatus))
|
||||
self.assertEqual(status.started_at, started_at)
|
||||
self.assertEqual(status.version,
|
||||
pkg_resources.get_distribution('teeth-agent').version)
|
||||
pkg_resources.get_distribution('ironic-python-agent')
|
||||
.version)
|
||||
|
||||
def test_execute_command(self):
|
||||
do_something_impl = mock.Mock()
|
||||
|
@ -21,17 +21,17 @@ import unittest
|
||||
import pecan
|
||||
import pecan.testing
|
||||
|
||||
from teeth_agent import agent
|
||||
from teeth_agent import base
|
||||
from ironic_python_agent import agent
|
||||
from ironic_python_agent import base
|
||||
|
||||
|
||||
PATH_PREFIX = '/v1'
|
||||
|
||||
|
||||
class TestTeethAPI(unittest.TestCase):
|
||||
class TestIronicAPI(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestTeethAPI, self).setUp()
|
||||
super(TestIronicAPI, self).setUp()
|
||||
self.mock_agent = mock.MagicMock()
|
||||
self.app = self._make_app(self.mock_agent)
|
||||
|
||||
@ -41,8 +41,9 @@ class TestTeethAPI(unittest.TestCase):
|
||||
def _make_app(self, enable_acl=False):
|
||||
self.config = {
|
||||
'app': {
|
||||
'root': 'teeth_agent.api.controllers.root.RootController',
|
||||
'modules': ['teeth_agent.api'],
|
||||
'root': 'ironic_python_agent.api.controllers.root.'
|
||||
'RootController',
|
||||
'modules': ['ironic_python_agent.api'],
|
||||
'static_root': '',
|
||||
'debug': True,
|
||||
},
|
||||
@ -165,7 +166,9 @@ class TestTeethAPI(unittest.TestCase):
|
||||
self.assertTrue('commands' in data.keys())
|
||||
|
||||
def test_get_agent_status(self):
|
||||
status = agent.TeethAgentStatus('TEST_MODE', time.time(), 'v72ac9')
|
||||
status = agent.IronicPythonAgentStatus('TEST_MODE',
|
||||
time.time(),
|
||||
'v72ac9')
|
||||
self.mock_agent.get_status.return_value = status
|
||||
|
||||
response = self.get_json('/status')
|
||||
|
@ -21,8 +21,8 @@ import json
|
||||
import mock
|
||||
import unittest
|
||||
|
||||
from teeth_agent import configdrive
|
||||
from teeth_agent import utils
|
||||
from ironic_python_agent import configdrive
|
||||
from ironic_python_agent import utils
|
||||
|
||||
|
||||
class ConfigDriveWriterTestCase(unittest.TestCase):
|
||||
@ -45,7 +45,7 @@ class ConfigDriveWriterTestCase(unittest.TestCase):
|
||||
def test_write_no_files(self, open_mock, makedirs_mock):
|
||||
metadata = {'admin_pass': 'password', 'hostname': 'test'}
|
||||
json_metadata = json.dumps(metadata)
|
||||
metadata_path = '/lol/teeth/latest/meta_data.json'
|
||||
metadata_path = '/lol/ironic/latest/meta_data.json'
|
||||
for k, v in metadata.iteritems():
|
||||
self.writer.add_metadata(k, v)
|
||||
|
||||
@ -53,12 +53,12 @@ class ConfigDriveWriterTestCase(unittest.TestCase):
|
||||
open_mock.return_value.__exit__ = mock.Mock()
|
||||
write_mock = open_mock.return_value.write
|
||||
|
||||
self.writer.write('/lol', prefix='teeth', version='latest')
|
||||
self.writer.write('/lol', prefix='ironic', version='latest')
|
||||
open_mock.assert_called_once_with(metadata_path, 'wb')
|
||||
write_mock.assert_called_once_with(json_metadata)
|
||||
makedirs_calls = [
|
||||
mock.call('/lol/teeth/latest'),
|
||||
mock.call('/lol/teeth/content')
|
||||
mock.call('/lol/ironic/latest'),
|
||||
mock.call('/lol/ironic/content')
|
||||
]
|
||||
self.assertEqual(makedirs_calls, makedirs_mock.call_args_list)
|
||||
|
||||
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||
|
||||
import unittest
|
||||
|
||||
from teeth_agent import decom
|
||||
from ironic_python_agent import decom
|
||||
|
||||
|
||||
class TestDecomMode(unittest.TestCase):
|
||||
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||
import mock
|
||||
import unittest
|
||||
|
||||
from teeth_agent import hardware
|
||||
from ironic_python_agent import hardware
|
||||
|
||||
|
||||
class TestGenericHardwareManager(unittest.TestCase):
|
||||
|
@ -20,16 +20,16 @@ import mock
|
||||
import time
|
||||
import unittest
|
||||
|
||||
from teeth_agent import errors
|
||||
from teeth_agent import hardware
|
||||
from teeth_agent import overlord_agent_api
|
||||
from ironic_python_agent import errors
|
||||
from ironic_python_agent import hardware
|
||||
from ironic_python_agent import ironic_api_client
|
||||
|
||||
API_URL = 'http://agent-api.overlord.example.org/'
|
||||
API_URL = 'http://agent-api.ironic.example.org/'
|
||||
|
||||
|
||||
class TestBaseTeethAgent(unittest.TestCase):
|
||||
class TestBaseIronicPythonAgent(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.api_client = overlord_agent_api.APIClient(API_URL)
|
||||
self.api_client = ironic_api_client.APIClient(API_URL)
|
||||
self.hardware_info = [
|
||||
hardware.HardwareInfo(hardware.HardwareType.MAC_ADDRESS,
|
||||
'aa:bb:cc:dd:ee:ff'),
|
@ -17,8 +17,8 @@ limitations under the License.
|
||||
import mock
|
||||
import unittest
|
||||
|
||||
from teeth_agent import errors
|
||||
from teeth_agent import standby
|
||||
from ironic_python_agent import errors
|
||||
from ironic_python_agent import standby
|
||||
|
||||
|
||||
class TestStandbyMode(unittest.TestCase):
|
||||
@ -177,7 +177,7 @@ class TestStandbyMode(unittest.TestCase):
|
||||
standby._download_image,
|
||||
image_info)
|
||||
|
||||
@mock.patch('teeth_agent.standby._verify_image', autospec=True)
|
||||
@mock.patch('ironic_python_agent.standby._verify_image', autospec=True)
|
||||
@mock.patch('__builtin__.open', autospec=True)
|
||||
@mock.patch('requests.get', autospec=True)
|
||||
def test_download_image_verify_fails(self, requests_mock, open_mock,
|
||||
@ -218,9 +218,9 @@ class TestStandbyMode(unittest.TestCase):
|
||||
self.assertFalse(verified)
|
||||
self.assertEqual(md5_mock.call_count, 1)
|
||||
|
||||
@mock.patch('teeth_agent.hardware.get_manager', autospec=True)
|
||||
@mock.patch('teeth_agent.standby._write_image', autospec=True)
|
||||
@mock.patch('teeth_agent.standby._download_image', autospec=True)
|
||||
@mock.patch('ironic_python_agent.hardware.get_manager', autospec=True)
|
||||
@mock.patch('ironic_python_agent.standby._write_image', autospec=True)
|
||||
@mock.patch('ironic_python_agent.standby._download_image', autospec=True)
|
||||
def test_cache_image(self, download_mock, write_mock, hardware_mock):
|
||||
image_info = self._build_fake_image_info()
|
||||
download_mock.return_value = None
|
||||
@ -236,13 +236,15 @@ class TestStandbyMode(unittest.TestCase):
|
||||
self.assertEqual('SUCCEEDED', async_result.command_status)
|
||||
self.assertEqual(None, async_result.command_result)
|
||||
|
||||
@mock.patch('teeth_agent.standby._copy_configdrive_to_disk', autospec=True)
|
||||
@mock.patch('teeth_agent.standby.configdrive.write_configdrive',
|
||||
@mock.patch('ironic_python_agent.standby._copy_configdrive_to_disk',
|
||||
autospec=True)
|
||||
@mock.patch('ironic_python_agent.standby.configdrive.write_configdrive',
|
||||
autospec=True)
|
||||
@mock.patch('ironic_python_agent.hardware.get_manager', autospec=True)
|
||||
@mock.patch('ironic_python_agent.standby._write_image', autospec=True)
|
||||
@mock.patch('ironic_python_agent.standby._download_image', autospec=True)
|
||||
@mock.patch('ironic_python_agent.standby._configdrive_location',
|
||||
autospec=True)
|
||||
@mock.patch('teeth_agent.hardware.get_manager', autospec=True)
|
||||
@mock.patch('teeth_agent.standby._write_image', autospec=True)
|
||||
@mock.patch('teeth_agent.standby._download_image', autospec=True)
|
||||
@mock.patch('teeth_agent.standby._configdrive_location', autospec=True)
|
||||
def test_prepare_image(self,
|
||||
location_mock,
|
||||
download_mock,
|
||||
|
@ -4,4 +4,4 @@
|
||||
modules=log
|
||||
|
||||
# The base module to hold the copy of openstack.common
|
||||
base=teeth_agent
|
||||
base=ironic_python_agent
|
||||
|
18
setup.cfg
18
setup.cfg
@ -1,8 +1,8 @@
|
||||
[metadata]
|
||||
name = teeth-agent
|
||||
name = ironic-python-agent
|
||||
author = Rackspace
|
||||
author-email = teeth-dev@lists.rackspace.com
|
||||
summary = Teeth Host Agent
|
||||
summary = Ironic Python Agent Ramdisk
|
||||
license = Apache-2
|
||||
classifier =
|
||||
Development Status :: 4 - Beta
|
||||
@ -12,18 +12,18 @@ classifier =
|
||||
Programming Language :: Python
|
||||
[files]
|
||||
packages =
|
||||
teeth_agent
|
||||
ironic_python_agent
|
||||
|
||||
[entry_points]
|
||||
console_scripts =
|
||||
teeth-agent = teeth_agent.cmd.agent:run
|
||||
ironic-python-agent = ironic_python_agent.cmd.agent:run
|
||||
|
||||
teeth_agent.modes =
|
||||
standby = teeth_agent.standby:StandbyMode
|
||||
decom = teeth_agent.decom:DecomMode
|
||||
ironic_python_agent.modes =
|
||||
standby = ironic_python_agent.standby:StandbyMode
|
||||
decom = ironic_python_agent.decom:DecomMode
|
||||
|
||||
teeth_agent.hardware_managers =
|
||||
generic = teeth_agent.hardware:GenericHardwareManager
|
||||
ironic_python_agent.hardware_managers =
|
||||
generic = ironic_python_agent.hardware:GenericHardwareManager
|
||||
|
||||
[pbr]
|
||||
autodoc_index_modules = True
|
||||
|
4
tox.ini
4
tox.ini
@ -17,12 +17,12 @@ downloadcache = ~/cache/pip
|
||||
|
||||
[testenv:pep8]
|
||||
commands =
|
||||
flake8 {posargs:teeth_agent}
|
||||
flake8 {posargs:ironic_python_agent}
|
||||
|
||||
[testenv:cover]
|
||||
setenv = VIRTUAL_ENV={envdir}
|
||||
commands =
|
||||
python setup.py testr --coverage {posargs:teeth_agent}
|
||||
python setup.py testr --coverage {posargs:ironic_python_agent}
|
||||
|
||||
[testenv:venv]
|
||||
commands = {posargs:}
|
||||
|
Loading…
Reference in New Issue
Block a user