Files
deb-nova/nova/api/metadata/password.py
Victor Stinner 67af1eefc5 Port test_metadata to Python 3
* convert_password(): on Python 3, decode password from UTF-8 if it
  is a byte string
* convert_password(): don't modify password in the loop body, use an
  index increased at each iteration. This is a minor cleanup,
  unrelated to Python 3.
* ec2_md_print() now returns byte strings unchanged. On Python 3,
  str(bytes) uses "b'...'" format which is not the expected result
  (or it raises a BytesWarinng exception when using python3 -bb).
* Replace the base64 module with oslo_serialization.base64 to control
  the output type (bytes or text) on Python 2 and Python 3.
* _make_cache_key(): on Python 3, don't encode the host to UTF-8.
  Python 3 requires text.
* MetadataRequestHandler: on Python 3, encode HTTP body to UTF-8 if
  the body type is Unicode.
* test_metadata:

  - encode hmac.new() parameters using encodeutils.to_utf8()
  - use response.text rather than response.body to compare with
    Unicode string
  - use a byte strings for the instance identifier
  - fix some Unicode versus bytes issues

* tests-py3.txt: run test_metadata on Python 3

Co-Authored-By: Davanum Srinivas <davanum@gmail.com>
Co-Authored-By: ChangBo Guo(gcb) <eric.guo@easystack.cn>
Partially-Implements: blueprint goal-python35

Change-Id: Ifb43ce164d9fd80f9f85c95c762d7b010e84dfeb
2016-11-29 11:28:24 +08:00

75 lines
2.3 KiB
Python

# Copyright 2012 Nebula, Inc.
# 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 six
from six.moves import range
from webob import exc
from nova import context
from nova.i18n import _
from nova import objects
from nova import utils
CHUNKS = 4
CHUNK_LENGTH = 255
MAX_SIZE = CHUNKS * CHUNK_LENGTH
def extract_password(instance):
result = ''
sys_meta = utils.instance_sys_meta(instance)
for key in sorted(sys_meta.keys()):
if key.startswith('password_'):
result += sys_meta[key]
return result or None
def convert_password(context, password):
"""Stores password as system_metadata items.
Password is stored with the keys 'password_0' -> 'password_3'.
"""
password = password or ''
if six.PY3 and isinstance(password, bytes):
password = password.decode('utf-8')
meta = {}
for i in range(CHUNKS):
meta['password_%d' % i] = password[:CHUNK_LENGTH]
password = password[CHUNK_LENGTH:]
return meta
def handle_password(req, meta_data):
ctxt = context.get_admin_context()
if req.method == 'GET':
return meta_data.password
elif req.method == 'POST':
# NOTE(vish): The conflict will only happen once the metadata cache
# updates, but it isn't a huge issue if it can be set for
# a short window.
if meta_data.password:
raise exc.HTTPConflict()
if (req.content_length > MAX_SIZE or len(req.body) > MAX_SIZE):
msg = _("Request is too large.")
raise exc.HTTPBadRequest(explanation=msg)
instance = objects.Instance.get_by_uuid(ctxt, meta_data.uuid)
instance.system_metadata.update(convert_password(ctxt, req.body))
instance.save()
else:
raise exc.HTTPBadRequest()