summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--system/virt-manager/Add-Slackware-to-OS-choices.patch1412
-rw-r--r--system/virt-manager/virt-manager.SlackBuild2
-rw-r--r--system/virt-manager/virt-manager.info6
3 files changed, 1397 insertions, 23 deletions
diff --git a/system/virt-manager/Add-Slackware-to-OS-choices.patch b/system/virt-manager/Add-Slackware-to-OS-choices.patch
index 209dff29b3..a4c1232739 100644
--- a/system/virt-manager/Add-Slackware-to-OS-choices.patch
+++ b/system/virt-manager/Add-Slackware-to-OS-choices.patch
@@ -1,27 +1,27 @@
-diff -Nur virt-manager-1.4.2.orig/virtinst/osdict.py virt-manager-1.4.2/virtinst/osdict.py
---- virt-manager-1.4.2.orig/virtinst/osdict.py 2017-08-02 12:57:43.000000000 -0500
-+++ virt-manager-1.4.2/virtinst/osdict.py 2017-08-24 00:18:55.961760047 -0500
+diff -Nur virt-manager-1.4.3.orig/virtinst/osdict.py virt-manager-1.4.3/virtinst/osdict.py
+--- virt-manager-1.4.3.orig/virtinst/osdict.py 2017-08-16 16:32:14.000000000 -0500
++++ virt-manager-1.4.3/virtinst/osdict.py 2017-10-03 01:02:59.322660395 -0500
@@ -159,6 +159,7 @@
- "rhel5" : "rhel5.0",
- "rhel6" : "rhel6.0",
- "rhel7" : "rhel7.0",
-+ "slackware" : "slackware14.2",
- "ubuntuhardy" : "ubuntu8.04",
- "ubuntuintrepid" : "ubuntu8.10",
- "ubuntujaunty" : "ubuntu9.04",
-@@ -374,7 +375,7 @@
+ "rhel5": "rhel5.0",
+ "rhel6": "rhel6.0",
+ "rhel7": "rhel7.0",
++ "slackware": "slackware14.2",
+ "ubuntuhardy": "ubuntu8.04",
+ "ubuntuintrepid": "ubuntu8.10",
+ "ubuntujaunty": "ubuntu9.04",
+@@ -373,7 +374,7 @@
+ # EOL date. So assume None == EOL, add some manual work arounds.
# We should fix this in a new libosinfo version, and then drop
# this hack
- if self._is_related_to(["fedora24", "rhel7.0", "debian6",
-- "ubuntu13.04", "win8", "win2k12", "mageia5", "centos7.0"],
-+ "slackware14.2", "ubuntu13.04", "win8", "win2k12", "mageia5", "centos7.0"],
+- if self._is_related_to(["fedora24", "rhel7.0", "debian6",
++ if self._is_related_to(["slackware14.2", "fedora24", "rhel7.0", "debian6",
+ "ubuntu13.04", "win8", "win2k12", "mageia5", "centos7.0"],
check_clones=False, check_derives=False):
return True
- return False
-diff -Nur virt-manager-1.4.2.orig/virtinst/urlfetcher.py virt-manager-1.4.2/virtinst/urlfetcher.py
---- virt-manager-1.4.2.orig/virtinst/urlfetcher.py 2017-08-02 12:57:43.000000000 -0500
-+++ virt-manager-1.4.2/virtinst/urlfetcher.py 2017-08-24 00:21:03.619233698 -0500
-@@ -1285,6 +1285,43 @@
+diff -Nur virt-manager-1.4.3.orig/virtinst/urlfetcher.py virt-manager-1.4.3/virtinst/urlfetcher.py
+--- virt-manager-1.4.3.orig/virtinst/urlfetcher.py 2017-09-14 16:49:00.000000000 -0500
++++ virt-manager-1.4.3/virtinst/urlfetcher.py 2017-10-03 01:02:26.932287601 -0500
+@@ -1347,6 +1347,43 @@
return False
@@ -65,3 +65,1377 @@ diff -Nur virt-manager-1.4.2.orig/virtinst/urlfetcher.py virt-manager-1.4.2/virt
# Build list of all *Distro classes
def _build_distro_list():
allstores = []
+diff -Nur virt-manager-1.4.3.orig/virtinst/urlfetcher.py.orig virt-manager-1.4.3/virtinst/urlfetcher.py.orig
+--- virt-manager-1.4.3.orig/virtinst/urlfetcher.py.orig 1969-12-31 18:00:00.000000000 -0600
++++ virt-manager-1.4.3/virtinst/urlfetcher.py.orig 2017-09-14 16:49:00.000000000 -0500
+@@ -0,0 +1,1370 @@
++#
++# Represents OS distribution specific install data
++#
++# Copyright 2006-2007, 2013 Red Hat, Inc.
++# Daniel P. Berrange <berrange@redhat.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., 51 Franklin Street, Fifth Floor, Boston,
++# MA 02110-1301 USA.
++
++import ConfigParser
++import ftplib
++import logging
++import os
++import re
++import stat
++import StringIO
++import subprocess
++import tempfile
++import urllib2
++import urlparse
++
++import requests
++
++from .osdict import OSDB
++
++
++#########################################################################
++# Backends for the various URL types we support (http, ftp, nfs, local) #
++#########################################################################
++
++class _URLFetcher(object):
++ """
++ This is a generic base class for fetching/extracting files from
++ a media source, such as CD ISO, NFS server, or HTTP/FTP server
++ """
++ _block_size = 16384
++
++ def __init__(self, location, scratchdir, meter):
++ self.location = location
++ self.scratchdir = scratchdir
++ self.meter = meter
++
++ self._srcdir = None
++
++ logging.debug("Using scratchdir=%s", scratchdir)
++
++
++ ####################
++ # Internal helpers #
++ ####################
++
++ def _make_full_url(self, filename):
++ """
++ Generate a full fetchable URL from the passed filename, which
++ is relative to the self.location
++ """
++ ret = self._srcdir or self.location
++ if not filename:
++ return ret
++
++ if not ret.endswith("/"):
++ ret += "/"
++ return ret + filename
++
++ def _grabURL(self, filename, fileobj):
++ """
++ Download the filename from self.location, and write contents to
++ fileobj
++ """
++ url = self._make_full_url(filename)
++
++ try:
++ urlobj, size = self._grabber(url)
++ except Exception as e:
++ raise ValueError(_("Couldn't acquire file %s: %s") %
++ (url, str(e)))
++
++ logging.debug("Fetching URI: %s", url)
++ self.meter.start(
++ text=_("Retrieving file %s...") % os.path.basename(filename),
++ size=size)
++
++ total = self._write(urlobj, fileobj)
++ self.meter.end(total)
++
++ def _write(self, urlobj, fileobj):
++ """
++ Write the contents of urlobj to python file like object fileobj
++ """
++ total = 0
++ while 1:
++ buff = urlobj.read(self._block_size)
++ if not buff:
++ break
++ fileobj.write(buff)
++ total += len(buff)
++ self.meter.update(total)
++ return total
++
++ def _grabber(self, url):
++ """
++ Returns the urlobj, size for the passed URL. urlobj is whatever
++ data needs to be passed to self._write
++ """
++ raise NotImplementedError("must be implemented in subclass")
++
++
++ ##############
++ # Public API #
++ ##############
++
++ def prepareLocation(self):
++ """
++ Perform any necessary setup
++ """
++ pass
++
++ def cleanupLocation(self):
++ """
++ Perform any necessary cleanup
++ """
++ pass
++
++ def _hasFile(self, url):
++ raise NotImplementedError("Must be implemented in subclass")
++
++ def hasFile(self, filename):
++ """
++ Return True if self.location has the passed filename
++ """
++ url = self._make_full_url(filename)
++ ret = self._hasFile(url)
++ logging.debug("hasFile(%s) returning %s", url, ret)
++ return ret
++
++ def acquireFile(self, filename):
++ """
++ Grab the passed filename from self.location and save it to
++ a temporary file, returning the temp filename
++ """
++ prefix = "virtinst-" + os.path.basename(filename) + "."
++
++ # pylint: disable=redefined-variable-type
++ if "VIRTINST_TEST_SUITE" in os.environ:
++ fn = os.path.join("/tmp", prefix)
++ fileobj = open(fn, "w")
++ else:
++ fileobj = tempfile.NamedTemporaryFile(
++ dir=self.scratchdir, prefix=prefix, delete=False)
++ fn = fileobj.name
++
++ self._grabURL(filename, fileobj)
++ logging.debug("Saved file to " + fn)
++ return fn
++
++ def acquireFileContent(self, filename):
++ """
++ Grab the passed filename from self.location and return it as a string
++ """
++ fileobj = StringIO.StringIO()
++ self._grabURL(filename, fileobj)
++ return fileobj.getvalue()
++
++
++class _HTTPURLFetcher(_URLFetcher):
++ def _hasFile(self, url):
++ """
++ We just do a HEAD request to see if the file exists
++ """
++ try:
++ response = requests.head(url, allow_redirects=True)
++ response.raise_for_status()
++ except Exception as e:
++ logging.debug("HTTP hasFile request failed: %s", str(e))
++ return False
++ return True
++
++ def _grabber(self, url):
++ """
++ Use requests for this
++ """
++ response = requests.get(url, stream=True)
++ response.raise_for_status()
++ try:
++ size = int(response.headers.get('content-length'))
++ except Exception:
++ size = None
++ return response, size
++
++ def _write(self, urlobj, fileobj):
++ """
++ The requests object doesn't have a file-like read() option, so
++ we need to implemente it ourselves
++ """
++ total = 0
++ for data in urlobj.iter_content(chunk_size=self._block_size):
++ fileobj.write(data)
++ total += len(data)
++ self.meter.update(total)
++ return total
++
++
++class _FTPURLFetcher(_URLFetcher):
++ _ftp = None
++
++ def prepareLocation(self):
++ if self._ftp:
++ return
++
++ try:
++ parsed = urlparse.urlparse(self.location)
++ self._ftp = ftplib.FTP()
++ self._ftp.connect(parsed.hostname, parsed.port)
++ self._ftp.login()
++ # Force binary mode
++ self._ftp.voidcmd("TYPE I")
++ except Exception as e:
++ raise ValueError(_("Opening URL %s failed: %s.") %
++ (self.location, str(e)))
++
++ def _grabber(self, url):
++ """
++ Use urllib2 and ftplib to grab the file
++ """
++ request = urllib2.Request(url)
++ urlobj = urllib2.urlopen(request)
++ size = self._ftp.size(urlparse.urlparse(url)[2])
++ return urlobj, size
++
++
++ def cleanupLocation(self):
++ if not self._ftp:
++ return
++
++ try:
++ self._ftp.quit()
++ except Exception:
++ logging.debug("Error quitting ftp connection", exc_info=True)
++
++ self._ftp = None
++
++ def _hasFile(self, url):
++ path = urlparse.urlparse(url)[2]
++
++ try:
++ try:
++ # If it's a file
++ self._ftp.size(path)
++ except ftplib.all_errors:
++ # If it's a dir
++ self._ftp.cwd(path)
++ except ftplib.all_errors as e:
++ logging.debug("FTP hasFile: couldn't access %s: %s",
++ url, str(e))
++ return False
++
++ return True
++
++
++class _LocalURLFetcher(_URLFetcher):
++ """
++ For grabbing files from a local directory
++ """
++ def _hasFile(self, url):
++ return os.path.exists(url)
++
++ def _grabber(self, url):
++ urlobj = open(url, "r")
++ size = os.path.getsize(url)
++ return urlobj, size
++
++
++class _MountedURLFetcher(_LocalURLFetcher):
++ """
++ Fetcher capable of extracting files from a NFS server
++ or loopback mounted file, or local CDROM device
++ """
++ _in_test_suite = bool("VIRTINST_TEST_SUITE" in os.environ)
++ _mounted = False
++
++ def prepareLocation(self):
++ if self._mounted:
++ return
++
++ if self._in_test_suite:
++ self._srcdir = os.environ["VIRTINST_TEST_URL_DIR"]
++ else:
++ self._srcdir = tempfile.mkdtemp(prefix="virtinstmnt.",
++ dir=self.scratchdir)
++ mountcmd = "/bin/mount"
++
++ logging.debug("Preparing mount at " + self._srcdir)
++ if self.location.startswith("nfs:"):
++ cmd = [mountcmd, "-o", "ro", self.location[4:], self._srcdir]
++ else:
++ if stat.S_ISBLK(os.stat(self.location)[stat.ST_MODE]):
++ mountopt = "ro"
++ else:
++ mountopt = "ro,loop"
++ cmd = [mountcmd, "-o", mountopt, self.location, self._srcdir]
++
++ logging.debug("mount cmd: %s", cmd)
++ if not self._in_test_suite:
++ ret = subprocess.call(cmd)
++ if ret != 0:
++ self.cleanupLocation()
++ raise ValueError(_("Mounting location '%s' failed") %
++ (self.location))
++
++ self._mounted = True
++
++ def cleanupLocation(self):
++ if not self._mounted:
++ return
++
++ logging.debug("Cleaning up mount at " + self._srcdir)
++ try:
++ if not self._in_test_suite:
++ cmd = ["/bin/umount", self._srcdir]
++ subprocess.call(cmd)
++ try:
++ os.rmdir(self._srcdir)
++ except Exception:
++ pass
++ finally:
++ self._mounted = False
++
++
++def fetcherForURI(uri, *args, **kwargs):
++ if uri.startswith("http://") or uri.startswith("https://"):
++ fclass = _HTTPURLFetcher
++ elif uri.startswith("ftp://"):
++ fclass = _FTPURLFetcher
++ elif uri.startswith("nfs:"):
++ fclass = _MountedURLFetcher
++ elif os.path.isdir(uri):
++ # Pointing to a local tree
++ fclass = _LocalURLFetcher
++ else:
++ # Pointing to a path, like an .iso to mount
++ fclass = _MountedURLFetcher
++ return fclass(uri, *args, **kwargs)
++
++
++###############################################
++# Helpers for detecting distro from given URL #
++###############################################
++
++def _grabTreeinfo(fetcher):
++ """
++ See if the URL has treeinfo, and if so return it as a ConfigParser
++ object.
++ """
++ try:
++ tmptreeinfo = fetcher.acquireFile(".treeinfo")
++ except ValueError:
++ return None
++
++ try:
++ treeinfo = ConfigParser.SafeConfigParser()
++ treeinfo.read(tmptreeinfo)
++ finally:
++ os.unlink(tmptreeinfo)
++
++ try:
++ treeinfo.get("general", "family")
++ except ConfigParser.NoSectionError:
++ logging.debug("Did not find 'family' section in treeinfo")
++ return None
++
++ logging.debug("treeinfo family=%s", treeinfo.get("general", "family"))
++ return treeinfo
++
++
++def _distroFromSUSEContent(fetcher, arch, vmtype=None):
++ # Parse content file for the 'LABEL' field containing the distribution name
++ # None if no content, GenericDistro if unknown label type.
++ try:
++ cbuf = fetcher.acquireFileContent("content")
++ except ValueError:
++ return None
++
++ distribution = None
++ distro_version = None
++ distro_summary = None
++ distro_distro = None
++ distro_arch = None
++
++ lines = cbuf.splitlines()[1:]
++ for line in lines:
++ if line.startswith("LABEL "):
++ distribution = line.split(' ', 1)
++ elif line.startswith("DISTRO "):
++ distro_distro = line.rsplit(',', 1)
++ elif line.startswith("VERSION "):
++ distro_version = line.split(' ', 1)
++ if len(distro_version) > 1:
++ d_version = distro_version[1].split('-', 1)
++ if len(d_version) > 1:
++ distro_version[1] = d_version[0]
++ elif line.startswith("SUMMARY "):
++ distro_summary = line.split(' ', 1)
++ elif line.startswith("BASEARCHS "):
++ distro_arch = line.split(' ', 1)
++ elif line.startswith("DEFAULTBASE "):
++ distro_arch = line.split(' ', 1)
++ elif line.startswith("REPOID "):
++ distro_arch = line.rsplit('/', 1)
++ if distribution and distro_version and distro_arch:
++ break
++
++ if not distribution:
++ if distro_summary:
++ distribution = distro_summary
++ elif distro_distro:
++ distribution = distro_distro
++ if distro_arch:
++ arch = distro_arch[1].strip()
++ # Fix for 13.2 official oss repo
++ if arch.find("i586-x86_64") != -1:
++ arch = "x86_64"
++ else:
++ if cbuf.find("x86_64") != -1:
++ arch = "x86_64"
++ elif cbuf.find("i586") != -1:
++ arch = "i586"
++ elif cbuf.find("s390x") != -1:
++ arch = "s390x"
++
++ def _parse_sle_distribution(d):
++ sle_version = d[1].strip().rsplit(' ')[4]
++ if len(d[1].strip().rsplit(' ')) > 5:
++ sle_version = sle_version + '.' + d[1].strip().rsplit(' ')[5][2]
++ return ['VERSION', sle_version]
++
++ dclass = GenericDistro
++ if distribution:
++ if re.match(".*SUSE Linux Enterprise Server*", distribution[1]) or \
++ re.match(".*SUSE SLES*", distribution[1]):
++ dclass = SLESDistro
++ if distro_version is None:
++ distro_version = _parse_sle_distribution(distribution)
++ elif re.match(".*SUSE Linux Enterprise Desktop*", distribution[1]):
++ dclass = SLEDDistro
++ if distro_version is None:
++ distro_version = _parse_sle_distribution(distribution)
++ elif re.match(".*openSUSE.*", distribution[1]):
++ dclass = OpensuseDistro
++ if distro_version is None:
++ distro_version = ['VERSION', distribution[0].strip().rsplit(':')[4]]
++
++ if distro_version is None:
++ return None
++
++ ob = dclass(fetcher, arch, vmtype)
++ if dclass != GenericDistro:
++ ob.version_from_content = distro_version
++
++ # Explictly call this, so we populate os_type/variant info
++ ob.isValidStore()
++
++ return ob
++
++
++def getDistroStore(guest, fetcher):
++ stores = []
++ logging.debug("Finding distro store for location=%s", fetcher.location)
++
++ arch = guest.os.arch
++ _type = guest.os.os_type
++ urldistro = OSDB.lookup_os(guest.os_variant).urldistro
++
++ treeinfo = _grabTreeinfo(fetcher)
++ if not treeinfo:
++ dist = _distroFromSUSEContent(fetcher, arch, _type)
++ if dist:
++ return dist
++
++ stores = _allstores[:]
++
++ # If user manually specified an os_distro, bump it's URL class
++ # to the top of the list
++ if urldistro:
++ logging.debug("variant=%s has distro=%s, looking for matching "
++ "distro store to prioritize",
++ guest.os_variant, urldistro)
++ found_store = None
++ for store in stores:
++ if store.urldistro == urldistro:
++ found_store = store
++
++ if found_store:
++ logging.debug("Prioritizing distro store=%s", found_store)
++ stores.remove(found_store)
++ stores.insert(0, found_store)
++ else:
++ logging.debug("No matching store found, not prioritizing anything")
++
++ if treeinfo:
++ stores.sort(key=lambda x: not x.uses_treeinfo)
++
++ for sclass in stores:
++ store = sclass(fetcher, arch, _type)
++ store.treeinfo = treeinfo
++ if store.isValidStore():
++ logging.debug("Detected distro name=%s osvariant=%s",
++ store.name, store.os_variant)
++ return store
++
++ # No distro was detected. See if the URL even resolves, and if not
++ # give the user a hint that maybe they mistyped. This won't always
++ # be true since some webservers don't allow directory listing.
++ # http://www.redhat.com/archives/virt-tools-list/2014-December/msg00048.html
++ extramsg = ""
++ if not fetcher.hasFile(""):
++ extramsg = (": " +
++ _("The URL could not be accessed, maybe you mistyped?"))
++
++ raise ValueError(
++ _("Could not find an installable distribution at '%s'%s\n\n"
++ "The location must be the root directory of an install tree.\n"
++ "See virt-install man page for various distro examples." %
++ (fetcher.location, extramsg)))
++
++
++##################
++# Distro classes #
++##################
++
++class Distro(object):
++ """
++ An image store is a base class for retrieving either a bootable
++ ISO image, or a kernel+initrd pair for a particular OS distribution
++ """
++ name = None
++ urldistro = None
++ uses_treeinfo = False
++
++ # osdict variant value
++ os_variant = None
++
++ _boot_iso_paths = []
++ _hvm_kernel_paths = []
++ _xen_kernel_paths = []
++ version_from_content = []
++
++ def __init__(self, fetcher, arch, vmtype):
++ self.fetcher = fetcher
++ self.type = vmtype
++ self.arch = arch
++
++ self.uri = fetcher.location
++
++ # This is set externally
++ self.treeinfo = None
++
++ def isValidStore(self):
++ """Determine if uri points to a tree of the store's distro"""
++ raise NotImplementedError
++
++ def acquireKernel(self, guest):
++ kernelpath = None
++ initrdpath = None
++ if self.treeinfo:
++ try:
++ kernelpath = self._getTreeinfoMedia("kernel")
++ initrdpath = self._getTreeinfoMedia("initrd")
++ except ConfigParser.NoSectionError:
++ pass
++
++ if not kernelpath or not initrdpath:
++ # fall back to old code
++ if self.type is None or self.type == "hvm":
++ paths = self._hvm_kernel_paths
++ else:
++ paths = self._xen_kernel_paths
++
++ for kpath, ipath in paths:
++ if self.fetcher.hasFile(kpath) and self.fetcher.hasFile(ipath):
++ kernelpath = kpath
++ initrdpath = ipath
++
++ if not kernelpath or not initrdpath:
++ raise RuntimeError(_("Couldn't find %(type)s kernel for "
++ "%(distro)s tree.") %
++ {"distro": self.name, "type": self.type})
++
++ return self._kernelFetchHelper(guest, kernelpath, initrdpath)
++
++ def acquireBootDisk(self, guest):
++ ignore = guest
++
++ if self.treeinfo:
++ return self.fetcher.acquireFile(self._getTreeinfoMedia("boot.iso"))
++
++ for path in self._boot_iso_paths:
++ if self.fetcher.hasFile(path):
++ return self.fetcher.acquireFile(path)
++ raise RuntimeError(_("Could not find boot.iso in %s tree." %
++ self.name))
++
++ def _check_osvariant_valid(self, os_variant):
++ return OSDB.lookup_os(os_variant) is not None
++
++ def get_osdict_info(self):
++ """
++ Return (distro, variant) tuple, checking to make sure they are valid
++ osdict entries
++ """
++ if not self.os_variant:
++ return None
++
++ if not self._check_osvariant_valid(self.os_variant):
++ logging.debug("%s set os_variant to %s, which is not in osdict.",
++ self, self.os_variant)
++ return None
++
++ return self.os_variant
++
++ def _get_method_arg(self):
++ return "method"
++
++ def _getTreeinfoMedia(self, mediaName):
++ if self.type == "xen":
++ t = "xen"
++ else:
++ t = self.treeinfo.get("general", "arch")
++
++ return self.treeinfo.get("images-%s" % t, mediaName)
++
++ def _fetchAndMatchRegex(self, filename, regex):
++ # Fetch 'filename' and return True/False if it matches the regex
++ try:
++ content = self.fetcher.acquireFileContent(filename)
++ except ValueError:
++ return False
++
++ for line in content.splitlines():
++ if re.match(regex, line):
++ return True
++
++ return False
++
++ def _kernelFetchHelper(self, guest, kernelpath, initrdpath):
++ # Simple helper for fetching kernel + initrd and performing
++ # cleanup if necessary
++ ignore = guest
++ kernel = self.fetcher.acquireFile(kernelpath)
++ args = ''
++
++ if not self.fetcher.location.startswith("/"):
++ args += "%s=%s" % (self._get_method_arg(), self.fetcher.location)
++
++ try:
++ initrd = self.fetcher.acquireFile(initrdpath)
++ return kernel, initrd, args
++ except Exception:
++ os.unlink(kernel)
++ raise
++
++
++class GenericDistro(Distro):
++ """
++ Generic distro store. Check well known paths for kernel locations
++ as a last resort if we can't recognize any actual distro
++ """
++ name = "Generic"
++ uses_treeinfo = True
++
++ _xen_paths = [("images/xen/vmlinuz",
++ "images/xen/initrd.img"), # Fedora
++ ]
++ _hvm_paths = [("images/pxeboot/vmlinuz",
++ "images/pxeboot/initrd.img"), # Fedora
++ ("ppc/ppc64/vmlinuz",
++ "ppc/ppc64/initrd.img"), # CenOS 7 ppc64le
++ ]
++ _iso_paths = ["images/boot.iso", # RH/Fedora
++ "boot/boot.iso", # Suse
++ "current/images/netboot/mini.iso", # Debian
++ "install/images/boot.iso", # Mandriva
++ ]
++
++ # Holds values to use when actually pulling down media
++ _valid_kernel_path = None
++ _valid_iso_path = None
++
++ def isValidStore(self):
++ if self.treeinfo:
++ # Use treeinfo to pull down media paths
++ if self.type == "xen":
++ typ = "xen"
++ else:
++ typ = self.treeinfo.get("general", "arch")
++
++ kernelSection = "images-%s" % typ
++ isoSection = "images-%s" % self.treeinfo.get("general", "arch")
++
++ if self.treeinfo.has_section(kernelSection):
++ try:
++ self._valid_kernel_path = (
++ self._getTreeinfoMedia("kernel"),
++ self._getTreeinfoMedia("initrd"))
++ except (ConfigParser.NoSectionError,
++ ConfigParser.NoOptionError) as e:
++ logging.debug(e)
++
++ if self.treeinfo.has_section(isoSection):
++ try:
++ self._valid_iso_path = self.treeinfo.get(isoSection,
++ "boot.iso")
++ except ConfigParser.NoOptionError as e:
++ logging.debug(e)
++
++ if self.type == "xen":
++ kern_list = self._xen_paths
++ else:
++ kern_list = self._hvm_paths
++
++ # If validated media paths weren't found (no treeinfo), check against
++ # list of media location paths.
++ for kern, init in kern_list:
++ if (self._valid_kernel_path is None and
++ self.fetcher.hasFile(kern) and
++ self.fetcher.hasFile(init)):
++ self._valid_kernel_path = (kern, init)
++ break
++
++ for iso in self._iso_paths:
++ if (self._valid_iso_path is None and
++ self.fetcher.hasFile(iso)):
++ self._valid_iso_path = iso
++ break
++
++ if self._valid_kernel_path or self._valid_iso_path:
++ return True
++ return False
++
++ def acquireKernel(self, guest):
++ if self._valid_kernel_path is None:
++ raise ValueError(_("Could not find a kernel path for virt type "
++ "'%s'" % self.type))
++
++ return self._kernelFetchHelper(guest,
++ self._valid_kernel_path[0],
++ self._valid_kernel_path[1])
++
++ def acquireBootDisk(self, guest):
++ if self._valid_iso_path is None:
++ raise ValueError(_("Could not find a boot iso path for this tree."))
++
++ return self.fetcher.acquireFile(self._valid_iso_path)
++
++
++class RedHatDistro(Distro):
++ """
++ Base image store for any Red Hat related distros which have
++ a common layout
++ """
++ uses_treeinfo = True
++ _version_number = None
++
++ _boot_iso_paths = ["images/boot.iso"]
++ _hvm_kernel_paths = [("images/pxeboot/vmlinuz",
++ "images/pxeboot/initrd.img")]
++ _xen_kernel_paths = [("images/xen/vmlinuz",
++ "images/xen/initrd.img")]
++
++ def isValidStore(self):
++ raise NotImplementedError()
++
++ def _get_method_arg(self):
++ if (self._version_number is not None and
++ ((self.urldistro == "rhel" and self._version_number >= 7) or
++ (self.urldistro == "fedora" and self._version_number >= 19))):
++ return "inst.repo"
++ return "method"
++
++
++# Fedora distro check
++class FedoraDistro(RedHatDistro):
++ name = "Fedora"
++ urldistro = "fedora"
++
++ def isValidStore(self):
++ if not self.treeinfo:
++ return self.fetcher.hasFile("Fedora")
++
++ if not re.match(".*Fedora.*", self.treeinfo.get("general", "family")):
++ return False
++
++ ver = self.treeinfo.get("general", "version")
++ if not ver:
++ logging.debug("No version found in .treeinfo")
++ return False
++ logging.debug("Found treeinfo version=%s", ver)
++
++ latest_variant = OSDB.latest_fedora_version()
++ if re.match("fedora[0-9]+", latest_variant):
++ latest_vernum = int(latest_variant[6:])
++ else:
++ logging.debug("Failed to parse version number from latest "
++ "fedora variant=%s. Using safe default 22", latest_variant)
++ latest_vernum = 22
++
++ # rawhide trees changed to use version=Rawhide in Apr 2016
++ if ver in ["development", "rawhide", "Rawhide"]:
++ self._version_number = latest_vernum
++ self.os_variant = latest_variant
++ return True
++
++ # Dev versions can be like '23_Alpha'
++ if "_" in ver:
++ ver = ver.split("_")[0]
++
++ # Typical versions are like 'fedora-23'
++ vernum = str(ver).split("-")[0]
++ if vernum.isdigit():
++ vernum = int(vernum)
++ else:
++ logging.debug("Failed to parse version number from treeinfo "
++ "version=%s, using vernum=latest=%s", ver, latest_vernum)
++ vernum = latest_vernum
++
++ if vernum > latest_vernum:
++ self.os_variant = latest_variant
++ else:
++ self.os_variant = "fedora" + str(vernum)
++
++ self._version_number = vernum
++ return True
++
++
++# Red Hat Enterprise Linux distro check
++class RHELDistro(RedHatDistro):
++ name = "Red Hat Enterprise Linux"
++ urldistro = "rhel"
++
++ def isValidStore(self):
++ if self.treeinfo:
++ # Matches:
++ # Red Hat Enterprise Linux
++ # RHEL Atomic Host
++ m = re.match(".*(Red Hat Enterprise Linux|RHEL).*",
++ self.treeinfo.get("general", "family"))
++ ret = (m is not None)
++
++ if ret:
++ self._variantFromVersion()
++ return ret
++
++ if (self.fetcher.hasFile("Server") or
++ self.fetcher.hasFile("Client")):
++ self.os_variant = "rhel5"
++ return True
++ return self.fetcher.hasFile("RedHat")
++
++
++ ################################
++ # osdict autodetection helpers #
++ ################################
++
++ def _parseTreeinfoVersion(self, verstr):
++ def _safeint(c):
++ try:
++ val = int(c)
++ except Exception:
++ val = 0
++ return val
++
++ version = _safeint(verstr[0])
++ update = 0
++
++ # RHEL has version=5.4, scientific linux=54
++ updinfo = verstr.split(".")
++ if len(updinfo) > 1:
++ update = _safeint(updinfo[1])
++ elif len(verstr) > 1:
++ update = _safeint(verstr[1])
++
++ return version, update
++
++ def _variantFromVersion(self):
++ ver = self.treeinfo.get("general", "version")
++ name = None
++ if self.treeinfo.has_option("general", "name"):
++ name = self.treeinfo.get("general", "name")
++ if not ver:
++ return
++
++ if name and name.startswith("Red Hat Enterprise Linux Server for ARM"):
++ # Kind of a hack, but good enough for the time being
++ version = 7
++ update = 0
++ else:
++ version, update = self._parseTreeinfoVersion(ver)
++
++ self._version_number = version
++ self._setRHELVariant(version, update)
++
++ def _setRHELVariant(self, version, update):
++ base = "rhel" + str(version)
++ if update < 0:
++ update = 0
++
++ ret = None
++ while update >= 0:
++ tryvar = base + ".%s" % update
++ if not self._check_osvariant_valid(tryvar):
++ update -= 1
++ continue
++
++ ret = tryvar
++ break
++
++ if not ret:
++ # Try plain rhel5, rhel6, whatev
++ if self._check_osvariant_valid(base):
++ ret = base
++
++ if ret:
++ self.os_variant = ret
++
++
++# CentOS distro check
++class CentOSDistro(RHELDistro):
++ name = "CentOS"
++ urldistro = "centos"
++
++ def isValidStore(self):
++ if not self.treeinfo:
++ return self.fetcher.hasFile("CentOS")
++
++ m = re.match(".*CentOS.*", self.treeinfo.get("general", "family"))
++ ret = (m is not None)
++ if ret:
++ self._variantFromVersion()
++ if self.os_variant:
++ new_variant = self.os_variant.replace("rhel", "centos")
++ if self._check_osvariant_valid(new_variant):
++ self.os_variant = new_variant
++ return ret
++
++
++# Scientific Linux distro check
++class SLDistro(RHELDistro):
++ name = "Scientific Linux"
++ urldistro = None
++
++ _boot_iso_paths = RHELDistro._boot_iso_paths + ["images/SL/boot.iso"]
++ _hvm_kernel_paths = RHELDistro._hvm_kernel_paths + [
++ ("images/SL/pxeboot/vmlinuz", "images/SL/pxeboot/initrd.img")]
++
++ def isValidStore(self):
++ if self.treeinfo:
++ m = re.match(".*Scientific.*",
++ self.treeinfo.get("general", "family"))
++ ret = (m is not None)
++
++ if ret:
++ self._variantFromVersion()
++ return ret
++
++ return self.fetcher.hasFile("SL")
++
++
++class SuseDistro(Distro):
++ name = "SUSE"
++
++ _boot_iso_paths = ["boot/boot.iso"]
++
++ def __init__(self, *args, **kwargs):
++ Distro.__init__(self, *args, **kwargs)
++ if re.match(r'i[4-9]86', self.arch):
++ self.arch = 'i386'
++
++ oldkern = "linux"
++ oldinit = "initrd"
++ if self.arch == "x86_64":
++ oldkern += "64"
++ oldinit += "64"
++
++ if self.arch == "s390x":
++ self._hvm_kernel_paths = [("boot/%s/linux" % self.arch,
++ "boot/%s/initrd" % self.arch)]
++ # No Xen on s390x
++ self._xen_kernel_paths = []
++ else:
++ # Tested with Opensuse >= 10.2, 11, and sles 10
++ self._hvm_kernel_paths = [("boot/%s/loader/linux" % self.arch,
++ "boot/%s/loader/initrd" % self.arch)]
++ # Tested with Opensuse 10.0
++ self._hvm_kernel_paths.append(("boot/loader/%s" % oldkern,
++ "boot/loader/%s" % oldinit))
++ # Tested with SLES 12 for ppc64le
++ self._hvm_kernel_paths.append(("boot/%s/linux" % self.arch,
++ "boot/%s/initrd" % self.arch))
++
++ # Matches Opensuse > 10.2 and sles 10
++ self._xen_kernel_paths = [("boot/%s/vmlinuz-xen" % self.arch,
++ "boot/%s/initrd-xen" % self.arch)]
++
++ def _variantFromVersion(self):
++ distro_version = self.version_from_content[1].strip()
++ version = distro_version.split('.', 1)[0].strip()
++ self.os_variant = self.urldistro
++ if int(version) >= 10:
++ if self.os_variant.startswith(("sles", "sled")):
++ sp_version = None
++ if len(distro_version.split('.', 1)) == 2:
++ sp_version = 'sp' + distro_version.split('.', 1)[1].strip()
++ self.os_variant += version
++ if sp_version:
++ self.os_variant += sp_version
++ else:
++ # Tumbleweed 8 digit date
++ if len(version) == 8:
++ self.os_variant += "tumbleweed"
++ else:
++ self.os_variant += distro_version
++ else:
++ self.os_variant += "9"
++
++ def isValidStore(self):
++ # self.version_from_content is the VERSION line from the contents file
++ if (not self.version_from_content or
++ self.version_from_content[1] is None):
++ return False
++
++ self._variantFromVersion()
++
++ self.os_variant = self._detect_osdict_from_url()
++
++ # Reset kernel name for sle11 source on s390x
++ if self.arch == "s390x":
++ if self.os_variant == "sles11" or self.os_variant == "sled11":
++ self._hvm_kernel_paths = [("boot/%s/vmrdr.ikr" % self.arch,
++ "boot/%s/initrd" % self.arch)]
++
++ return True
++
++ def _get_method_arg(self):
++ return "install"
++
++ ################################
++ # osdict autodetection helpers #
++ ################################
++
++ def _detect_osdict_from_url(self):
++ root = "opensuse"
++ oses = [n for n in OSDB.list_os() if n.name.startswith(root)]
++
++ for osobj in oses:
++ codename = osobj.name[len(root):]
++ if re.search("/%s/" % codename, self.uri):
++ return osobj.name
++ return self.os_variant
++
++
++class SLESDistro(SuseDistro):
++ urldistro = "sles"
++
++
++class SLEDDistro(SuseDistro):
++ urldistro = "sled"
++
++
++# Suse image store is harder - we fetch the kernel RPM and a helper
++# RPM and then munge bits together to generate a initrd
++class OpensuseDistro(SuseDistro):
++ urldistro = "opensuse"
++
++
++class DebianDistro(Distro):
++ # ex. http://ftp.egr.msu.edu/debian/dists/sarge/main/installer-i386/
++ # daily builds: http://d-i.debian.org/daily-images/amd64/
++ name = "Debian"
++ urldistro = "debian"
++
++ def __init__(self, *args, **kwargs):
++ Distro.__init__(self, *args, **kwargs)
++
++ self._url_prefix = ""
++ self._treeArch = self._find_treearch()
++ self._installer_dirname = self.name.lower() + "-installer"
++
++ def _find_treearch(self):
++ for pattern in ["^.*/installer-(\w+)/?$",
++ "^.*/daily-images/(\w+)/?$"]:
++ arch = re.findall(pattern, self.uri)
++ if not arch:
++ continue
++ logging.debug("Found pattern=%s treearch=%s in uri",
++ pattern, arch[0])
++ return arch[0]
++
++ # Check for standard 'i386' and 'amd64' which will be
++ # in the URI name for --location $ISO mounts
++ for arch in ["i386", "amd64", "x86_64"]:
++ if arch in self.uri:
++ logging.debug("Found treearch=%s in uri", arch)
++ if arch == "x86_64":
++ arch = "amd64"
++ return arch
++
++ # Otherwise default to i386
++ arch = "i386"
++ logging.debug("No treearch found in uri, defaulting to arch=%s", arch)
++ return arch
++
++ def _set_media_paths(self):
++ self._boot_iso_paths = ["%s/netboot/mini.iso" % self._url_prefix]
++
++ hvmroot = "%s/netboot/%s/%s/" % (self._url_prefix,
++ self._installer_dirname,
++ self._treeArch)
++ initrd_basename = "initrd.gz"
++ kernel_basename = "linux"
++ if self._treeArch in ["ppc64el"]:
++ kernel_basename = "vmlinux"
++
++ if self._treeArch == "s390x":
++ hvmroot = "%s/generic/" % self._url_prefix
++ kernel_basename = "kernel.%s" % self.name.lower()
++ initrd_basename = "initrd.%s" % self.name.lower()
++
++ self._hvm_kernel_paths = [
++ (hvmroot + kernel_basename, hvmroot + initrd_basename)]
++
++ xenroot = "%s/netboot/xen/" % self._url_prefix
++ self._xen_kernel_paths = [(xenroot + "vmlinuz", xenroot + "initrd.gz")]
++
++ def _check_manifest(self, filename):
++ if not self.fetcher.hasFile(filename):
++ return False
++
++ if self.arch == "s390x":
++ regex = ".*generic/kernel\.%s.*" % self.name.lower()
++ else:
++ regex = ".*%s.*" % self._installer_dirname
++
++ if not self._fetchAndMatchRegex(filename, regex):
++ logging.debug("Regex didn't match, not a %s distro", self.name)
++ return False
++
++ return True
++
++ def _check_info(self, filename):
++ if not self.fetcher.hasFile(filename):
++ return False
++
++ regex = "%s.*" % self.name
++
++ if not self._fetchAndMatchRegex(filename, regex):
++ logging.debug("Regex didn't match, not a %s distro", self.name)
++ return False
++
++ return True
++
++ def _is_regular_tree(self):
++ # For regular trees
++ if not self._check_manifest("current/images/MANIFEST"):
++ return False
++
++ self._url_prefix = "current/images"
++ self._set_media_paths()
++ self.os_variant = self._detect_debian_osdict_from_url()
++
++ return True
++
++ def _is_daily_tree(self):
++ # For daily trees
++ if not self._check_manifest("daily/MANIFEST"):
++ return False
++
++ self._url_prefix = "daily"
++ self._set_media_paths()
++ self.os_variant = self._detect_debian_osdict_from_url()
++
++ return True
++
++ def _is_install_cd(self):
++ # For install CDs
++ if not self._check_info(".disk/info"):
++ return False
++
++ if self.arch == "x86_64":
++ kernel_initrd_pair = ("install.amd/vmlinuz", "install.amd/initrd.gz")
++ elif self.arch == "i686":
++ kernel_initrd_pair = ("install.386/vmlinuz", "install.386/initrd.gz")
++ elif self.arch == "s390x":
++ kernel_initrd_pair = ("boot/linux_vm", "boot/root.bin")
++ else:
++ kernel_initrd_pair = ("install/vmlinuz", "install/initrd.gz")
++ self._hvm_kernel_paths += [kernel_initrd_pair]
++ self._xen_kernel_paths += [kernel_initrd_pair]
++
++ return True
++
++ def isValidStore(self):
++ return any(check() for check in [
++ self._is_regular_tree,
++ self._is_daily_tree,
++ self._is_install_cd,
++ ])
++
++
++ ################################
++ # osdict autodetection helpers #
++ ################################
++
++ def _detect_debian_osdict_from_url(self):
++ root = self.name.lower()
++ oses = [n for n in OSDB.list_os() if n.name.startswith(root)]
++
++ if self._url_prefix == "daily":
++ logging.debug("Appears to be debian 'daily' URL, using latest "
++ "debian OS")
++ return oses[0].name
++
++ for osobj in oses:
++ if osobj.codename:
++ # Ubuntu codenames look like 'Warty Warthog'
++ codename = osobj.codename.split()[0].lower()
++ else:
++ if " " not in osobj.label:
++ continue
++ # Debian labels look like 'Debian Sarge'
++ codename = osobj.label.split()[1].lower()
++
++ if ("/%s/" % codename) in self.uri:
++ logging.debug("Found codename=%s in the URL string", codename)
++ return osobj.name
++
++ logging.debug("Didn't find any known codename in the URL string")
++ return self.os_variant
++
++
++class UbuntuDistro(DebianDistro):
++ # http://archive.ubuntu.com/ubuntu/dists/natty/main/installer-amd64/
++ name = "Ubuntu"
++ urldistro = "ubuntu"
++
++ def _is_tree_iso(self):
++ # For trees based on ISO's
++ if not self._check_info("install/netboot/version.info"):
++ return False
++
++ self._url_prefix = "install"
++ self._set_media_paths()
++ self.os_variant = self._detect_debian_osdict_from_url()
++
++ return True
++
++ def _is_install_cd(self):
++ # For install CDs
++ if not self._check_info(".disk/info"):
++ return False
++
++ if not self.arch == "s390x":
++ kernel_initrd_pair = ("linux", "initrd.gz")
++ else:
++ kernel_initrd_pair = ("boot/kernel.ubuntu", "boot/initrd.ubuntu")
++
++ self._hvm_kernel_paths += [kernel_initrd_pair]
++ self._xen_kernel_paths += [kernel_initrd_pair]
++
++ return True
++
++
++
++class MandrivaDistro(Distro):
++ # ftp://ftp.uwsg.indiana.edu/linux/mandrake/official/2007.1/x86_64/
++ name = "Mandriva/Mageia"
++ urldistro = "mandriva"
++
++ _boot_iso_paths = ["install/images/boot.iso"]
++ _xen_kernel_paths = []
++
++ def __init__(self, *args, **kwargs):
++ Distro.__init__(self, *args, **kwargs)
++ self._hvm_kernel_paths = []
++
++ # At least Mageia 5 uses arch in the names
++ self._hvm_kernel_paths += [
++ ("isolinux/%s/vmlinuz" % self.arch,
++ "isolinux/%s/all.rdz" % self.arch)]
++
++ # Kernels for HVM: valid for releases 2007.1, 2008.*, 2009.0
++ self._hvm_kernel_paths += [
++ ("isolinux/alt0/vmlinuz", "isolinux/alt0/all.rdz")]
++
++
++ def isValidStore(self):
++ # Don't support any paravirt installs
++ if self.type is not None and self.type != "hvm":
++ return False
++
++ # Mandriva websites / media appear to have a VERSION
++ # file in top level which we can use as our 'magic'
++ # check for validity
++ if not self.fetcher.hasFile("VERSION"):
++ return False
++
++ for name in ["Mandriva", "Mageia"]:
++ if self._fetchAndMatchRegex("VERSION", ".*%s.*" % name):
++ return True
++
++ logging.debug("Regex didn't match, not a %s distro", self.name)
++ return False
++
++
++class ALTLinuxDistro(Distro):
++ # altlinux doesn't have installable URLs, so this is just for a
++ # mounted ISO
++ name = "ALT Linux"
++ urldistro = "altlinux"
++
++ _boot_iso_paths = [("altinst", "live")]
++ _hvm_kernel_paths = [("syslinux/alt0/vmlinuz", "syslinux/alt0/full.cz")]
++ _xen_kernel_paths = []
++
++ def isValidStore(self):
++ # Don't support any paravirt installs
++ if self.type is not None and self.type != "hvm":
++ return False
++
++ if not self.fetcher.hasFile(".disk/info"):
++ return False
++
++ if self._fetchAndMatchRegex(".disk/info", ".*%s.*" % self.name):
++ return True
++
++ logging.debug("Regex didn't match, not a %s distro", self.name)
++ return False
++
++
++# Build list of all *Distro classes
++def _build_distro_list():
++ allstores = []
++ for obj in globals().values():
++ if type(obj) is type and issubclass(obj, Distro) and obj.name:
++ allstores.append(obj)
++
++ seen_urldistro = []
++ for obj in allstores:
++ if obj.urldistro and obj.urldistro in seen_urldistro:
++ raise RuntimeError("programming error: duplicate urldistro=%s" %
++ obj.urldistro)
++ seen_urldistro.append(obj.urldistro)
++
++ # Always stick GenericDistro at the end, since it's a catchall
++ allstores.remove(GenericDistro)
++ allstores.append(GenericDistro)
++
++ return allstores
++
++_allstores = _build_distro_list()
diff --git a/system/virt-manager/virt-manager.SlackBuild b/system/virt-manager/virt-manager.SlackBuild
index 68306f40a7..fee8d674ab 100644
--- a/system/virt-manager/virt-manager.SlackBuild
+++ b/system/virt-manager/virt-manager.SlackBuild
@@ -7,7 +7,7 @@
# Lots of mods by rworkman for 1.x
PRGNAM=virt-manager
-VERSION=${VERSION:-1.4.2}
+VERSION=${VERSION:-1.4.3}
BUILD=${BUILD:-1}
TAG=${TAG:-_SBo}
diff --git a/system/virt-manager/virt-manager.info b/system/virt-manager/virt-manager.info
index afdf4940fc..142455be70 100644
--- a/system/virt-manager/virt-manager.info
+++ b/system/virt-manager/virt-manager.info
@@ -1,8 +1,8 @@
PRGNAM="virt-manager"
-VERSION="1.4.2"
+VERSION="1.4.3"
HOMEPAGE="http://virt-manager.org/"
-DOWNLOAD="http://virt-manager.org/download/sources/virt-manager/virt-manager-1.4.2.tar.gz"
-MD5SUM="e143252290501b21da1a213885c12ed8"
+DOWNLOAD="http://virt-manager.org/download/sources/virt-manager/virt-manager-1.4.3.tar.gz"
+MD5SUM="077916aae947bf2461e7d7d1fb2ddfd3"
DOWNLOAD_x86_64=""
MD5SUM_x86_64=""
REQUIRES="libosinfo libvirt-glib libvirt-python gnome-python2-gconf tunctl ipaddr-py python-requests gtk-vnc spice-gtk vte3"