Handle binary userdata files such as gzip
The current code in the servers api assumes only text files will be provided as userdata. That is, the data is utf-8 encoded before it is base64 encoded and sent. This breaks for binary userdata files, (example, gzip files) as they can't be utf-8 encoded. This change ignores specifically the exceptions that are raised when utf-8 encoding is attempted on non-text data: AttributeError and UnicodeDecodeError. These exceptions will be ignored to let binary files proceed to the base64 encoding step. Closes-Bug: #1419859 Change-Id: Ie96283f6ff892ae30485722cf7c3ec40f3f1b5df
This commit is contained in:
parent
3681c186f7
commit
19d4d35a4e
novaclient
@ -12,6 +12,10 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import base64
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
import mock
|
||||
from oslo.serialization import jsonutils
|
||||
import six
|
||||
@ -199,6 +203,32 @@ class ServersTest(utils.FixturedTestCase):
|
||||
self.assert_called('POST', '/servers')
|
||||
self.assertIsInstance(s, servers.Server)
|
||||
|
||||
def test_create_server_userdata_bin(self):
|
||||
with tempfile.TemporaryFile(mode='wb+') as bin_file:
|
||||
original_data = os.urandom(1024)
|
||||
bin_file.write(original_data)
|
||||
bin_file.flush()
|
||||
bin_file.seek(0)
|
||||
s = self.cs.servers.create(
|
||||
name="My server",
|
||||
image=1,
|
||||
flavor=1,
|
||||
meta={'foo': 'bar'},
|
||||
userdata=bin_file,
|
||||
key_name="fakekey",
|
||||
files={
|
||||
'/etc/passwd': 'some data', # a file
|
||||
'/tmp/foo.txt': six.StringIO('data'), # a stream
|
||||
},
|
||||
)
|
||||
self.assert_called('POST', '/servers')
|
||||
self.assertIsInstance(s, servers.Server)
|
||||
# verify userdata matches original
|
||||
body = jsonutils.loads(self.requests.last_request.body)
|
||||
transferred_data = body['server']['user_data']
|
||||
transferred_data = base64.b64decode(transferred_data)
|
||||
self.assertEqual(original_data, transferred_data)
|
||||
|
||||
def _create_disk_config(self, disk_config):
|
||||
s = self.cs.servers.create(
|
||||
name="My server",
|
||||
|
@ -433,10 +433,19 @@ class ServerManager(base.BootingManagerWithFind):
|
||||
if hasattr(userdata, 'read'):
|
||||
userdata = userdata.read()
|
||||
|
||||
# NOTE(melwitt): Text file data is converted to bytes prior to
|
||||
# base64 encoding. The utf-8 encoding will fail for binary files.
|
||||
if six.PY3:
|
||||
userdata = userdata.encode("utf-8")
|
||||
try:
|
||||
userdata = userdata.encode("utf-8")
|
||||
except AttributeError:
|
||||
# In python 3, 'bytes' object has no attribute 'encode'
|
||||
pass
|
||||
else:
|
||||
userdata = encodeutils.safe_encode(userdata)
|
||||
try:
|
||||
userdata = encodeutils.safe_encode(userdata)
|
||||
except UnicodeDecodeError:
|
||||
pass
|
||||
|
||||
userdata_b64 = base64.b64encode(userdata).decode('utf-8')
|
||||
body["server"]["user_data"] = userdata_b64
|
||||
|
Loading…
x
Reference in New Issue
Block a user