Add workers table

This patch adds workers table required for the cleanup of failed
services, needed for the new cleanup mechanism we'll be implementing to
support Active-Active configurations.

They will be used for non Active-Active configurations as well.

Specs: https://review.openstack.org/236977

Implements: blueprint cinder-volume-active-active-support
Change-Id: I5057a4c9071ef9ca78b680bad72fd81373473ed9
This commit is contained in:
Gorka Eguileor 2016-03-23 16:26:20 +01:00
parent 8b713e5327
commit 7294cf0352
3 changed files with 115 additions and 20 deletions

View File

@ -0,0 +1,52 @@
# Copyright (c) 2016 Red Hat, Inc.
# 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.
from sqlalchemy import Boolean, Column, DateTime, Integer
from sqlalchemy import MetaData, String, Table, UniqueConstraint
from migrate.changeset.constraint import ForeignKeyConstraint
def upgrade(migrate_engine):
"""Add workers table."""
meta = MetaData()
meta.bind = migrate_engine
workers = Table(
'workers', meta,
# Inherited fields from CinderBase
Column('created_at', DateTime(timezone=False)),
Column('updated_at', DateTime(timezone=False)),
Column('deleted_at', DateTime(timezone=False)),
Column('deleted', Boolean(), default=False),
# Workers table specific fields
Column('id', Integer, primary_key=True),
Column('resource_type', String(40), nullable=False),
Column('resource_id', String(36), nullable=False),
Column('status', String(255), nullable=False),
Column('service_id', Integer, nullable=True),
UniqueConstraint('resource_type', 'resource_id'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
workers.create()
services = Table('services', meta, autoload=True)
ForeignKeyConstraint(
columns=[workers.c.service_id],
refcolumns=[services.c.id]).create()

View File

@ -700,6 +700,43 @@ class ImageVolumeCacheEntry(BASE, models.ModelBase):
last_used = Column(DateTime, default=lambda: timeutils.utcnow())
class Worker(BASE, CinderBase):
"""Represents all resources that are being worked on by a node."""
__tablename__ = 'workers'
__table_args__ = (schema.UniqueConstraint('resource_type', 'resource_id'),
{'mysql_engine': 'InnoDB'})
# We want to overwrite default updated_at definition so we timestamp at
# creation as well
updated_at = Column(DateTime, default=timeutils.utcnow,
onupdate=timeutils.utcnow)
# Id added for convenience and speed on some operations
id = Column(Integer, primary_key=True)
# Type of the resource we are working on (Volume, Snapshot, Backup) it must
# match the Versioned Object class name.
resource_type = Column(String(40), primary_key=True, nullable=False)
# UUID of the resource we are working on
resource_id = Column(String(36), primary_key=True, nullable=False)
# Status that should be cleaned on service failure
status = Column(String(255), nullable=False)
# Service that is currently processing the operation
service_id = Column(Integer, nullable=True)
# This is a flag we don't need to store in the DB as it is only used when
# we are doing the cleanup to let decorators know
cleaning = False
service = relationship(
'Service',
backref="workers",
foreign_keys=service_id,
primaryjoin='Worker.service_id == Service.id')
def register_models():
"""Register Models and create metadata.

View File

@ -807,6 +807,13 @@ class MigrationsMixin(test_migrations.WalkVersionsMixin):
self.assertIsInstance(reservations.c.allocated_id.type,
self.INTEGER_TYPE)
def __check_cinderbase_fields(self, columns):
"""Check fields inherited from CinderBase ORM class."""
self.assertIsInstance(columns.created_at.type, self.TIME_TYPE)
self.assertIsInstance(columns.updated_at.type, self.TIME_TYPE)
self.assertIsInstance(columns.deleted_at.type, self.TIME_TYPE)
self.assertIsInstance(columns.deleted.type, self.BOOL_TYPE)
def _check_067(self, engine, data):
iscsi_targets = db_utils.get_table(engine, 'iscsi_targets')
fkey, = iscsi_targets.c.volume_id.foreign_keys
@ -843,28 +850,15 @@ class MigrationsMixin(test_migrations.WalkVersionsMixin):
"""Test adding cluster table and cluster_id fields."""
self.assertTrue(engine.dialect.has_table(engine.connect(), 'clusters'))
clusters = db_utils.get_table(engine, 'clusters')
# Inherited fields from CinderBase
self.assertIsInstance(clusters.c.created_at.type,
self.TIME_TYPE)
self.assertIsInstance(clusters.c.updated_at.type,
self.TIME_TYPE)
self.assertIsInstance(clusters.c.deleted_at.type,
self.TIME_TYPE)
self.assertIsInstance(clusters.c.deleted.type,
self.BOOL_TYPE)
columns = clusters.c
self.__check_cinderbase_fields(columns)
# Cluster specific fields
self.assertIsInstance(clusters.c.id.type,
self.INTEGER_TYPE)
self.assertIsInstance(clusters.c.name.type,
self.VARCHAR_TYPE)
self.assertIsInstance(clusters.c.binary.type,
self.VARCHAR_TYPE)
self.assertIsInstance(clusters.c.disabled.type,
self.BOOL_TYPE)
self.assertIsInstance(clusters.c.disabled_reason.type,
self.VARCHAR_TYPE)
self.assertIsInstance(columns.id.type, self.INTEGER_TYPE)
self.assertIsInstance(columns.name.type, self.VARCHAR_TYPE)
self.assertIsInstance(columns.binary.type, self.VARCHAR_TYPE)
self.assertIsInstance(columns.disabled.type, self.BOOL_TYPE)
self.assertIsInstance(columns.disabled_reason.type, self.VARCHAR_TYPE)
# Check that we have added cluster_name field to all required tables
for table_name in ('services', 'consistencygroups', 'volumes'):
@ -872,6 +866,18 @@ class MigrationsMixin(test_migrations.WalkVersionsMixin):
self.assertIsInstance(table.c.cluster_name.type,
self.VARCHAR_TYPE)
def _check_076(self, engine, data):
workers = db_utils.get_table(engine, 'workers')
columns = workers.c
self.__check_cinderbase_fields(columns)
# Workers specific fields
self.assertIsInstance(columns.id.type, self.INTEGER_TYPE)
self.assertIsInstance(columns.resource_type.type, self.VARCHAR_TYPE)
self.assertIsInstance(columns.resource_id.type, self.VARCHAR_TYPE)
self.assertIsInstance(columns.status.type, self.VARCHAR_TYPE)
self.assertIsInstance(columns.service_id.type, self.INTEGER_TYPE)
def test_walk_versions(self):
self.walk_versions(False, False)