cinder/cinder/db/sqlalchemy/migrate_repo/versions/040_add_volume_attachment.py

148 lines
5.3 KiB
Python

# (c) Copyright 2012-2014 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.
import datetime
import uuid
import six
from sqlalchemy import Boolean, Column, DateTime
from sqlalchemy import ForeignKey, MetaData, String, Table
from cinder.i18n import _LE
from cinder.openstack.common import log as logging
LOG = logging.getLogger(__name__)
CREATED_AT = datetime.datetime.now()
def upgrade(migrate_engine):
"""Add volume multi attachment table."""
meta = MetaData()
meta.bind = migrate_engine
# add the multiattach flag to the volumes table.
volumes = Table('volumes', meta, autoload=True)
multiattach = Column('multiattach', Boolean)
volumes.create_column(multiattach)
volumes.update().values(multiattach=False).execute()
# The new volume_attachment table
volume_attachment = Table(
'volume_attachment', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('deleted_at', DateTime),
Column('deleted', Boolean),
Column('id', String(length=36), primary_key=True, nullable=False),
Column('volume_id', String(length=36), ForeignKey('volumes.id'),
nullable=False),
Column('attached_host', String(length=255)),
Column('instance_uuid', String(length=36)),
Column('mountpoint', String(length=255)),
Column('attach_time', DateTime),
Column('detach_time', DateTime),
Column('attach_mode', String(length=36)),
Column('attach_status', String(length=255)),
mysql_engine='InnoDB'
)
try:
volume_attachment.create()
except Exception:
LOG.error(_LE("Table volume_attachment not created!"))
raise
# now migrate existing volume attachment info into the
# new volume_attachment table
volumes_list = list(volumes.select().execute())
for volume in volumes_list:
if volume.attach_status == 'attached':
attachment = volume_attachment.insert()
values = {'id': six.text_type(uuid.uuid4()),
'created_at': CREATED_AT,
'deleted_at': None,
'deleted': 0,
'volume_id': volume.id,
'attached_host': volume.host,
'instance_uuid': volume.instance_uuid,
'mountpoint': volume.mountpoint,
'attach_time': volume.attach_time,
'attach_mode': 'rw',
'attach_status': 'attached',
}
attachment.execute(values)
# we have no reason to keep the columns that now
# exist in the volume_attachment table
mountpoint = volumes.columns.mountpoint
volumes.drop_column(mountpoint)
instance_uuid = volumes.columns.instance_uuid
volumes.drop_column(instance_uuid)
attach_time = volumes.columns.attach_time
volumes.drop_column(attach_time)
attached_host = volumes.columns.attached_host
volumes.drop_column(attached_host)
def downgrade(migrate_engine):
"""Remove volume_attachment table."""
meta = MetaData()
meta.bind = migrate_engine
# Put the needed volumes table columns back
volumes = Table('volumes', meta, autoload=True)
multiattach = volumes.columns.multiattach
volumes.drop_column(multiattach)
attached_host = Column('attached_host', String(length=255))
volumes.create_column(attached_host)
volumes.update().values(attached_host=None).execute()
attach_time = Column('attach_time', String(length=255))
volumes.create_column(attach_time)
volumes.update().values(attach_time=None).execute()
instance_uuid = Column('instance_uuid', String(length=36))
volumes.create_column(instance_uuid)
volumes.update().values(instance_uuid=None).execute()
mountpoint = Column('mountpoint', String(length=255))
volumes.create_column(mountpoint)
volumes.update().values(mountpoint=None).execute()
volume_attachment = Table('volume_attachment', meta, autoload=True)
attachments = list(volume_attachment.select().execute())
for attachment in attachments:
# we are going to lose data here for
# multiple attaches. We'll migrate and the
# last update wins.
if not attachment.deleted_at:
volume_id = attachment.volume_id
volumes.update().\
where(volumes.c.id == volume_id).\
values(mountpoint=attachment.mountpoint,
attached_host=attachment.attached_host,
attach_time=attachment.attach_time,
instance_uuid=attachment.instance_uuid).\
execute()
try:
volume_attachment.drop()
except Exception:
LOG.error(_LE("Dropping volume_attachment table failed."))
raise