util: Move uri_split to its own URISplit class

Does what uri_split did, but wraps it all up in an object that makes
handling the data easier, and makes it easy to extend.
This commit is contained in:
Cole Robinson 2014-12-09 08:22:51 -05:00
parent 81009caa54
commit cff08223ba
7 changed files with 154 additions and 133 deletions

View File

@ -22,7 +22,6 @@ from gi.repository import GObject
import logging
import os
import re
import socket
import time
import traceback
@ -359,36 +358,17 @@ class vmmConnection(vmmGObject):
@show_kvm: Show hv as QEMU/KVM. Only works if connection is
active though
"""
def match_whole_string(orig, reg):
match = re.match(reg, orig)
if not match:
return False
uriinfo = virtinst.URISplit(self.get_uri())
return ((match.end() - match.start()) == len(orig))
def is_ip_addr(orig):
return match_whole_string(orig, "[0-9.]+")
(scheme, username, hostname,
path, ignore, ignore) = util.uri_split(self.get_uri())
hostname, port = self.get_backend().get_uri_host_port()
port = port or ""
hv = ""
rest = ""
transport = ""
port = ""
if scheme.count("+"):
transport = scheme.split("+")[1]
scheme = scheme.split("+")[0]
if uriinfo.hostname:
hostname = uriinfo.hostname
if show_user and uriinfo.username:
hostname = uriinfo.username + "@" + hostname
if uriinfo.port:
hostname += ":" + uriinfo.port
if hostname:
if show_user and username:
hostname = username + "@" + hostname
if port:
hostname += ":" + port
if shorthost and not is_ip_addr(hostname):
if shorthost and not uriinfo.host_is_ipv4_string:
rest = hostname.split(".")[0]
else:
rest = hostname
@ -411,21 +391,21 @@ class vmmConnection(vmmGObject):
"xenapi" : "XenAPI",
}
hv = scheme
if scheme in pretty_map:
hv = pretty_map[scheme]
hv = uriinfo.scheme
if hv in pretty_map:
hv = pretty_map[hv]
if hv == "QEMU" and show_kvm and self.caps.is_kvm_available():
hv += "/KVM"
if show_transport and transport:
hv += "+" + transport
if show_transport and uriinfo.transport:
hv += "+" + uriinfo.transport
if path and path != "/system" and path != "/":
if path == "/session":
if uriinfo.path and uriinfo.path != "/system" and uriinfo.path != "/":
if uriinfo.path == "/session":
hv += " Usermode"
else:
hv += " %s" % os.path.basename(path)
hv += " %s" % os.path.basename(uriinfo.path)
if self._backend.fake_name():
hv = self._backend.fake_name()

View File

@ -26,6 +26,7 @@ from gi.repository import Gdk
from gi.repository import GdkPixbuf
from virtinst import util
from virtinst import URISplit
from . import vmmenu
from . import uiutil
@ -703,8 +704,8 @@ class vmmManager(vmmGObjectUI):
connrows = [row for row in self.rows.values() if row[ROW_IS_CONN]]
for row in connrows:
conn = row[ROW_HANDLE]
connsplit = util.uri_split(conn.get_uri())
scheme = connsplit[0]
connuriinfo = URISplit(conn.get_uri())
scheme = connuriinfo.scheme
show_transport = False
show_user = False
@ -713,15 +714,15 @@ class vmmManager(vmmGObjectUI):
checkconn = checkrow[ROW_HANDLE]
if conn is checkconn:
continue
checkconnsplit = util.uri_split(checkconn.get_uri())
checkscheme = checkconnsplit[0]
checkuriinfo = URISplit(checkconn.get_uri())
checkscheme = checkuriinfo.scheme
if ((scheme.split("+")[0] == checkscheme.split("+")[0]) and
connsplit[2] == checkconnsplit[2] and
connsplit[3] == checkconnsplit[3]):
if (scheme == checkscheme and
connuriinfo.hostname == checkuriinfo.hostname and
connuriinfo.path == checkuriinfo.path):
show_transport = True
if ("+" in scheme and "+" in checkscheme and
scheme.split("+")[1] == checkscheme.split("+")[1]):
if (connuriinfo.transport and
connuriinfo.transport == checkuriinfo.transport):
show_user = True
newname = conn.get_pretty_desc(

View File

@ -28,6 +28,7 @@ from gi.repository import Gtk
import libvirt
from virtinst import util
from virtinst import URISplit
from . import uiutil
from .baseclass import vmmGObjectUI
@ -35,18 +36,6 @@ from .asyncjob import vmmAsyncJob
from .domain import vmmDomain
def uri_join(uri_tuple):
scheme, user, host, path, query, fragment = uri_tuple
user = (user and (user + "@") or "")
host = host or ""
path = path or "/"
query = (query and ("?" + query) or "")
fragment = (fragment and ("#" + fragment) or "")
return "%s://%s%s%s%s%s" % (scheme, user, host, path, fragment, query)
class vmmMigrateDialog(vmmGObjectUI):
def __init__(self, vm, engine):
vmmGObjectUI.__init__(self, "migrate.ui", "vmm-migrate")
@ -267,16 +256,11 @@ class vmmMigrateDialog(vmmGObjectUI):
return self.edit_uri(srcuri, desthost, None)
def edit_uri(self, uri, hostname, port):
split = list(util.uri_split(uri))
uriinfo = URISplit(uri)
hostname = hostname or split[2]
if port:
if hostname.count(":"):
hostname = hostname.split(":")[0]
hostname += ":%s" % port
split[2] = hostname
return uri_join(tuple(split))
uriinfo.hostname = hostname or uriinfo.hostname
uriinfo.port = port or uriinfo.port
return uriinfo.rebuild_uri()
def build_migrate_uri(self, destconn, srcuri):
conn = self.conn

View File

@ -36,6 +36,7 @@ stable_defaults = _cliconfig.stable_defaults
from . import util
from virtinst import support
from virtinst.uri import URISplit
from virtinst.osxml import OSXML
from virtinst.domainfeatures import DomainFeatures

View File

@ -26,6 +26,7 @@ from . import pollhelpers
from . import support
from . import util
from . import capabilities as CapabilitiesParser
from . import URISplit
from .cli import VirtOptionString
from .guest import Guest
from .nodedev import NodeDevice
@ -81,7 +82,7 @@ class VirtualConnection(object):
self._test_opts = {}
self._libvirtconn = None
self._urisplits = util.uri_split(self._uri)
self._urisplits = URISplit(self._uri)
self._caps = None
self._support_cache = {}
@ -162,7 +163,7 @@ class VirtualConnection(object):
self._libvirtconn = conn
if not self._open_uri:
self._uri = self._libvirtconn.getURI()
self._urisplits = util.uri_split(self._uri)
self._urisplits = URISplit(self._uri)
def set_keep_alive(self, interval, count):
if hasattr(self._libvirtconn, "setKeepAlive"):
@ -335,56 +336,40 @@ class VirtualConnection(object):
def is_remote(self):
return (hasattr(self, "_virtinst__fake_conn_remote") or
self._urisplits[2])
self._urisplits.hostname)
def get_uri_hostname(self):
return self._urisplits[2] or "localhost"
return self._urisplits.hostname or "localhost"
def get_uri_host_port(self):
hostname = self.get_uri_hostname()
port = None
if hostname.startswith("[") and "]" in hostname:
if "]:" in hostname:
hostname, port = hostname.rsplit(":", 1)
hostname = "".join(hostname[1:].split("]", 1))
elif ":" in hostname:
hostname, port = hostname.split(":", 1)
return hostname, port
return self.get_uri_hostname(), self._urisplits.port
def get_uri_transport(self):
scheme = self._urisplits[0]
username = self._urisplits[1]
offset = scheme.find("+")
if offset != -1:
return [scheme[offset + 1:], username]
if self._urisplits.transport:
return [self._urisplits.transport, self._urisplits.username]
return [None, None]
def get_uri_driver(self):
scheme = self._urisplits[0]
offset = scheme.find("+")
if offset > 0:
return scheme[:offset]
return scheme
return self._urisplits.scheme
def is_session_uri(self):
return self._urisplits[3] == "/session"
return self._urisplits.path == "/session"
def is_qemu(self):
return self._urisplits[0].startswith("qemu")
return self._urisplits.scheme.startswith("qemu")
def is_qemu_system(self):
return (self.is_qemu() and self._urisplits[3] == "/system")
return (self.is_qemu() and self._urisplits.path == "/system")
def is_qemu_session(self):
return (self.is_qemu() and self.is_session_uri())
def is_test(self):
return self._urisplits[0].startswith("test")
return self._urisplits.scheme.startswith("test")
def is_xen(self):
return (self._urisplits[0].startswith("xen") or
self._urisplits[0].startswith("libxl"))
return (self._urisplits.scheme.startswith("xen") or
self._urisplits.scheme.startswith("libxl"))
def is_lxc(self):
return self._urisplits[0].startswith("lxc")
return self._urisplits.scheme.startswith("lxc")
def is_openvz(self):
return self._urisplits[0].startswith("openvz")
return self._urisplits.scheme.startswith("openvz")
def is_container(self):
return self.is_lxc() or self.is_openvz()

105
virtinst/uri.py Normal file
View File

@ -0,0 +1,105 @@
#
# Copyright 2014 Red Hat, Inc.
#
# 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 re
class URISplit(object):
"""
Parse an arbitrary URI into its individual parts
"""
def __init__(self, uri):
self.uri = uri
(self.scheme, self.username, self.hostname,
self.path, self.query, self.fragment) = self._split(self.uri)
self.transport = ''
if "+" in self.scheme:
self.scheme, self.transport = self.scheme.rsplit("+", 1)
self.port = ''
self.is_ipv6 = False
if self.hostname.startswith("[") and "]" in self.hostname:
if "]:" in self.hostname:
self.hostname, self.port = self.hostname.rsplit(":", 1)
self.hostname = "".join(self.hostname[1:].split("]", 1))
self.is_ipv6 = True
elif ":" in self.hostname:
self.hostname, self.port = self.hostname.split(":", 1)
self.host_is_ipv4_string = bool(re.match(self.hostname, "[0-9.]+"))
###################
# Private helpers #
###################
def _split(self, uri):
def splitnetloc(url, start=0):
for c in '/?#': # the order is important!
delim = url.find(c, start)
if delim >= 0:
break
else:
delim = len(url)
return url[start:delim], url[delim:]
username = netloc = query = fragment = ''
i = uri.find(":")
if i > 0:
scheme, uri = uri[:i].lower(), uri[i + 1:]
if uri[:2] == '//':
netloc, uri = splitnetloc(uri, 2)
offset = netloc.find("@")
if offset > 0:
username = netloc[0:offset]
netloc = netloc[offset + 1:]
if '#' in uri:
uri, fragment = uri.split('#', 1)
if '?' in uri:
uri, query = uri.split('?', 1)
else:
scheme = uri.lower()
return scheme, username, netloc, uri, query, fragment
##############
# Public API #
##############
def rebuild_uri(self):
ret = self.scheme
if self.transport:
ret += "+" % self.transport
ret += "://"
if self.username:
ret += self.username + "@"
if self.hostname:
host = self.hostname
if self.is_ipv6:
host = "[%s]" % self.hostname
ret += host
if self.port:
ret += ":" + self.port
if self.query:
ret += "?" + self.query
if self.fragment:
ret += "#" + self.fragment
return ret

View File

@ -365,41 +365,6 @@ def xml_escape(xml):
return xml
def uri_split(uri):
"""
Parse a libvirt hypervisor uri into it's individual parts
@returns: tuple of the form (scheme (ex. 'qemu', 'xen+ssh'), username,
hostname, path (ex. '/system'), query,
fragment)
"""
def splitnetloc(url, start=0):
for c in '/?#': # the order is important!
delim = url.find(c, start)
if delim >= 0:
break
else:
delim = len(url)
return url[start:delim], url[delim:]
username = netloc = query = fragment = ''
i = uri.find(":")
if i > 0:
scheme, uri = uri[:i].lower(), uri[i + 1:]
if uri[:2] == '//':
netloc, uri = splitnetloc(uri, 2)
offset = netloc.find("@")
if offset > 0:
username = netloc[0:offset]
netloc = netloc[offset + 1:]
if '#' in uri:
uri, fragment = uri.split('#', 1)
if '?' in uri:
uri, query = uri.split('?', 1)
else:
scheme = uri.lower()
return scheme, username, netloc, uri, query, fragment
def is_error_nosupport(err):
"""
Check if passed exception indicates that the called libvirt command isn't