Add --nic attr to get-connector command

Added attribute permits usage of different network
interfaces for getting connector.

Change-Id: If08c7094b233ee440642f6e4651656f6332c9460
This commit is contained in:
Michael Dovgal
2017-01-23 16:33:03 +02:00
parent 63a3014dec
commit f909d1d870
6 changed files with 150 additions and 5 deletions

View File

@@ -37,6 +37,8 @@ ENFORCE_MULTIPATH_HELP_MESSAGE = (
'If enforce_multipath=True is specified too, an exception is thrown when '
'multipathd is not running. Otherwise, it falls back to multipath=False '
'and only the first path shown up is used.')
NETWORK_INTERFACE_HELP_MESSAGE = ('Use a specific network interface to '
'determine IP address.')
@utils.arg('--multipath',
@@ -47,12 +49,17 @@ ENFORCE_MULTIPATH_HELP_MESSAGE = (
metavar='<enforce_multipath>',
default=False,
help=ENFORCE_MULTIPATH_HELP_MESSAGE)
@utils.arg('--nic',
metavar='<nic>',
default=None,
help=NETWORK_INTERFACE_HELP_MESSAGE)
@brick_utils.require_root
def do_get_connector(client, args):
"""Get the connection properties for all protocols."""
brickclient = brick_client.Client(client)
connector = brickclient.get_connector(args.multipath,
args.enforce_multipath)
args.enforce_multipath,
args.nic)
utils.print_dict(connector)

View File

@@ -1,4 +1,3 @@
# Copyright 2011-2014 OpenStack Foundation
# All Rights Reserved.
#
@@ -14,9 +13,11 @@
# License for the specific language governing permissions and limitations
# under the License.
import netifaces
import os
import socket
from brick_cinderclient_ext import exceptions as exc
from cinderclient import exceptions
from oslo_concurrency import processutils
@@ -32,6 +33,28 @@ def get_my_ip():
return None
def get_ip(nic_name=None):
"""Getting ip address by network interface name.
:param nic_name: interface name
:returns: ip address from interface or default ip
"""
# TODO(mdovgal): add ipv6 support
if not nic_name:
return get_my_ip()
existing_ifaces = netifaces.interfaces()
if nic_name not in existing_ifaces:
raise exc.NicNotFound(iface=nic_name)
# get necessary iface information
iface = netifaces.ifaddresses(nic_name)
try:
return iface[netifaces.AF_INET][0]['addr']
except KeyError:
raise exc.IncorrectNic(iface=nic_name)
def get_root_helper():
# NOTE (e0ne): We don't use rootwrap now
return 'sudo'

View File

@@ -21,7 +21,17 @@ from brick_cinderclient_ext import volume_actions as actions
class Client(object):
version = '1.1.0'
"""Python client for os-brick
Version history:
1.0.0 - Initial version
1.1.0 - Query volume paths implementation
1.2.0 - Add --nic attribute to get-connector
"""
version = '1.2.0'
def __init__(self, volumes_client=None):
self.volumes_client = volumes_client
@@ -45,10 +55,11 @@ class Client(object):
device_scan_attempts=device_scan_attempts,
*args, **kwargs)
def get_connector(self, multipath=False, enforce_multipath=False):
def get_connector(self, multipath=False, enforce_multipath=False,
nic=None):
conn_prop = connector.get_connector_properties(
brick_utils.get_root_helper(),
brick_utils.get_my_ip(),
brick_utils.get_ip(nic),
multipath=multipath,
enforce_multipath=(enforce_multipath),
execute=processutils.execute)

View File

@@ -0,0 +1,41 @@
# Copyright 2017 Mirantis.Inc
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Exception definitions.
"""
from cinderclient._i18n import _
class BrickInterfaceException(Exception):
"""Base exception for brick-cinderclient."""
message = _("An unknown exception occurred.")
def __init__(self, message=None, **kwargs):
if message:
self.message = message
self.message = self.message % kwargs
def __str__(self):
return self.message
class NicNotFound(BrickInterfaceException):
message = _("Could not find network interface %(iface)s.")
class IncorrectNic(BrickInterfaceException):
# TODO(mdovgal): change message after adding ipv6 support
message = _("Network interface %(iface)s has not ipv4 address assigned.")

View File

@@ -0,0 +1,60 @@
# Copyright 2017 Mirantis.Inc
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import ddt
import mock
import netifaces
from oslotest import base
from brick_cinderclient_ext import brick_utils
from brick_cinderclient_ext import exceptions as exc
@ddt.ddt
class TestBrickUtils(base.BaseTestCase):
@mock.patch('netifaces.ifaddresses',
return_value={netifaces.AF_INET: [{'addr': '127.0.0.1'}]})
@mock.patch('netifaces.interfaces', return_value=['eth1'])
@mock.patch('brick_cinderclient_ext.brick_utils.get_my_ip',
return_value='1.0.0.0')
@ddt.data((None, '1.0.0.0'),
('eth1', '127.0.0.1'))
@ddt.unpack
def test_get_ip(self, nic, expected,
_fake_my_ip, _fake_interfaces,
_fake_ifaddresses):
"""Test getting ip address using interface name.
Test cases:
1. Getting address from existing interface;
2. Getting default value when network-iface param is missing;
"""
self.assertEqual(expected, brick_utils.get_ip(nic))
@mock.patch('netifaces.interfaces', return_value=[])
def test_get_ip_failed_interface(self, _fake_interfaces):
"""Test getting ip from nonexistent interface."""
nic = 'fake_nic'
self.assertRaises(exc.NicNotFound, brick_utils.get_ip,
nic)
@mock.patch('netifaces.ifaddresses', return_value={})
@mock.patch('netifaces.interfaces', return_value=['without_addr'])
def test_get_ip_non_addr_in_iface(self, _fake_interfaces,
_fake_ifaddresses):
"""Test getting ip using nic that doesn't have ipv4 address."""
nic = 'without_addr'
self.assertRaises(exc.IncorrectNic, brick_utils.get_ip, nic)

View File

@@ -0,0 +1,3 @@
---
features:
- Added attribute --nic to get-connector command.