Merge "Compact Mitaka database migrations"
This commit is contained in:
commit
38aae0602b
@ -26,7 +26,7 @@ from stevedore import driver
|
|||||||
from cinder.db.sqlalchemy import api as db_api
|
from cinder.db.sqlalchemy import api as db_api
|
||||||
|
|
||||||
|
|
||||||
INIT_VERSION = 60
|
INIT_VERSION = 72
|
||||||
|
|
||||||
_IMPL = None
|
_IMPL = None
|
||||||
_LOCK = threading.Lock()
|
_LOCK = threading.Lock()
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
# 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 Integer
|
|
||||||
from sqlalchemy import MetaData, Table
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade(migrate_engine):
|
|
||||||
"""Deleted col of volume_type_projects converted(tinyint->Int)."""
|
|
||||||
meta = MetaData()
|
|
||||||
meta.bind = migrate_engine
|
|
||||||
|
|
||||||
volume_type_projects = Table('volume_type_projects', meta, autoload=True)
|
|
||||||
|
|
||||||
if migrate_engine.name == 'postgresql':
|
|
||||||
# NOTE: PostgreSQL can't cast Boolean to int automatically
|
|
||||||
sql = 'ALTER TABLE volume_type_projects ALTER COLUMN deleted ' + \
|
|
||||||
'TYPE INTEGER USING deleted::integer'
|
|
||||||
migrate_engine.execute(sql)
|
|
||||||
else:
|
|
||||||
volume_type_projects.c.deleted.alter(Integer)
|
|
@ -1,29 +0,0 @@
|
|||||||
-- As sqlite does not support the DROP CHECK, we need to create
|
|
||||||
-- the table, and move all the data to it.
|
|
||||||
|
|
||||||
CREATE TABLE volume_type_projects_new (
|
|
||||||
created_at DATETIME,
|
|
||||||
updated_at DATETIME,
|
|
||||||
deleted_at DATETIME,
|
|
||||||
deleted INTEGER,
|
|
||||||
id INTEGER NOT NULL,
|
|
||||||
volume_type_id VARCHAR(36),
|
|
||||||
project_id VARCHAR(255),
|
|
||||||
PRIMARY KEY (id),
|
|
||||||
FOREIGN KEY (volume_type_id) REFERENCES volume_types(id),
|
|
||||||
CONSTRAINT uniq_volume_type_projects0volume_type_id0project_id0deleted UNIQUE (volume_type_id, project_id, deleted)
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO volume_type_projects_new
|
|
||||||
SELECT created_at,
|
|
||||||
updated_at,
|
|
||||||
deleted_at,
|
|
||||||
deleted,
|
|
||||||
id,
|
|
||||||
volume_type_id,
|
|
||||||
project_id
|
|
||||||
FROM volume_type_projects;
|
|
||||||
|
|
||||||
DROP TABLE volume_type_projects;
|
|
||||||
|
|
||||||
ALTER TABLE volume_type_projects_new RENAME TO volume_type_projects;
|
|
@ -1,17 +0,0 @@
|
|||||||
# 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.
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade(migrate_engine):
|
|
||||||
# This used to drop iscsi_targets, but since dropping it before L release
|
|
||||||
# stops using it breaks rolling upgrades we postpone the dropping until N.
|
|
||||||
pass
|
|
@ -1,26 +0,0 @@
|
|||||||
# Copyright (c) 2015 Intel Corporation
|
|
||||||
# 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 Column, MetaData, String, Table
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade(migrate_engine):
|
|
||||||
meta = MetaData()
|
|
||||||
meta.bind = migrate_engine
|
|
||||||
|
|
||||||
backups = Table('backups', meta, autoload=True)
|
|
||||||
restore_volume_id = Column('restore_volume_id', String(length=36))
|
|
||||||
|
|
||||||
backups.create_column(restore_volume_id)
|
|
@ -1,30 +0,0 @@
|
|||||||
# 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 Column
|
|
||||||
from sqlalchemy import Boolean, MetaData, String, Table
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade(migrate_engine):
|
|
||||||
"""Add replication info to services table."""
|
|
||||||
meta = MetaData()
|
|
||||||
meta.bind = migrate_engine
|
|
||||||
|
|
||||||
services = Table('services', meta, autoload=True)
|
|
||||||
replication_status = Column('replication_status', String(length=36),
|
|
||||||
default="not-capable")
|
|
||||||
active_backend_id = Column('active_backend_id', String(length=255))
|
|
||||||
frozen = Column('frozen', Boolean, default=False)
|
|
||||||
|
|
||||||
services.create_column(replication_status)
|
|
||||||
services.create_column(frozen)
|
|
||||||
services.create_column(active_backend_id)
|
|
@ -1,28 +0,0 @@
|
|||||||
# 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 Column
|
|
||||||
from sqlalchemy import MetaData, Integer, Table, ForeignKey
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade(migrate_engine):
|
|
||||||
"""Add allocated_id to the reservations table."""
|
|
||||||
meta = MetaData()
|
|
||||||
meta.bind = migrate_engine
|
|
||||||
|
|
||||||
reservations = Table('reservations', meta, autoload=True)
|
|
||||||
Table('quotas', meta, autoload=True)
|
|
||||||
allocated_id = Column('allocated_id', Integer, ForeignKey('quotas.id'),
|
|
||||||
nullable=True)
|
|
||||||
reservations.create_column(allocated_id)
|
|
||||||
usage_id = reservations.c.usage_id
|
|
||||||
usage_id.alter(nullable=True)
|
|
@ -1,40 +0,0 @@
|
|||||||
# 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, ForeignKey
|
|
||||||
from sqlalchemy import Integer, MetaData, String, Table
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade(migrate_engine):
|
|
||||||
meta = MetaData()
|
|
||||||
meta.bind = migrate_engine
|
|
||||||
Table('volumes', meta, autoload=True)
|
|
||||||
|
|
||||||
table = Table(
|
|
||||||
'iscsi_targets', meta,
|
|
||||||
Column('created_at', DateTime),
|
|
||||||
Column('updated_at', DateTime),
|
|
||||||
Column('deleted_at', DateTime),
|
|
||||||
Column('deleted', Boolean),
|
|
||||||
Column('id', Integer, primary_key=True, nullable=False),
|
|
||||||
Column('target_num', Integer),
|
|
||||||
Column('host', String(length=255)),
|
|
||||||
Column('volume_id', String(length=36), ForeignKey('volumes.id'),
|
|
||||||
nullable=True),
|
|
||||||
mysql_engine='InnoDB',
|
|
||||||
mysql_charset='utf8'
|
|
||||||
)
|
|
||||||
|
|
||||||
# We use checkfirst argument because this table may already exist if the
|
|
||||||
# migration is performed on a system that was on a migration earlier than
|
|
||||||
# 063 when performing the upgrade.
|
|
||||||
table.create(checkfirst=True)
|
|
@ -1,22 +0,0 @@
|
|||||||
# 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.
|
|
||||||
|
|
||||||
# This is a placeholder for Mitaka backports.
|
|
||||||
# Do not use this number for new Newton work. New work starts after
|
|
||||||
# all the placeholders.
|
|
||||||
#
|
|
||||||
# See this for more information:
|
|
||||||
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade(migrate_engine):
|
|
||||||
pass
|
|
@ -1,22 +0,0 @@
|
|||||||
# 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.
|
|
||||||
|
|
||||||
# This is a placeholder for Mitaka backports.
|
|
||||||
# Do not use this number for new Newton work. New work starts after
|
|
||||||
# all the placeholders.
|
|
||||||
#
|
|
||||||
# See this for more information:
|
|
||||||
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade(migrate_engine):
|
|
||||||
pass
|
|
@ -1,22 +0,0 @@
|
|||||||
# 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.
|
|
||||||
|
|
||||||
# This is a placeholder for Mitaka backports.
|
|
||||||
# Do not use this number for new Newton work. New work starts after
|
|
||||||
# all the placeholders.
|
|
||||||
#
|
|
||||||
# See this for more information:
|
|
||||||
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade(migrate_engine):
|
|
||||||
pass
|
|
@ -1,22 +0,0 @@
|
|||||||
# 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.
|
|
||||||
|
|
||||||
# This is a placeholder for Mitaka backports.
|
|
||||||
# Do not use this number for new Newton work. New work starts after
|
|
||||||
# all the placeholders.
|
|
||||||
#
|
|
||||||
# See this for more information:
|
|
||||||
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade(migrate_engine):
|
|
||||||
pass
|
|
@ -1,22 +0,0 @@
|
|||||||
# 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.
|
|
||||||
|
|
||||||
# This is a placeholder for Mitaka backports.
|
|
||||||
# Do not use this number for new Newton work. New work starts after
|
|
||||||
# all the placeholders.
|
|
||||||
#
|
|
||||||
# See this for more information:
|
|
||||||
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade(migrate_engine):
|
|
||||||
pass
|
|
@ -49,9 +49,10 @@ def define_tables(meta):
|
|||||||
Column('disabled_reason', String(255)),
|
Column('disabled_reason', String(255)),
|
||||||
Column('modified_at', DateTime(timezone=False)),
|
Column('modified_at', DateTime(timezone=False)),
|
||||||
Column('rpc_current_version', String(36)),
|
Column('rpc_current_version', String(36)),
|
||||||
Column('rpc_available_version', String(36)),
|
|
||||||
Column('object_current_version', String(36)),
|
Column('object_current_version', String(36)),
|
||||||
Column('object_available_version', String(36)),
|
Column('replication_status', String(36), default='not-capable'),
|
||||||
|
Column('frozen', Boolean, default=False),
|
||||||
|
Column('active_backend_id', String(255)),
|
||||||
mysql_engine='InnoDB',
|
mysql_engine='InnoDB',
|
||||||
mysql_charset='utf8'
|
mysql_charset='utf8'
|
||||||
)
|
)
|
||||||
@ -242,7 +243,7 @@ def define_tables(meta):
|
|||||||
Column('volume_type_id', String(36),
|
Column('volume_type_id', String(36),
|
||||||
ForeignKey('volume_types.id')),
|
ForeignKey('volume_types.id')),
|
||||||
Column('project_id', String(255)),
|
Column('project_id', String(255)),
|
||||||
Column('deleted', Boolean(create_constraint=True, name=None)),
|
Column('deleted', Integer),
|
||||||
UniqueConstraint('volume_type_id', 'project_id', 'deleted'),
|
UniqueConstraint('volume_type_id', 'project_id', 'deleted'),
|
||||||
mysql_engine='InnoDB',
|
mysql_engine='InnoDB',
|
||||||
mysql_charset='utf8'
|
mysql_charset='utf8'
|
||||||
@ -295,21 +296,6 @@ def define_tables(meta):
|
|||||||
mysql_charset='utf8'
|
mysql_charset='utf8'
|
||||||
)
|
)
|
||||||
|
|
||||||
iscsi_targets = Table(
|
|
||||||
'iscsi_targets', meta,
|
|
||||||
Column('created_at', DateTime),
|
|
||||||
Column('updated_at', DateTime),
|
|
||||||
Column('deleted_at', DateTime),
|
|
||||||
Column('deleted', Boolean),
|
|
||||||
Column('id', Integer, primary_key=True, nullable=False),
|
|
||||||
Column('target_num', Integer),
|
|
||||||
Column('host', String(255)),
|
|
||||||
Column('volume_id', String(36), ForeignKey('volumes.id'),
|
|
||||||
nullable=True),
|
|
||||||
mysql_engine='InnoDB',
|
|
||||||
mysql_charset='utf8'
|
|
||||||
)
|
|
||||||
|
|
||||||
quota_classes = Table(
|
quota_classes = Table(
|
||||||
'quota_classes', meta,
|
'quota_classes', meta,
|
||||||
Column('created_at', DateTime(timezone=False)),
|
Column('created_at', DateTime(timezone=False)),
|
||||||
@ -354,11 +340,13 @@ def define_tables(meta):
|
|||||||
Column('usage_id',
|
Column('usage_id',
|
||||||
Integer(),
|
Integer(),
|
||||||
ForeignKey('quota_usages.id'),
|
ForeignKey('quota_usages.id'),
|
||||||
nullable=False),
|
nullable=True),
|
||||||
Column('project_id', String(255), index=True),
|
Column('project_id', String(255), index=True),
|
||||||
Column('resource', String(255)),
|
Column('resource', String(255)),
|
||||||
Column('delta', Integer(), nullable=False),
|
Column('delta', Integer(), nullable=False),
|
||||||
Column('expire', DateTime(timezone=False)),
|
Column('expire', DateTime(timezone=False)),
|
||||||
|
Column('allocated_id', Integer, ForeignKey('quotas.id'),
|
||||||
|
nullable=True),
|
||||||
Index('reservations_deleted_expire_idx',
|
Index('reservations_deleted_expire_idx',
|
||||||
'deleted', 'expire'),
|
'deleted', 'expire'),
|
||||||
mysql_engine='InnoDB',
|
mysql_engine='InnoDB',
|
||||||
@ -409,6 +397,7 @@ def define_tables(meta):
|
|||||||
Column('num_dependent_backups', Integer, default=0),
|
Column('num_dependent_backups', Integer, default=0),
|
||||||
Column('snapshot_id', String(36)),
|
Column('snapshot_id', String(36)),
|
||||||
Column('data_timestamp', DateTime),
|
Column('data_timestamp', DateTime),
|
||||||
|
Column('restore_volume_id', String(36)),
|
||||||
mysql_engine='InnoDB',
|
mysql_engine='InnoDB',
|
||||||
mysql_charset='utf8'
|
mysql_charset='utf8'
|
||||||
)
|
)
|
||||||
@ -510,7 +499,6 @@ def define_tables(meta):
|
|||||||
quality_of_service_specs,
|
quality_of_service_specs,
|
||||||
volume_types,
|
volume_types,
|
||||||
volume_type_projects,
|
volume_type_projects,
|
||||||
iscsi_targets,
|
|
||||||
quotas,
|
quotas,
|
||||||
services,
|
services,
|
||||||
volume_metadata,
|
volume_metadata,
|
||||||
@ -548,7 +536,6 @@ def upgrade(migrate_engine):
|
|||||||
"volume_type_projects",
|
"volume_type_projects",
|
||||||
"volumes",
|
"volumes",
|
||||||
"volume_attachment",
|
"volume_attachment",
|
||||||
"iscsi_targets",
|
|
||||||
"migrate_version",
|
"migrate_version",
|
||||||
"quotas",
|
"quotas",
|
||||||
"services",
|
"services",
|
@ -1,25 +0,0 @@
|
|||||||
# 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 MetaData, Table
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade(migrate_engine):
|
|
||||||
meta = MetaData()
|
|
||||||
meta.bind = migrate_engine
|
|
||||||
|
|
||||||
services = Table('services', meta, autoload=True)
|
|
||||||
services.c.rpc_available_version.drop()
|
|
||||||
services.c.object_available_version.drop()
|
|
||||||
|
|
||||||
iscsi_targets = Table('iscsi_targets', meta, autoload=True)
|
|
||||||
iscsi_targets.drop()
|
|
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
upgrade:
|
||||||
|
- The Cinder database can now only be upgraded from changes since the
|
||||||
|
Mitaka release. In order to upgrade from a version prior to that,
|
||||||
|
you must now upgrade to at least Mitaka first, then to Pike or later.
|
Loading…
Reference in New Issue
Block a user