275 lines
11 KiB
Python
275 lines
11 KiB
Python
#
|
|
# 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 distutils import version
|
|
|
|
from gnocchiclient import client
|
|
from gnocchiclient import exceptions as gnocchi_exc
|
|
import keystoneauth1.session
|
|
from oslo_log import log
|
|
|
|
from ceilometer import keystone_client
|
|
|
|
LOG = log.getLogger(__name__)
|
|
|
|
|
|
def get_gnocchiclient(conf, request_timeout=None):
|
|
group = conf.gnocchi.auth_section
|
|
session = keystone_client.get_session(conf, group=group,
|
|
timeout=request_timeout)
|
|
adapter = keystoneauth1.session.TCPKeepAliveAdapter(
|
|
pool_maxsize=conf.max_parallel_requests)
|
|
session.mount("http://", adapter)
|
|
session.mount("https://", adapter)
|
|
return client.Client(
|
|
'1', session, adapter_options={'connect_retries': 3,
|
|
'interface': conf[group].interface,
|
|
'region_name': conf[group].region_name})
|
|
|
|
|
|
# NOTE(sileht): This is the initial resource types created in Gnocchi
|
|
# This list must never change to keep in sync with what Gnocchi early
|
|
# database contents was containing
|
|
resources_initial = {
|
|
"image": {
|
|
"name": {"type": "string", "min_length": 0, "max_length": 255,
|
|
"required": True},
|
|
"container_format": {"type": "string", "min_length": 0,
|
|
"max_length": 255, "required": True},
|
|
"disk_format": {"type": "string", "min_length": 0, "max_length": 255,
|
|
"required": True},
|
|
},
|
|
"instance": {
|
|
"flavor_id": {"type": "string", "min_length": 0, "max_length": 255,
|
|
"required": True},
|
|
"image_ref": {"type": "string", "min_length": 0, "max_length": 255,
|
|
"required": False},
|
|
"host": {"type": "string", "min_length": 0, "max_length": 255,
|
|
"required": True},
|
|
"display_name": {"type": "string", "min_length": 0, "max_length": 255,
|
|
"required": True},
|
|
"server_group": {"type": "string", "min_length": 0, "max_length": 255,
|
|
"required": False},
|
|
},
|
|
"instance_disk": {
|
|
"name": {"type": "string", "min_length": 0, "max_length": 255,
|
|
"required": True},
|
|
"instance_id": {"type": "uuid", "required": True},
|
|
},
|
|
"instance_network_interface": {
|
|
"name": {"type": "string", "min_length": 0, "max_length": 255,
|
|
"required": True},
|
|
"instance_id": {"type": "uuid", "required": True},
|
|
},
|
|
"volume": {
|
|
"display_name": {"type": "string", "min_length": 0, "max_length": 255,
|
|
"required": False},
|
|
},
|
|
"swift_account": {},
|
|
"ceph_account": {},
|
|
"network": {},
|
|
"identity": {},
|
|
"ipmi": {},
|
|
"stack": {},
|
|
"host": {
|
|
"host_name": {"type": "string", "min_length": 0, "max_length": 255,
|
|
"required": True},
|
|
},
|
|
"host_network_interface": {
|
|
"host_name": {"type": "string", "min_length": 0, "max_length": 255,
|
|
"required": True},
|
|
"device_name": {"type": "string", "min_length": 0, "max_length": 255,
|
|
"required": False},
|
|
},
|
|
"host_disk": {
|
|
"host_name": {"type": "string", "min_length": 0, "max_length": 255,
|
|
"required": True},
|
|
"device_name": {"type": "string", "min_length": 0, "max_length": 255,
|
|
"required": False},
|
|
},
|
|
}
|
|
|
|
# NOTE(sileht): Order matter this have to be considered like alembic migration
|
|
# code, because it updates the resources schema of Gnocchi
|
|
resources_update_operations = [
|
|
{"desc": "add volume_type to volume",
|
|
"type": "update_attribute_type",
|
|
"resource_type": "volume",
|
|
"data": [{
|
|
"op": "add",
|
|
"path": "/attributes/volume_type",
|
|
"value": {"type": "string", "min_length": 0, "max_length": 255,
|
|
"required": False}
|
|
}]},
|
|
{"desc": "add flavor_name to instance",
|
|
"type": "update_attribute_type",
|
|
"resource_type": "instance",
|
|
"data": [{
|
|
"op": "add",
|
|
"path": "/attributes/flavor_name",
|
|
"value": {"type": "string", "min_length": 0, "max_length": 255,
|
|
"required": True, "options": {'fill': ''}}
|
|
}]},
|
|
{"desc": "add nova_compute resource type",
|
|
"type": "create_resource_type",
|
|
"resource_type": "nova_compute",
|
|
"data": [{
|
|
"attributes": {"host_name": {"type": "string", "min_length": 0,
|
|
"max_length": 255, "required": True}}
|
|
}]},
|
|
{"desc": "add manila share type",
|
|
"type": "create_resource_type",
|
|
"resource_type": "manila_share",
|
|
"data": [{
|
|
"attributes": {"name": {"type": "string", "min_length": 0,
|
|
"max_length": 255, "required": False},
|
|
"host": {"type": "string", "min_length": 0,
|
|
"max_length": 255, "required": True},
|
|
"protocol": {"type": "string", "min_length": 0,
|
|
"max_length": 255, "required": False},
|
|
"availability_zone": {"type": "string",
|
|
"min_length": 0,
|
|
"max_length": 255,
|
|
"required": False},
|
|
"status": {"type": "string", "min_length": 0,
|
|
"max_length": 255,
|
|
"required": True}}
|
|
}]},
|
|
{"desc": "add switch resource type",
|
|
"type": "create_resource_type",
|
|
"resource_type": "switch",
|
|
"data": [{
|
|
"attributes": {"controller": {"type": "string", "min_length": 0,
|
|
"max_length": 255, "required": True}}
|
|
}]},
|
|
{"desc": "add switch_port resource type",
|
|
"type": "create_resource_type",
|
|
"resource_type": "switch_port",
|
|
"data": [{
|
|
"attributes": {"switch": {"type": "string", "min_length": 0,
|
|
"max_length": 64, "required": True},
|
|
"port_number_on_switch": {"type": "number", "min": 0,
|
|
"max": 4294967295,
|
|
"required": False},
|
|
"neutron_port_id": {"type": "string",
|
|
"min_length": 0,
|
|
"max_length": 255,
|
|
"required": False},
|
|
"controller": {"type": "string", "min_length": 0,
|
|
"max_length": 255, "required": True}}
|
|
}]},
|
|
{"desc": "add port resource type",
|
|
"type": "create_resource_type",
|
|
"resource_type": "port",
|
|
"data": [{
|
|
"attributes": {"controller": {"type": "string", "min_length": 0,
|
|
"max_length": 255, "required": True}}
|
|
}]},
|
|
{"desc": "add switch_table resource type",
|
|
"type": "create_resource_type",
|
|
"resource_type": "switch_table",
|
|
"data": [{
|
|
"attributes": {"switch": {"type": "string", "min_length": 0,
|
|
"max_length": 64, "required": True},
|
|
"controller": {"type": "string", "min_length": 0,
|
|
"max_length": 255, "required": True}}
|
|
}]},
|
|
{"desc": "add volume provider resource type",
|
|
"type": "create_resource_type",
|
|
"resource_type": "volume_provider",
|
|
"data": [{
|
|
"attributes": {}
|
|
}]},
|
|
{"desc": "add volume provider pool resource type",
|
|
"type": "create_resource_type",
|
|
"resource_type": "volume_provider_pool",
|
|
"data": [{
|
|
"attributes": {"provider": {"type": "string", "min_length": 0,
|
|
"max_length": 255, "required": True}}
|
|
}]},
|
|
{"desc": "add ipmi sensor resource type",
|
|
"type": "create_resource_type",
|
|
"resource_type": "ipmi_sensor",
|
|
"data": [{
|
|
"attributes": {"node": {"type": "string", "min_length": 0,
|
|
"max_length": 255, "required": True}}
|
|
}]},
|
|
{"desc": "add launched_at to instance",
|
|
"type": "update_attribute_type",
|
|
"resource_type": "instance",
|
|
"data": [
|
|
{"op": "add", "path": "/attributes/launched_at",
|
|
"value": {"type": "datetime", "required": False}},
|
|
{"op": "add", "path": "/attributes/created_at",
|
|
"value": {"type": "datetime", "required": False}},
|
|
{"op": "add", "path": "/attributes/deleted_at",
|
|
"value": {"type": "datetime", "required": False}},
|
|
]},
|
|
{"desc": "add instance_id/image_id to volume",
|
|
"type": "update_attribute_type",
|
|
"resource_type": "volume",
|
|
"data": [
|
|
{"op": "add", "path": "/attributes/image_id",
|
|
"value": {"type": "uuid", "required": False}},
|
|
{"op": "add", "path": "/attributes/instance_id",
|
|
"value": {"type": "uuid", "required": False}},
|
|
]},
|
|
{"desc": "add availability_zone to instance",
|
|
"type": "update_attribute_type",
|
|
"resource_type": "instance",
|
|
"data": [{
|
|
"op": "add",
|
|
"path": "/attributes/availability_zone",
|
|
"value": {"type": "string", "min_length": 0, "max_length": 255,
|
|
"required": False}
|
|
}]},
|
|
]
|
|
|
|
# NOTE(sileht): We use LooseVersion because pbr can generate invalid
|
|
# StrictVersion like 9.0.1.dev226
|
|
REQUIRED_VERSION = version.LooseVersion("4.2.0")
|
|
|
|
|
|
def upgrade_resource_types(conf):
|
|
gnocchi = get_gnocchiclient(conf)
|
|
|
|
gnocchi_version = version.LooseVersion(gnocchi.build.get())
|
|
if gnocchi_version < REQUIRED_VERSION:
|
|
raise Exception("required gnocchi version is %s, got %s",
|
|
REQUIRED_VERSION, gnocchi_version)
|
|
|
|
for name, attributes in resources_initial.items():
|
|
try:
|
|
gnocchi.resource_type.get(name=name)
|
|
except gnocchi_exc.ResourceTypeNotFound:
|
|
rt = {'name': name, 'attributes': attributes}
|
|
gnocchi.resource_type.create(resource_type=rt)
|
|
|
|
for ops in resources_update_operations:
|
|
if ops['type'] == 'update_attribute_type':
|
|
rt = gnocchi.resource_type.get(name=ops['resource_type'])
|
|
first_op = ops['data'][0]
|
|
attrib = first_op['path'].replace('/attributes', '')
|
|
if first_op['op'] == 'add' and attrib in rt['attributes']:
|
|
continue
|
|
if first_op['op'] == 'remove' and attrib not in rt['attributes']:
|
|
continue
|
|
gnocchi.resource_type.update(ops['resource_type'], ops['data'])
|
|
elif ops['type'] == 'create_resource_type':
|
|
try:
|
|
gnocchi.resource_type.get(name=ops['resource_type'])
|
|
except gnocchi_exc.ResourceTypeNotFound:
|
|
rt = {'name': ops['resource_type'],
|
|
'attributes': ops['data'][0]['attributes']}
|
|
gnocchi.resource_type.create(resource_type=rt)
|