blob: ef05f1b84166f329d86c8128333915ade1f4ce61 [file] [log] [blame]
Ben Nemec9a973262019-08-12 20:10:49 +00001#!/usr/bin/env python3
2# Copyright 2016 Red Hat, Inc.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16import socket
17import sys
18import os
19import os.path
20import json
21
22server_address = "/tmp/openstack.sock"
23
24sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
25
26try:
27 sock.connect(server_address)
28except socket.error as msg:
29 print(msg, file=sys.stderr)
30 sys.exit(1)
31
32
33def send(sock, doc):
34 jdoc = json.dumps(doc)
35 sock.send(b'%d\n' % len(jdoc))
36 sock.sendall(jdoc.encode('utf-8'))
37
38def recv(sock):
39 length_str = b''
40
41 char = sock.recv(1)
42 if len(char) == 0:
43 print("Unexpected end of file", file=sys.stderr)
44 sys.exit(1)
45
46 while char != b'\n':
47 length_str += char
48 char = sock.recv(1)
49 if len(char) == 0:
50 print("Unexpected end of file", file=sys.stderr)
51 sys.exit(1)
52
53 total = int(length_str)
54
55 # use a memoryview to receive the data chunk by chunk efficiently
56 jdoc = memoryview(bytearray(total))
57 next_offset = 0
58 while total - next_offset > 0:
59 recv_size = sock.recv_into(jdoc[next_offset:], total - next_offset)
60 next_offset += recv_size
61 try:
62 doc = json.loads(jdoc.tobytes())
63 except (TypeError, ValueError) as e:
64 raise Exception('Data received was not in JSON format')
65 return doc
66
67try:
68 env = {}
69 passenv = ["CINDER_VERSION",
70 "OS_AUTH_URL",
71 "OS_IDENTITY_API_VERSION",
72 "OS_NO_CACHE",
73 "OS_PASSWORD",
74 "OS_PROJECT_NAME",
75 "OS_REGION_NAME",
76 "OS_TENANT_NAME",
77 "OS_USERNAME",
78 "OS_VOLUME_API_VERSION",
79 "OS_CLOUD"]
80 for name in passenv:
81 if name in os.environ:
82 env[name] = os.environ[name]
83
84 cmd = {
85 "app": os.path.basename(sys.argv[0]),
86 "env": env,
87 "argv": sys.argv[1:]
88 }
89 try:
90 image_idx = sys.argv.index('image')
91 create_idx = sys.argv.index('create')
92 missing_file = image_idx < create_idx and \
93 not any(x.startswith('--file') for x in sys.argv)
94 except ValueError:
95 missing_file = False
96
97 if missing_file:
98 # This means we were called with an image create command, but were
99 # not provided a --file option. That likely means we're being passed
100 # the image data to stdin, which won't work because we do not proxy
101 # stdin to the server. So, we just reject the operation and ask the
102 # caller to provide the file with --file instead.
103 # We've already connected to the server, we need to send it some dummy
104 # data so it doesn't wait forever.
105 send(sock, {})
106 print('Image create without --file is not allowed in server mode',
107 file=sys.stderr)
108 sys.exit(1)
109 else:
110 send(sock, cmd)
111
112 doc = recv(sock)
113 if doc["stdout"] != b'':
114 print(doc["stdout"], end='')
115 if doc["stderr"] != b'':
116 print(doc["stderr"], file=sys.stderr)
117 sys.exit(doc["status"])
118finally:
119 sock.close()