Skip to content

Commit 1b83b2f

Browse files
andreykurilinEuKudryashova
authored andcommitted
Move to oslo.db
Replace common oslo code nova.openstack.common.db by usage of oslo.db library and remove common code. Replaced catching of raw sqlalchemy exceptions by catches of oslo.db exceptions(such as DBError, DBDuplicateEntry, etc). Co-Authored-By: Eugeniya Kudryashova <ekudryashova@mirantis.com> Closes-Bug: #1364986 Closes-Bug: #1353131 Closes-Bug: #1283987 Closes-Bug: #1274523 Change-Id: I0649539e071b2318ec85ed5d70259c949408e64b
1 parent 717650e commit 1b83b2f

40 files changed

+107
-3112
lines changed

HACKING.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Nova Specific Commandments
1010

1111
- ``nova.db`` imports are not allowed in ``nova/virt/*``
1212
- [N309] no db session in public API methods (disabled)
13-
This enforces a guideline defined in ``nova.openstack.common.db.sqlalchemy.session``
13+
This enforces a guideline defined in ``oslo.db.sqlalchemy.session``
1414
- [N310] timeutils.utcnow() wrapper must be used instead of direct calls to
1515
datetime.datetime.utcnow() to make it easy to override its return value in tests
1616
- [N311] importing code from other virt drivers forbidden

nova/cells/state.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@
2222
import time
2323

2424
from oslo.config import cfg
25+
from oslo.db import exception as db_exc
2526

2627
from nova.cells import rpc_driver
2728
from nova import context
2829
from nova.db import base
2930
from nova import exception
3031
from nova.i18n import _
31-
from nova.openstack.common.db import exception as db_exc
3232
from nova.openstack.common import fileutils
3333
from nova.openstack.common import jsonutils
3434
from nova.openstack.common import log as logging

nova/cmd/manage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
import decorator
6262
import netaddr
6363
from oslo.config import cfg
64+
from oslo.db import exception as db_exc
6465
from oslo import messaging
6566
import six
6667

@@ -75,7 +76,6 @@
7576
from nova.i18n import _
7677
from nova import objects
7778
from nova.openstack.common import cliutils
78-
from nova.openstack.common.db import exception as db_exc
7979
from nova.openstack.common import importutils
8080
from nova.openstack.common import log as logging
8181
from nova import quota

nova/compute/flavors.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@
2222
import uuid
2323

2424
from oslo.config import cfg
25+
from oslo.db import exception as db_exc
2526
import six
2627

2728
from nova import context
2829
from nova import db
2930
from nova import exception
3031
from nova.i18n import _
3132
from nova.i18n import _LE
32-
from nova.openstack.common.db import exception as db_exc
3333
from nova.openstack.common import log as logging
3434
from nova.openstack.common import strutils
3535
from nova.pci import pci_request

nova/config.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,26 @@
1616
# under the License.
1717

1818
from oslo.config import cfg
19+
from oslo.db import options
1920

2021
from nova import debugger
21-
from nova.openstack.common.db import options
2222
from nova import paths
2323
from nova import rpc
2424
from nova import version
2525

26+
27+
CONF = cfg.CONF
28+
2629
_DEFAULT_SQL_CONNECTION = 'sqlite:///' + paths.state_path_def('nova.sqlite')
2730

2831

2932
def parse_args(argv, default_config_files=None):
30-
options.set_defaults(sql_connection=_DEFAULT_SQL_CONNECTION,
33+
options.set_defaults(CONF, connection=_DEFAULT_SQL_CONNECTION,
3134
sqlite_db='nova.sqlite')
3235
rpc.set_defaults(control_exchange='nova')
3336
debugger.register_cli_opts()
34-
cfg.CONF(argv[1:],
35-
project='nova',
36-
version=version.version_string(),
37-
default_config_files=default_config_files)
38-
rpc.init(cfg.CONF)
37+
CONF(argv[1:],
38+
project='nova',
39+
version=version.version_string(),
40+
default_config_files=default_config_files)
41+
rpc.init(CONF)

nova/db/api.py

Lines changed: 2 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,11 @@
2727
2828
"""
2929

30-
from eventlet import tpool
3130
from oslo.config import cfg
31+
from oslo.db import concurrency
3232

3333
from nova.cells import rpcapi as cells_rpcapi
3434
from nova.i18n import _
35-
from nova.openstack.common.db import api as db_api
3635
from nova.openstack.common import log as logging
3736

3837

@@ -48,51 +47,13 @@
4847
help='Template string to be used to generate snapshot names'),
4948
]
5049

51-
tpool_opts = [
52-
cfg.BoolOpt('use_tpool',
53-
default=False,
54-
deprecated_name='dbapi_use_tpool',
55-
deprecated_group='DEFAULT',
56-
help='Enable the experimental use of thread pooling for '
57-
'all DB API calls'),
58-
]
59-
6050
CONF = cfg.CONF
6151
CONF.register_opts(db_opts)
62-
CONF.register_opts(tpool_opts, 'database')
63-
CONF.import_opt('backend', 'nova.openstack.common.db.options',
64-
group='database')
6552

6653
_BACKEND_MAPPING = {'sqlalchemy': 'nova.db.sqlalchemy.api'}
6754

6855

69-
class NovaDBAPI(object):
70-
"""Nova's DB API wrapper class.
71-
72-
This wraps the oslo DB API with an option to be able to use eventlet's
73-
thread pooling. Since the CONF variable may not be loaded at the time
74-
this class is instantiated, we must look at it on the first DB API call.
75-
"""
76-
77-
def __init__(self):
78-
self.__db_api = None
79-
80-
@property
81-
def _db_api(self):
82-
if not self.__db_api:
83-
nova_db_api = db_api.DBAPI(CONF.database.backend,
84-
backend_mapping=_BACKEND_MAPPING)
85-
if CONF.database.use_tpool:
86-
self.__db_api = tpool.Proxy(nova_db_api)
87-
else:
88-
self.__db_api = nova_db_api
89-
return self.__db_api
90-
91-
def __getattr__(self, key):
92-
return getattr(self._db_api, key)
93-
94-
95-
IMPL = NovaDBAPI()
56+
IMPL = concurrency.TpoolDbapiWrapper(CONF, backend_mapping=_BACKEND_MAPPING)
9657

9758
LOG = logging.getLogger(__name__)
9859

nova/db/sqlalchemy/api.py

Lines changed: 26 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,17 @@
2222
import datetime
2323
import functools
2424
import sys
25+
import threading
2526
import time
2627
import uuid
2728

2829
from oslo.config import cfg
30+
from oslo.db import exception as db_exc
31+
from oslo.db.sqlalchemy import session as db_session
32+
from oslo.db.sqlalchemy import utils as sqlalchemyutils
2933
import six
3034
from sqlalchemy import and_
3135
from sqlalchemy import Boolean
32-
from sqlalchemy.exc import DataError
33-
from sqlalchemy.exc import IntegrityError
3436
from sqlalchemy.exc import NoSuchTableError
3537
from sqlalchemy import Integer
3638
from sqlalchemy import MetaData
@@ -56,9 +58,6 @@
5658
from nova.db.sqlalchemy import models
5759
from nova import exception
5860
from nova.i18n import _
59-
from nova.openstack.common.db import exception as db_exc
60-
from nova.openstack.common.db.sqlalchemy import session as db_session
61-
from nova.openstack.common.db.sqlalchemy import utils as sqlalchemyutils
6261
from nova.openstack.common import excutils
6362
from nova.openstack.common import log as logging
6463
from nova.openstack.common import timeutils
@@ -73,57 +72,34 @@
7372
'Should be empty, "project" or "global".'),
7473
]
7574

76-
connection_opts = [
77-
cfg.StrOpt('slave_connection',
78-
secret=True,
79-
help='The SQLAlchemy connection string used to connect to the '
80-
'slave database'),
81-
]
82-
8375
CONF = cfg.CONF
8476
CONF.register_opts(db_opts)
85-
CONF.register_opts(connection_opts, group='database')
8677
CONF.import_opt('compute_topic', 'nova.compute.rpcapi')
87-
CONF.import_opt('connection',
88-
'nova.openstack.common.db.options',
89-
group='database')
9078

9179
LOG = logging.getLogger(__name__)
9280

9381

94-
_MASTER_FACADE = None
95-
_SLAVE_FACADE = None
96-
82+
_ENGINE_FACADE = None
83+
_LOCK = threading.Lock()
9784

98-
def _create_facade_lazily(use_slave=False):
99-
global _MASTER_FACADE
100-
global _SLAVE_FACADE
10185

102-
return_slave = use_slave and CONF.database.slave_connection
103-
if not return_slave:
104-
if _MASTER_FACADE is None:
105-
_MASTER_FACADE = db_session.EngineFacade(
106-
CONF.database.connection,
107-
**dict(CONF.database.iteritems())
108-
)
109-
return _MASTER_FACADE
110-
else:
111-
if _SLAVE_FACADE is None:
112-
_SLAVE_FACADE = db_session.EngineFacade(
113-
CONF.database.slave_connection,
114-
**dict(CONF.database.iteritems())
115-
)
116-
return _SLAVE_FACADE
86+
def _create_facade_lazily():
87+
global _LOCK, _ENGINE_FACADE
88+
if _ENGINE_FACADE is None:
89+
with _LOCK:
90+
if _ENGINE_FACADE is None:
91+
_ENGINE_FACADE = db_session.EngineFacade.from_config(CONF)
92+
return _ENGINE_FACADE
11793

11894

11995
def get_engine(use_slave=False):
120-
facade = _create_facade_lazily(use_slave)
121-
return facade.get_engine()
96+
facade = _create_facade_lazily()
97+
return facade.get_engine(use_slave=use_slave)
12298

12399

124100
def get_session(use_slave=False, **kwargs):
125-
facade = _create_facade_lazily(use_slave)
126-
return facade.get_session(**kwargs)
101+
facade = _create_facade_lazily()
102+
return facade.get_session(use_slave=use_slave, **kwargs)
127103

128104

129105
_SHADOW_TABLE_PREFIX = 'shadow_'
@@ -749,7 +725,7 @@ def floating_ip_get(context, id):
749725

750726
if not result:
751727
raise exception.FloatingIpNotFound(id=id)
752-
except DataError:
728+
except db_exc.DBError:
753729
msg = _("Invalid floating ip id %s in request") % id
754730
LOG.warn(msg)
755731
raise exception.InvalidID(id=id)
@@ -1003,7 +979,7 @@ def _floating_ip_get_by_address(context, address, session=None):
1003979

1004980
if not result:
1005981
raise exception.FloatingIpNotFoundForAddress(address=address)
1006-
except DataError:
982+
except db_exc.DBError:
1007983
msg = _("Invalid floating IP %s in request") % address
1008984
LOG.warn(msg)
1009985
raise exception.InvalidIpAddressError(msg)
@@ -1306,7 +1282,7 @@ def _fixed_ip_get_by_address(context, address, session=None,
13061282
result = result.filter_by(address=address).first()
13071283
if not result:
13081284
raise exception.FixedIpNotFoundForAddress(address=address)
1309-
except DataError:
1285+
except db_exc.DBError:
13101286
msg = _("Invalid fixed IP Address %s in request") % address
13111287
LOG.warn(msg)
13121288
raise exception.FixedIpInvalid(msg)
@@ -1345,7 +1321,7 @@ def fixed_ip_get_by_address_detailed(context, address):
13451321
if not result:
13461322
raise exception.FixedIpNotFoundForAddress(address=address)
13471323

1348-
except DataError:
1324+
except db_exc.DBError:
13491325
msg = _("Invalid fixed IP Address %s in request") % address
13501326
LOG.warn(msg)
13511327
raise exception.FixedIpInvalid(msg)
@@ -1480,7 +1456,7 @@ def virtual_interface_get_by_address(context, address):
14801456
vif_ref = _virtual_interface_query(context).\
14811457
filter_by(address=address).\
14821458
first()
1483-
except DataError:
1459+
except db_exc.DBError:
14841460
msg = _("Invalid virtual interface address %s in request") % address
14851461
LOG.warn(msg)
14861462
raise exception.InvalidIpAddressError(msg)
@@ -1735,7 +1711,7 @@ def instance_get(context, instance_id, columns_to_join=None):
17351711
raise exception.InstanceNotFound(instance_id=instance_id)
17361712

17371713
return result
1738-
except DataError:
1714+
except db_exc.DBError:
17391715
# NOTE(sdague): catch all in case the db engine chokes on the
17401716
# id because it's too long of an int to store.
17411717
msg = _("Invalid instance id %s in request") % instance_id
@@ -5729,7 +5705,9 @@ def archive_deleted_rows_for_table(context, tablename, max_rows):
57295705
with conn.begin():
57305706
conn.execute(insert_statement)
57315707
result_delete = conn.execute(delete_statement)
5732-
except IntegrityError:
5708+
except db_exc.DBError:
5709+
# TODO(ekudryashova): replace by DBReferenceError when db layer
5710+
# raise it.
57335711
# A foreign key constraint keeps us from deleting some of
57345712
# these rows until we clean up a dependent table. Just
57355713
# skip this table for now; we'll come back to it later.

nova/db/sqlalchemy/migrate_repo/versions/230_add_details_column_to_instance_actions_events.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
# License for the specific language governing permissions and limitations
1313
# under the License.
1414

15+
from oslo.db.sqlalchemy import utils
1516
from sqlalchemy import Column, String, Text
1617

1718
from nova.db.sqlalchemy import api
18-
from nova.openstack.common.db.sqlalchemy import utils
1919

2020

2121
def upgrade(migrate_engine):

nova/db/sqlalchemy/models.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@
1919
SQLAlchemy models for nova data.
2020
"""
2121

22+
from oslo.config import cfg
23+
from oslo.db.sqlalchemy import models
2224
from sqlalchemy import Column, Index, Integer, BigInteger, Enum, String, schema
2325
from sqlalchemy.dialects.mysql import MEDIUMTEXT
2426
from sqlalchemy.ext.declarative import declarative_base
2527
from sqlalchemy import orm
2628
from sqlalchemy import ForeignKey, DateTime, Boolean, Text, Float
27-
from oslo.config import cfg
2829

2930
from nova.db.sqlalchemy import types
30-
from nova.openstack.common.db.sqlalchemy import models
3131
from nova.openstack.common import timeutils
3232

3333
CONF = cfg.CONF
@@ -43,6 +43,16 @@ class NovaBase(models.SoftDeleteMixin,
4343
models.ModelBase):
4444
metadata = None
4545

46+
# TODO(ekudryashova): remove this after both nova and oslo.db
47+
# will use oslo.utils library
48+
# NOTE: Both projects(nova and oslo.db) use `timeutils.utcnow`, which
49+
# returns specified time(if override_time is set). Time overriding is
50+
# only used by unit tests, but in a lot of places, temporarily overriding
51+
# this columns helps to avoid lots of calls of timeutils.set_override
52+
# from different places in unit tests.
53+
created_at = Column(DateTime, default=lambda: timeutils.utcnow())
54+
updated_at = Column(DateTime, onupdate=lambda: timeutils.utcnow())
55+
4656
def save(self, session=None):
4757
from nova.db.sqlalchemy import api
4858

0 commit comments

Comments
 (0)