|  | #!/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() |