mirror of
https://github.com/openembedded/meta-openembedded.git
synced 2026-07-27 07:57:27 +00:00
python3-pykickstart: add recipe 2.35
Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com> Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
This commit is contained in:
+151
@@ -0,0 +1,151 @@
|
|||||||
|
From d0d8890b5ef74c315381c9e1cff4b1d32892116b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Hongxu Jia <hongxu.jia@windriver.com>
|
||||||
|
Date: Thu, 1 Jun 2017 15:07:36 +0800
|
||||||
|
Subject: [PATCH 1/4] support authentication for kickstart
|
||||||
|
|
||||||
|
While download kickstart file from web server,
|
||||||
|
we support basic/digest authentication.
|
||||||
|
|
||||||
|
Add KickstartAuthError to report authentication failure,
|
||||||
|
which the invoker could parse this specific error.
|
||||||
|
|
||||||
|
Upstream-Status: inappropriate [oe specific]
|
||||||
|
|
||||||
|
Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
|
||||||
|
---
|
||||||
|
pykickstart/errors.py | 19 +++++++++++++++++++
|
||||||
|
pykickstart/load.py | 32 +++++++++++++++++++++++++++-----
|
||||||
|
pykickstart/parser.py | 4 ++--
|
||||||
|
3 files changed, 48 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/pykickstart/errors.py b/pykickstart/errors.py
|
||||||
|
index b76e84c..fd81bc8 100644
|
||||||
|
--- a/pykickstart/errors.py
|
||||||
|
+++ b/pykickstart/errors.py
|
||||||
|
@@ -35,6 +35,10 @@ It also exports several exception classes:
|
||||||
|
|
||||||
|
KickstartVersionError - An exception for errors relating to unsupported
|
||||||
|
syntax versions.
|
||||||
|
+
|
||||||
|
+ KickstartAuthError - An exception for errors relating to authentication
|
||||||
|
+ failed while downloading kickstart from web server
|
||||||
|
+
|
||||||
|
"""
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
@@ -103,3 +107,18 @@ class KickstartVersionError(KickstartError):
|
||||||
|
|
||||||
|
def __str__ (self):
|
||||||
|
return self.value
|
||||||
|
+
|
||||||
|
+class KickstartAuthError(KickstartError):
|
||||||
|
+ """An exception for errors relating to authentication failed while
|
||||||
|
+ downloading kickstart from web server
|
||||||
|
+ """
|
||||||
|
+ def __init__(self, msg):
|
||||||
|
+ """Create a new KickstartAuthError exception instance with the
|
||||||
|
+ descriptive message val. val should be the return value of
|
||||||
|
+ formatErrorMsg.
|
||||||
|
+ """
|
||||||
|
+ KickstartError.__init__(self, msg)
|
||||||
|
+
|
||||||
|
+ def __str__(self):
|
||||||
|
+ return self.value
|
||||||
|
+
|
||||||
|
diff --git a/pykickstart/load.py b/pykickstart/load.py
|
||||||
|
index 1f69b9c..0f5741b 100644
|
||||||
|
--- a/pykickstart/load.py
|
||||||
|
+++ b/pykickstart/load.py
|
||||||
|
@@ -18,10 +18,13 @@
|
||||||
|
# with the express permission of Red Hat, Inc.
|
||||||
|
#
|
||||||
|
import requests
|
||||||
|
+from requests.auth import HTTPDigestAuth
|
||||||
|
+from requests.auth import HTTPBasicAuth
|
||||||
|
+
|
||||||
|
import shutil
|
||||||
|
import six
|
||||||
|
|
||||||
|
-from pykickstart.errors import KickstartError
|
||||||
|
+from pykickstart.errors import KickstartError, KickstartAuthError
|
||||||
|
from pykickstart.i18n import _
|
||||||
|
from requests.exceptions import SSLError, RequestException
|
||||||
|
|
||||||
|
@@ -29,7 +32,7 @@ _is_url = lambda location: '://' in location # RFC 3986
|
||||||
|
|
||||||
|
SSL_VERIFY = True
|
||||||
|
|
||||||
|
-def load_to_str(location):
|
||||||
|
+def load_to_str(location, user=None, passwd=None):
|
||||||
|
'''Load a destination URL or file into a string.
|
||||||
|
Type of input is inferred automatically.
|
||||||
|
|
||||||
|
@@ -40,7 +43,7 @@ def load_to_str(location):
|
||||||
|
Raises: KickstartError on error reading'''
|
||||||
|
|
||||||
|
if _is_url(location):
|
||||||
|
- return _load_url(location)
|
||||||
|
+ return _load_url(location, user=user, passwd=passwd)
|
||||||
|
else:
|
||||||
|
return _load_file(location)
|
||||||
|
|
||||||
|
@@ -71,13 +74,32 @@ def load_to_file(location, destination):
|
||||||
|
_copy_file(location, destination)
|
||||||
|
return destination
|
||||||
|
|
||||||
|
+def _get_auth(location, user=None, passwd=None):
|
||||||
|
+
|
||||||
|
+ auth = None
|
||||||
|
+ request = requests.get(location, verify=SSL_VERIFY)
|
||||||
|
+ if request.status_code == requests.codes.unauthorized:
|
||||||
|
+ if user is None or passwd is None:
|
||||||
|
+ log.info("Require Authentication")
|
||||||
|
+ raise KickstartAuthError("Require Authentication.\nAppend 'ksuser=<username> kspasswd=<password>' to boot command")
|
||||||
|
|
||||||
|
+ reasons = request.headers.get("WWW-Authenticate", "").split()
|
||||||
|
+ if reasons:
|
||||||
|
+ auth_type = reasons[0]
|
||||||
|
+ if auth_type == "Basic":
|
||||||
|
+ auth = HTTPBasicAuth(user, passwd)
|
||||||
|
+ elif auth_type == "Digest":
|
||||||
|
+ auth=HTTPDigestAuth(user, passwd)
|
||||||
|
|
||||||
|
-def _load_url(location):
|
||||||
|
+ return auth
|
||||||
|
+
|
||||||
|
+def _load_url(location, user=None, passwd=None):
|
||||||
|
'''Load a location (URL or filename) and return contents as string'''
|
||||||
|
|
||||||
|
+ auth = _get_auth(location, user=user, passwd=passwd)
|
||||||
|
+
|
||||||
|
try:
|
||||||
|
- request = requests.get(location, verify=SSL_VERIFY)
|
||||||
|
+ request = requests.get(location, verify=SSL_VERIFY, auth=auth)
|
||||||
|
except SSLError as e:
|
||||||
|
raise KickstartError(_('Error securely accessing URL "%s"') % location + ': {e}'.format(e=str(e)))
|
||||||
|
except RequestException as e:
|
||||||
|
diff --git a/pykickstart/parser.py b/pykickstart/parser.py
|
||||||
|
index d2b0fbe..26b5de9 100644
|
||||||
|
--- a/pykickstart/parser.py
|
||||||
|
+++ b/pykickstart/parser.py
|
||||||
|
@@ -773,7 +773,7 @@ class KickstartParser(object):
|
||||||
|
i = PutBackIterator(s.splitlines(True) + [""])
|
||||||
|
self._stateMachine (i)
|
||||||
|
|
||||||
|
- def readKickstart(self, f, reset=True):
|
||||||
|
+ def readKickstart(self, f, reset=True, username=None, password=None):
|
||||||
|
"""Process a kickstart file, given by the filename f."""
|
||||||
|
if reset:
|
||||||
|
self._reset()
|
||||||
|
@@ -794,7 +794,7 @@ class KickstartParser(object):
|
||||||
|
self.currentdir[self._includeDepth] = cd
|
||||||
|
|
||||||
|
try:
|
||||||
|
- s = load_to_str(f)
|
||||||
|
+ s = load_to_str(f, user=username, passwd=password)
|
||||||
|
except KickstartError as e:
|
||||||
|
raise KickstartError(formatErrorMsg(0, msg=_("Unable to open input kickstart file: %s") % str(e)))
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
+76
@@ -0,0 +1,76 @@
|
|||||||
|
From e6e747b883114bfad51ad93f823e65f5a4d6438a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Hongxu Jia <hongxu.jia@windriver.com>
|
||||||
|
Date: Thu, 1 Jun 2017 15:12:29 +0800
|
||||||
|
Subject: [PATCH 2/4] pykickstart/parser.py: add lock for readKickstart and
|
||||||
|
support https without certification
|
||||||
|
|
||||||
|
- Add lock for readKickstart to fix race issue
|
||||||
|
|
||||||
|
- Support to download kickstart file through https without certification
|
||||||
|
|
||||||
|
Upstream-Status: Inappropriate[oe specific]
|
||||||
|
|
||||||
|
Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
|
||||||
|
---
|
||||||
|
pykickstart/load.py | 2 +-
|
||||||
|
pykickstart/parser.py | 24 ++++++++++++++++++++++++
|
||||||
|
2 files changed, 25 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/pykickstart/load.py b/pykickstart/load.py
|
||||||
|
index 0f5741b..48c8276 100644
|
||||||
|
--- a/pykickstart/load.py
|
||||||
|
+++ b/pykickstart/load.py
|
||||||
|
@@ -30,7 +30,7 @@ from requests.exceptions import SSLError, RequestException
|
||||||
|
|
||||||
|
_is_url = lambda location: '://' in location # RFC 3986
|
||||||
|
|
||||||
|
-SSL_VERIFY = True
|
||||||
|
+SSL_VERIFY = False
|
||||||
|
|
||||||
|
def load_to_str(location, user=None, passwd=None):
|
||||||
|
'''Load a destination URL or file into a string.
|
||||||
|
diff --git a/pykickstart/parser.py b/pykickstart/parser.py
|
||||||
|
index 26b5de9..264ba05 100644
|
||||||
|
--- a/pykickstart/parser.py
|
||||||
|
+++ b/pykickstart/parser.py
|
||||||
|
@@ -57,6 +57,26 @@ STATE_COMMANDS = "commands"
|
||||||
|
|
||||||
|
ver = version.DEVEL
|
||||||
|
|
||||||
|
+import logging
|
||||||
|
+log = logging.getLogger("anaconda")
|
||||||
|
+
|
||||||
|
+import inspect
|
||||||
|
+import threading
|
||||||
|
+_private_ks_lock = threading.RLock()
|
||||||
|
+
|
||||||
|
+class KsLock(object):
|
||||||
|
+ def __enter__(self):
|
||||||
|
+ log.info("%s %s" % (self.__class__.__name__, inspect.stack()[0][3]))
|
||||||
|
+ _private_ks_lock.acquire()
|
||||||
|
+ return _private_ks_lock
|
||||||
|
+
|
||||||
|
+ def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
|
+ log.info("%s %s" % (self.__class__.__name__, inspect.stack()[0][3]))
|
||||||
|
+ _private_ks_lock.release()
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+_ks_lock = KsLock()
|
||||||
|
+
|
||||||
|
def _preprocessStateMachine (lineIter):
|
||||||
|
l = None
|
||||||
|
lineno = 0
|
||||||
|
@@ -774,6 +794,10 @@ class KickstartParser(object):
|
||||||
|
self._stateMachine (i)
|
||||||
|
|
||||||
|
def readKickstart(self, f, reset=True, username=None, password=None):
|
||||||
|
+ with _ks_lock:
|
||||||
|
+ self._readKickstart(f, reset=reset, username=username, password=password)
|
||||||
|
+
|
||||||
|
+ def _readKickstart(self, f, reset=True, username=None, password=None):
|
||||||
|
"""Process a kickstart file, given by the filename f."""
|
||||||
|
if reset:
|
||||||
|
self._reset()
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
From be6012a5dd49ae5e8ac035654ab1c6f37f0dc8f4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Hongxu Jia <hongxu.jia@windriver.com>
|
||||||
|
Date: Thu, 1 Jun 2017 15:15:15 +0800
|
||||||
|
Subject: [PATCH 3/4] comment out sections shutdown and environment in
|
||||||
|
generated kickstart file
|
||||||
|
|
||||||
|
Both of them is disabled by default.
|
||||||
|
|
||||||
|
Upstream-Status: Inappropriate[oe specific]
|
||||||
|
|
||||||
|
Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
|
||||||
|
|
||||||
|
fixup! add comments of shutdown for user
|
||||||
|
---
|
||||||
|
pykickstart/commands/reboot.py | 3 +++
|
||||||
|
pykickstart/parser.py | 2 +-
|
||||||
|
2 files changed, 4 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/pykickstart/commands/reboot.py b/pykickstart/commands/reboot.py
|
||||||
|
index 88799ba..2d0cea9 100644
|
||||||
|
--- a/pykickstart/commands/reboot.py
|
||||||
|
+++ b/pykickstart/commands/reboot.py
|
||||||
|
@@ -41,6 +41,9 @@ class FC3_Reboot(KickstartCommand):
|
||||||
|
elif self.action == KS_SHUTDOWN:
|
||||||
|
retval += "# Shutdown after installation\nshutdown"
|
||||||
|
retval += self._getArgsAsStr() + "\n"
|
||||||
|
+ else:
|
||||||
|
+ retval += "# Shutdown after installation\n#shutdown"
|
||||||
|
+ retval += self._getArgsAsStr() + "\n"
|
||||||
|
|
||||||
|
return retval
|
||||||
|
|
||||||
|
diff --git a/pykickstart/parser.py b/pykickstart/parser.py
|
||||||
|
index 264ba05..b3f33d7 100644
|
||||||
|
--- a/pykickstart/parser.py
|
||||||
|
+++ b/pykickstart/parser.py
|
||||||
|
@@ -383,7 +383,7 @@ class Packages(KickstartObject):
|
||||||
|
|
||||||
|
if not self.default:
|
||||||
|
if self.environment:
|
||||||
|
- pkgs += "@^%s\n" % self.environment
|
||||||
|
+ pkgs += "#@^%s\n" % self.environment
|
||||||
|
|
||||||
|
grps = self.groupList
|
||||||
|
grps.sort()
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
+82
@@ -0,0 +1,82 @@
|
|||||||
|
From c0e63f0d3c09bdabb0ad2c88b7cc73e7618dd86a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Hongxu Jia <hongxu.jia@windriver.com>
|
||||||
|
Date: Thu, 15 Jun 2017 17:35:33 +0800
|
||||||
|
Subject: [PATCH 4/4] load.py: retry to invoke request with timeout
|
||||||
|
|
||||||
|
While networkless, use request to fetch kickstart file from
|
||||||
|
network, it failed and wait 300s to break, we should retry
|
||||||
|
to invoke request with timeout explicitly. So if it the
|
||||||
|
network is up, the fetch works.
|
||||||
|
|
||||||
|
Upstream-Status: inappropriate [oe specific]
|
||||||
|
|
||||||
|
Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
|
||||||
|
---
|
||||||
|
pykickstart/load.py | 30 ++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 30 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/pykickstart/load.py b/pykickstart/load.py
|
||||||
|
index 48c8276..74b266b 100644
|
||||||
|
--- a/pykickstart/load.py
|
||||||
|
+++ b/pykickstart/load.py
|
||||||
|
@@ -21,6 +21,7 @@ import requests
|
||||||
|
from requests.auth import HTTPDigestAuth
|
||||||
|
from requests.auth import HTTPBasicAuth
|
||||||
|
|
||||||
|
+import time
|
||||||
|
import shutil
|
||||||
|
import six
|
||||||
|
|
||||||
|
@@ -28,6 +29,9 @@ from pykickstart.errors import KickstartError, KickstartAuthError
|
||||||
|
from pykickstart.i18n import _
|
||||||
|
from requests.exceptions import SSLError, RequestException
|
||||||
|
|
||||||
|
+import logging
|
||||||
|
+log = logging.getLogger("anaconda")
|
||||||
|
+
|
||||||
|
_is_url = lambda location: '://' in location # RFC 3986
|
||||||
|
|
||||||
|
SSL_VERIFY = False
|
||||||
|
@@ -74,6 +78,29 @@ def load_to_file(location, destination):
|
||||||
|
_copy_file(location, destination)
|
||||||
|
return destination
|
||||||
|
|
||||||
|
+def _access_url(location):
|
||||||
|
+ status = False
|
||||||
|
+
|
||||||
|
+ # Retry 45 times, wait 45s~135s
|
||||||
|
+ i = 0
|
||||||
|
+ while i < 45:
|
||||||
|
+
|
||||||
|
+ try:
|
||||||
|
+ request = requests.get(location, verify=SSL_VERIFY, timeout=2)
|
||||||
|
+ except RequestException as e:
|
||||||
|
+ log.info("Try '%s' %d times, %s" % (location, i, str(e)))
|
||||||
|
+ status = False
|
||||||
|
+ i += 1
|
||||||
|
+ time.sleep(1)
|
||||||
|
+ continue
|
||||||
|
+
|
||||||
|
+ else:
|
||||||
|
+ status = True
|
||||||
|
+ return status
|
||||||
|
+
|
||||||
|
+ return status
|
||||||
|
+
|
||||||
|
+
|
||||||
|
def _get_auth(location, user=None, passwd=None):
|
||||||
|
|
||||||
|
auth = None
|
||||||
|
@@ -96,6 +123,9 @@ def _get_auth(location, user=None, passwd=None):
|
||||||
|
def _load_url(location, user=None, passwd=None):
|
||||||
|
'''Load a location (URL or filename) and return contents as string'''
|
||||||
|
|
||||||
|
+ if not _access_url(location):
|
||||||
|
+ raise KickstartError(_("Connection %s failed" % location))
|
||||||
|
+
|
||||||
|
auth = _get_auth(location, user=user, passwd=passwd)
|
||||||
|
|
||||||
|
try:
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
DESCRIPTION = "A python library for manipulating kickstart files"
|
||||||
|
HOMEPAGE = "http://fedoraproject.org/wiki/pykickstart"
|
||||||
|
LICENSE = "GPLv2+"
|
||||||
|
|
||||||
|
LIC_FILES_CHKSUM = "file://COPYING;md5=8ca43cbc842c2336e835926c2166c28b"
|
||||||
|
FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
|
||||||
|
|
||||||
|
DEPENDS = "python3"
|
||||||
|
RDEPENDS_${PN} = "python3 \
|
||||||
|
python3-requests \
|
||||||
|
python3-six \
|
||||||
|
"
|
||||||
|
|
||||||
|
S = "${WORKDIR}/git"
|
||||||
|
SRC_URI = "git://github.com/rhinstaller/pykickstart.git;protocol=https;branch=pykickstart-2 \
|
||||||
|
file://0001-support-authentication-for-kickstart.patch \
|
||||||
|
file://0002-pykickstart-parser.py-add-lock-for-readKickstart-and.patch \
|
||||||
|
file://0003-comment-out-sections-shutdown-and-environment-in-gen.patch \
|
||||||
|
file://0004-load.py-retry-to-invoke-request-with-timeout.patch \
|
||||||
|
"
|
||||||
|
SRCREV = "b2787a818540e678c2f9c5dca0c6bbd65b8b55e5"
|
||||||
|
|
||||||
|
inherit setuptools3
|
||||||
|
|
||||||
|
PROVIDES = "pykickstart"
|
||||||
|
RPROVIDES_${PN} = "pykickstart"
|
||||||
Reference in New Issue
Block a user