Change in vdsm[ovirt-3.5]: sd: fix volume path returned by linkBCImage
by Federico Simoncelli
Hello Dan Kenigsberg,
I'd like you to do a code review. Please visit
http://gerrit.ovirt.org/29485
to review the following change.
Change subject: sd: fix volume path returned by linkBCImage
......................................................................
sd: fix volume path returned by linkBCImage
In a previous commit (c072945 One shot prepare) we involuntarily
changed the path used for virtual machine images from:
/rhev/data-center/<spUUID>/<sdUUID>/images/<imgUUID>/<volUUID>
to:
/rhev/data-center/mnt/blockSD/<sdUUID>/images/<imgUUID>/<volUUID>
This patch reverts to the previous path in order to minimize the
differences between different versions of vdsm that could lead to
live migration issues, e.g.
libvirtError: invalid argument: invalid path ... not assigned to
domain
Change-Id: Iea497b574d9a9a7e0e9b8e234e2bd9b9d983a60c
Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=1059482
Signed-off-by: Federico Simoncelli <fsimonce(a)redhat.com>
Reviewed-on: http://gerrit.ovirt.org/24315
Reviewed-by: Dan Kenigsberg <danken(a)redhat.com>
---
M vdsm/storage/blockSD.py
M vdsm/storage/fileSD.py
M vdsm/storage/sd.py
3 files changed, 8 insertions(+), 4 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/85/29485/1
diff --git a/vdsm/storage/blockSD.py b/vdsm/storage/blockSD.py
index 5c7bf42..36078d0 100644
--- a/vdsm/storage/blockSD.py
+++ b/vdsm/storage/blockSD.py
@@ -1041,8 +1041,7 @@
return rems
def linkBCImage(self, imgPath, imgUUID):
- dst = os.path.join(self.mountpoint, self.sdUUID, sd.DOMAIN_IMAGES,
- imgUUID)
+ dst = self.getLinkBCImagePath(imgUUID)
self.log.debug("Creating symlink from %s to %s", imgPath, dst)
try:
os.symlink(imgPath, dst)
diff --git a/vdsm/storage/fileSD.py b/vdsm/storage/fileSD.py
index 6732ddc..e6b1a7c 100644
--- a/vdsm/storage/fileSD.py
+++ b/vdsm/storage/fileSD.py
@@ -452,8 +452,8 @@
for k, v in volumes.iteritems())
def linkBCImage(self, imgPath, imgUUID):
- return os.path.join(self.mountpoint, self.sdUUID, sd.DOMAIN_IMAGES,
- imgUUID)
+ # Nothing to do here other than returning the path
+ return self.getLinkBCImagePath(imgUUID)
def createImageLinks(self, srcImgPath, imgUUID):
"""
diff --git a/vdsm/storage/sd.py b/vdsm/storage/sd.py
index be3cc34..c65fd03 100644
--- a/vdsm/storage/sd.py
+++ b/vdsm/storage/sd.py
@@ -25,6 +25,7 @@
from collections import namedtuple
import codecs
+import image
import storage_exception as se
import misc
import resourceFactories
@@ -663,6 +664,10 @@
# If it has a repo we don't have multiple domains. Assume single pool
return os.path.join(self.storage_repository, self.getPools()[0])
+ def getLinkBCImagePath(self, imgUUID):
+ return image.Image(self._getRepoPath()) \
+ .getImageDir(self.sdUUID, imgUUID)
+
def getIsoDomainImagesDir(self):
"""
Get 'images' directory from Iso domain
--
To view, visit http://gerrit.ovirt.org/29485
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iea497b574d9a9a7e0e9b8e234e2bd9b9d983a60c
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: ovirt-3.5
Gerrit-Owner: Federico Simoncelli <fsimonce(a)redhat.com>
Gerrit-Reviewer: Dan Kenigsberg <danken(a)redhat.com>
9 years, 9 months
Change in vdsm[ovirt-3.5]: api: Make remove optional
by Nir Soffer
Hello Piotr Kliczewski, Yaniv Bronhaim, Dan Kenigsberg,
I'd like you to do a code review. Please visit
http://gerrit.ovirt.org/29480
to review the following change.
Change subject: api: Make remove optional
......................................................................
api: Make remove optional
According to the scheama, the "remove" argument in
StoragePool.disconnect is optional, but in API it is defined as
positional argument and requires a value.
This error was probbaly hidden by the fact that engine send False when
using xmlprc. But when using jsonrpc this cause the method call to fail,
which eventually cause host to be stuck in "Unassigned" state in the
engine side. This fix the error on the vdsm side.
Change-Id: Ia6948e4fd1ddefd7e33406a214f0cbfe301c958b
Bug-Url: https://bugzilla.redhat.com/1115033
Relates-to: https://bugzilla.redhat.com/1115044
Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
Reviewed-on: http://gerrit.ovirt.org/29465
Reviewed-by: Yaniv Bronhaim <ybronhei(a)redhat.com>
Reviewed-by: Piotr Kliczewski <piotr.kliczewski(a)gmail.com>
Reviewed-by: Dan Kenigsberg <danken(a)redhat.com>
---
M vdsm/API.py
1 file changed, 1 insertion(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/80/29480/1
diff --git a/vdsm/API.py b/vdsm/API.py
index e739294..ace68d1 100644
--- a/vdsm/API.py
+++ b/vdsm/API.py
@@ -1034,7 +1034,7 @@
def destroy(self, hostID, deprecatedSCSIKey):
return self._irs.destroyStoragePool(self._UUID, hostID)
- def disconnect(self, hostID, deprecatedSCSIKey, remove):
+ def disconnect(self, hostID, deprecatedSCSIKey, remove=False):
return self._irs.disconnectStoragePool(self._UUID, hostID, remove)
def disconnectStorageServer(self, domainType, connectionParams):
--
To view, visit http://gerrit.ovirt.org/29480
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia6948e4fd1ddefd7e33406a214f0cbfe301c958b
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: ovirt-3.5
Gerrit-Owner: Nir Soffer <nsoffer(a)redhat.com>
Gerrit-Reviewer: Dan Kenigsberg <danken(a)redhat.com>
Gerrit-Reviewer: Piotr Kliczewski <piotr.kliczewski(a)gmail.com>
Gerrit-Reviewer: Yaniv Bronhaim <ybronhei(a)redhat.com>
9 years, 9 months
Change in vdsm[ovirt-3.5]: bridge: Show more info when method call fail
by Nir Soffer
Hello Yaniv Bronhaim, Dan Kenigsberg,
I'd like you to do a code review. Please visit
http://gerrit.ovirt.org/29476
to review the following change.
Change subject: bridge: Show more info when method call fail
......................................................................
bridge: Show more info when method call fail
When the bridge try to run a method dynamically and the number of
arguments does not match the function definition, we get an unhelpful
TypeError. Now a more specific and verbose error is raised:
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/yajsonrpc/__init__.py",
line 480, in _serveRequest
res = method(**params)
File "/usr/share/vdsm/rpc/Bridge.py", line 254, in _dynamicMethod
raise InvalidCall(fn, methodArgs, e)
InvalidCall: Attempt to call function: <bound method
StoragePool.disconnect of <API.StoragePool object at 0x7f77046397d0>>
with arguments: (1, u'2440ff3d-275f-42e6-b204-7d055b26b174') error:
disconnect() takes exactly 4 arguments (3 given)
(Traceback lines wrapped for the commit message)
Change-Id: I9ec0a745ec65d3994e06a0b72ded9b7bbe55b1ae
Relates-to: https://bugzilla.redhat.com/1115033
Relates-to: https://bugzilla.redhat.com/1115044
Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
Reviewed-on: http://gerrit.ovirt.org/29457
Reviewed-by: Yaniv Bronhaim <ybronhei(a)redhat.com>
Reviewed-by: Dan Kenigsberg <danken(a)redhat.com>
---
M vdsm/rpc/Bridge.py
1 file changed, 16 insertions(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/76/29476/1
diff --git a/vdsm/rpc/Bridge.py b/vdsm/rpc/Bridge.py
index 7e898de..e6fcd9a 100644
--- a/vdsm/rpc/Bridge.py
+++ b/vdsm/rpc/Bridge.py
@@ -36,6 +36,18 @@
self.message = message
+class InvalidCall(Exception):
+
+ def __init__(self, function, arguments, error):
+ self.function = function
+ self.arguments = arguments
+ self.error = error
+
+ def __str__(self):
+ return ("Attempt to call function: %s with arguments: %s error: %s" %
+ (self.function, self.arguments, self.error))
+
+
class DynamicBridge(object):
def __init__(self):
self.api = vdsmapi.get_api()
@@ -236,7 +248,10 @@
result = fn(api, argobj)
else:
fn = getattr(api, methodName)
- result = fn(*methodArgs)
+ try:
+ result = fn(*methodArgs)
+ except TypeError as e:
+ raise InvalidCall(fn, methodArgs, e)
if result['status']['code']:
code = result['status']['code']
--
To view, visit http://gerrit.ovirt.org/29476
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I9ec0a745ec65d3994e06a0b72ded9b7bbe55b1ae
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: ovirt-3.5
Gerrit-Owner: Nir Soffer <nsoffer(a)redhat.com>
Gerrit-Reviewer: Dan Kenigsberg <danken(a)redhat.com>
Gerrit-Reviewer: Yaniv Bronhaim <ybronhei(a)redhat.com>
9 years, 9 months
Change in vdsm[master]: vdsm: verifyingTransport testing
by Nir Soffer
Nir Soffer has posted comments on this change.
Change subject: vdsm: verifyingTransport testing
......................................................................
Patch Set 9:
(1 comment)
Nice - but there is duplicate test.
http://gerrit.ovirt.org/#/c/28858/9/tests/sslTests.py
File tests/sslTests.py:
Line 122: with verifyingclient(KEY_FILE, OTHER_CRT_FILE) as client:
Line 123: with self.assertRaises(ssl.SSLError):
Line 124: client.add(2, 3)
Line 125:
Line 126: def test_key_do_not_match_with_cert(self):
This is the same as test_cert_do_not_match_with_key - did you mean to use different combination here?
Line 127: with verifyingclient(KEY_FILE, OTHER_CRT_FILE) as client:
Line 128: with self.assertRaises(ssl.SSLError):
Line 129: client.add(2, 3)
Line 130:
--
To view, visit http://gerrit.ovirt.org/28858
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: comment
Gerrit-Change-Id: I1a706d4d90fdf446b06530288d947d96934e45f2
Gerrit-PatchSet: 9
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Piotr Kliczewski <piotr.kliczewski(a)gmail.com>
Gerrit-Reviewer: Dan Kenigsberg <danken(a)redhat.com>
Gerrit-Reviewer: Francesco Romani <fromani(a)redhat.com>
Gerrit-Reviewer: Nir Soffer <nsoffer(a)redhat.com>
Gerrit-Reviewer: Piotr Kliczewski <piotr.kliczewski(a)gmail.com>
Gerrit-Reviewer: Saggi Mizrahi <smizrahi(a)redhat.com>
Gerrit-Reviewer: Yaniv Bronhaim <ybronhei(a)redhat.com>
Gerrit-Reviewer: automation(a)ovirt.org
Gerrit-Reviewer: oVirt Jenkins CI Server
Gerrit-HasComments: Yes
9 years, 9 months
Change in vdsm[master]: netlink: simplify string conversion methods
by asegurap@redhat.com
Antoni Segura Puimedon has uploaded a new change for review.
Change subject: netlink: simplify string conversion methods
......................................................................
netlink: simplify string conversion methods
There are multiple string handling needs shared between the netlink
modules. This patch unifies them to simplify all the modules.
Change-Id: I3cdd56cd243095d75a37c66d79e13c2715642d97
Signed-off-by: Antoni S. Puimedon <asegurap(a)redhat.com>
---
M lib/vdsm/netlink/__init__.py
M lib/vdsm/netlink/addr.py
M lib/vdsm/netlink/link.py
3 files changed, 31 insertions(+), 48 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/73/27473/1
diff --git a/lib/vdsm/netlink/__init__.py b/lib/vdsm/netlink/__init__.py
index c7bb58f..4eaf80a 100644
--- a/lib/vdsm/netlink/__init__.py
+++ b/lib/vdsm/netlink/__init__.py
@@ -18,8 +18,8 @@
# Refer to the README and COPYING files for full details of the license
#
from contextlib import contextmanager
-from ctypes import (CDLL, CFUNCTYPE, c_char_p, c_int, c_void_p, c_size_t,
- get_errno)
+from ctypes import (CDLL, CFUNCTYPE, c_char, c_char_p, c_int, c_void_p,
+ c_size_t, get_errno, sizeof)
from distutils.version import StrictVersion
from Queue import Empty, Queue
from threading import BoundedSemaphore
@@ -28,6 +28,7 @@
_POOL_SIZE = 5
_NETLINK_ROUTE = 0
+CHARBUFFSIZE = 40 # Increased to fit IPv6 expanded representations
class NLSocketPool(object):
@@ -84,6 +85,25 @@
_nl_cache_free(cache)
+def _nladdr_to_str(addr):
+ """Returns the textual representation of a netlink address (be it hardware
+ or IP) or None if the address is None"""
+ if addr is not None:
+ address = (c_char * CHARBUFFSIZE)()
+ return _nl_addr2str(addr, address, sizeof(address))
+
+
+def _nlaf_to_str(af_num):
+ """Returns the textual address family representation of the numerical id"""
+ family = (c_char * CHARBUFFSIZE)()
+ return _nl_af2str(af_num, family, sizeof(family))
+
+
+def _nlscope_to_str(scope_num):
+ """Returns the textual scope representation of the numerical id"""
+ scope = (c_char * CHARBUFFSIZE)()
+ return _rtnl_scope2str(scope_num, scope, sizeof(scope))
+
# C function prototypes
# http://docs.python.org/2/library/ctypes.html#function-prototypes
# This helps ctypes know the calling conventions it should use to communicate
diff --git a/lib/vdsm/netlink/addr.py b/lib/vdsm/netlink/addr.py
index 33542f5..2b14b7e 100644
--- a/lib/vdsm/netlink/addr.py
+++ b/lib/vdsm/netlink/addr.py
@@ -16,18 +16,15 @@
#
# Refer to the README and COPYING files for full details of the license
#
-from ctypes import (CFUNCTYPE, byref, c_char, c_char_p, c_int, c_size_t,
- c_void_p, sizeof)
+from ctypes import CFUNCTYPE, byref, c_int, c_void_p
from functools import partial
from . import (_alloc_cache, _cache_manager, _nl_cache_get_first,
_nl_cache_get_next)
from . import _char_proto, _int_proto, _void_proto
-from . import (_ethtool_uses_libnl3, LIBNL_ROUTE, _nl_addr2str, _nl_af2str,
- _nl_geterror, _pool)
+from . import _ethtool_uses_libnl3, LIBNL_ROUTE, _nl_geterror, _pool
+from . import (_nladdr_to_str, _nlaf_to_str, _nlscope_to_str)
from .link import _nl_link_cache, _link_index_to_name
-
-CHARBUFFSIZE = 40 # Increased to fit IPv6 expanded representations
def iter_addrs():
@@ -49,30 +46,11 @@
'label': (_rtnl_addr_get_label(addr) or
_link_index_to_name(link_cache, index)),
'index': index,
- 'family': _addr_family(addr),
+ 'family': _nlaf_to_str(_rtnl_addr_get_family(addr)),
'prefixlen': _rtnl_addr_get_prefixlen(addr),
- 'scope': _addr_scope(addr),
+ 'scope': _nlscope_to_str(_rtnl_addr_get_scope(addr)),
'flags': _rtnl_addr_get_flags(addr),
- 'address': _addr_local(addr)}
-
-
-def _addr_scope(addr):
- """Returns the scope name for which the address is defined."""
- scope = (c_char * CHARBUFFSIZE)()
- return _rtnl_scope2str(_rtnl_addr_get_scope(addr), scope, sizeof(scope))
-
-
-def _addr_family(addr):
- """Returns the family name of the address."""
- family = (c_char * CHARBUFFSIZE)()
- return _nl_af2str(_rtnl_addr_get_family(addr), family, sizeof(family))
-
-
-def _addr_local(addr):
- """Returns the textual representation of the address."""
- address = (c_char * CHARBUFFSIZE)()
- return _nl_addr2str(_rtnl_addr_get_local(addr), address, sizeof(address))
-
+ 'address': _nladdr_to_str(_rtnl_addr_get_local(addr))}
# C function prototypes
# http://docs.python.org/2/library/ctypes.html#function-prototypes
@@ -107,5 +85,3 @@
_rtnl_addr_get_scope = _int_proto(('rtnl_addr_get_scope', LIBNL_ROUTE))
_rtnl_addr_get_flags = _int_proto(('rtnl_addr_get_flags', LIBNL_ROUTE))
_rtnl_addr_get_local = _void_proto(('rtnl_addr_get_local', LIBNL_ROUTE))
-_rtnl_scope2str = CFUNCTYPE(c_char_p, c_int, c_char_p, c_size_t)((
- 'rtnl_scope2str', LIBNL_ROUTE))
diff --git a/lib/vdsm/netlink/link.py b/lib/vdsm/netlink/link.py
index 5c3583d..e138c67 100644
--- a/lib/vdsm/netlink/link.py
+++ b/lib/vdsm/netlink/link.py
@@ -24,10 +24,8 @@
from . import (_alloc_cache, _cache_manager, _nl_cache_get_first,
_nl_cache_get_next)
from . import _char_proto, _int_proto, _void_proto
-from . import (_ethtool_uses_libnl3, LIBNL_ROUTE, _nl_addr2str, _nl_geterror,
- _pool)
-
-CHARBUFFSIZE = 40 # Increased to fit IPv6 expanded representations
+from . import _ethtool_uses_libnl3, LIBNL_ROUTE, _nl_geterror, _pool
+from . import _nladdr_to_str, CHARBUFFSIZE
def get_link(name):
@@ -55,7 +53,7 @@
def _link_info(cache, link):
"""Returns a dictionary with the information of the link object."""
info = {}
- info['address'] = _link_address(link)
+ info['address'] = _nladdr_to_str(_rtnl_link_get_addr(link)),
info['flags'] = _rtnl_link_get_flags(link)
info['index'] = _rtnl_link_get_ifindex(link)
info['mtu'] = _rtnl_link_get_mtu(link)
@@ -90,17 +88,6 @@
"""Returns the textual name of the link with index equal to link_index."""
name = (c_char * CHARBUFFSIZE)()
return _rtnl_link_i2name(cache, link_index, name, sizeof(name))
-
-
-def _link_address(link):
- """Returns the MAC address of a link object or None if the link does not
- have a physical address."""
- nl_addr = _rtnl_link_get_addr(link)
- if nl_addr:
- address = (c_char * CHARBUFFSIZE)()
- return _nl_addr2str(nl_addr, address, sizeof(address))
- else:
- return None
def _link_state(link):
--
To view, visit http://gerrit.ovirt.org/27473
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I3cdd56cd243095d75a37c66d79e13c2715642d97
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Antoni Segura Puimedon <asegurap(a)redhat.com>
9 years, 9 months
Change in vdsm[master]: netlink: move netlink into a lib vdsm subpackage
by asegurap@redhat.com
Antoni Segura Puimedon has uploaded a new change for review.
Change subject: netlink: move netlink into a lib vdsm subpackage
......................................................................
netlink: move netlink into a lib vdsm subpackage
netlink.py was increasingly getting new netlink entities making the
module difficult to follow. This patch splits each entity on a
separate module of a netlink package so that each new module is
easy to reason about.
Change-Id: I9b393588ccb3ac0c4529446c285570f49cdb1e28
Signed-off-by: Antoni S. Puimedon <asegurap(a)redhat.com>
---
M debian/vdsm-python.install
M lib/vdsm/Makefile.am
M lib/vdsm/ipwrapper.py
M lib/vdsm/netinfo.py
D lib/vdsm/netlink.py
A lib/vdsm/netlink/Makefile.am
A lib/vdsm/netlink/__init__.py
A lib/vdsm/netlink/addr.py
A lib/vdsm/netlink/link.py
M vdsm.spec.in
10 files changed, 446 insertions(+), 338 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/72/27472/1
diff --git a/debian/vdsm-python.install b/debian/vdsm-python.install
index eac4a4b..bb7339e 100644
--- a/debian/vdsm-python.install
+++ b/debian/vdsm-python.install
@@ -11,7 +11,9 @@
./usr/lib/python2.7/dist-packages/vdsm/libvirtconnection.py
./usr/lib/python2.7/dist-packages/vdsm/netconfpersistence.py
./usr/lib/python2.7/dist-packages/vdsm/netinfo.py
-./usr/lib/python2.7/dist-packages/vdsm/netlink.py
+./usr/lib/python2.7/dist-packages/vdsm/netlink/__init__.py
+./usr/lib/python2.7/dist-packages/vdsm/netlink/addr.py
+./usr/lib/python2.7/dist-packages/vdsm/netlink/link.py
./usr/lib/python2.7/dist-packages/vdsm/profile.py
./usr/lib/python2.7/dist-packages/vdsm/qemuimg.py
./usr/lib/python2.7/dist-packages/vdsm/tool/__init__.py
diff --git a/lib/vdsm/Makefile.am b/lib/vdsm/Makefile.am
index bb033e1..90f737e 100644
--- a/lib/vdsm/Makefile.am
+++ b/lib/vdsm/Makefile.am
@@ -19,7 +19,7 @@
#
include $(top_srcdir)/build-aux/Makefile.subs
-SUBDIRS=tool
+SUBDIRS=netlink tool
dist_vdsmpylib_PYTHON = \
__init__.py \
@@ -30,7 +30,6 @@
libvirtconnection.py \
netconfpersistence.py \
netinfo.py \
- netlink.py \
profile.py \
qemuimg.py \
SecureXMLRPCServer.py \
diff --git a/lib/vdsm/ipwrapper.py b/lib/vdsm/ipwrapper.py
index c8d6b36..7cd924d 100644
--- a/lib/vdsm/ipwrapper.py
+++ b/lib/vdsm/ipwrapper.py
@@ -286,12 +286,12 @@
def getLinks():
"""Returns a list of Link objects for each link in the system."""
- return [Link.fromDict(data) for data in netlink.iter_links()]
+ return [Link.fromDict(data) for data in netlink.link.iter_links()]
def getLink(dev):
"""Returns the Link object for the specified dev."""
- return Link.fromDict(netlink.get_link(dev))
+ return Link.fromDict(netlink.link.get_link(dev))
@equals
diff --git a/lib/vdsm/netinfo.py b/lib/vdsm/netinfo.py
index 1734966..5301290 100644
--- a/lib/vdsm/netinfo.py
+++ b/lib/vdsm/netinfo.py
@@ -42,8 +42,8 @@
from .ipwrapper import routeGet
from .ipwrapper import routeShowGateways, routeShowAllDefaultGateways
from . import libvirtconnection
+from . import netlink
from .netconfpersistence import RunningConfig
-from .netlink import iter_addrs, iter_links
NET_CONF_DIR = '/etc/sysconfig/network-scripts/'
@@ -636,7 +636,7 @@
def _getIpAddrs():
addrs = defaultdict(list)
- for addr in iter_addrs():
+ for addr in netlink.addr.iter_addrs():
addrs[addr['label']].append(addr)
return addrs
@@ -921,7 +921,7 @@
require a NetInfo object."""
if os.path.exists(os.path.join(NET_PATH, iface, 'brport')): # Is it a port
return True
- for linkDict in iter_links():
+ for linkDict in netlink.link.iter_links():
if linkDict['name'] == iface and 'master' in linkDict: # Is it a slave
return True
if linkDict.get('device') == iface: # Does it back a vlan
@@ -933,6 +933,6 @@
def vlanDevsForIface(iface):
- for linkDict in iter_links():
+ for linkDict in netlink.link.iter_links():
if linkDict.get('device') == iface:
yield linkDict['name']
diff --git a/lib/vdsm/netlink.py b/lib/vdsm/netlink.py
deleted file mode 100644
index 1638ef7..0000000
--- a/lib/vdsm/netlink.py
+++ /dev/null
@@ -1,328 +0,0 @@
-# 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
-#
-# Refer to the README and COPYING files for full details of the license
-#
-
-from contextlib import contextmanager
-from ctypes import (CDLL, CFUNCTYPE, byref, c_char, c_char_p, c_int, c_void_p,
- c_size_t, get_errno, sizeof)
-from distutils.version import StrictVersion
-from functools import partial
-from Queue import Empty, Queue
-from threading import BoundedSemaphore
-import errno
-import ethtool
-
-NETLINK_ROUTE = 0
-_POOL_SIZE = 5
-CHARBUFFSIZE = 40 # Increased to fit IPv6 expanded representations
-
-
-def iter_links():
- """Generator that yields an information dictionary for each link of the
- system."""
- with _pool.socket() as sock:
- with _nl_link_cache(sock) as cache:
- link = _nl_cache_get_first(cache)
- while link:
- yield _link_info(cache, link)
- link = _nl_cache_get_next(link)
-
-
-def iter_addrs():
- """Generator that yields an information dictionary for each network address
- in the system."""
- with _pool.socket() as sock:
- with _nl_addr_cache(sock) as addr_cache:
- with _nl_link_cache(sock) as link_cache: # for index to label
- addr = _nl_cache_get_first(addr_cache)
- while addr:
- yield _addr_info(link_cache, addr)
- addr = _nl_cache_get_next(addr)
-
-
-def get_link(name):
- """Returns the information dictionary of the name specified link."""
- with _pool.socket() as sock:
- with _nl_link_cache(sock) as cache:
- link = _rtnl_link_get_by_name(cache, name)
- if not link:
- raise IOError(errno.ENODEV, '%s is not present in the system' %
- name)
- return _link_info(cache, link)
-
-
-class NLSocketPool(object):
- """Pool of netlink sockets."""
- def __init__(self, size):
- if size <= 0:
- raise ValueError('Invalid socket pool size %r. Must be positive')
- self._semaphore = BoundedSemaphore(size)
- self._sockets = Queue(maxsize=size)
-
- @contextmanager
- def socket(self):
- """Returns a socket from the pool (creating it when needed)."""
- with self._semaphore:
- try:
- sock = self._sockets.get_nowait()
- except Empty:
- sock = _open_socket()
- try:
- yield sock
- finally:
- self._sockets.put_nowait(sock)
-
-
-_pool = NLSocketPool(_POOL_SIZE)
-
-
-def _open_socket():
- """Returns an open netlink socket."""
- sock = _nl_socket_alloc()
- if sock is None:
- raise IOError(get_errno(), 'Failed to allocate netlink handle')
-
- err = _nl_connect(sock, NETLINK_ROUTE)
- if err:
- _nl_socket_free(sock)
- raise IOError(-err, _nl_geterror())
- return sock
-
-
-def _close_socket(sock):
- """Closes and frees the resources of the passed netlink socket."""
- _nl_socket_free(sock)
-
-
-@contextmanager
-def _cache_manager(cache_allocator, sock):
- """Provides a cache using cache_allocator and frees it and its links upon
- exit."""
- cache = cache_allocator(sock)
- try:
- yield cache
- finally:
- _nl_cache_free(cache)
-
-
-def _addr_info(link_cache, addr):
- """Returns a dictionary with the address information."""
- index = _rtnl_addr_get_ifindex(addr)
- return {
- 'label': (_rtnl_addr_get_label(addr) or
- _link_index_to_name(link_cache, index)),
- 'index': index,
- 'family': _addr_family(addr),
- 'prefixlen': _rtnl_addr_get_prefixlen(addr),
- 'scope': _addr_scope(addr),
- 'flags': _rtnl_addr_get_flags(addr),
- 'address': _addr_local(addr)}
-
-
-def _link_info(cache, link):
- """Returns a dictionary with the information of the link object."""
- info = {}
- info['address'] = _link_address(link)
- info['flags'] = _rtnl_link_get_flags(link)
- info['index'] = _rtnl_link_get_ifindex(link)
- info['mtu'] = _rtnl_link_get_mtu(link)
- info['name'] = _rtnl_link_get_name(link)
- info['qdisc'] = _rtnl_link_get_qdisc(link)
- info['state'] = _link_state(link)
-
- # libnl-1 has a bug when getting type information.
- # https://github.com/tgraf/libnl-1.1-stable/issues/1
- # TODO: Add for libnl1 if the bug is fixed
- if _ethtool_uses_libnl3():
- link_type = _rtnl_link_get_type(link)
- if link_type is not None:
- info['type'] = link_type
-
- underlying_device_index = _rtnl_link_get_link(link)
- if underlying_device_index > 0:
- info['device'] = _link_index_to_name(cache, underlying_device_index)
-
- master_index = _rtnl_link_get_master(link)
- if master_index > 0:
- info['master'] = _link_index_to_name(cache, master_index)
-
- vlanid = _rtnl_link_vlan_get_id(link)
- if vlanid >= 0:
- info['vlanid'] = vlanid
-
- return info
-
-
-def _link_index_to_name(cache, link_index):
- """Returns the textual name of the link with index equal to link_index."""
- name = (c_char * CHARBUFFSIZE)()
- return _rtnl_link_i2name(cache, link_index, name, sizeof(name))
-
-
-def _link_address(link):
- """Returns the MAC address of a link object or None if the link does not
- have a physical address."""
- nl_addr = _rtnl_link_get_addr(link)
- if nl_addr:
- address = (c_char * CHARBUFFSIZE)()
- return _nl_addr2str(nl_addr, address, sizeof(address))
- else:
- return None
-
-
-def _link_state(link):
- """Returns the textual representation of the link's operstate."""
- state = _rtnl_link_get_operstate(link)
- operstate = (c_char * CHARBUFFSIZE)()
- return _rtnl_link_operstate2str(state, operstate, sizeof(operstate))
-
-
-def _addr_scope(addr):
- """Returns the scope name for which the address is defined."""
- scope = (c_char * CHARBUFFSIZE)()
- return _rtnl_scope2str(_rtnl_addr_get_scope(addr), scope, sizeof(scope))
-
-
-def _addr_family(addr):
- """Returns the family name of the address."""
- family = (c_char * CHARBUFFSIZE)()
- return _nl_af2str(_rtnl_addr_get_family(addr), family, sizeof(family))
-
-
-def _addr_local(addr):
- """Returns the textual representation of the address."""
- address = (c_char * CHARBUFFSIZE)()
- return _nl_addr2str(_rtnl_addr_get_local(addr), address, sizeof(address))
-
-
-def _ethtool_uses_libnl3():
- """Returns whether ethtool uses libnl3."""
- return (StrictVersion('0.9') <=
- StrictVersion(ethtool.version.split()[1].lstrip('v')))
-
-
-# C function prototypes
-# http://docs.python.org/2/library/ctypes.html#function-prototypes
-# This helps ctypes know the calling conventions it should use to communicate
-# with the binary interface of libnl and which types it should allocate and
-# cast. Without it ctypes fails when not running on the main thread.
-_int_proto = CFUNCTYPE(c_int, c_void_p)
-_char_proto = CFUNCTYPE(c_char_p, c_void_p)
-_void_proto = CFUNCTYPE(c_void_p, c_void_p)
-_none_proto = CFUNCTYPE(None, c_void_p)
-
-if _ethtool_uses_libnl3():
- LIBNL = CDLL('libnl-3.so.200', use_errno=True)
- LIBNL_ROUTE = CDLL('libnl-route-3.so.200', use_errno=True)
-
- _nl_socket_alloc = CFUNCTYPE(c_void_p)(('nl_socket_alloc', LIBNL))
- _nl_socket_free = _none_proto(('nl_socket_free', LIBNL))
-
- _link_alloc_cache = CFUNCTYPE(c_int, c_void_p, c_int, c_void_p)(
- ('rtnl_link_alloc_cache', LIBNL_ROUTE))
- _addr_alloc_cache = CFUNCTYPE(c_int, c_void_p, c_void_p)(
- ('rtnl_addr_alloc_cache', LIBNL_ROUTE))
- _link_is_vlan = _int_proto(('rtnl_link_is_vlan', LIBNL_ROUTE))
- _vlan_get_id = _int_proto(('rtnl_link_vlan_get_id', LIBNL_ROUTE))
-
- def _rtnl_link_alloc_cache(sock):
- """Wraps the new link alloc cache to expose the libnl1 signature"""
- AF_UNSPEC = 0
- cache = c_void_p()
- err = _link_alloc_cache(sock, AF_UNSPEC, byref(cache))
- if err:
- raise IOError(-err, _nl_geterror())
- return cache
-
- def _rtnl_addr_alloc_cache(sock):
- """Wraps the new addr alloc cache to expose the libnl1 signature"""
- cache = c_void_p()
- err = _addr_alloc_cache(sock, byref(cache))
- if err:
- raise IOError(-err, _nl_geterror())
- return cache
-
- _rtnl_link_get_type = _char_proto(('rtnl_link_get_type', LIBNL_ROUTE))
-
- def _rtnl_link_vlan_get_id(link):
- """Wraps the new vlan id retrieval to expose the libnl1 signature"""
- if _link_is_vlan(link):
- return _vlan_get_id(link)
- else:
- return -1
-else: # libnl-1
- # Change from handle to socket as it is now more accurately called in
- # libnl-3
- LIBNL_ROUTE = LIBNL = CDLL('libnl.so.1', use_errno=True)
-
- _nl_socket_alloc = CFUNCTYPE(c_void_p)(('nl_handle_alloc', LIBNL))
- _nl_socket_free = _none_proto(('nl_handle_destroy', LIBNL))
-
- _rtnl_link_vlan_get_id = _int_proto(('rtnl_link_vlan_get_id', LIBNL))
- _link_alloc_cache = _void_proto(('rtnl_link_alloc_cache', LIBNL))
- _addr_alloc_cache = _void_proto(('rtnl_addr_alloc_cache', LIBNL))
-
- def _alloc_cache(allocator, sock):
- cache = allocator(sock)
- if cache is None:
- raise IOError(get_errno(), 'Failed to allocate the cache')
- return cache
-
- _rtnl_link_alloc_cache = partial(_alloc_cache, _link_alloc_cache)
- _rtnl_addr_alloc_cache = partial(_alloc_cache, _addr_alloc_cache)
-
-_nl_connect = CFUNCTYPE(c_int, c_void_p, c_int)(('nl_connect', LIBNL))
-_nl_geterror = CFUNCTYPE(c_char_p)(('nl_geterror', LIBNL))
-
-_nl_cache_free = _none_proto(('nl_cache_free', LIBNL))
-_nl_cache_get_first = _void_proto(('nl_cache_get_first', LIBNL))
-_nl_cache_get_next = _void_proto(('nl_cache_get_next', LIBNL))
-
-_rtnl_link_get_addr = _void_proto(('rtnl_link_get_addr', LIBNL_ROUTE))
-_rtnl_link_get_flags = _int_proto(('rtnl_link_get_flags', LIBNL_ROUTE))
-_rtnl_link_get_ifindex = _int_proto(('rtnl_link_get_ifindex', LIBNL_ROUTE))
-_rtnl_link_get_link = _int_proto(('rtnl_link_get_link', LIBNL_ROUTE))
-_rtnl_link_get_master = _int_proto(('rtnl_link_get_master', LIBNL_ROUTE))
-_rtnl_link_get_mtu = _int_proto(('rtnl_link_get_mtu', LIBNL_ROUTE))
-_rtnl_link_get_name = _char_proto(('rtnl_link_get_name', LIBNL_ROUTE))
-_rtnl_link_get_operstate = _int_proto(('rtnl_link_get_operstate', LIBNL_ROUTE))
-_rtnl_link_get_qdisc = _char_proto(('rtnl_link_get_qdisc', LIBNL_ROUTE))
-
-_rtnl_addr_get_label = _char_proto(('rtnl_addr_get_label', LIBNL_ROUTE))
-_rtnl_addr_get_ifindex = _int_proto(('rtnl_addr_get_ifindex', LIBNL_ROUTE))
-_rtnl_addr_get_family = _int_proto(('rtnl_addr_get_family', LIBNL_ROUTE))
-_rtnl_addr_get_prefixlen = _int_proto(('rtnl_addr_get_prefixlen', LIBNL_ROUTE))
-_rtnl_addr_get_scope = _int_proto(('rtnl_addr_get_scope', LIBNL_ROUTE))
-_rtnl_addr_get_flags = _int_proto(('rtnl_addr_get_flags', LIBNL_ROUTE))
-_rtnl_addr_get_local = _void_proto(('rtnl_addr_get_local', LIBNL_ROUTE))
-
-_nl_addr2str = CFUNCTYPE(c_char_p, c_void_p, c_char_p, c_size_t)((
- 'nl_addr2str', LIBNL))
-_rtnl_link_get_by_name = CFUNCTYPE(c_void_p, c_void_p, c_char_p)((
- 'rtnl_link_get_by_name', LIBNL_ROUTE))
-_rtnl_link_i2name = CFUNCTYPE(c_char_p, c_void_p, c_int, c_char_p, c_size_t)((
- 'rtnl_link_i2name', LIBNL_ROUTE))
-_rtnl_link_operstate2str = CFUNCTYPE(c_char_p, c_int, c_char_p, c_size_t)((
- 'rtnl_link_operstate2str', LIBNL_ROUTE))
-_nl_af2str = CFUNCTYPE(c_char_p, c_int, c_char_p, c_size_t)(('nl_af2str',
- LIBNL))
-_rtnl_scope2str = CFUNCTYPE(c_char_p, c_int, c_char_p, c_size_t)((
- 'rtnl_scope2str', LIBNL_ROUTE))
-
-_nl_link_cache = partial(_cache_manager, _rtnl_link_alloc_cache)
-_nl_addr_cache = partial(_cache_manager, _rtnl_addr_alloc_cache)
diff --git a/lib/vdsm/netlink/Makefile.am b/lib/vdsm/netlink/Makefile.am
new file mode 100644
index 0000000..a5007c0
--- /dev/null
+++ b/lib/vdsm/netlink/Makefile.am
@@ -0,0 +1,25 @@
+# Copyright 2014 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
+#
+# Refer to the README and COPYING files for full details of the license
+#
+include $(top_srcdir)/build-aux/Makefile.subs
+
+dist_vdsmnetlink_PYTHON = \
+ __init__.py \
+ addr.py \
+ link.py \
+ $(NULL)
diff --git a/lib/vdsm/netlink/__init__.py b/lib/vdsm/netlink/__init__.py
new file mode 100644
index 0000000..c7bb58f
--- /dev/null
+++ b/lib/vdsm/netlink/__init__.py
@@ -0,0 +1,135 @@
+#
+# 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
+#
+# Refer to the README and COPYING files for full details of the license
+#
+from contextlib import contextmanager
+from ctypes import (CDLL, CFUNCTYPE, c_char_p, c_int, c_void_p, c_size_t,
+ get_errno)
+from distutils.version import StrictVersion
+from Queue import Empty, Queue
+from threading import BoundedSemaphore
+
+import ethtool
+
+_POOL_SIZE = 5
+_NETLINK_ROUTE = 0
+
+
+class NLSocketPool(object):
+ """Pool of netlink sockets."""
+ def __init__(self, size):
+ if size <= 0:
+ raise ValueError('Invalid socket pool size %r. Must be positive')
+ self._semaphore = BoundedSemaphore(size)
+ self._sockets = Queue(maxsize=size)
+
+ @contextmanager
+ def socket(self):
+ """Returns a socket from the pool (creating it when needed)."""
+ with self._semaphore:
+ try:
+ sock = self._sockets.get_nowait()
+ except Empty:
+ sock = _open_socket()
+ try:
+ yield sock
+ finally:
+ self._sockets.put_nowait(sock)
+
+
+_pool = NLSocketPool(_POOL_SIZE)
+
+
+def _open_socket():
+ """Returns an open netlink socket."""
+ sock = _nl_socket_alloc()
+ if sock is None:
+ raise IOError(get_errno(), 'Failed to allocate netlink handle')
+
+ err = _nl_connect(sock, _NETLINK_ROUTE)
+ if err:
+ _nl_socket_free(sock)
+ raise IOError(-err, _nl_geterror())
+ return sock
+
+
+def _close_socket(sock):
+ """Closes and frees the resources of the passed netlink socket."""
+ _nl_socket_free(sock)
+
+
+@contextmanager
+def _cache_manager(cache_allocator, sock):
+ """Provides a cache using cache_allocator and frees it and its links upon
+ exit."""
+ cache = cache_allocator(sock)
+ try:
+ yield cache
+ finally:
+ _nl_cache_free(cache)
+
+
+# C function prototypes
+# http://docs.python.org/2/library/ctypes.html#function-prototypes
+# This helps ctypes know the calling conventions it should use to communicate
+# with the binary interface of libnl and which types it should allocate and
+# cast. Without it ctypes fails when not running on the main thread.
+_int_proto = CFUNCTYPE(c_int, c_void_p)
+_char_proto = CFUNCTYPE(c_char_p, c_void_p)
+_void_proto = CFUNCTYPE(c_void_p, c_void_p)
+_none_proto = CFUNCTYPE(None, c_void_p)
+
+
+def _ethtool_uses_libnl3():
+ """Returns whether ethtool uses libnl3."""
+ return (StrictVersion('0.9') <=
+ StrictVersion(ethtool.version.split()[1].lstrip('v')))
+
+if _ethtool_uses_libnl3():
+ LIBNL = CDLL('libnl-3.so.200', use_errno=True)
+ LIBNL_ROUTE = CDLL('libnl-route-3.so.200', use_errno=True)
+
+ _nl_socket_alloc = CFUNCTYPE(c_void_p)(('nl_socket_alloc', LIBNL))
+ _nl_socket_free = _none_proto(('nl_socket_free', LIBNL))
+
+else: # libnl-1
+ # Change from handle to socket as it is now more accurately called in
+ # libnl-3
+ LIBNL_ROUTE = LIBNL = CDLL('libnl.so.1', use_errno=True)
+
+ _nl_socket_alloc = CFUNCTYPE(c_void_p)(('nl_handle_alloc', LIBNL))
+ _nl_socket_free = _none_proto(('nl_handle_destroy', LIBNL))
+
+ def _alloc_cache(allocator, sock):
+ cache = allocator(sock)
+ if cache is None:
+ raise IOError(get_errno(), 'Failed to allocate the cache')
+ return cache
+
+_nl_connect = CFUNCTYPE(c_int, c_void_p, c_int)(('nl_connect', LIBNL))
+_nl_geterror = CFUNCTYPE(c_char_p)(('nl_geterror', LIBNL))
+
+_nl_cache_free = _none_proto(('nl_cache_free', LIBNL))
+_nl_cache_get_first = _void_proto(('nl_cache_get_first', LIBNL))
+_nl_cache_get_next = _void_proto(('nl_cache_get_next', LIBNL))
+_nl_addr2str = CFUNCTYPE(c_char_p, c_void_p, c_char_p, c_size_t)((
+ 'nl_addr2str', LIBNL))
+_nl_af2str = CFUNCTYPE(c_char_p, c_int, c_char_p, c_size_t)(('nl_af2str',
+ LIBNL))
+_rtnl_scope2str = CFUNCTYPE(c_char_p, c_int, c_char_p, c_size_t)((
+ 'rtnl_scope2str', LIBNL_ROUTE))
diff --git a/lib/vdsm/netlink/addr.py b/lib/vdsm/netlink/addr.py
new file mode 100644
index 0000000..33542f5
--- /dev/null
+++ b/lib/vdsm/netlink/addr.py
@@ -0,0 +1,111 @@
+# 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
+#
+# Refer to the README and COPYING files for full details of the license
+#
+from ctypes import (CFUNCTYPE, byref, c_char, c_char_p, c_int, c_size_t,
+ c_void_p, sizeof)
+from functools import partial
+
+from . import (_alloc_cache, _cache_manager, _nl_cache_get_first,
+ _nl_cache_get_next)
+from . import _char_proto, _int_proto, _void_proto
+from . import (_ethtool_uses_libnl3, LIBNL_ROUTE, _nl_addr2str, _nl_af2str,
+ _nl_geterror, _pool)
+from .link import _nl_link_cache, _link_index_to_name
+
+CHARBUFFSIZE = 40 # Increased to fit IPv6 expanded representations
+
+
+def iter_addrs():
+ """Generator that yields an information dictionary for each network address
+ in the system."""
+ with _pool.socket() as sock:
+ with _nl_addr_cache(sock) as addr_cache:
+ with _nl_link_cache(sock) as link_cache: # for index to label
+ addr = _nl_cache_get_first(addr_cache)
+ while addr:
+ yield _addr_info(link_cache, addr)
+ addr = _nl_cache_get_next(addr)
+
+
+def _addr_info(link_cache, addr):
+ """Returns a dictionary with the address information."""
+ index = _rtnl_addr_get_ifindex(addr)
+ return {
+ 'label': (_rtnl_addr_get_label(addr) or
+ _link_index_to_name(link_cache, index)),
+ 'index': index,
+ 'family': _addr_family(addr),
+ 'prefixlen': _rtnl_addr_get_prefixlen(addr),
+ 'scope': _addr_scope(addr),
+ 'flags': _rtnl_addr_get_flags(addr),
+ 'address': _addr_local(addr)}
+
+
+def _addr_scope(addr):
+ """Returns the scope name for which the address is defined."""
+ scope = (c_char * CHARBUFFSIZE)()
+ return _rtnl_scope2str(_rtnl_addr_get_scope(addr), scope, sizeof(scope))
+
+
+def _addr_family(addr):
+ """Returns the family name of the address."""
+ family = (c_char * CHARBUFFSIZE)()
+ return _nl_af2str(_rtnl_addr_get_family(addr), family, sizeof(family))
+
+
+def _addr_local(addr):
+ """Returns the textual representation of the address."""
+ address = (c_char * CHARBUFFSIZE)()
+ return _nl_addr2str(_rtnl_addr_get_local(addr), address, sizeof(address))
+
+
+# C function prototypes
+# http://docs.python.org/2/library/ctypes.html#function-prototypes
+# This helps ctypes know the calling conventions it should use to communicate
+# with the binary interface of libnl and which types it should allocate and
+# cast. Without it ctypes fails when not running on the main thread.
+if _ethtool_uses_libnl3():
+ _addr_alloc_cache = CFUNCTYPE(c_int, c_void_p, c_void_p)(
+ ('rtnl_addr_alloc_cache', LIBNL_ROUTE))
+
+ def _rtnl_addr_alloc_cache(sock):
+ """Wraps the new addr alloc cache to expose the libnl1 signature"""
+ cache = c_void_p()
+ err = _addr_alloc_cache(sock, byref(cache))
+ if err:
+ raise IOError(-err, _nl_geterror())
+ return cache
+
+else: # libnl-1
+ # Change from handle to socket as it is now more accurately called in
+ # libnl-3
+ _addr_alloc_cache = _void_proto(('rtnl_addr_alloc_cache', LIBNL_ROUTE))
+
+ _rtnl_addr_alloc_cache = partial(_alloc_cache, _addr_alloc_cache)
+
+_nl_addr_cache = partial(_cache_manager, _rtnl_addr_alloc_cache)
+
+_rtnl_addr_get_label = _char_proto(('rtnl_addr_get_label', LIBNL_ROUTE))
+_rtnl_addr_get_ifindex = _int_proto(('rtnl_addr_get_ifindex', LIBNL_ROUTE))
+_rtnl_addr_get_family = _int_proto(('rtnl_addr_get_family', LIBNL_ROUTE))
+_rtnl_addr_get_prefixlen = _int_proto(('rtnl_addr_get_prefixlen', LIBNL_ROUTE))
+_rtnl_addr_get_scope = _int_proto(('rtnl_addr_get_scope', LIBNL_ROUTE))
+_rtnl_addr_get_flags = _int_proto(('rtnl_addr_get_flags', LIBNL_ROUTE))
+_rtnl_addr_get_local = _void_proto(('rtnl_addr_get_local', LIBNL_ROUTE))
+_rtnl_scope2str = CFUNCTYPE(c_char_p, c_int, c_char_p, c_size_t)((
+ 'rtnl_scope2str', LIBNL_ROUTE))
diff --git a/lib/vdsm/netlink/link.py b/lib/vdsm/netlink/link.py
new file mode 100644
index 0000000..5c3583d
--- /dev/null
+++ b/lib/vdsm/netlink/link.py
@@ -0,0 +1,161 @@
+# 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
+#
+# Refer to the README and COPYING files for full details of the license
+#
+from ctypes import (CFUNCTYPE, byref, c_char, c_char_p, c_int, c_void_p,
+ c_size_t, sizeof)
+from functools import partial
+import errno
+
+from . import (_alloc_cache, _cache_manager, _nl_cache_get_first,
+ _nl_cache_get_next)
+from . import _char_proto, _int_proto, _void_proto
+from . import (_ethtool_uses_libnl3, LIBNL_ROUTE, _nl_addr2str, _nl_geterror,
+ _pool)
+
+CHARBUFFSIZE = 40 # Increased to fit IPv6 expanded representations
+
+
+def get_link(name):
+ """Returns the information dictionary of the name specified link."""
+ with _pool.socket() as sock:
+ with _nl_link_cache(sock) as cache:
+ link = _rtnl_link_get_by_name(cache, name)
+ if not link:
+ raise IOError(errno.ENODEV, '%s is not present in the system' %
+ name)
+ return _link_info(cache, link)
+
+
+def iter_links():
+ """Generator that yields an information dictionary for each link of the
+ system."""
+ with _pool.socket() as sock:
+ with _nl_link_cache(sock) as cache:
+ link = _nl_cache_get_first(cache)
+ while link:
+ yield _link_info(cache, link)
+ link = _nl_cache_get_next(link)
+
+
+def _link_info(cache, link):
+ """Returns a dictionary with the information of the link object."""
+ info = {}
+ info['address'] = _link_address(link)
+ info['flags'] = _rtnl_link_get_flags(link)
+ info['index'] = _rtnl_link_get_ifindex(link)
+ info['mtu'] = _rtnl_link_get_mtu(link)
+ info['name'] = _rtnl_link_get_name(link)
+ info['qdisc'] = _rtnl_link_get_qdisc(link)
+ info['state'] = _link_state(link)
+
+ # libnl-1 has a bug when getting type information.
+ # https://github.com/tgraf/libnl-1.1-stable/issues/1
+ # TODO: Add for libnl1 if the bug is fixed
+ if _ethtool_uses_libnl3():
+ link_type = _rtnl_link_get_type(link)
+ if link_type is not None:
+ info['type'] = link_type
+
+ underlying_device_index = _rtnl_link_get_link(link)
+ if underlying_device_index > 0:
+ info['device'] = _link_index_to_name(cache, underlying_device_index)
+
+ master_index = _rtnl_link_get_master(link)
+ if master_index > 0:
+ info['master'] = _link_index_to_name(cache, master_index)
+
+ vlanid = _rtnl_link_vlan_get_id(link)
+ if vlanid >= 0:
+ info['vlanid'] = vlanid
+
+ return info
+
+
+def _link_index_to_name(cache, link_index):
+ """Returns the textual name of the link with index equal to link_index."""
+ name = (c_char * CHARBUFFSIZE)()
+ return _rtnl_link_i2name(cache, link_index, name, sizeof(name))
+
+
+def _link_address(link):
+ """Returns the MAC address of a link object or None if the link does not
+ have a physical address."""
+ nl_addr = _rtnl_link_get_addr(link)
+ if nl_addr:
+ address = (c_char * CHARBUFFSIZE)()
+ return _nl_addr2str(nl_addr, address, sizeof(address))
+ else:
+ return None
+
+
+def _link_state(link):
+ """Returns the textual representation of the link's operstate."""
+ state = _rtnl_link_get_operstate(link)
+ operstate = (c_char * CHARBUFFSIZE)()
+ return _rtnl_link_operstate2str(state, operstate, sizeof(operstate))
+
+
+# C function prototypes
+# http://docs.python.org/2/library/ctypes.html#function-prototypes
+# This helps ctypes know the calling conventions it should use to communicate
+# with the binary interface of libnl and which types it should allocate and
+# cast. Without it ctypes fails when not running on the main thread.
+if _ethtool_uses_libnl3():
+ _link_alloc_cache = CFUNCTYPE(c_int, c_void_p, c_int, c_void_p)(
+ ('rtnl_link_alloc_cache', LIBNL_ROUTE))
+ _link_is_vlan = _int_proto(('rtnl_link_is_vlan', LIBNL_ROUTE))
+ _vlan_get_id = _int_proto(('rtnl_link_vlan_get_id', LIBNL_ROUTE))
+ _rtnl_link_get_type = _char_proto(('rtnl_link_get_type', LIBNL_ROUTE))
+
+ def _rtnl_link_alloc_cache(sock):
+ """Wraps the new link alloc cache to expose the libnl1 signature"""
+ AF_UNSPEC = 0
+ cache = c_void_p()
+ err = _link_alloc_cache(sock, AF_UNSPEC, byref(cache))
+ if err:
+ raise IOError(-err, _nl_geterror())
+ return cache
+
+ def _rtnl_link_vlan_get_id(link):
+ """Wraps the new vlan id retrieval to expose the libnl1 signature"""
+ if _link_is_vlan(link):
+ return _vlan_get_id(link)
+ else:
+ return -1
+else:
+ _link_alloc_cache = _void_proto(('rtnl_link_alloc_cache', LIBNL_ROUTE))
+ _rtnl_link_alloc_cache = partial(_alloc_cache, _link_alloc_cache)
+ _rtnl_link_vlan_get_id = _int_proto(('rtnl_link_vlan_get_id', LIBNL_ROUTE))
+
+_nl_link_cache = partial(_cache_manager, _rtnl_link_alloc_cache)
+
+_rtnl_link_get_addr = _void_proto(('rtnl_link_get_addr', LIBNL_ROUTE))
+_rtnl_link_get_flags = _int_proto(('rtnl_link_get_flags', LIBNL_ROUTE))
+_rtnl_link_get_ifindex = _int_proto(('rtnl_link_get_ifindex', LIBNL_ROUTE))
+_rtnl_link_get_link = _int_proto(('rtnl_link_get_link', LIBNL_ROUTE))
+_rtnl_link_get_master = _int_proto(('rtnl_link_get_master', LIBNL_ROUTE))
+_rtnl_link_get_mtu = _int_proto(('rtnl_link_get_mtu', LIBNL_ROUTE))
+_rtnl_link_get_name = _char_proto(('rtnl_link_get_name', LIBNL_ROUTE))
+_rtnl_link_get_operstate = _int_proto(('rtnl_link_get_operstate', LIBNL_ROUTE))
+_rtnl_link_get_qdisc = _char_proto(('rtnl_link_get_qdisc', LIBNL_ROUTE))
+_rtnl_link_get_by_name = CFUNCTYPE(c_void_p, c_void_p, c_char_p)((
+ 'rtnl_link_get_by_name', LIBNL_ROUTE))
+_rtnl_link_i2name = CFUNCTYPE(c_char_p, c_void_p, c_int, c_char_p, c_size_t)((
+ 'rtnl_link_i2name', LIBNL_ROUTE))
+_rtnl_link_operstate2str = CFUNCTYPE(c_char_p, c_int, c_char_p, c_size_t)((
+ 'rtnl_link_operstate2str', LIBNL_ROUTE))
diff --git a/vdsm.spec.in b/vdsm.spec.in
index 564ff20..aecb25f 100644
--- a/vdsm.spec.in
+++ b/vdsm.spec.in
@@ -1134,6 +1134,7 @@
%defattr(-, root, root, -)
%{_bindir}/vdsm-tool
%dir %{python_sitearch}/%{vdsm_name}
+%dir %{python_sitearch}/%{vdsm_name}/netlink
%dir %{python_sitearch}/%{vdsm_name}/tool
%{python_sitearch}/%{vdsm_name}/__init__.py*
%{python_sitearch}/%{vdsm_name}/compat.py*
@@ -1144,7 +1145,9 @@
%{python_sitearch}/%{vdsm_name}/ipwrapper.py*
%{python_sitearch}/%{vdsm_name}/libvirtconnection.py*
%{python_sitearch}/%{vdsm_name}/netinfo.py*
-%{python_sitearch}/%{vdsm_name}/netlink.py*
+%{python_sitearch}/%{vdsm_name}/netlink/__init__.py*
+%{python_sitearch}/%{vdsm_name}/netlink/addr.py*
+%{python_sitearch}/%{vdsm_name}/netlink/link.py*
%{python_sitearch}/%{vdsm_name}/profile.py*
%{python_sitearch}/%{vdsm_name}/qemuimg.py*
%{python_sitearch}/%{vdsm_name}/SecureXMLRPCServer.py*
--
To view, visit http://gerrit.ovirt.org/27472
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I9b393588ccb3ac0c4529446c285570f49cdb1e28
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Antoni Segura Puimedon <asegurap(a)redhat.com>
9 years, 9 months