|
83 |
|
83 |
|
84 |
def add_steps(self, steps = 1): |
84 |
def add_steps(self, steps = 1): |
85 |
self._steps += steps |
85 |
self._steps += steps |
86 |
|
|
|
87 |
### mostly copied from app_center/util.py -> should be refactored, see Bug #31059 |
88 |
class UMCConnection(object): |
89 |
def __init__(self, host, username=None, password=None): |
90 |
self._host = host |
91 |
self._headers = { |
92 |
'Content-Type' : 'application/json; charset=UTF-8' |
93 |
} |
94 |
if username is not None: |
95 |
self.auth(username, password) |
96 |
|
97 |
### new method that was not in app_center/util.py |
98 |
@staticmethod |
99 |
def get_machine_connection(): |
100 |
# open a new connection to the master UMC |
101 |
username = '%s$' % ucr.get('hostname') |
102 |
password = '' |
103 |
try: |
104 |
with open('/etc/machine.secret') as machineFile: |
105 |
password = machineFile.readline().strip() |
106 |
except (OSError, IOError) as e: |
107 |
MODULE.error('Could not read /etc/machine.secret: %s' % e) |
108 |
try: |
109 |
connection = UMCConnection(ucr.get('ldap/master')) |
110 |
connection.auth(username, password) |
111 |
return connection |
112 |
except (HTTPException, SocketError) as e: |
113 |
MODULE.error('Could not connect to UMC on %s: %s' % (ucr.get('ldap/master'), e)) |
114 |
return None |
115 |
|
116 |
def get_connection(self): |
117 |
# once keep-alive is over, the socket closes |
118 |
# so create a new connection on every request |
119 |
return HTTPSConnection(self._host) |
120 |
|
121 |
def auth(self, username, password): |
122 |
data = self.build_data({'username' : username, 'password' : password}) |
123 |
con = self.get_connection() |
124 |
try: |
125 |
con.request('POST', '/umcp/auth', data) |
126 |
except Exception as e: |
127 |
# probably unreachable |
128 |
MODULE.warn(str(e)) |
129 |
error_message = '%s: Authentication failed while contacting: %s' % (self._host, e) |
130 |
raise HTTPException(error_message) |
131 |
else: |
132 |
try: |
133 |
response = con.getresponse() |
134 |
cookie = response.getheader('set-cookie') |
135 |
if cookie is None: |
136 |
raise ValueError('No cookie') |
137 |
self._headers['Cookie'] = cookie |
138 |
except Exception as e: |
139 |
MODULE.warn(str(e)) |
140 |
error_message = '%s: Authentication failed: %s' % (self._host, response.read()) |
141 |
raise HTTPException(error_message) |
142 |
|
143 |
def build_data(self, data, flavor=None): |
144 |
data = {'options' : data} |
145 |
if flavor: |
146 |
data['flavor'] = flavor |
147 |
return dumps(data) |
148 |
|
149 |
def request(self, url, data=None, flavor=None): |
150 |
if data is None: |
151 |
data = {} |
152 |
data = self.build_data(data, flavor) |
153 |
con = self.get_connection() |
154 |
con.request('POST', '/umcp/command/%s' % url, data, headers=self._headers) |
155 |
response = con.getresponse() |
156 |
if response.status != 200: |
157 |
error_message = '%s on %s (%s): %s' % (response.status, self._host, url, response.read()) |
158 |
if response.status == 403: |
159 |
# 403 is either command is unknown |
160 |
# or command is known but forbidden |
161 |
# as the user was allowed to invoke the same command |
162 |
# on the local host, it means that the command |
163 |
# is unknown (older app center) |
164 |
MODULE.warn(error_message) |
165 |
raise NotImplementedError('command forbidden: %s' % url) |
166 |
raise HTTPException(error_message) |
167 |
content = response.read() |
168 |
return loads(content)['result'] |
169 |
|