Linux lhjmq-records 5.15.0-118-generic #128-Ubuntu SMP Fri Jul 5 09:28:59 UTC 2024 x86_64
Your IP : 18.223.210.196
# LivePatchSocket.py
# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*-
#
# Copyright (c) 2017 Canonical
#
# Author: Andrea Azzarone <andrea.azzarone@canonical.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
from gi.repository import GLib
import http.client
import socket
import threading
import yaml
HOST_NAME = '/var/snap/canonical-livepatch/current/livepatchd.sock'
class UHTTPConnection(http.client.HTTPConnection):
def __init__(self, path):
http.client.HTTPConnection.__init__(self, 'localhost')
self.path = path
def connect(self):
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect(self.path)
self.sock = sock
class LivePatchSocket(object):
def __init__(self, http_conn=None):
if http_conn is None:
self.conn = UHTTPConnection(HOST_NAME)
else:
self.conn = http_conn
def get_status(self, on_done):
def do_call():
try:
self.conn.request('GET', '/status?verbose=True')
r = self.conn.getresponse()
active = r.status == 200
data = yaml.safe_load(r.read())
except Exception:
active = False
data = dict()
check_state = LivePatchSocket.get_check_state(data)
patch_state = LivePatchSocket.get_patch_state(data)
fixes = LivePatchSocket.get_fixes(data)
GLib.idle_add(lambda: on_done(
active, check_state, patch_state, fixes))
thread = threading.Thread(target=do_call)
thread.start()
@staticmethod
def get_check_state(data):
try:
status = data['status']
kernel = next((k for k in status if k['running']), None)
return kernel['livepatch']['checkState']
except Exception:
return 'check-failed'
@staticmethod
def get_patch_state(data):
try:
status = data['status']
kernel = next((k for k in status if k['running']), None)
return kernel['livepatch']['patchState']
except Exception:
return 'unknown'
@staticmethod
def get_fixes(data):
try:
status = data['status']
kernel = next((k for k in status if k['running']), None)
fixes = kernel['livepatch']['fixes']
return [LivePatchFix(f)
for f in fixes.replace('* ', '').split('\n') if len(f) > 0]
except Exception:
return list()
class LivePatchFix(object):
def __init__(self, text):
patched_pattern = ' (unpatched)'
self.patched = text.find(patched_pattern) == -1
self.name = text.replace(patched_pattern, '')
def __eq__(self, other):
if isinstance(other, LivePatchFix):
return self.name == other.name and self.patched == other.patched
return NotImplemented
def __ne__(self, other):
result = self.__eq__(other)
if result is NotImplemented:
return result
return not result
|