Remove etcd db backend

The etcd backend is duplicated for removal. This commit removes
the etcd db backend related code.

Change-Id: Id7849576a94f66b681d8d346a90d4e151548eaa7
This commit is contained in:
Hongbin Lu 2019-04-27 18:11:04 +00:00
parent 271ca60ce2
commit 08fe07743f
13 changed files with 13 additions and 1864 deletions

View File

@ -7,7 +7,6 @@ eventlet!=0.18.3,!=0.20.1,>=0.18.2 # MIT
keystonemiddleware>=4.18.0 # Apache-2.0 keystonemiddleware>=4.18.0 # Apache-2.0
pecan!=1.0.2,!=1.0.3,!=1.0.4,!=1.2,>=1.0.0 # BSD pecan!=1.0.2,!=1.0.3,!=1.0.4,!=1.2,>=1.0.0 # BSD
psutil>=3.2.2 # BSD psutil>=3.2.2 # BSD
python-etcd>=0.4.3 # MIT License
python-glanceclient>=2.8.0 # Apache-2.0 python-glanceclient>=2.8.0 # Apache-2.0
python-neutronclient>=6.7.0 # Apache-2.0 python-neutronclient>=6.7.0 # Apache-2.0
python-cinderclient>=3.3.0 # Apache-2.0 python-cinderclient>=3.3.0 # Apache-2.0

View File

@ -115,10 +115,6 @@ class ContainersActionsController(base.Controller):
raise exception.ResourceNotFound(name="Action", id=request_ident) raise exception.ResourceNotFound(name="Action", id=request_ident)
action_id = action.id action_id = action.id
if CONF.database.backend == 'etcd':
# etcd using action.uuid get the unique action instead of action.id
action_id = action.uuid
action = actions_view.format_action(action) action = actions_view.format_action(action)
show_traceback = False show_traceback = False
if policy.enforce(context, "container:action:events", if policy.enforce(context, "container:action:events",

View File

@ -21,28 +21,12 @@ sql_opts = [
help='MySQL engine to use.') help='MySQL engine to use.')
] ]
etcd_opts = [
cfg.HostAddressOpt('etcd_host',
default='$my_ip',
help="Host IP address on which etcd service "
"running. The default is ``$my_ip``, "
"the IP address of this host."),
cfg.PortOpt('etcd_port',
default=2379,
help="Port on which etcd listen client request.")
]
etcd_group = cfg.OptGroup(name='etcd', title='Options for etcd connection')
DEFAULT_OPTS = (sql_opts) DEFAULT_OPTS = (sql_opts)
ETCD_OPTS = (etcd_opts)
def register_opts(conf): def register_opts(conf):
conf.register_opts(sql_opts, 'database') conf.register_opts(sql_opts, 'database')
conf.register_group(etcd_group)
conf.register_opts(etcd_opts, etcd_group)
def list_opts(): def list_opts():
return {"DEFAULT": DEFAULT_OPTS, etcd_group: ETCD_OPTS} return {"DEFAULT": DEFAULT_OPTS}

View File

@ -31,7 +31,6 @@ Possible values:
Related options: Related options:
* docker_remote_api_host * docker_remote_api_host
* etcd_host
* wsproxy_host * wsproxy_host
* host_ip * host_ip
* my_block_storage_ip * my_block_storage_ip

View File

@ -23,8 +23,7 @@ import zun.conf
"""Add the database backend mapping here""" """Add the database backend mapping here"""
CONF = zun.conf.CONF CONF = zun.conf.CONF
_BACKEND_MAPPING = {'sqlalchemy': 'zun.db.sqlalchemy.api', _BACKEND_MAPPING = {'sqlalchemy': 'zun.db.sqlalchemy.api'}
'etcd': 'zun.db.etcd.api'}
IMPL = db_api.DBAPI.from_config(CONF, IMPL = db_api.DBAPI.from_config(CONF,
backend_mapping=_BACKEND_MAPPING, backend_mapping=_BACKEND_MAPPING,
lazy=True) lazy=True)

File diff suppressed because it is too large Load Diff

View File

@ -1,463 +0,0 @@
# Copyright 2016 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.
"""
etcd models
"""
import etcd
from oslo_serialization import jsonutils as json
from zun.common import exception
import zun.db.etcd as db
from zun import objects
class Base(object):
def __setitem__(self, key, value):
setattr(self, key, value)
def __getitem__(self, key):
return getattr(self, key)
def get(self, key):
return getattr(self, key)
def etcd_path(self, sub_path):
return self.path + '/' + sub_path
def as_dict(self):
d = {}
for f in self._fields:
d[f] = getattr(self, f, None)
return d
def path_already_exist(self, client, path):
try:
client.read(path)
except etcd.EtcdKeyNotFound:
return False
return True
def update(self, values):
"""Make the model object behave like a dict."""
for k, v in values.items():
setattr(self, k, v)
def save(self, session=None):
if session is None:
session = db.api.get_backend()
client = session.client
path = self.etcd_path(self.uuid)
if self.path_already_exist(client, path):
raise exception.ResourceExists(name=getattr(self, '__class__'))
client.write(path, json.dump_as_bytes(self.as_dict()))
return
def items(self):
"""Make the model object behave like a dict."""
return self.as_dict().items()
def iteritems(self):
"""Make the model object behave like a dict."""
return self.as_dict().items()
def keys(self):
"""Make the model object behave like a dict."""
return [key for key, value in self.iteritems()]
class ZunService(Base):
"""Represents health status of various zun services"""
_path = '/zun_services'
_fields = objects.ZunService.fields.keys()
def __init__(self, service_data):
self.path = ZunService.path()
for f in ZunService.fields():
setattr(self, f, None)
self.id = 1
self.disabled = False
self.forced_down = False
self.report_count = 0
self.update(service_data)
@classmethod
def path(cls):
return cls._path
@classmethod
def fields(cls):
return cls._fields
def save(self, session=None):
if session is None:
session = db.api.get_backend()
client = session.client
path = self.etcd_path(self.host + '_' + self.binary)
if self.path_already_exist(client, path):
raise exception.ZunServiceAlreadyExists(host=self.host,
binary=self.binary)
client.write(path, json.dump_as_bytes(self.as_dict()))
return
class Container(Base):
"""Represents a container."""
_path = '/containers'
_fields = objects.Container.fields.keys()
def __init__(self, container_data):
self.path = Container.path()
for f in Container.fields():
setattr(self, f, None)
self.id = 1
self.disk = 0
self.auto_remove = False
self.interactive = False
self.auto_heal = False
self.privileged = False
self.update(container_data)
@classmethod
def path(cls):
return cls._path
@classmethod
def fields(cls):
return cls._fields
class Image(Base):
"""Represents a container image."""
_path = '/images'
_fields = objects.Image.fields.keys()
def __init__(self, image_data):
self.path = Image.path()
for f in Image.fields():
setattr(self, f, None)
self.id = 1
self.update(image_data)
@classmethod
def path(cls):
return cls._path
@classmethod
def fields(cls):
return cls._fields
class ResourceClass(Base):
"""Represents a resource class."""
_path = '/resource_classes'
_fields = objects.ResourceClass.fields.keys()
def __init__(self, resource_class_data):
self.path = ResourceClass.path()
for f in ResourceClass.fields():
setattr(self, f, None)
self.id = 1
self.update(resource_class_data)
@classmethod
def path(cls):
return cls._path
@classmethod
def fields(cls):
return cls._fields
class Capsule(Base):
"""Represents a capsule."""
_path = '/capsules'
_fields = objects.Capsule.fields.keys()
def __init__(self, capsule_data):
self.path = Capsule.path()
for f in Capsule.fields():
setattr(self, f, None)
self.id = 1
self.update(capsule_data)
@classmethod
def path(cls):
return cls._path
@classmethod
def fields(cls):
return cls._fields
class ComputeNode(Base):
"""Represents a compute node. """
_path = '/compute_nodes'
# NOTE(kiennt): Use list(fields) instead of fields.keys()
# because in Python 3, the dict.keys() method
# returns a dictionary view object, which acts
# as a set. To do the replacement, _fields should
# be a list.
_fields = list(objects.ComputeNode.fields)
def __init__(self, compute_node_data):
self.path = ComputeNode.path()
for f in ComputeNode.fields():
setattr(self, f, None)
self.cpus = 0
self.cpu_used = 0
self.mem_used = 0
self.mem_total = 0
self.mem_free = 0
self.mem_available = 0
self.total_containers = 0
self.stopped_containers = 0
self.paused_containers = 0
self.running_containers = 0
self.disk_used = 0
self.disk_total = 0
self.disk_quota_supported = False
self.enable_cpu_pinning = False
self.update(compute_node_data)
@classmethod
def path(cls):
return cls._path
@classmethod
def fields(cls):
# NOTE(kiennt): The pci_device_pools field in object maps to the
# pci_stats field in the database. Therefore, need
# replace these fields.
for index, value in enumerate(cls._fields):
if value == 'pci_device_pools':
cls._fields.pop(index)
cls._fields.insert(index, 'pci_stats')
break
return cls._fields
def save(self, session=None):
if session is None:
session = db.api.get_backend()
client = session.client
path = self.etcd_path(self.uuid)
if self.path_already_exist(client, path):
raise exception.ComputeNodeAlreadyExists(
field='UUID', value=self.uuid)
client.write(path, json.dump_as_bytes(self.as_dict()))
return
class PciDevice(Base):
"""Represents a PciDevice. """
_path = '/pcidevices'
_fields = objects.PciDevice.fields.keys()
def __init__(self, pci_data):
self.path = PciDevice.path()
for f in PciDevice.fields():
setattr(self, f, None)
self.id = 1
self.numa_node = 0
self.update(pci_data)
@classmethod
def path(cls):
return cls._path
@classmethod
def fields(cls):
return cls._fields
class VolumeMapping(Base):
"""Represents a VolumeMapping."""
_path = '/volume_mapping'
_fields = objects.VolumeMapping.fields.keys()
def __init__(self, volume_mapping_data):
self.path = VolumeMapping.path()
for f in VolumeMapping.fields():
setattr(self, f, None)
self.id = 1
self.auto_remove = False
self.update(volume_mapping_data)
@classmethod
def path(cls):
return cls._path
@classmethod
def fields(cls):
return cls._fields
class ContainerAction(Base):
"""Represents a container action.
The intention is that there will only be one of these pre user request. A
lookup by(container_uuid, request_id) should always return a single result.
"""
_path = '/container_actions'
_fields = list(objects.ContainerAction.fields) + ['uuid']
def __init__(self, action_data):
self.path = ContainerAction.path(action_data['container_uuid'])
for f in ContainerAction.fields():
setattr(self, f, None)
self.id = 1
self.update(action_data)
@classmethod
def path(cls, container_uuid):
return cls._path + '/' + container_uuid
@classmethod
def fields(cls):
return cls._fields
class ContainerActionEvent(Base):
"""Track events that occur during an ContainerAction."""
_path = '/container_actions_events'
_fields = list(objects.ContainerActionEvent.fields) + ['action_uuid',
'uuid']
def __init__(self, event_data):
self.path = ContainerActionEvent.path(event_data['action_uuid'])
for f in ContainerActionEvent.fields():
setattr(self, f, None)
self.id = 1
self.action_id = 0
self.update(event_data)
@classmethod
def path(cls, action_uuid):
return cls._path + '/' + action_uuid
@classmethod
def fields(cls):
return cls._fields
class Quota(Base):
"""Represents a Quota."""
_path = '/quotas'
_fields = list(objects.Quota.fields) + ['uuid']
def __init__(self, quota_data):
self.path = Quota.path(project_id=quota_data.get('class_name'),
resource=quota_data.get('resource'))
for f in Quota.fields():
setattr(self, f, None)
self.id = 1
self.update(quota_data)
@classmethod
def path(cls, project_id, resource=None):
if resource is not None:
path = '{}/{}/{}' . format(cls._path, project_id, resource)
else:
path = '{}/{}' . format(cls._path, project_id)
return path
@classmethod
def fields(cls):
return cls._fields
class QuotaClass(Base):
"""Represents a QuotaClass."""
_path = '/quota_classes'
_fields = list(objects.QuotaClass.fields) + ['uuid']
def __init__(self, quota_class_data):
self.path = QuotaClass.path(
class_name=quota_class_data.get('class_name'),
resource=quota_class_data.get('resource'))
for f in QuotaClass.fields():
setattr(self, f, None)
self.id = 1
self.update(quota_class_data)
@classmethod
def path(cls, class_name, resource=None):
if resource is not None:
path = '{}/{}/{}' . format(cls._path, class_name, resource)
else:
path = '{}/{}' . format(cls._path, class_name)
return path
@classmethod
def fields(cls):
return cls._fields
class QuotaUsage(Base):
"""Represents the current usage for a given resource."""
_path = '/quota_usages'
_fields = ['id', 'project_id', 'resource', 'in_use', 'reserved']
def __init__(self, quota_usage_data):
self.path = QuotaUsage.path(
project_id=quota_usage_data['project_id'],
resource=quota_usage_data['resource'])
for f in QuotaUsage.fields():
setattr(self, f, None)
self.id = 1
self.update(quota_usage_data)
@classmethod
def path(cls, project_id, resource):
return '{}/{}/{}' . format(cls._path, project_id, resource)
@classmethod
def fields(cls):
return cls._fields

View File

@ -28,7 +28,8 @@ class ContainerAction(base.ZunPersistentObject, base.ZunObject):
# Version 1.0: Initial version # Version 1.0: Initial version
# Version 1.1: Add uuid column. # Version 1.1: Add uuid column.
VERSION = '1.1' # Version 1.2: Remove uuid column.
VERSION = '1.2'
fields = { fields = {
'id': fields.IntegerField(), 'id': fields.IntegerField(),
@ -40,9 +41,6 @@ class ContainerAction(base.ZunPersistentObject, base.ZunObject):
'start_time': fields.DateTimeField(tzinfo_aware=False, nullable=True), 'start_time': fields.DateTimeField(tzinfo_aware=False, nullable=True),
'finish_time': fields.DateTimeField(tzinfo_aware=False, nullable=True), 'finish_time': fields.DateTimeField(tzinfo_aware=False, nullable=True),
'message': fields.StringField(nullable=True), 'message': fields.StringField(nullable=True),
# NOTE: By now, this field is only used for etcd. If using sql,
# this field will be None.
'uuid': fields.StringField(nullable=True),
} }
@staticmethod @staticmethod

View File

@ -21,16 +21,14 @@ class Quota(base.ZunPersistentObject, base.ZunObject):
# Version 1.0: Initial version # Version 1.0: Initial version
# Version 1.1: Add uuid column # Version 1.1: Add uuid column
# Version 1.2: Add destroy_all_by_project method # Version 1.2: Add destroy_all_by_project method
VERSION = '1.2' # Version 1.3: Remove uuid column
VERSION = '1.3'
fields = { fields = {
'id': fields.IntegerField(), 'id': fields.IntegerField(),
'project_id': fields.StringField(nullable=True), 'project_id': fields.StringField(nullable=True),
'resource': fields.StringField(), 'resource': fields.StringField(),
'hard_limit': fields.IntegerField(nullable=True), 'hard_limit': fields.IntegerField(nullable=True),
# NOTE(kiennt): By now, this field is only used for etcd. If using sql,
# this field will be None.
'uuid': fields.StringField(nullable=True),
} }
@staticmethod @staticmethod

View File

@ -20,16 +20,14 @@ from zun.objects import base
class QuotaClass(base.ZunPersistentObject, base.ZunObject): class QuotaClass(base.ZunPersistentObject, base.ZunObject):
# Version 1.0: Initial version # Version 1.0: Initial version
# Version 1.1: Add uuid column # Version 1.1: Add uuid column
VERSION = '1.1' # Version 1.2: Remove uuid column
VERSION = '1.2'
fields = { fields = {
'id': fields.IntegerField(), 'id': fields.IntegerField(),
'class_name': fields.StringField(nullable=True), 'class_name': fields.StringField(nullable=True),
'resource': fields.StringField(nullable=True), 'resource': fields.StringField(nullable=True),
'hard_limit': fields.IntegerField(nullable=True), 'hard_limit': fields.IntegerField(nullable=True),
# NOTE(kiennt): By now, this field is only used for etcd. If using sql,
# this field will be None.
'uuid': fields.StringField(nullable=True),
} }
@staticmethod @staticmethod

View File

@ -16,7 +16,6 @@ import fixtures
import zun.conf import zun.conf
from zun.db import api as db_api from zun.db import api as db_api
from zun.db.etcd import api as etcd_api
from zun.db.sqlalchemy import api as sqla_api from zun.db.sqlalchemy import api as sqla_api
from zun.db.sqlalchemy import migration from zun.db.sqlalchemy import migration
from zun.db.sqlalchemy import models from zun.db.sqlalchemy import models
@ -61,9 +60,7 @@ class DbTestCase(base.TestCase):
def setUp(self): def setUp(self):
super(DbTestCase, self).setUp() super(DbTestCase, self).setUp()
self.dbapi = (db_api._get_dbdriver_instance() self.dbapi = db_api._get_dbdriver_instance()
if CONF.database.backend == "sqlalchemy"
else etcd_api.get_backend())
global _DB_CACHE global _DB_CACHE
if not _DB_CACHE: if not _DB_CACHE:

View File

@ -16,7 +16,6 @@ from oslo_config import cfg
from zun.common import consts from zun.common import consts
from zun.common import name_generator from zun.common import name_generator
from zun.db import api as db_api from zun.db import api as db_api
from zun.db.etcd import api as etcd_api
from zun.objects.container import Cpuset from zun.objects.container import Cpuset
CONF = cfg.CONF CONF = cfg.CONF
@ -106,10 +105,7 @@ def get_test_container(**kwargs):
def _get_dbapi(): def _get_dbapi():
if CONF.database.backend == 'sqlalchemy': dbapi = db_api._get_dbdriver_instance()
dbapi = db_api._get_dbdriver_instance()
else:
dbapi = etcd_api.get_backend()
return dbapi return dbapi

View File

@ -362,11 +362,11 @@ object_data = {
'ComputeNode': '1.13-3c122f455c38d3665d327c05d2df6617', 'ComputeNode': '1.13-3c122f455c38d3665d327c05d2df6617',
'PciDevicePool': '1.0-3f5ddc3ff7bfa14da7f6c7e9904cc000', 'PciDevicePool': '1.0-3f5ddc3ff7bfa14da7f6c7e9904cc000',
'PciDevicePoolList': '1.0-15ecf022a68ddbb8c2a6739cfc9f8f5e', 'PciDevicePoolList': '1.0-15ecf022a68ddbb8c2a6739cfc9f8f5e',
'Quota': '1.2-3a7d520d119fe1e886baad968ef7990a', 'Quota': '1.3-fcaaaf4b6e983207edba27a1cf8e51ab',
'QuotaClass': '1.1-239ae335b32036b86504684d3fdbeb7f', 'QuotaClass': '1.2-4739583a70891fbc145031228fb8001e',
'ContainerPCIRequest': '1.0-b060f9f9f734bedde79a71a4d3112ee0', 'ContainerPCIRequest': '1.0-b060f9f9f734bedde79a71a4d3112ee0',
'ContainerPCIRequests': '1.0-7b8f7f044661fe4e24e6949c035af2c4', 'ContainerPCIRequests': '1.0-7b8f7f044661fe4e24e6949c035af2c4',
'ContainerAction': '1.1-bdf41c7cc36a0cb113eb6e0f5800a0d8', 'ContainerAction': '1.2-e8c494b11ea259655256d87aef877eef',
'ContainerActionEvent': '1.0-2974d0a6f5d4821fd4e223a88c10181a', 'ContainerActionEvent': '1.0-2974d0a6f5d4821fd4e223a88c10181a',
'Network': '1.1-26e8d37a54e5fc905ede657744a221d9', 'Network': '1.1-26e8d37a54e5fc905ede657744a221d9',
'ExecInstance': '1.0-59464e7b96db847c0abb1e96d3cec30a', 'ExecInstance': '1.0-59464e7b96db847c0abb1e96d3cec30a',