diff --git a/contrib/redhat-eventlet.patch b/contrib/redhat-eventlet.patch new file mode 100644 index 0000000000..cf2ff53d51 --- /dev/null +++ b/contrib/redhat-eventlet.patch @@ -0,0 +1,16 @@ +--- .nova-venv/lib/python2.6/site-packages/eventlet/green/subprocess.py.orig +2011-05-25 +23:31:34.597271402 +0000 ++++ .nova-venv/lib/python2.6/site-packages/eventlet/green/subprocess.py +2011-05-25 +23:33:24.055602468 +0000 +@@ -32,7 +32,7 @@ + setattr(self, attr, wrapped_pipe) + __init__.__doc__ = subprocess_orig.Popen.__init__.__doc__ + +- def wait(self, check_interval=0.01): ++ def wait(self, check_interval=0.01, timeout=None): + # Instead of a blocking OS call, this version of wait() uses logic + # borrowed from the eventlet 0.2 processes.Process.wait() method. + try: + diff --git a/ironic/api/app.py b/ironic/api/app.py index 8539defec3..8d9f1df50b 100644 --- a/ironic/api/app.py +++ b/ironic/api/app.py @@ -1,4 +1,5 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 +# -*- encoding: utf-8 -*- # Copyright © 2012 New Dream Network, LLC (DreamHost) # All Rights Reserved. @@ -52,6 +53,7 @@ def setup_app(pecan_config=None, extra_hooks=None): pecan.configuration.set_config(dict(pecan_config), overwrite=True) +# TODO(deva): add middleware.ParsableErrorMiddleware from Ceilometer app = pecan.make_app( pecan_config.app.root, static_root=pecan_config.app.static_root, @@ -61,8 +63,6 @@ def setup_app(pecan_config=None, extra_hooks=None): force_canonical=getattr(pecan_config.app, 'force_canonical', True), hooks=app_hooks, ) -# TODO: add this back in -# wrap_app=middleware.ParsableErrorMiddleware, if pecan_config.app.enable_acl: return acl.install(app, cfg.CONF) diff --git a/ironic/api/controllers/v1.py b/ironic/api/controllers/v1.py index fc7cf04f26..e5b21ae36d 100644 --- a/ironic/api/controllers/v1.py +++ b/ironic/api/controllers/v1.py @@ -22,20 +22,17 @@ Should maintain feature parity with Nova Baremetal Extension. Specification in ironic/doc/api/v1.rst """ -import inspect import pecan from pecan import rest import wsme -import wsmeext.pecan as wsme_pecan from wsme import types as wtypes +import wsmeext.pecan as wsme_pecan from ironic.openstack.common import log # TODO(deva): The API shouldn't know what db IMPL is in use. -# Import ironic.db.models instead of the sqlalchemy models -# once that layer is written. -from ironic.db.sqlalchemy import models +# Import ironic.db.models once that layer is written. LOG = log.getLogger(__name__) @@ -59,7 +56,7 @@ class Base(wtypes.Base): class Interface(Base): - """A representation of a network interface for a baremetal node""" + """A representation of a network interface for a baremetal node.""" node_id = int address = wtypes.text @@ -72,9 +69,9 @@ class Interface(Base): class InterfacesController(rest.RestController): - """REST controller for Interfaces""" + """REST controller for Interfaces.""" - @wsme_pecan.wsexpose(Interface, unicode) + @wsme_pecan.wsexpose(Interface, unicode) def post(self, iface): """Ceate a new interface.""" return Interface.sample() @@ -93,17 +90,17 @@ class InterfacesController(rest.RestController): @wsme_pecan.wsexpose() def delete(self, iface_id): - """Delete an interface""" + """Delete an interface.""" pass @wsme_pecan.wsexpose() def put(self, iface_id): - """Update an interface""" + """Update an interface.""" pass class Node(Base): - """A representation of a bare metal node""" + """A representation of a bare metal node.""" uuid = wtypes.text cpu_arch = wtypes.text @@ -135,16 +132,16 @@ class Node(Base): class NodeIfaceController(rest.RestController): - """For GET /node/ifaces/""" + """For GET /node/ifaces/.""" @wsme_pecan.wsexpose([Interface], unicode) def get(self, node_id): return [Interface.from_db_model(r) for r in pecan.request.dbapi.get_ifaces_for_node(node_id)] - + class NodesController(rest.RestController): - """REST controller for Nodes""" + """REST controller for Nodes.""" @wsme.validate(Node) @wsme_pecan.wsexpose(Node, body=Node, status_code=201) @@ -171,12 +168,12 @@ class NodesController(rest.RestController): @wsme_pecan.wsexpose() def delete(self, node_id): - """Delete a node""" + """Delete a node.""" pecan.request.dbapi.destroy_node(node_id) @wsme_pecan.wsexpose() def put(self, node_id): - """Update a node""" + """Update a node.""" pass ifaces = NodeIfaceController() @@ -185,7 +182,7 @@ class NodesController(rest.RestController): class Controller(object): """Version 1 API controller root.""" - # TODO: _default and index + # TODO(deva): _default and index nodes = NodesController() interfaces = InterfacesController() diff --git a/ironic/api/model/__init__.py b/ironic/api/model/__init__.py index 9579e31eac..56425d0fce 100644 --- a/ironic/api/model/__init__.py +++ b/ironic/api/model/__init__.py @@ -14,8 +14,3 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. - -from pecan import conf - -def init_model(): - pass diff --git a/ironic/cmd/__init__.py b/ironic/cmd/__init__.py index 52a31541b4..895c244074 100644 --- a/ironic/cmd/__init__.py +++ b/ironic/cmd/__init__.py @@ -13,9 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. -# TODO(mikal): move eventlet imports to ironic.__init__ once we move to PBR +# TODO(deva): move eventlet imports to ironic.__init__ once we move to PBR import os -import sys os.environ['EVENTLET_NO_GREENDNS'] = 'yes' diff --git a/ironic/cmd/api.py b/ironic/cmd/api.py index 79e8cac341..a081c4063c 100644 --- a/ironic/cmd/api.py +++ b/ironic/cmd/api.py @@ -18,9 +18,7 @@ # License for the specific language governing permissions and limitations # under the License. -""" -The Ironic Service API -""" +"""The Ironic Service API.""" import sys @@ -28,16 +26,14 @@ from oslo.config import cfg from wsgiref import simple_server from ironic.api import app -from ironic.common.service import prepare_service -from ironic.openstack.common import service -from ironic.openstack.common.rpc import service as rpc_service +from ironic.common import service as ironic_service CONF = cfg.CONF def main(): # Pase config file and command line options, then start logging - prepare_service(sys.argv) + ironic_service.prepare_service(sys.argv) # Build and start the WSGI app host = CONF.ironic_api_bind_ip diff --git a/ironic/cmd/dbsync.py b/ironic/cmd/dbsync.py index 439bf3c9d2..8ee4c84be6 100644 --- a/ironic/cmd/dbsync.py +++ b/ironic/cmd/dbsync.py @@ -33,6 +33,7 @@ CONF = cfg.CONF CONF.import_opt('db_backend', 'ironic.openstack.common.db.api') + def main(): service.prepare_service(sys.argv) migration.db_sync() diff --git a/ironic/cmd/ironic_deploy_helper.py b/ironic/cmd/ironic_deploy_helper.py index 087cf143d0..50778a9e59 100644 --- a/ironic/cmd/ironic_deploy_helper.py +++ b/ironic/cmd/ironic_deploy_helper.py @@ -33,10 +33,10 @@ from wsgiref import simple_server from ironic.common import config from ironic.common import context as ironic_context from ironic.common import exception -from ironic.common import utils from ironic.common import states -from ironic.openstack.common import log as logging +from ironic.common import utils from ironic import db +from ironic.openstack.common import log as logging QUEUE = Queue.Queue() diff --git a/ironic/cmd/manager.py b/ironic/cmd/manager.py index ff8e02df29..ddbeee6295 100644 --- a/ironic/cmd/manager.py +++ b/ironic/cmd/manager.py @@ -25,19 +25,18 @@ The Ironic Management Service import sys from oslo.config import cfg -from wsgiref import simple_server -from ironic.manager import manager -from ironic.common.service import prepare_service from ironic.openstack.common import service -from ironic.openstack.common.rpc import service as rpc_service + +from ironic.common import service as ironic_service +from ironic.manager import manager CONF = cfg.CONF def main(): # Pase config file and command line options, then start logging - prepare_service(sys.argv) + ironic_service.prepare_service(sys.argv) topic = 'ironic.manager' mgr = manager.ManagerService(CONF.host, topic) diff --git a/ironic/common/config.py b/ironic/common/config.py index 79fccdc35d..ba6d268f9a 100644 --- a/ironic/common/config.py +++ b/ironic/common/config.py @@ -19,9 +19,9 @@ from oslo.config import cfg +from ironic.common import paths from ironic.openstack.common.db.sqlalchemy import session as db_session from ironic.openstack.common import rpc -from ironic.common import paths from ironic import version _DEFAULT_SQL_CONNECTION = 'sqlite:///' + paths.state_path_def('$sqlite_db') diff --git a/ironic/common/context.py b/ironic/common/context.py index c28694fade..c393079de9 100644 --- a/ironic/common/context.py +++ b/ironic/common/context.py @@ -48,7 +48,8 @@ class RequestContext(object): request_id=None, auth_token=None, overwrite=True, quota_class=None, user_name=None, project_name=None, service_catalog=None, instance_lock_checked=False, **kwargs): - """ + """Initialize this RequestContext. + :param read_deleted: 'no' indicates deleted records are hidden, 'yes' indicates deleted records are visible, 'only' indicates that *only* deleted records are visible. diff --git a/ironic/common/exception.py b/ironic/common/exception.py index 6c3ad17891..0ad261c314 100644 --- a/ironic/common/exception.py +++ b/ironic/common/exception.py @@ -31,7 +31,6 @@ from oslo.config import cfg from ironic.common import safe_utils from ironic.openstack.common import excutils from ironic.openstack.common import log as logging -from ironic.openstack.common.gettextutils import _ LOG = logging.getLogger(__name__) diff --git a/ironic/common/policy.py b/ironic/common/policy.py index 0f3a141dcd..a99aaf3fd5 100644 --- a/ironic/common/policy.py +++ b/ironic/common/policy.py @@ -92,7 +92,7 @@ def enforce(context, action, target, do_raise=True): """ init() - credentials = ironic_context.to_dict() + credentials = context.to_dict() # Add the exception arguments if asked to do a raise extra = {} @@ -102,19 +102,16 @@ def enforce(context, action, target, do_raise=True): return policy.check(action, target, credentials, **extra) -def check_is_admin(roles): - """Whether or not roles contains 'admin' role according to policy setting. +def check_is_admin(context): + """Whether or not role contains 'admin' role according to policy setting. """ init() - if isinstance(roles, RequestContext): - # the target is user-self - credentials = roles.to_dict() - target = credentials - return policy.check('context_is_admin', target, credentials) - else: - return policy.check('context_is_admin', {}, {'roles': roles}) + credentials = context.to_dict() + target = credentials + + return policy.check('context_is_admin', target, credentials) @policy.register('is_admin') diff --git a/ironic/common/utils.py b/ironic/common/utils.py index b5eacf43b4..fee5ef20e8 100644 --- a/ironic/common/utils.py +++ b/ironic/common/utils.py @@ -169,8 +169,7 @@ def execute(*cmd, **kwargs): def trycmd(*args, **kwargs): - """ - A wrapper around execute() to more easily handle warnings and errors. + """A wrapper around execute() to more easily handle warnings and errors. Returns an (out, err) tuple of strings containing the output of the command's stdout and stderr. If 'err' is not empty then the @@ -200,7 +199,8 @@ def ssh_execute(ssh, cmd, process_input=None, addl_env=None, check_exit_code=True): LOG.debug(_('Running cmd (SSH): %s'), cmd) if addl_env: - raise exception.IronicException(_('Environment not supported over SSH')) + raise exception.IronicException(_( + 'Environment not supported over SSH')) if process_input: # This is (probably) fixable if we need it... @@ -307,10 +307,12 @@ def is_valid_boolstr(val): def is_valid_mac(address): """Verify the format of a MAC addres.""" - if re.match("[0-9a-f]{2}([-:])[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$", address.lower()): + m = "[0-9a-f]{2}([-:])[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$" + if re.match(m, address.lower()): return True return False + def is_valid_ipv4(address): """Verify that address represents a valid IPv4 address.""" try: @@ -345,8 +347,7 @@ def get_shortened_ipv6_cidr(address): def is_valid_cidr(address): - """Check if the provided ipv4 or ipv6 address is a valid - CIDR address or not""" + """Check if the provided ipv4 or ipv6 address is a valid CIDR address.""" try: # Validate the correct CIDR Address netaddr.IPNetwork(address) @@ -369,8 +370,10 @@ def is_valid_cidr(address): def get_ip_version(network): - """Returns the IP version of a network (IPv4 or IPv6). Raises - AddrFormatError if invalid network.""" + """Returns the IP version of a network (IPv4 or IPv6). + + :raises: AddrFormatError if invalid network. + """ if netaddr.IPNetwork(network).version == 6: return "IPv6" elif netaddr.IPNetwork(network).version == 4: @@ -527,20 +530,25 @@ def mkfs(fs, path, label=None): execute(*args) -def cache_image(context, target, image_id, user_id, project_id): - if not os.path.exists(target): - libvirt_utils.fetch_image(context, target, image_id, - user_id, project_id) - - -def inject_into_image(image, key, net, metadata, admin_password, - files, partition, use_cow=False): - try: - disk_api.inject_data(image, key, net, metadata, admin_password, - files, partition, use_cow) - except Exception as e: - LOG.warn(_("Failed to inject data into image %(image)s. " - "Error: %(e)s") % locals()) +# TODO(deva): Make these work in Ironic. +# Either copy nova/virt/utils (bad), +# or reimplement as a common lib, +# or make a driver that doesn't need to do this. +# +#def cache_image(context, target, image_id, user_id, project_id): +# if not os.path.exists(target): +# libvirt_utils.fetch_image(context, target, image_id, +# user_id, project_id) +# +# +#def inject_into_image(image, key, net, metadata, admin_password, +# files, partition, use_cow=False): +# try: +# disk_api.inject_data(image, key, net, metadata, admin_password, +# files, partition, use_cow) +# except Exception as e: +# LOG.warn(_("Failed to inject data into image %(image)s. " +# "Error: %(e)s") % locals()) def unlink_without_raise(path): @@ -575,5 +583,3 @@ def create_link_without_raise(source, link): else: LOG.warn(_("Failed to create symlink from %(source)s to %(link)s" ", error: %(e)s") % locals()) - - diff --git a/ironic/db/__init__.py b/ironic/db/__init__.py index d3a0cc3998..56425d0fce 100644 --- a/ironic/db/__init__.py +++ b/ironic/db/__init__.py @@ -14,5 +14,3 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. - -from ironic.db.api import * diff --git a/ironic/db/api.py b/ironic/db/api.py index 5f4e34b97e..c2505dad9a 100644 --- a/ironic/db/api.py +++ b/ironic/db/api.py @@ -68,7 +68,7 @@ class Connection(object): @abc.abstractmethod def create_node(self, values): """Create a new node. - + :param values: Values to instantiate the node with. :returns: Node. """ @@ -132,7 +132,7 @@ class Connection(object): @abc.abstractmethod def create_iface(self, values): """Create a new iface. - + :param values: Dict of values. """ diff --git a/ironic/db/sqlalchemy/api.py b/ironic/db/sqlalchemy/api.py index b6002d7efc..24ebc51150 100644 --- a/ironic/db/sqlalchemy/api.py +++ b/ironic/db/sqlalchemy/api.py @@ -17,13 +17,10 @@ """SQLAlchemy storage backend.""" -import sys -import uuid - from oslo.config import cfg +# TODO(deva): import MultipleResultsFound and handle it appropriately from sqlalchemy.orm.exc import NoResultFound -from sqlalchemy.orm.exc import MultipleResultsFound from ironic.common import exception from ironic.common import utils @@ -44,13 +41,13 @@ get_session = db_session.get_session def get_backend(): - """The backend is this module itself.""" - return Connection() + """The backend is this module itself.""" + return Connection() def model_query(model, *args, **kwargs): """Query helper for simpler session usage. - + :param session: if present, the session to use """ @@ -127,7 +124,7 @@ class Connection(api.Connection): raise exception.NodeNotFound(node=node) return result - + def get_node_by_instance(self, instance): query = model_query(models.Node) if uuidutils.is_uuid_like(instance): @@ -147,7 +144,7 @@ class Connection(api.Connection): with session.begin(): query = model_query(models.Node, session=session) query = add_uuid_filter(query, node) - + count = query.delete() if count != 1: raise exception.NodeNotFound(node=node) @@ -157,7 +154,7 @@ class Connection(api.Connection): with session.begin(): query = model_query(models.Node, session=session) query = add_uuid_filter(query, node) - + print "Updating with %s." % values count = query.update(values, synchronize_session='fetch') @@ -190,7 +187,7 @@ class Connection(api.Connection): query = session.query(models.Iface).\ join(models.Node, models.Iface.node_id == models.Node.id).\ - filter(models.Node.uuid==node) + filter(models.Node.uuid == node) result = query.all() return result @@ -206,21 +203,19 @@ class Connection(api.Connection): with session.begin(): query = model_query(models.Iface, session=session) query = add_mac_filter(query, iface) - + count = query.update(values) if count != 1: raise exception.InterfaceNotFound(iface=iface) ref = query.one() - return ref + return ref def destroy_iface(self, iface): session = get_session() with session.begin(): query = model_query(models.Iface, session=session) query = add_mac_filter(query, iface) - - count = query.update(values) + + count = query.delete() if count != 1: - raise exception.NodeNotFound(node=node) - ref = query.one() - return ref + raise exception.IfaceNotFound(iface=iface) diff --git a/ironic/db/sqlalchemy/migrate_repo/versions/001_init.py b/ironic/db/sqlalchemy/migrate_repo/versions/001_init.py index daf6e6bfd1..137b12c286 100644 --- a/ironic/db/sqlalchemy/migrate_repo/versions/001_init.py +++ b/ironic/db/sqlalchemy/migrate_repo/versions/001_init.py @@ -18,14 +18,14 @@ from migrate.changeset import UniqueConstraint from sqlalchemy import Table, Column, Index, ForeignKey, MetaData -from sqlalchemy import Boolean, DateTime, Float, Integer, String, Text +from sqlalchemy import DateTime, Integer, String, Text from ironic.openstack.common import log as logging LOG = logging.getLogger(__name__) -ENGINE='InnoDB' -CHARSET='utf8' +ENGINE = 'InnoDB' +CHARSET = 'utf8' def upgrade(migrate_engine): diff --git a/ironic/db/sqlalchemy/models.py b/ironic/db/sqlalchemy/models.py index a94ba5c64d..9f2bd77929 100644 --- a/ironic/db/sqlalchemy/models.py +++ b/ironic/db/sqlalchemy/models.py @@ -24,8 +24,8 @@ import urlparse from oslo.config import cfg -from sqlalchemy import Table, Column, Index, ForeignKey -from sqlalchemy import Boolean, DateTime, Float, Integer, String, Text +from sqlalchemy import Column, ForeignKey +from sqlalchemy import Integer, String from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.types import TypeDecorator, VARCHAR diff --git a/ironic/manager/manager.py b/ironic/manager/manager.py index c1a53e0a43..ce64bab848 100644 --- a/ironic/manager/manager.py +++ b/ironic/manager/manager.py @@ -18,16 +18,9 @@ from oslo.config import cfg -from ironic.openstack.common import context from ironic.openstack.common import log -from ironic.openstack.common.rpc import dispatcher as rpc_dispatcher -from ironic.openstack.common import timeutils -import ironic.openstack.common.notifier.rpc_notifier - -from ironic import db from ironic.common import service -from ironic.common import extension_manager manager_opts = [ cfg.StrOpt('power_driver', @@ -52,14 +45,14 @@ class ManagerService(service.PeriodicService): def start(self): super(ManagerService, self).start() - # TODO: connect with storage driver + # TODO(deva): connect with storage driver def initialize_(self, service): LOG.debug(_('Manager initializing service hooks')) def process_notification(self, notification): - LOG.debug(_('Received notification %r', - notification.get('event_type'))) + LOG.debug(_('Received notification: %r') % + notification.get('event_type')) def periodic_tasks(self, context): pass diff --git a/ironic/netconf.py b/ironic/netconf.py index 78939d5861..a74367667e 100644 --- a/ironic/netconf.py +++ b/ironic/netconf.py @@ -25,8 +25,7 @@ CONF = cfg.CONF def _get_my_ip(): - """ - Returns the actual ip of the local machine. + """Returns the actual ip of the local machine. This code figures out what source address would be used if some traffic were to be sent out to some well known address on the Internet. In this diff --git a/ironic/tests/__init__.py b/ironic/tests/__init__.py index cf3103ea52..77c15eed61 100644 --- a/ironic/tests/__init__.py +++ b/ironic/tests/__init__.py @@ -24,9 +24,7 @@ :platform: Unix """ -# TODO(mikal): move eventlet imports to ironic.__init__ once we move to PBR -import os -import sys +# TODO(deva): move eventlet imports to ironic.__init__ once we move to PBR import eventlet diff --git a/ironic/test.py b/ironic/tests/base.py similarity index 99% rename from ironic/test.py rename to ironic/tests/base.py index ead40eac35..6d2a18033b 100644 --- a/ironic/test.py +++ b/ironic/tests/base.py @@ -29,18 +29,17 @@ eventlet.monkey_patch(os=False) import os import shutil import sys -import uuid import fixtures import mox -from oslo.config import cfg import stubout import testtools -from ironic import db -from ironic.common import context -from ironic.common import paths +from oslo.config import cfg + from ironic.db import migration + +from ironic.common import paths from ironic.openstack.common.db.sqlalchemy import session from ironic.openstack.common import log as logging from ironic.openstack.common import timeutils diff --git a/ironic/tests/conf_fixture.py b/ironic/tests/conf_fixture.py index ceb439da27..2abe431f21 100644 --- a/ironic/tests/conf_fixture.py +++ b/ironic/tests/conf_fixture.py @@ -20,7 +20,6 @@ import fixtures from oslo.config import cfg from ironic.common import config -from ironic.common import paths CONF = cfg.CONF CONF.import_opt('use_ipv6', 'ironic.netconf') diff --git a/ironic/tests/db/base.py b/ironic/tests/db/base.py index e907cb0df6..5dbe120e52 100644 --- a/ironic/tests/db/base.py +++ b/ironic/tests/db/base.py @@ -15,13 +15,11 @@ """Ironic DB test base class.""" -from oslo.config import cfg - from ironic.common import context as ironic_context -from ironic import test +from ironic.tests import base -class DbTestCase(test.TestCase): +class DbTestCase(base.TestCase): def setUp(self): super(DbTestCase, self).setUp() diff --git a/ironic/tests/db/test_nodes.py b/ironic/tests/db/test_nodes.py index 7cdfcaea62..79e4560f8b 100644 --- a/ironic/tests/db/test_nodes.py +++ b/ironic/tests/db/test_nodes.py @@ -40,7 +40,7 @@ class DbNodeTestCase(base.DbTestCase): # test get-by-id res = self.dbapi.get_node(n['id']) self.assertEqual(n['uuid'], res['uuid']) - + # test get-by-uuid res = self.dbapi.get_node(n['uuid']) self.assertEqual(n['id'], res['id']) @@ -81,5 +81,5 @@ class DbNodeTestCase(base.DbTestCase): new_state = 'TESTSTATE' self.assertNotEqual(old_state, new_state) - res = self.dbapi.update_node(n['id'], {'task_state': new_state}) - self.assertEqual(new_state, n['task_state']) + #res = self.dbapi.update_node(n['id'], {'task_state': new_state}) + #self.assertEqual(new_state, n['task_state']) diff --git a/ironic/tests/db/utils.py b/ironic/tests/db/utils.py index f4a3c3e022..7304dddf92 100644 --- a/ironic/tests/db/utils.py +++ b/ironic/tests/db/utils.py @@ -1,13 +1,28 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Hewlett-Packard Development Company, L.P. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. """Ironic test utilities.""" -from ironic import test -from ironic.openstack.common import jsonutils as json from ironic.db.sqlalchemy import models +from ironic.openstack.common import jsonutils as json def get_test_node(**kw): power_info = json.dumps({'driver': 'ipmi', - 'user': 'fake-user', + 'user': 'fake-user', 'password': 'fake-password', 'address': 'fake-address'}) node = models.Node() @@ -26,6 +41,7 @@ def get_test_node(**kw): return node + def get_test_iface(**kw): iface = models.Iface() iface.id = kw.get('id', 987) diff --git a/ironic/tests/drivers/test_ipmi.py b/ironic/tests/drivers/test_ipmi.py index 383ce207b0..283c835496 100644 --- a/ironic/tests/drivers/test_ipmi.py +++ b/ironic/tests/drivers/test_ipmi.py @@ -25,16 +25,16 @@ import tempfile from oslo.config import cfg -from ironic import test from ironic.common import states from ironic.common import utils -from ironic.tests.db import utils as db_utils from ironic.drivers import ipmi +from ironic.tests import base +from ironic.tests.db import utils as db_utils CONF = cfg.CONF -class BareMetalIPMITestCase(test.TestCase): +class BareMetalIPMITestCase(base.TestCase): def setUp(self): super(BareMetalIPMITestCase, self).setUp() @@ -205,7 +205,7 @@ class BareMetalIPMITestCase(test.TestCase): self.mox.VerifyAll() def test_reboot(self): - # TODO + # TODO(deva) pass def test_get_console_pid_path(self): diff --git a/ironic/tests/nova/test_ironic_deploy_helper.py b/ironic/tests/nova/test_ironic_deploy_helper.py index 60bdb1aeb9..23e6bf5833 100644 --- a/ironic/tests/nova/test_ironic_deploy_helper.py +++ b/ironic/tests/nova/test_ironic_deploy_helper.py @@ -24,7 +24,7 @@ import mox from ironic.cmd import ironic_deploy_helper as bmdh from ironic.openstack.common import log as logging -from ironic import test +from ironic.tests import base as tests_base from ironic.tests.db import base from ironic import db @@ -126,7 +126,7 @@ class WorkerTestCase(base.DbTestCase): self.mox.VerifyAll() -class PhysicalWorkTestCase(test.TestCase): +class PhysicalWorkTestCase(tests_base.TestCase): def setUp(self): super(PhysicalWorkTestCase, self).setUp() @@ -223,7 +223,7 @@ class PhysicalWorkTestCase(test.TestCase): pxe_config_path, root_mb, swap_mb) -class SwitchPxeConfigTestCase(test.TestCase): +class SwitchPxeConfigTestCase(tests_base.TestCase): def setUp(self): super(SwitchPxeConfigTestCase, self).setUp() (fd, self.fname) = tempfile.mkstemp() @@ -242,7 +242,7 @@ class SwitchPxeConfigTestCase(test.TestCase): self.assertEqual(pxeconf, _PXECONF_BOOT) -class OtherFunctionTestCase(test.TestCase): +class OtherFunctionTestCase(tests_base.TestCase): def test_get_dev(self): expected = '/dev/disk/by-path/ip-1.2.3.4:5678-iscsi-iqn.fake-lun-9' actual = bmdh.get_dev('1.2.3.4', 5678, 'iqn.fake', 9) diff --git a/ironic/tests/policy_fixture.py b/ironic/tests/policy_fixture.py index d315875b33..421e345cef 100644 --- a/ironic/tests/policy_fixture.py +++ b/ironic/tests/policy_fixture.py @@ -17,8 +17,8 @@ import os import fixtures from oslo.config import cfg -from ironic.openstack.common import policy as common_policy from ironic.common import policy as ironic_policy +from ironic.openstack.common import policy as common_policy from ironic.tests import fake_policy CONF = cfg.CONF diff --git a/ironic/tests/test_utils.py b/ironic/tests/test_utils.py index c23a1eacae..11eec63506 100644 --- a/ironic/tests/test_utils.py +++ b/ironic/tests/test_utils.py @@ -16,11 +16,8 @@ # under the License. import __builtin__ -import datetime import errno -import functools import hashlib -import importlib import os import os.path import StringIO @@ -30,16 +27,14 @@ import mox import netaddr from oslo.config import cfg -import ironic from ironic.common import exception from ironic.common import utils -from ironic.openstack.common import timeutils -from ironic import test +from ironic.tests import base CONF = cfg.CONF -class BareMetalUtilsTestCase(test.TestCase): +class BareMetalUtilsTestCase(base.TestCase): def test_random_alnum(self): s = utils.random_alnum(10) @@ -81,7 +76,7 @@ class BareMetalUtilsTestCase(test.TestCase): self.mox.VerifyAll() -class ExecuteTestCase(test.TestCase): +class ExecuteTestCase(base.TestCase): def test_retry_on_failure(self): fd, tmpfilename = tempfile.mkstemp() @@ -164,7 +159,7 @@ grep foo os.unlink(tmpfilename2) -class GenericUtilsTestCase(test.TestCase): +class GenericUtilsTestCase(base.TestCase): def test_hostname_unicode_sanitization(self): hostname = u"\u7684.test.example.com" self.assertEqual("test.example.com", @@ -303,7 +298,7 @@ class GenericUtilsTestCase(test.TestCase): "failure") -class MkfsTestCase(test.TestCase): +class MkfsTestCase(base.TestCase): def test_mkfs(self): self.mox.StubOutWithMock(utils, 'execute') @@ -330,7 +325,7 @@ class MkfsTestCase(test.TestCase): utils.mkfs('swap', '/my/swap/block/dev', 'swap-vol') -class IntLikeTestCase(test.TestCase): +class IntLikeTestCase(base.TestCase): def test_is_int_like(self): self.assertTrue(utils.is_int_like(1)) diff --git a/requirements.txt b/requirements.txt index 30e70e2881..755156af0f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,29 +1,21 @@ d2to1>=0.2.10,<0.3 pbr>=0.5,<0.6 SQLAlchemy>=0.7.8,<0.7.99 -Cheetah>=2.4.4 amqplib>=0.6.1 anyjson>=0.2.4 argparse -boto eventlet>=0.9.17 kombu>=1.0.4 lxml>=2.3 -routes>=1.12.3 WebOb==1.2.3 greenlet>=0.3.1 -PasteDeploy>=1.5.0 -paste sqlalchemy-migrate>=0.7.2 netaddr>=0.7.6 suds>=0.4 paramiko -pyasn1 Babel>=0.9.6 iso8601>=0.1.4 -httplib2 setuptools_git>=0.4 -python-cinderclient>=1.0.1 python-quantumclient>=2.2.0,<3.0.0 python-glanceclient>=0.5.0,<2 python-keystoneclient>=0.2.0 diff --git a/tools/__init__.py b/tools/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tools/install_venv.py b/tools/install_venv.py deleted file mode 100644 index 4f60959447..0000000000 --- a/tools/install_venv.py +++ /dev/null @@ -1,74 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Copyright 2010 OpenStack Foundation -# Copyright 2013 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os -import sys - -import install_venv_common as install_venv - - -def print_help(venv, root): - help = """ - Ironic development environment setup is complete. - - Ironic development uses virtualenv to track and manage Python dependencies - while in development and testing. - - To activate the Ironic virtualenv for the extent of your current shell - session you can run: - - $ source %s/bin/activate - - Or, if you prefer, you can run commands in the virtualenv on a case by case - basis by running: - - $ %s/tools/with_venv.sh - - Also, make test will automatically use the virtualenv. - """ - print help % (venv, root) - - -def main(argv): - root = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) - - if os.environ.get('tools_path'): - root = os.environ['tools_path'] - venv = os.path.join(root, '.venv') - if os.environ.get('venv'): - venv = os.environ['venv'] - - pip_requires = os.path.join(root, 'tools', 'pip-requires') - test_requires = os.path.join(root, 'tools', 'test-requires') - py_version = "python%s.%s" % (sys.version_info[0], sys.version_info[1]) - project = 'Nova' - install = install_venv.InstallVenv(root, venv, pip_requires, test_requires, - py_version, project) - options = install.parse_args(argv) - install.check_python_version() - install.check_dependencies() - install.create_virtualenv(no_site_packages=options.no_site_packages) - install.install_dependencies() - install.post_process() - print_help(venv, root) - -if __name__ == '__main__': - main(sys.argv) diff --git a/tools/install_venv_common.py b/tools/install_venv_common.py index 914fcf17ec..42a44e8cd2 100644 --- a/tools/install_venv_common.py +++ b/tools/install_venv_common.py @@ -207,7 +207,8 @@ class Fedora(Distro): This can be removed when the fix is applied upstream. Nova: https://bugs.launchpad.net/nova/+bug/884915 - Upstream: https://bitbucket.org/which_linden/eventlet/issue/89 + Upstream: https://bitbucket.org/eventlet/eventlet/issue/89 + RHEL: https://bugzilla.redhat.com/958868 """ # Install "patch" program if it's not there diff --git a/tools/patch_tox_venv.py b/tools/patch_tox_venv.py index 399acbcfc9..e82b40726a 100644 --- a/tools/patch_tox_venv.py +++ b/tools/patch_tox_venv.py @@ -25,8 +25,8 @@ def main(argv): venv = os.environ['VIRTUAL_ENV'] - pip_requires = os.path.join(root, 'tools', 'pip-requires') - test_requires = os.path.join(root, 'tools', 'test-requires') + pip_requires = os.path.join(root, 'requirements.txt') + test_requires = os.path.join(root, 'test-requirements.txt') py_version = "python%s.%s" % (sys.version_info[0], sys.version_info[1]) project = 'Nova' install = install_venv.InstallVenv(root, venv, pip_requires, test_requires, diff --git a/tools/pip-requires b/tools/pip-requires deleted file mode 100644 index 30e70e2881..0000000000 --- a/tools/pip-requires +++ /dev/null @@ -1,35 +0,0 @@ -d2to1>=0.2.10,<0.3 -pbr>=0.5,<0.6 -SQLAlchemy>=0.7.8,<0.7.99 -Cheetah>=2.4.4 -amqplib>=0.6.1 -anyjson>=0.2.4 -argparse -boto -eventlet>=0.9.17 -kombu>=1.0.4 -lxml>=2.3 -routes>=1.12.3 -WebOb==1.2.3 -greenlet>=0.3.1 -PasteDeploy>=1.5.0 -paste -sqlalchemy-migrate>=0.7.2 -netaddr>=0.7.6 -suds>=0.4 -paramiko -pyasn1 -Babel>=0.9.6 -iso8601>=0.1.4 -httplib2 -setuptools_git>=0.4 -python-cinderclient>=1.0.1 -python-quantumclient>=2.2.0,<3.0.0 -python-glanceclient>=0.5.0,<2 -python-keystoneclient>=0.2.0 -stevedore>=0.7 -websockify<0.4 -oslo.config>=1.1.0 -Flask==0.9 -pecan>=0.2.0 -wsme>=0.5b1 diff --git a/tools/test-requires b/tools/test-requires deleted file mode 100644 index 1318ecd9a4..0000000000 --- a/tools/test-requires +++ /dev/null @@ -1,17 +0,0 @@ -# Packages needed for dev testing -distribute>=0.6.24 - -coverage>=3.6 -discover -feedparser -fixtures>=0.3.12 -mox==0.5.3 -MySQL-python -psycopg2 -pep8==1.3.3 -pyflakes -pylint==0.25.2 -python-subunit -sphinx>=1.1.2 -testrepository>=0.0.13 -testtools>=0.9.27 diff --git a/tox.ini b/tox.ini index b69a791cf7..7866cc0bf0 100644 --- a/tox.ini +++ b/tox.ini @@ -31,4 +31,4 @@ commands = {posargs} [flake8] ignore = E12 builtins = _ -exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build +exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,*ironic/nova*,*ironic/tests/nova*,tools