#!/usr/bin/env python3 # Copyright 2016 Red Hat, Inc. # # 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 socket import sys import os import os.path import json server_address = "/tmp/openstack.sock" sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) try: sock.connect(server_address) except socket.error as msg: print(msg, file=sys.stderr) sys.exit(1) def send(sock, doc): jdoc = json.dumps(doc) sock.send(b'%d\n' % len(jdoc)) sock.sendall(jdoc.encode('utf-8')) def recv(sock): length_str = b'' char = sock.recv(1) if len(char) == 0: print("Unexpected end of file", file=sys.stderr) sys.exit(1) while char != b'\n': length_str += char char = sock.recv(1) if len(char) == 0: print("Unexpected end of file", file=sys.stderr) sys.exit(1) total = int(length_str) # use a memoryview to receive the data chunk by chunk efficiently jdoc = memoryview(bytearray(total)) next_offset = 0 while total - next_offset > 0: recv_size = sock.recv_into(jdoc[next_offset:], total - next_offset) next_offset += recv_size try: doc = json.loads(jdoc.tobytes()) except (TypeError, ValueError) as e: raise Exception('Data received was not in JSON format') return doc try: env = {} passenv = ["CINDER_VERSION", "OS_AUTH_URL", "OS_NO_CACHE", "OS_PASSWORD", "OS_PROJECT_NAME", "OS_REGION_NAME", "OS_TENANT_NAME", "OS_USERNAME", "OS_VOLUME_API_VERSION", "OS_CLOUD"] for name in passenv: if name in os.environ: env[name] = os.environ[name] cmd = { "app": os.path.basename(sys.argv[0]), "env": env, "argv": sys.argv[1:] } try: image_idx = sys.argv.index('image') create_idx = sys.argv.index('create') missing_file = image_idx < create_idx and \ not any(x.startswith('--file') for x in sys.argv) except ValueError: missing_file = False if missing_file: # This means we were called with an image create command, but were # not provided a --file option. That likely means we're being passed # the image data to stdin, which won't work because we do not proxy # stdin to the server. So, we just reject the operation and ask the # caller to provide the file with --file instead. # We've already connected to the server, we need to send it some dummy # data so it doesn't wait forever. send(sock, {}) print('Image create without --file is not allowed in server mode', file=sys.stderr) sys.exit(1) else: send(sock, cmd) doc = recv(sock) if doc["stdout"] != b'': print(doc["stdout"], end='') if doc["stderr"] != b'': print(doc["stderr"], file=sys.stderr) sys.exit(doc["status"]) finally: sock.close()