57610fce4b
the host names in them are not necessarily the same, and Masakari service itself validates the input against the nova service list, not hypervisor list, since change I9c591d33f17a8d5950bdb1fc2d686e2301fc6d95 in Masakari. Closes-Bug: #1944679 Change-Id: Id017b91c59aff54435c35d410fcb56a086a732ef (cherry picked from commit021d1c184e
) (cherry picked from commitfae46199bb
) (cherry picked from commita879b6bbfb
)
238 lines
8.0 KiB
Python
238 lines
8.0 KiB
Python
# Copyright (C) 2018 NTT DATA
|
|
# 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 itertools
|
|
|
|
from django.conf import settings
|
|
from django.utils.translation import ugettext_lazy as _
|
|
|
|
from horizon.utils import functions as utils
|
|
from horizon.utils import memoized
|
|
from keystoneauth1.identity.generic import token
|
|
from keystoneauth1 import session as ks_session
|
|
from masakariclient import api_versions
|
|
from masakariclient import plugin
|
|
from openstack import connection
|
|
from openstack_dashboard.api import nova as nova_api
|
|
|
|
from masakaridashboard.handle_errors import handle_errors
|
|
|
|
MICROVERSION_FEATURES = {"recovery_workflow_details": ["1.1"]}
|
|
|
|
|
|
@memoized.memoized
|
|
def openstack_connection(request, version=None):
|
|
interface = getattr(settings, 'OPENSTACK_ENDPOINT_TYPE', 'publicURL')
|
|
|
|
auth = token.Token(
|
|
auth_url=getattr(settings, 'OPENSTACK_KEYSTONE_URL'),
|
|
token=request.user.token.id,
|
|
project_name=request.user.project_name,
|
|
project_id=request.user.tenant_id)
|
|
cacert = getattr(settings, 'OPENSTACK_SSL_CACERT')
|
|
session = ks_session.Session(auth=auth, verify=cacert or True)
|
|
conn = connection.Connection(session=session,
|
|
interface=interface,
|
|
ha_api_version=version)
|
|
|
|
return conn.instance_ha
|
|
|
|
|
|
def get_compute_service_list(request):
|
|
return nova_api.service_list(request, binary="nova-compute")
|
|
|
|
|
|
@handle_errors(_("Unable to retrieve segments"), [])
|
|
def get_segment_list(request, marker='', paginate=False, filters=None):
|
|
"""Returns segments as per page size."""
|
|
page_size = utils.get_page_size(request)
|
|
client = openstack_connection(request)
|
|
kwargs = get_request_param(marker, paginate, filters, page_size)
|
|
entities_iter = client.segments(**kwargs)
|
|
has_prev_data = has_more_data = False
|
|
if paginate:
|
|
entities, has_more_data, has_prev_data = pagination_process(
|
|
entities_iter, kwargs['limit'], page_size, marker)
|
|
else:
|
|
entities = list(entities_iter)
|
|
|
|
return entities, has_more_data, has_prev_data
|
|
|
|
|
|
def get_request_param(marker, paginate, filters, page_size):
|
|
limit = getattr(settings, 'API_RESULT_LIMIT', 100)
|
|
|
|
if paginate:
|
|
request_size = page_size + 1
|
|
else:
|
|
request_size = limit
|
|
|
|
kwargs = {"marker": marker,
|
|
"limit": request_size
|
|
}
|
|
if filters is not None:
|
|
kwargs.update(filters)
|
|
return kwargs
|
|
|
|
|
|
def pagination_process(data, request_size, page_size, marker):
|
|
"""Retrieve a listing of specific entity and handles pagination.
|
|
|
|
:param request: Request data
|
|
:param marker: Pagination marker for large data sets: entity id
|
|
:param paginate: If true will perform pagination based on settings.
|
|
Default:False
|
|
"""
|
|
prev_data = more_data = False
|
|
entities = list(itertools.islice(data, request_size))
|
|
# first and middle page condition
|
|
if len(entities) > page_size:
|
|
entities.pop()
|
|
more_data = True
|
|
# middle page condition
|
|
if marker is not None:
|
|
prev_data = True
|
|
elif marker is not None:
|
|
prev_data = True
|
|
|
|
return entities, more_data, prev_data
|
|
|
|
|
|
@handle_errors(_("Unable to retrieve segments"), [])
|
|
def segment_list(request):
|
|
return list(openstack_connection(request).segments())
|
|
|
|
|
|
def segment_create(request, data):
|
|
"""Create segment."""
|
|
return openstack_connection(request).create_segment(**data)
|
|
|
|
|
|
@handle_errors(_("Unable to retrieve segment"), [])
|
|
def get_segment(request, segment_id):
|
|
"""Returns segment by id"""
|
|
return openstack_connection(request).get_segment(segment_id)
|
|
|
|
|
|
@handle_errors(_("Unable to delete segment"), [])
|
|
def segment_delete(request, segment_id, ignore_missing=True):
|
|
return openstack_connection(request).delete_segment(
|
|
segment_id, ignore_missing)
|
|
|
|
|
|
@handle_errors(_("Unable to update segment"), [])
|
|
def segment_update(request, segment_id, fields_to_update):
|
|
"""Update segment."""
|
|
return openstack_connection(request).update_segment(
|
|
segment_id, **fields_to_update)
|
|
|
|
|
|
def create_host(request, data):
|
|
"""Create Host."""
|
|
attrs = {'name': data['name'],
|
|
'reserved': data['reserved'],
|
|
'type': data['type'],
|
|
'control_attributes': data['control_attributes'],
|
|
'on_maintenance': data['on_maintenance']}
|
|
|
|
return openstack_connection(request).create_host(
|
|
data['segment_id'], **attrs)
|
|
|
|
|
|
@handle_errors(_("Unable to get host list"), [])
|
|
def get_host_list(request, segment_id, filters):
|
|
"""Returns host list."""
|
|
return openstack_connection(request).hosts(segment_id, **filters)
|
|
|
|
|
|
def delete_host(request, host_id, segment_id):
|
|
return openstack_connection(request).delete_host(
|
|
host_id, segment_id, False)
|
|
|
|
|
|
def update_host(request, host_uuid, failover_segment_id, fields_to_update):
|
|
return openstack_connection(request).update_host(
|
|
host_uuid, failover_segment_id, **fields_to_update)
|
|
|
|
|
|
def get_host(request, host_id, segment_id):
|
|
"""return single host """
|
|
return openstack_connection(request).get_host(host_id, segment_id)
|
|
|
|
|
|
def notification_list(request, filters=None, marker='', paginate=False):
|
|
"""return notifications list """
|
|
page_size = utils.get_page_size(request)
|
|
kwargs = get_request_param(marker, paginate, filters, page_size)
|
|
entities_iter = openstack_connection(request).notifications(**kwargs)
|
|
has_prev_data = has_more_data = False
|
|
if paginate:
|
|
entities, has_more_data, has_prev_data = pagination_process(
|
|
entities_iter, kwargs['limit'], page_size, marker)
|
|
else:
|
|
entities = list(entities_iter)
|
|
|
|
return entities, has_more_data, has_prev_data
|
|
|
|
|
|
def get_notification(request, notification_id):
|
|
"""return single notifications"""
|
|
return openstack_connection(request).get_notification(notification_id)
|
|
|
|
|
|
def get_requested_versions(features):
|
|
if not features:
|
|
return None
|
|
# Convert a single feature string into a list for backward compatibility.
|
|
if isinstance(features, str):
|
|
features = [features]
|
|
service_features = MICROVERSION_FEATURES
|
|
feature_versions = set(service_features[features[0]])
|
|
for feature in features[1:]:
|
|
feature_versions &= set(service_features[feature])
|
|
if not feature_versions:
|
|
return None
|
|
# Sort version candidates from larger versins
|
|
feature_versions = sorted(feature_versions, reverse=True,
|
|
key=lambda v: [int(i) for i in v.split('.')])
|
|
return feature_versions
|
|
|
|
|
|
def get_microversion_for_features(features, wrapper_class, min_ver, max_ver):
|
|
"""Retrieves that highest known functional microversion for features"""
|
|
feature_versions = get_requested_versions(features)
|
|
if not feature_versions:
|
|
return None
|
|
for version in feature_versions:
|
|
microversion = wrapper_class(version)
|
|
if microversion.matches(min_ver, max_ver):
|
|
return microversion
|
|
return None
|
|
|
|
|
|
@memoized.memoized
|
|
def get_microversion(features):
|
|
min_ver = api_versions.APIVersion(plugin.SUPPORTED_VERSIONS[1])
|
|
max_ver = api_versions.APIVersion(plugin.SUPPORTED_VERSIONS[-1])
|
|
return (get_microversion_for_features(
|
|
features, api_versions.APIVersion, min_ver, max_ver))
|
|
|
|
|
|
def get_notification_with_progress_details(request, notification_id):
|
|
microversion = get_microversion("recovery_workflow_details")
|
|
return openstack_connection(
|
|
request, version=microversion.get_string()).get_notification(
|
|
notification_id)
|