
The purpose of this patch set is to provide the end users with the following functionalities: 1. Create volume metadata for a given volume. 2. Get the list of metadata for a given volume. 3. Update a given volume's metadata. 4. Delete an existing metadata of a given volume. Change-Id: Id10eb6b9b68fcb2c496d1e8fa4fecec3c8d613d8
191 lines
5.1 KiB
Python
191 lines
5.1 KiB
Python
# Copyright 2015 Huawei Technologies Co., Ltd.
|
|
# 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 urllib
|
|
import urlparse
|
|
|
|
from requests import Request
|
|
from requests import Session
|
|
|
|
from oslo_log import log as logging
|
|
|
|
from tricircle.common import client
|
|
from tricircle.common import constants as cons
|
|
from tricircle.common.i18n import _LE
|
|
from tricircle.common import utils
|
|
from tricircle.db import api as db_api
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
# the url could be endpoint registered in the keystone
|
|
# or url sent to tricircle service, which is stored in
|
|
# pecan.request.url
|
|
def get_version_from_url(url):
|
|
|
|
components = urlparse.urlsplit(url)
|
|
|
|
path = components.path
|
|
pos = path.find('/')
|
|
|
|
ver = ''
|
|
if pos == 0:
|
|
path = path[1:]
|
|
i = path.find('/')
|
|
if i >= 0:
|
|
ver = path[:i]
|
|
else:
|
|
ver = path
|
|
elif pos > 0:
|
|
ver = path[:pos]
|
|
else:
|
|
ver = path
|
|
|
|
return ver
|
|
|
|
|
|
def get_bottom_url(t_ver, t_url, b_ver, b_endpoint):
|
|
"""get_bottom_url
|
|
|
|
convert url received by Tricircle service to bottom OpenStack
|
|
request url through the configured endpoint in the KeyStone
|
|
|
|
:param t_ver: version of top service
|
|
:param t_url: request url to the top service
|
|
:param b_ver: version of bottom service
|
|
:param b_endpoint: endpoint registered in keystone for bottom service
|
|
:return: request url to bottom service
|
|
"""
|
|
t_parse = urlparse.urlsplit(t_url)
|
|
|
|
after_ver = t_parse.path
|
|
|
|
remove_ver = '/' + t_ver + '/'
|
|
pos = after_ver.find(remove_ver)
|
|
|
|
if pos == 0:
|
|
after_ver = after_ver[len(remove_ver):]
|
|
else:
|
|
remove_ver = t_ver + '/'
|
|
pos = after_ver.find(remove_ver)
|
|
if pos == 0:
|
|
after_ver = after_ver[len(remove_ver):]
|
|
|
|
if after_ver == t_parse.path:
|
|
# wrong t_url
|
|
return ''
|
|
|
|
b_parse = urlparse.urlsplit(b_endpoint)
|
|
|
|
scheme = b_parse.scheme
|
|
netloc = b_parse.netloc
|
|
path = '/' + b_ver + '/' + after_ver
|
|
if b_ver == '':
|
|
path = '/' + after_ver
|
|
|
|
# Remove availability_zone filter since it is handled by VolumeController.
|
|
# VolumeController will send GET request only to bottom pods whose AZ
|
|
# is specified in availability_zone filter.
|
|
query_filters = []
|
|
for k, v in urlparse.parse_qsl(t_parse.query):
|
|
if k == 'availability_zone':
|
|
continue
|
|
query_filters.append((k, v))
|
|
query = urllib.urlencode(query_filters)
|
|
|
|
fragment = t_parse.fragment
|
|
|
|
b_url = urlparse.urlunsplit((scheme,
|
|
netloc,
|
|
path,
|
|
query,
|
|
fragment))
|
|
return b_url
|
|
|
|
|
|
def get_pod_service_endpoint(context, pod_name, st):
|
|
|
|
pod = db_api.get_pod_by_name(context, pod_name)
|
|
|
|
if pod:
|
|
c = client.Client()
|
|
return c.get_endpoint(context, pod['pod_id'], st)
|
|
|
|
return ''
|
|
|
|
|
|
def get_pod_service_ctx(context, t_url, pod_name, s_type=cons.ST_NOVA):
|
|
t_ver = get_version_from_url(t_url)
|
|
b_endpoint = get_pod_service_endpoint(context,
|
|
pod_name,
|
|
s_type)
|
|
b_ver = get_version_from_url(b_endpoint)
|
|
b_url = ''
|
|
if b_endpoint != '':
|
|
b_url = get_bottom_url(t_ver, t_url, b_ver, b_endpoint)
|
|
|
|
return {'t_ver': t_ver, 'b_ver': b_ver,
|
|
't_url': t_url, 'b_url': b_url}
|
|
|
|
|
|
def forward_req(context, action, b_headers, b_url, b_body):
|
|
s = Session()
|
|
req = Request(action, b_url,
|
|
data=b_body,
|
|
headers=b_headers)
|
|
prepped = req.prepare()
|
|
|
|
# do something with prepped.body
|
|
# do something with prepped.headers
|
|
resp = s.send(prepped,
|
|
timeout=60)
|
|
|
|
return resp
|
|
|
|
|
|
def get_res_routing_ref(context, _id, t_url, s_type):
|
|
"""Get the service context according to resource routing.
|
|
|
|
:param _id: the top id of resource
|
|
:param t_url: request url
|
|
:param s_type: service type
|
|
:returns: service context
|
|
"""
|
|
pod = utils.get_pod_by_top_id(context, _id)
|
|
|
|
if not pod:
|
|
return None
|
|
|
|
pod_name = pod['pod_name']
|
|
|
|
s_ctx = get_pod_service_ctx(context, t_url, pod_name,
|
|
s_type=s_type)
|
|
|
|
if s_ctx['b_url'] == '':
|
|
LOG.error(_LE("bottom pod endpoint incorrect %s") %
|
|
pod_name)
|
|
|
|
return s_ctx
|
|
|
|
|
|
def convert_header(from_release, to_release, header):
|
|
return header
|
|
|
|
|
|
def convert_object(from_release, to_release, res_object,
|
|
res_type=cons.RT_VOLUME):
|
|
return res_object
|