Move plug/unplug bash command to ansible module

added new ansile module - iptables, that responsible for
adding/removing of iptables rules.

Change-Id: I97fc69103149794502653d052784b2d3586bb79e
This commit is contained in:
Anton Studenov
2016-10-13 11:25:57 +03:00
parent 4c777edb6b
commit dc64ad38c2
4 changed files with 136 additions and 16 deletions

View File

@@ -0,0 +1,48 @@
#!/usr/bin/python
# 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.
from ansible.module_utils.basic import * # noqa
def main():
module = AnsibleModule(
argument_spec=dict(
service=dict(required=True, type='str'),
action=dict(required=True, choices=['block', 'unblock']),
port=dict(required=True, type='int'),
protocol=dict(required=True, choices=['tcp', 'udp']),
))
service = module.params['service']
action = module.params['action']
port = module.params['port']
protocol = module.params['protocol']
comment = '{}_temporary_DROP'.format(service)
if action == 'block':
cmd = ('bash -c "iptables -I INPUT 1 -p {protocol} --dport {port} '
'-j DROP -m comment --comment "{comment}""'.format(
comment=comment, port=port, protocol=protocol))
else:
cmd = ('bash -c "rule=`iptables -L INPUT -n --line-numbers | '
'grep "{comment}" | cut -d \' \' -f1`; for arg in $rule;'
' do iptables -D INPUT -p {protocol} --dport {port} '
'-j DROP -m comment --comment "{comment}"; done"'.format(
comment=comment, port=port, protocol=protocol))
rc, stdout, stderr = module.run_command(cmd, check_rc=True)
module.exit_json(cmd=cmd, rc=rc, stderr=stderr, stdout=stdout)
if __name__ == '__main__':
main()

View File

@@ -170,15 +170,21 @@ class FuelService(service.Service):
def plug(self, nodes=None):
nodes = nodes if nodes is not None else self.get_nodes()
logging.info("Open port %d for '%s' service on nodes: %s", self.PORT,
self.SERVICE_NAME, nodes.get_ips())
self._run_task({'command': self.PLUG_CMD.format(self.PORT)}, nodes)
logging.info("Open port %d for '%s' service on nodes: %s",
self.PORT[1], self.SERVICE_NAME, nodes.get_ips())
self._run_task({'iptables': {'protocol': self.PORT[0],
'port': self.PORT[1],
'action': 'unblock',
'service': self.SERVICE_NAME}}, nodes)
def unplug(self, nodes=None):
nodes = nodes if nodes is not None else self.get_nodes()
logging.info("Close port %d for '%s' service on nodes: %s",
self.PORT, self.SERVICE_NAME, nodes.get_ips())
self._run_task({'command': self.UNPLUG_CMD.format(self.PORT)}, nodes)
self.PORT[1], self.SERVICE_NAME, nodes.get_ips())
self._run_task({'iptables': {'protocol': self.PORT[0],
'port': self.PORT[1],
'action': 'block',
'service': self.SERVICE_NAME}}, nodes)
class KeystoneService(FuelService):
@@ -196,13 +202,7 @@ class MemcachedService(FuelService):
class MySQLService(FuelService):
SERVICE_NAME = 'mysql'
GREP = '[m]ysqld'
PORT = 3307
PLUG_CMD = ('bash -c "rule=`iptables -L INPUT -n --line-numbers | '
'grep \"MySQL_temporary_DROP\" | cut -d \' \' -f1`; '
'for arg in $rule; do iptables -D INPUT -p tcp --dport {0} '
'-j DROP -m comment --comment "MySQL_temporary_DROP"; done"')
UNPLUG_CMD = ('bash -c "iptables -I INPUT 1 -p tcp --dport {0} -j DROP '
'-m comment --comment \"MySQL_temporary_DROP\""')
PORT = ('tcp', 3307)
class RabbitMQService(FuelService):

View File

@@ -0,0 +1,68 @@
# 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 mock
from os_faults.ansible.modules import iptables
from os_faults.tests.unit import test
class IptablesTestCase(test.TestCase):
@mock.patch("os_faults.ansible.modules.iptables.AnsibleModule")
def test_main_unblock(self, mock_ansible_module):
ansible_module_inst = mock_ansible_module.return_value
ansible_module_inst.run_command.return_value = [
'myrc', 'mystdout', 'mystderr']
ansible_module_inst.params = {
'service': 'foo',
'action': 'unblock',
'port': 5555,
'protocol': 'tcp',
}
iptables.main()
cmd = (
'bash -c "rule=`iptables -L INPUT -n --line-numbers | '
'grep "foo_temporary_DROP" | cut -d \' \' -f1`; for arg in $rule;'
' do iptables -D INPUT -p tcp --dport 5555 '
'-j DROP -m comment --comment "foo_temporary_DROP"; done"')
ansible_module_inst.exit_json.assert_called_once_with(
cmd=cmd,
rc='myrc',
stdout='mystdout',
stderr='mystderr',
)
@mock.patch("os_faults.ansible.modules.iptables.AnsibleModule")
def test_main_block(self, mock_ansible_module):
ansible_module_inst = mock_ansible_module.return_value
ansible_module_inst.run_command.return_value = [
'myrc', 'mystdout', 'mystderr']
ansible_module_inst.params = {
'service': 'foo',
'action': 'block',
'port': 5555,
'protocol': 'tcp',
}
iptables.main()
cmd = (
'bash -c "iptables -I INPUT 1 -p tcp --dport 5555 '
'-j DROP -m comment --comment "foo_temporary_DROP""')
ansible_module_inst.exit_json.assert_called_once_with(
cmd=cmd,
rc='myrc',
stdout='mystdout',
stderr='mystderr',
)

View File

@@ -202,8 +202,10 @@ class FuelServiceTestCase(test.TestCase):
mock.call(['10.0.0.2', '10.0.0.3'],
{'command': get_nodes_cmd}, []),
mock.call(['10.0.0.2', '10.0.0.3'],
{'command':
service_cls.UNPLUG_CMD.format(service_cls.PORT)}),
{'iptables': {'protocol': service_cls.PORT[0],
'port': service_cls.PORT[1],
'action': 'block',
'service': service_cls.SERVICE_NAME}}),
])
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@@ -237,8 +239,10 @@ class FuelServiceTestCase(test.TestCase):
mock.call(['10.0.0.2', '10.0.0.3'],
{'command': get_nodes_cmd}, []),
mock.call(['10.0.0.2', '10.0.0.3'],
{'command':
service_cls.PLUG_CMD.format(service_cls.PORT)}),
{'iptables': {'protocol': service_cls.PORT[0],
'port': service_cls.PORT[1],
'action': 'unblock',
'service': service_cls.SERVICE_NAME}}),
])
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)