gui/cgcs_dashboard/api/patch.py

240 lines
7.0 KiB
Python
Executable File

# 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.
#
# Copyright (c) 2014 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
#
import logging
import urlparse
import requests
from openstack_dashboard.api import base
from requests_toolbelt import MultipartEncoder
LOG = logging.getLogger(__name__)
class Client(object):
def __init__(self, version, url, token_id):
self.version = version
self.url = url
self.token_id = token_id
def _make_request(self, token_id, method, api_version, api_cmd,
encoder=None):
url = self.url
url += "/%s/%s" % (api_version, api_cmd)
# url += "/patch/%s" % (api_cmd)
headers = {"X-Auth-Token": token_id,
"Accept": "application/json"}
if method == 'GET':
req = requests.get(url, headers=headers)
elif method == 'POST':
if encoder is not None:
headers['Content-Type'] = encoder.content_type
req = requests.post(url, headers=headers, data=encoder)
resp = req.json()
return resp
def get_patches(self):
return self._make_request(self.token_id, "GET", self.version,
"query?show=all")
def show_patch(self, patch_id):
return self._make_request(self.token_id, "GET", self.version,
"show/%s" % patch_id)
def get_hosts(self):
return self._make_request(self.token_id, "GET", self.version,
"query_hosts")
def upload(self, file):
encoder = MultipartEncoder(fields=file)
return self._make_request(self.token_id, "POST", self.version,
"upload", encoder=encoder)
def apply(self, patch_ids):
patches = "/".join(patch_ids)
return self._make_request(self.token_id, "POST", self.version,
"apply/%s" % patches)
def remove(self, patch_ids):
patches = "/".join(patch_ids)
return self._make_request(self.token_id, "POST", self.version,
"remove/%s" % patches)
def delete(self, patch_ids):
patches = "/".join(patch_ids)
return self._make_request(self.token_id, "POST", self.version,
"delete/%s" % patches)
def host_install(self, host):
return self._make_request(self.token_id, "POST", self.version,
"host_install/%s" % host)
def host_install_async(self, host):
return self._make_request(self.token_id, "POST", self.version,
"host_install_async/%s" % host)
def _patching_client(request):
o = urlparse.urlparse(base.url_for(request, 'patching'))
url = "://".join((o.scheme, o.netloc))
return Client("v1", url, token_id=request.user.token.id)
class Patch(object):
_attrs = ['status',
'sw_version',
'install_instructions',
'description',
'warnings',
'summary',
'repostate',
'patchstate',
'requires',
'unremovable',
'reboot_required']
class Host(object):
_attrs = ['hostname',
'installed',
'ip',
'missing_pkgs',
'nodetype',
'patch_current',
'patch_failed',
'requires_reboot',
'secs_since_ack',
'stale_details',
'to_remove',
'sw_version',
'state',
'allow_insvc_patching',
'interim_state']
def get_patches(request):
patches = []
try:
info = _patching_client(request).get_patches()
except Exception:
return patches
if info:
for p in info['pd'].iteritems():
patch = Patch()
for a in patch._attrs:
if a == 'requires':
patch.requires = [str(rp) for rp in p[1][a]]
continue
if a == 'reboot_required':
# Default to "N"
setattr(patch, a, str(p[1].get(a, "N")))
continue
# Must handle older patches that have metadata that is missing
# newer attributes. Default missing attributes to "".
setattr(patch, a, str(p[1].get(a, "")))
patch.patch_id = str(p[0])
patches.append(patch)
return patches
def get_patch(request, patch_id):
patches = get_patches(request)
patch = next((p for p in patches if p.patch_id == patch_id), None)
# add on patch contents
data = _patching_client(request).show_patch(patch_id)
patch.contents = [str(pkg) for pkg in data['contents'][patch_id]]
return patch
def get_hosts(request):
hosts = []
try:
info = _patching_client(request).get_hosts()
except Exception:
return hosts
if info:
for h in info['data']:
host = Host()
for a in host._attrs:
setattr(host, a, h[a])
hosts.append(host)
return hosts
def get_host(request, hostname):
phosts = get_hosts(request)
return next((phost for phost in phosts if phost.hostname == hostname),
None)
def get_message(data):
LOG.info("RESPONSE: %s", data)
if not data or ('error' in data and data["error"] != ""):
raise ValueError(data["error"] or "Invalid patch file")
if 'warning' in data and data["warning"] != "":
return data["warning"]
if 'info' in data and data["info"] != "":
return data["info"]
return ""
def upload_patch(request, patchfile, name):
file = {'file': (name, patchfile,)}
resp = _patching_client(request).upload(file)
return get_message(resp)
def patch_apply_req(request, patch_id):
resp = _patching_client(request).apply(patch_id)
return get_message(resp)
def patch_remove_req(request, patch_id):
resp = _patching_client(request).remove(patch_id)
return get_message(resp)
def patch_delete_req(request, patch_id):
resp = _patching_client(request).delete(patch_id)
return get_message(resp)
def host_install(request, hostname):
resp = _patching_client(request).host_install(hostname)
return get_message(resp)
def host_install_async(request, hostname):
resp = _patching_client(request).host_install_async(hostname)
return get_message(resp)