diff --git a/.gitignore b/.gitignore index 62240adf06..059baac6f1 100644 --- a/.gitignore +++ b/.gitignore @@ -23,5 +23,4 @@ lock .idea .DS_Store -Nailgun.egg-info -Shotgun.egg-info +*.egg-info diff --git a/dhcp-checker/dhcp_checker/__init__.py b/dhcp-checker/dhcp_checker/__init__.py index 6eb121f2f2..141ca6ab9a 100644 --- a/dhcp-checker/dhcp_checker/__init__.py +++ b/dhcp-checker/dhcp_checker/__init__.py @@ -1 +1,13 @@ -__author__ = 'dshulyak' +# Copyright 2013 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. diff --git a/dhcp-checker/dhcp_checker/api.py b/dhcp-checker/dhcp_checker/api.py index 302f2c023e..71455cebd0 100644 --- a/dhcp-checker/dhcp_checker/api.py +++ b/dhcp-checker/dhcp_checker/api.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # Copyright 2013 Mirantis, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -13,13 +12,11 @@ # License for the specific language governing permissions and limitations # under the License. -from scapy.all import * import itertools import multiprocessing -import functools -import subprocess + +from scapy import all as scapy from dhcp_checker import utils -from dhcp_checker import vlans_utils @utils.multiproc_map @@ -31,24 +28,25 @@ def check_dhcp_on_eth(iface, timeout): >>> check_dhcp_on_eth('eth1') """ - conf.iface = iface + scapy.conf.iface = iface - conf.checkIPaddr = False + scapy.conf.checkIPaddr = False dhcp_options = [("message-type", "discover"), - ("param_req_list", utils.format_options([1, 2, 3, 4, 5, 6, - 11, 12, 13, 15, 16, 17, 18, 22, 23, - 28, 40, 41, 42, 43, 50, 51, 54, 58, 59, 60, 66, 67])), + ("param_req_list", utils.format_options( + [1, 2, 3, 4, 5, 6, + 11, 12, 13, 15, 16, 17, 18, 22, 23, + 28, 40, 41, 42, 43, 50, 51, 54, 58, 59, 60, 66, 67])), "end"] - fam, hw = get_if_raw_hwaddr(iface) + fam, hw = scapy.get_if_raw_hwaddr(iface) dhcp_discover = ( - Ether(src=hw, dst="ff:ff:ff:ff:ff:ff") / - IP(src="0.0.0.0", dst="255.255.255.255") / - UDP(sport=68, dport=67) / - BOOTP(chaddr=hw) / - DHCP(options=dhcp_options)) - ans, unans = srp(dhcp_discover, multi=True, - nofilter=1, timeout=timeout, verbose=0) + scapy.Ether(src=hw, dst="ff:ff:ff:ff:ff:ff") / + scapy.IP(src="0.0.0.0", dst="255.255.255.255") / + scapy.UDP(sport=68, dport=67) / + scapy.BOOTP(chaddr=hw) / + scapy.DHCP(options=dhcp_options)) + ans, unans = scapy.srp(dhcp_discover, multi=True, + nofilter=1, timeout=timeout, verbose=0) return ans @@ -64,8 +62,8 @@ def check_dhcp(ifaces, timeout=5, repeat=2): if not ifaces_filtered: raise EnvironmentError("No valid interfaces provided.") pool = multiprocessing.Pool(len(ifaces_filtered)*repeat) - return itertools.chain(*pool.map(check_dhcp_on_eth, - ((iface, timeout) for iface in ifaces_filtered*repeat))) + return itertools.chain(*pool.map(check_dhcp_on_eth, ( + (iface, timeout) for iface in ifaces_filtered*repeat))) def check_dhcp_with_vlans(config, timeout=5, repeat=2): @@ -74,7 +72,7 @@ def check_dhcp_with_vlans(config, timeout=5, repeat=2): @ifaces - string : eth0, eth1 @vlans - iterable (100, 101, 102) """ - with vlans_utils.VlansActor(config) as vifaces: + with utils.VlansContext(config) as vifaces: return check_dhcp(list(vifaces), timeout=timeout, repeat=repeat) @@ -85,22 +83,23 @@ def check_dhcp_request(iface, server, range_start, range_end, timeout=5): >>> check_dhcp_request('eth1','10.10.0.5','10.10.0.10','10.10.0.15') """ - conf.iface = iface + scapy.conf.iface = iface - conf.checkIPaddr = False + scapy.conf.checkIPaddr = False - fam, hw = get_if_raw_hwaddr(iface) + fam, hw = scapy.get_if_raw_hwaddr(iface) ip_address = next(utils.pick_ip(range_start, range_end)) # note lxc dhcp server does not respond to unicast - dhcp_request = (Ether(src=hw, dst="ff:ff:ff:ff:ff:ff") / - IP(src="0.0.0.0", dst="255.255.255.255") / - UDP(sport=68, dport=67) / - BOOTP(chaddr=hw) / - DHCP(options=[("message-type", "request"), - ("server_id", server), - ("requested_addr", ip_address), "end"])) - ans, unans = srp(dhcp_request, nofilter=1, multi=True, - timeout=timeout, verbose=0) + dhcp_request = (scapy.Ether(src=hw, dst="ff:ff:ff:ff:ff:ff") / + scapy.IP(src="0.0.0.0", dst="255.255.255.255") / + scapy.UDP(sport=68, dport=67) / + scapy.BOOTP(chaddr=hw) / + scapy.DHCP(options=[("message-type", "request"), + ("server_id", server), + ("requested_addr", ip_address), + "end"])) + ans, unans = scapy.srp(dhcp_request, nofilter=1, multi=True, + timeout=timeout, verbose=0) return ans diff --git a/dhcp-checker/dhcp_checker/commands.py b/dhcp-checker/dhcp_checker/commands.py index 964a70cb4c..a3b0aad32b 100644 --- a/dhcp-checker/dhcp_checker/commands.py +++ b/dhcp-checker/dhcp_checker/commands.py @@ -12,11 +12,11 @@ # 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 json + from cliff import lister from cliff import command from dhcp_checker import api -from itertools import chain -import json class BaseCommand(command.Command): @@ -25,9 +25,9 @@ class BaseCommand(command.Command): def get_parser(self, prog_name): parser = super(BaseCommand, self).get_parser(prog_name) parser.add_argument('--timeout', default=5, type=int, - help="Provide timeout for each network request") + help="Provide timeout for each network request") parser.add_argument('--repeat', default=2, type=int, - help="Provide number of repeats for request") + help="Provide number of repeats for request") return parser @@ -44,8 +44,8 @@ class ListDhcpServers(lister.Lister, BaseCommand): def take_action(self, parsed_args): res = api.check_dhcp(parsed_args.ifaces, - timeout=parsed_args.timeout, - repeat=parsed_args.repeat) + timeout=parsed_args.timeout, + repeat=parsed_args.repeat) first = res.next() columns = first.keys() return columns, [first.values()] + [item.values() for item in res] @@ -86,13 +86,13 @@ class DhcpWithVlansCheck(lister.Lister, BaseCommand): def get_parser(self, prog_name): parser = super(DhcpWithVlansCheck, self).get_parser(prog_name) parser.add_argument('config', - help='Ethernet interface name') + help='Ethernet interface name') return parser def take_action(self, parsed_args): res = api.check_dhcp_with_vlans(json.loads(parsed_args.config), - timeout=parsed_args.timeout, - repeat=parsed_args.repeat) + timeout=parsed_args.timeout, + repeat=parsed_args.repeat) first = res.next() columns = first.keys() return columns, [first.values()] + [item.values() for item in res] diff --git a/dhcp-checker/dhcp_checker/utils.py b/dhcp-checker/dhcp_checker/utils.py index 0e80e9cc14..53f44bbd61 100644 --- a/dhcp-checker/dhcp_checker/utils.py +++ b/dhcp-checker/dhcp_checker/utils.py @@ -11,10 +11,12 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -from scapy.all import * import subprocess import functools import re +import sys + +from scapy import all as scapy def command_util(*command): @@ -39,7 +41,7 @@ def check_network_up(iface): def check_iface_exist(iface): """Check provided interface exists """ - return not command_util("ip","link", "show", iface).stderr.read() + return not command_util("ip", "link", "show", iface).stderr.read() def filtered_ifaces(ifaces): @@ -48,7 +50,8 @@ def filtered_ifaces(ifaces): sys.stderr.write('Iface {0} does not exist.'.format(iface)) else: if not check_network_up(iface): - sys.stderr.write('Network for iface {0} is down.'.format(iface)) + sys.stderr.write('Network for iface {0} is down.'.format( + iface)) else: yield iface @@ -104,18 +107,18 @@ def single_format(func): iface = args[0] ans = func(*args, **kwargs) columns = ('iface', 'mac', 'server_ip', 'server_id', 'gateway', - 'dport', 'message', 'yiaddr') + 'dport', 'message', 'yiaddr') data = [] #scapy stores all sequence of requests #so ans[0][1] would be response to first request for response in ans: - dhcp_options = dict(_dhcp_options(response[1][DHCP].options)) + dhcp_options = dict(_dhcp_options(response[1][scapy.DHCP].options)) results = ( - iface, response[1][Ether].src, response[1][IP].src, - dhcp_options['server_id'], response[1][BOOTP].giaddr, - response[1][UDP].sport, - DHCPTypes[dhcp_options['message-type']], - response[1][BOOTP].yiaddr) + iface, response[1][scapy.Ether].src, response[1][scapy.IP].src, + dhcp_options['server_id'], response[1][scapy.BOOTP].giaddr, + response[1][scapy.UDP].sport, + scapy.DHCPTypes[dhcp_options['message-type']], + response[1][scapy.BOOTP].yiaddr) data.append(dict(zip(columns, results))) return data return formatter @@ -138,3 +141,24 @@ def filter_duplicated_results(func): resp = func(*args, **kwargs) return (dict(t) for t in set([tuple(d.items()) for d in resp])) return wrapper + + +class VlansContext(object): + """Contains all logic to manage vlans + """ + + def __init__(self, config): + """ + @config - list or tuple of (iface, vlan) pairs + """ + self.config = config + + def __enter__(self): + for iface, vlans in self.config.iteritems(): + yield str(iface) + for vlan in vlans: + if vlan > 0: + yield '{0}.{1}'.format(iface, vlan) + + def __exit__(self, type, value, trace): + pass diff --git a/dhcp-checker/dhcp_checker/vlans_utils.py b/dhcp-checker/dhcp_checker/vlans_utils.py deleted file mode 100644 index b9da0ff321..0000000000 --- a/dhcp-checker/dhcp_checker/vlans_utils.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2013 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. - - -class VlansActor(object): - """Contains all logic to manage vlans - """ - - def __init__(self, config): - """ - @config - list or tuple of (iface, vlan) pairs - """ - self.config = config - - def __enter__(self): - for iface, vlans in self.config.iteritems(): - yield str(iface) - for vlan in vlans: - if vlan > 0: - yield '{0}.{1}'.format(iface, vlan) - - def __exit__(self, type, value, trace): - pass diff --git a/dhcp-checker/test_env/tests.py b/dhcp-checker/test_env/tests.py index 8dbee1701f..290fdd4e59 100644 --- a/dhcp-checker/test_env/tests.py +++ b/dhcp-checker/test_env/tests.py @@ -13,13 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. -import subprocess -import json import unittest -import time -from dhcp_checker import utils -from dhcp_checker import vlans_utils from dhcp_checker import api @@ -39,49 +34,3 @@ class TestDhcpServers(unittest.TestCase): response = api.check_dhcp_on_eth('eth2', 5) self.assertEqual(len(response), 1) self.assertEqual(response[0]['server_ip'], '10.10.0.10') - - -class VlanCreationTestCase(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.vlan = vlans_utils.Vlan('eth0', '100') - - def test_vlan_creation(self): - self.vlan.up() - time.sleep(5) - self.assertTrue(self.vlan.state) - - def test_vlan_deletion(self): - self.assertTrue(self.vlan.state) - self.vlan.down() - time.sleep(5) - - -class VlanCreationWithExistingTestCase(unittest.TestCase): - - def test_check_vlan_down_status(self): - self.vlan_down = vlans_utils.Vlan('eth0', '110') - self.vlan_down.create() - time.sleep(5) - self.assertEqual(self.vlan_down.state, 'DOWN') - self.vlan_down.down() - time.sleep(5) - - def test_repeat_created_vlan(self): - self.vlan_up = vlans_utils.Vlan('eth0', '112') - self.vlan_up.up() - time.sleep(5) - self.assertEqual(self.vlan_up.state, 'UP') - self.vlan_up.down() - time.sleep(5) - - -class WithVlanDecoratorTestCase(unittest.TestCase): - - - def test_with_vlan_enter(self): - with vlans_utils.VlansContext('eth0', ('101','102','103'), delete=True) as vlan_list: - time.sleep(5) - for v in vlan_list: - self.assertEqual('UP', v.state)