Greatly improved code in dhcp checker. Fixed bug with dhcp behaviour on network down

For example of usage look at tests.py:TestDhcpWithNetworkDown
This commit is contained in:
Dmitry Shulyak 2013-09-30 16:48:22 +03:00
parent c8de4de836
commit 76a3ca1701
6 changed files with 164 additions and 52 deletions

2
.gitignore vendored
View File

@ -11,7 +11,7 @@
*.pid
# Vagrant housekeeping file
/.vagrant
.vagrant
/build
/local_mirror

View File

@ -32,10 +32,17 @@ def _check_vconfig():
return not command_util('which', 'vconfig').stderr.read()
def check_network_up(iface):
def _iface_state(iface):
"""For a given iface return it's state
returns UP, DOWN, UNKNOWN
"""
state = command_util('ip', 'link', 'show', iface)
response = re.search(r'state (?P<state>[A-Z]*)', state.stdout.read())
return response.groupdict()['state'] == 'UP'
return re.search(r'state (?P<state>[A-Z]*)',
state.stdout.read()).groupdict()['state']
def check_network_up(iface):
return _iface_state(iface) == 'UP'
def check_iface_exist(iface):
@ -162,3 +169,36 @@ class VlansContext(object):
def __exit__(self, type, value, trace):
pass
class IfaceState(object):
"""Context manager to control state of iface when dhcp checker is running
"""
def __init__(self, iface, rollback=True, retry=3):
self.rollback = rollback
self.retry = retry
self.iface = iface
self.pre_iface_state = _iface_state(iface)
self.iface_state = self.pre_iface_state
self.post_iface_state = ''
def iface_up(self):
while self.retry or self.iface_state != 'UP':
command_util('ifconfig', self.iface, 'up')
self.iface_state = _iface_state(self.iface)
self.retry -= 1
if self.iface_state != 'UP':
raise EnvironmentError(
'Tried my best to ifup iface {0}.'.format(self.iface))
def __enter__(self):
self.iface_up()
return self.iface
def __exit__(self, exc_type, exc_val, exc_tb):
if self.pre_iface_state != 'UP' and self.rollback:
print 'stuff'
command_util('ifconfig', self.iface, 'down')
self.post_iface_state = _iface_state(self.iface)

View File

@ -1,36 +0,0 @@
#!/usr/bin/python
# 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.
import unittest
from dhcp_checker import api
class TestDhcpServers(unittest.TestCase):
def test_dhcp_server_on_eth0(self):
response = api.check_dhcp_on_eth('eth0', 5)
self.assertEqual(len(response), 1)
self.assertEqual(response[0]['server_ip'], '10.0.2.2')
def test_dhcp_server_on_eth1(self):
response = api.check_dhcp_on_eth('eth1', 5)
self.assertEqual(len(response), 1)
self.assertEqual(response[0]['server_ip'], '192.168.0.5')
def test_dhcp_server_on_eth2(self):
response = api.check_dhcp_on_eth('eth2', 5)
self.assertEqual(len(response), 1)
self.assertEqual(response[0]['server_ip'], '10.10.0.10')

102
dhcp-checker/tests.py Normal file
View File

@ -0,0 +1,102 @@
#!/usr/bin/python
# 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.
"""
For this tests you need
vagrant up develop dhcp1 dhcp2
"""
import unittest
from dhcp_checker import api
from dhcp_checker import utils
class TestDhcpServers(unittest.TestCase):
def test_dhcp_server_on_eth0(self):
"""Test verifies dhcp server on eth0 iface
"""
response = api.check_dhcp_on_eth('eth0', 2)
self.assertEqual(len(response), 1)
self.assertEqual(response[0]['server_ip'], '10.0.2.2')
def test_dhcp_server_on_eth1(self):
"""Test verifies dhcp server on eth1 iface
"""
response = api.check_dhcp_on_eth('eth1', 2)
self.assertEqual(len(response), 1)
self.assertEqual(response[0]['server_ip'], '192.168.0.5')
def test_dhcp_server_on_eth2(self):
"""Test verifies dhcp server on eth2 iface
"""
response = api.check_dhcp_on_eth('eth2', 2)
self.assertEqual(len(response), 1)
self.assertEqual(response[0]['server_ip'], '10.10.0.8')
class TestDhcpUtils(unittest.TestCase):
def setUp(self):
self.iface_down = 'eth1'
utils.command_util('ifconfig', self.iface_down, 'down')
def test_check_network_up(self):
result = utils.check_network_up('eth0')
self.assertTrue(result)
def test_check_network_down(self):
self.assertFalse(utils.check_network_up(self.iface_down))
def tearDown(self):
utils.command_util('ifconfig', self.iface_down, 'up')
class TestDhcpWithNetworkDown(unittest.TestCase):
def setUp(self):
self.iface_up = 'eth0'
self.iface_down = 'eth2'
utils.command_util('ifconfig', self.iface_down, 'down')
def test_dhcp_server_on_eth1_down(self):
"""Test verifies that iface would be ifuped in case it's down
and rolledback after
"""
manager = utils.IfaceState(self.iface_down)
with manager as iface:
response = api.check_dhcp_on_eth(iface, 2)
self.assertEqual(len(response), 1)
self.assertEqual(response[0]['server_ip'], '10.10.0.8')
self.assertEqual(manager.pre_iface_state, 'DOWN')
self.assertEqual(manager.iface_state, 'UP')
self.assertEqual(manager.post_iface_state, 'DOWN')
def test_dhcp_server_on_eth0_up(self):
"""Test verifies that if iface is up, it won't be touched
"""
manager = utils.IfaceState(self.iface_up)
with manager as iface:
response = api.check_dhcp_on_eth(iface, 2)
self.assertEqual(len(response), 1)
self.assertEqual(response[0]['server_ip'], '10.0.2.2')
self.assertEqual(manager.pre_iface_state, 'UP')
self.assertEqual(manager.iface_state, 'UP')
self.assertEqual(manager.post_iface_state, 'UP')
def tearDown(self):
utils.command_util('ifconfig', self.iface_down, 'up')

View File

@ -64,7 +64,7 @@ class HTTPLoggerMiddleware(object):
env['REQUEST_METHOD'],
env['REQUEST_URI'],
self.__get_remote_ip(env),
env['REMOTE_PORT'],
env['REQUEST_METHOD'],
)
if response_code == SERVER_ERROR_MSG:
@ -84,7 +84,7 @@ class HTTPLoggerMiddleware(object):
env['REQUEST_METHOD'],
env['REQUEST_URI'],
self.__get_remote_ip(env),
env['REMOTE_PORT'],
env['REQUEST_METHOD'],
body
)

View File

@ -20,6 +20,7 @@ import web
from web.httpserver import StaticMiddleware
from web.httpserver import WSGIServer
curdir = os.path.dirname(__file__)
sys.path.insert(0, curdir)
@ -93,20 +94,25 @@ def appstart(keepalive=False):
logger.info("Running KeepAlive watcher...")
keep_alive.start()
rpc_process = threaded.RPCKombuThread()
rpc_process_two = threaded.RPCKombuThread()
logger.info("Running RPC consumer...")
rpc_process.start()
rpc_process_two.start()
logger.info("Running WSGI app...")
wsgifunc = build_middleware(app.wsgifunc)
run_server(wsgifunc,
(settings.LISTEN_ADDRESS, int(settings.LISTEN_PORT)))
#run_server(wsgifunc,
# (settings.LISTEN_ADDRESS, int(settings.LISTEN_PORT)))
logger.info("Stopping WSGI app...")
if keep_alive.is_alive():
logger.info("Stopping KeepAlive watcher...")
keep_alive.join()
if not settings.FAKE_TASKS:
logger.info("Stopping RPC consumer...")
rpc_process.join()
logger.info("Done")
#logger.info("Stopping WSGI app...")
#if keep_alive.is_alive():
# logger.info("Stopping KeepAlive watcher...")
# keep_alive.join()
#if not settings.FAKE_TASKS:
# logger.info("Stopping RPC consumer...")
# rpc_process.join()
#logger.info("Done")
return wsgifunc
application = appstart()