"Fossies" - the Fresh Open Source Software Archive

Member "octavia-8.0.0/octavia/tests/functional/amphorae/backend/agent/api_server/test_keepalivedlvs.py" (14 Apr 2021, 19779 Bytes) of package /linux/misc/openstack/octavia-8.0.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "test_keepalivedlvs.py": 7.1.1_vs_8.0.0.

    1 # Copyright 2015 Hewlett Packard Enterprise Development Company LP
    2 #
    3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
    4 # not use this file except in compliance with the License. You may obtain
    5 # a copy of the License at
    6 #
    7 # http://www.apache.org/licenses/LICENSE-2.0
    8 #
    9 # Unless required by applicable law or agreed to in writing, software
   10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   11 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   12 #    License for the specific language governing permissions and limitations
   13 #    under the License.
   14 
   15 import os
   16 import stat
   17 import subprocess
   18 from unittest import mock
   19 
   20 import flask
   21 
   22 from oslo_config import cfg
   23 from oslo_config import fixture as oslo_fixture
   24 from oslo_utils import uuidutils
   25 
   26 from octavia.amphorae.backends.agent.api_server import keepalivedlvs
   27 from octavia.amphorae.backends.agent.api_server import server
   28 from octavia.amphorae.backends.agent.api_server import util
   29 from octavia.common import constants as consts
   30 from octavia.tests.common import utils as test_utils
   31 from octavia.tests.unit import base
   32 
   33 
   34 class KeepalivedLvsTestCase(base.TestCase):
   35     FAKE_ID = uuidutils.generate_uuid()
   36     LISTENER_ID = 'listener-1111-1111-1111-listenerid00'
   37     POOL_ID = 'poolpool-1111-1111-1111-poolid000000'
   38     MEMBER_ID1 = 'memberid-1111-1111-1111-memberid1111'
   39     MEMBER_ID2 = 'memberid-2222-2222-2222-memberid2222'
   40     HEALTHMONITOR_ID = 'hmidhmid-1111-1111-1111-healthmonito'
   41     NORMAL_CFG_CONTENT = (
   42         "# Configuration for Listener %(listener_id)s\n\n"
   43         "net_namespace haproxy-amphora\n\n"
   44         "virtual_server 10.0.0.2 80 {\n"
   45         "    lb_algo rr\n"
   46         "    lb_kind NAT\n"
   47         "    protocol udp\n"
   48         "    delay_loop 30\n"
   49         "    delay_before_retry 31\n"
   50         "    retry 3\n\n\n"
   51         "    # Configuration for Pool %(pool_id)s\n"
   52         "    # Configuration for HealthMonitor %(hm_id)s\n"
   53         "    # Configuration for Member %(member1_id)s\n"
   54         "    real_server 10.0.0.99 82 {\n"
   55         "        weight 13\n"
   56         "        inhibit_on_failure\n"
   57         "        uthreshold 98\n"
   58         "        persistence_timeout 33\n"
   59         "        persistence_granularity 255.255.0.0\n"
   60         "        delay_before_retry 31\n"
   61         "        retry 3\n"
   62         "        MISC_CHECK {\n"
   63         "            misc_path \"/var/lib/octavia/lvs/check/"
   64         "udp_check.sh 10.0.0.99 82\"\n"
   65         "            misc_timeout 30\n"
   66         "            misc_dynamic\n"
   67         "        }\n"
   68         "    }\n\n"
   69         "    # Configuration for Member %(member2_id)s\n"
   70         "    real_server 10.0.0.98 82 {\n"
   71         "        weight 13\n"
   72         "        inhibit_on_failure\n"
   73         "        uthreshold 98\n"
   74         "        persistence_timeout 33\n"
   75         "        persistence_granularity 255.255.0.0\n"
   76         "        delay_before_retry 31\n"
   77         "        retry 3\n"
   78         "        MISC_CHECK {\n"
   79         "            misc_path \"/var/lib/octavia/lvs/check/"
   80         "udp_check.sh 10.0.0.98 82\"\n"
   81         "            misc_timeout 30\n"
   82         "            misc_dynamic\n"
   83         "        }\n"
   84         "    }\n\n"
   85         "}\n\n") % {'listener_id': LISTENER_ID, 'pool_id': POOL_ID,
   86                     'hm_id': HEALTHMONITOR_ID, 'member1_id': MEMBER_ID1,
   87                     'member2_id': MEMBER_ID2}
   88     PROC_CONTENT = (
   89         "IP Virtual Server version 1.2.1 (size=4096)\n"
   90         "Prot LocalAddress:Port Scheduler Flags\n"
   91         "  -> RemoteAddress:Port Forward Weight ActiveConn InActConn\n"
   92         "UDP  0A000002:0050 sh\n"
   93         "  -> 0A000063:0052      Masq    13     1          0\n"
   94         "  -> 0A000062:0052      Masq    13     1          0\n"
   95     )
   96     NORMAL_PID_CONTENT = "1988"
   97     TEST_URL = server.PATH_PREFIX + '/listeners/%s/%s/udp_listener'
   98 
   99     def setUp(self):
  100         super().setUp()
  101         self.app = flask.Flask(__name__)
  102         self.client = self.app.test_client()
  103         self._ctx = self.app.test_request_context()
  104         self._ctx.push()
  105         self.test_keepalivedlvs = keepalivedlvs.KeepalivedLvs()
  106         self.app.add_url_rule(
  107             rule=self.TEST_URL % ('<amphora_id>', '<listener_id>'),
  108             view_func=(lambda amphora_id, listener_id:
  109                        self.test_keepalivedlvs.upload_lvs_listener_config(
  110                            listener_id)),
  111             methods=['PUT'])
  112 
  113     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  114                 'run_systemctl_command')
  115     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  116                 'install_netns_systemd_service')
  117     @mock.patch('pyroute2.NetNS', create=True)
  118     @mock.patch('shutil.copy2')
  119     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  120                 'get_os_init_system', return_value=consts.INIT_SYSTEMD)
  121     @mock.patch('os.chmod')
  122     @mock.patch('os.path.exists')
  123     @mock.patch('os.makedirs')
  124     @mock.patch('os.remove')
  125     @mock.patch('subprocess.check_output')
  126     def test_upload_lvs_listener_config_no_vrrp_check_dir(
  127             self, m_check_output, m_os_rm, m_os_mkdir, m_exists, m_os_chmod,
  128             m_os_sysinit, m_copy2, mock_netns, mock_install_netns,
  129             mock_systemctl):
  130         m_exists.side_effect = [False, False, True, True, False, False]
  131         cfg_path = util.keepalived_lvs_cfg_path(self.FAKE_ID)
  132         m = self.useFixture(test_utils.OpenFixture(cfg_path)).mock_open
  133 
  134         with mock.patch('os.open') as m_open, mock.patch.object(os,
  135                                                                 'fdopen',
  136                                                                 m) as m_fdopen:
  137             m_open.side_effect = ['TEST-WRITE-CFG',
  138                                   'TEST-WRITE-SYSINIT']
  139 
  140             res = self.client.put(self.TEST_URL % ('123', self.FAKE_ID),
  141                                   data=self.NORMAL_CFG_CONTENT)
  142 
  143             mock_install_netns.assert_called_once()
  144             systemctl_calls = [
  145                 mock.call(consts.ENABLE,
  146                           consts.AMP_NETNS_SVC_PREFIX),
  147                 mock.call(consts.ENABLE,
  148                           'octavia-keepalivedlvs-%s' % str(self.FAKE_ID)),
  149             ]
  150             mock_systemctl.assert_has_calls(systemctl_calls)
  151             os_mkdir_calls = [
  152                 mock.call(util.keepalived_lvs_dir()),
  153                 mock.call(util.keepalived_backend_check_script_dir())
  154             ]
  155             m_os_mkdir.assert_has_calls(os_mkdir_calls)
  156 
  157             m_os_chmod.assert_called_with(
  158                 util.keepalived_backend_check_script_path(), stat.S_IEXEC)
  159 
  160             flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
  161             mode = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH
  162             systemd_cfg_path = util.keepalived_lvs_init_path(
  163                 consts.INIT_SYSTEMD, self.FAKE_ID)
  164 
  165             m_open_calls = [
  166                 mock.call(cfg_path, flags, mode),
  167                 mock.call(systemd_cfg_path, flags, mode)
  168             ]
  169             m_open.assert_has_calls(m_open_calls)
  170             m_fdopen.assert_any_call('TEST-WRITE-CFG', 'wb')
  171             m_fdopen.assert_any_call('TEST-WRITE-SYSINIT', 'w')
  172             self.assertEqual(200, res.status_code)
  173 
  174     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  175                 'get_lvs_listeners')
  176     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  177                 'get_loadbalancers')
  178     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  179                 'run_systemctl_command')
  180     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  181                 'install_netns_systemd_service')
  182     @mock.patch('pyroute2.NetNS', create=True)
  183     @mock.patch('shutil.copy2')
  184     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  185                 'get_os_init_system', return_value=consts.INIT_SYSTEMD)
  186     @mock.patch('os.chmod')
  187     @mock.patch('os.path.exists')
  188     @mock.patch('os.makedirs')
  189     @mock.patch('os.remove')
  190     @mock.patch('subprocess.check_output')
  191     def test_upload_lvs_listener_config_with_vrrp_check_dir(
  192             self, m_check_output, m_os_rm, m_os_mkdir, m_exists, m_os_chmod,
  193             m_os_sysinit, m_copy2, mock_netns, mock_install_netns,
  194             mock_systemctl, mock_get_lbs, mock_get_lvs_listeners):
  195         m_exists.side_effect = [False, False, True, True, False, False, False]
  196         mock_get_lbs.return_value = []
  197         mock_get_lvs_listeners.return_value = [self.FAKE_ID]
  198         cfg_path = util.keepalived_lvs_cfg_path(self.FAKE_ID)
  199         m = self.useFixture(test_utils.OpenFixture(cfg_path)).mock_open
  200 
  201         conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
  202         conf.config(group='controller_worker',
  203                     loadbalancer_topology=consts.TOPOLOGY_ACTIVE_STANDBY)
  204 
  205         with mock.patch('os.open') as m_open, mock.patch.object(os,
  206                                                                 'fdopen',
  207                                                                 m) as m_fdopen:
  208             m_open.side_effect = ['TEST-WRITE-CFG',
  209                                   'TEST-WRITE-SYSINIT',
  210                                   'TEST-WRITE-UDP-VRRP-CHECK']
  211             res = self.client.put(self.TEST_URL % ('123', self.FAKE_ID),
  212                                   data=self.NORMAL_CFG_CONTENT)
  213             os_mkdir_calls = [
  214                 mock.call(util.keepalived_lvs_dir()),
  215                 mock.call(util.keepalived_backend_check_script_dir())
  216             ]
  217             m_os_mkdir.assert_has_calls(os_mkdir_calls)
  218 
  219             mock_install_netns.assert_called_once()
  220             systemctl_calls = [
  221                 mock.call(consts.ENABLE,
  222                           consts.AMP_NETNS_SVC_PREFIX),
  223                 mock.call(consts.ENABLE,
  224                           'octavia-keepalivedlvs-%s' % str(self.FAKE_ID)),
  225             ]
  226             mock_systemctl.assert_has_calls(systemctl_calls)
  227 
  228             m_os_chmod.assert_called_with(
  229                 util.keepalived_backend_check_script_path(), stat.S_IEXEC)
  230             flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
  231             mode = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH
  232             systemd_cfg_path = util.keepalived_lvs_init_path(
  233                 consts.INIT_SYSTEMD, self.FAKE_ID)
  234             script_path = os.path.join(
  235                 util.keepalived_check_scripts_dir(),
  236                 keepalivedlvs.KEEPALIVED_CHECK_SCRIPT_NAME)
  237             m_open_calls = [
  238                 mock.call(cfg_path, flags, mode),
  239                 mock.call(systemd_cfg_path, flags, mode),
  240                 mock.call(script_path, flags, stat.S_IEXEC)
  241             ]
  242             m_open.assert_has_calls(m_open_calls)
  243             m_fdopen.assert_any_call('TEST-WRITE-CFG', 'wb')
  244             m_fdopen.assert_any_call('TEST-WRITE-SYSINIT', 'w')
  245             m_fdopen.assert_any_call('TEST-WRITE-UDP-VRRP-CHECK', 'w')
  246 
  247             m_os_rm.assert_called_once_with(util.haproxy_check_script_path())
  248             self.assertEqual(200, res.status_code)
  249 
  250     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  251                 'run_systemctl_command')
  252     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  253                 'install_netns_systemd_service')
  254     @mock.patch('shutil.copy2')
  255     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  256                 'get_os_init_system', return_value=consts.INIT_SYSTEMD)
  257     @mock.patch('os.chmod')
  258     @mock.patch('os.path.exists')
  259     @mock.patch('os.makedirs')
  260     @mock.patch('os.remove')
  261     @mock.patch('subprocess.check_output')
  262     def test_upload_lvs_listener_config_start_service_failure(
  263             self, m_check_output, m_os_rm, m_os_mkdir, m_exists, m_os_chmod,
  264             m_os_sysinit, m_copy2, mock_install_netns, mock_systemctl):
  265         m_exists.side_effect = [False, False, True, True, False]
  266         cfg_path = util.keepalived_lvs_cfg_path(self.FAKE_ID)
  267         m = self.useFixture(test_utils.OpenFixture(cfg_path)).mock_open
  268         mock_systemctl.side_effect = [mock.DEFAULT, Exception('boom')]
  269 
  270         with mock.patch('os.open') as m_open, mock.patch.object(os,
  271                                                                 'fdopen',
  272                                                                 m) as m_fdopen:
  273             m_open.side_effect = ['TEST-WRITE-CFG',
  274                                   'TEST-WRITE-SYSINIT']
  275             res = self.client.put(self.TEST_URL % ('123', self.FAKE_ID),
  276                                   data=self.NORMAL_CFG_CONTENT)
  277             os_mkdir_calls = [
  278                 mock.call(util.keepalived_lvs_dir()),
  279                 mock.call(util.keepalived_backend_check_script_dir())
  280             ]
  281             m_os_mkdir.assert_has_calls(os_mkdir_calls)
  282 
  283             mock_install_netns.assert_called_once()
  284             systemctl_calls = [
  285                 mock.call(consts.ENABLE,
  286                           consts.AMP_NETNS_SVC_PREFIX),
  287                 mock.call(consts.ENABLE,
  288                           'octavia-keepalivedlvs-%s' % str(self.FAKE_ID)),
  289             ]
  290             mock_systemctl.assert_has_calls(systemctl_calls)
  291 
  292             m_os_chmod.assert_called_with(
  293                 util.keepalived_backend_check_script_path(), stat.S_IEXEC)
  294             flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
  295             mode = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH
  296             systemd_cfg_path = util.keepalived_lvs_init_path(
  297                 consts.INIT_SYSTEMD, self.FAKE_ID)
  298             m_open_calls = [
  299                 mock.call(cfg_path, flags, mode),
  300                 mock.call(systemd_cfg_path, flags, mode)
  301             ]
  302             m_open.assert_has_calls(m_open_calls)
  303             m_fdopen.assert_any_call('TEST-WRITE-CFG', 'wb')
  304             m_fdopen.assert_any_call('TEST-WRITE-SYSINIT', 'w')
  305             self.assertEqual(500, res.status_code)
  306 
  307     @mock.patch('subprocess.check_output')
  308     @mock.patch('octavia.amphorae.backends.agent.api_server.'
  309                 'keepalivedlvs.KeepalivedLvs.'
  310                 '_check_lvs_listener_exists')
  311     def test_manage_lvs_listener(self, mock_lvs_exist, mock_check_output):
  312         res = self.test_keepalivedlvs.manage_lvs_listener(self.FAKE_ID,
  313                                                           'start')
  314         cmd = ("/usr/sbin/service octavia-keepalivedlvs-{listener_id}"
  315                " {action}".format(listener_id=self.FAKE_ID, action='start'))
  316         mock_check_output.assert_called_once_with(cmd.split(),
  317                                                   stderr=subprocess.STDOUT)
  318         self.assertEqual(202, res.status_code)
  319 
  320         res = self.test_keepalivedlvs.manage_lvs_listener(self.FAKE_ID,
  321                                                           'restart')
  322         self.assertEqual(400, res.status_code)
  323 
  324         mock_check_output.side_effect = subprocess.CalledProcessError(1,
  325                                                                       'blah!')
  326 
  327         res = self.test_keepalivedlvs.manage_lvs_listener(self.FAKE_ID,
  328                                                           'start')
  329         self.assertEqual(500, res.status_code)
  330 
  331     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  332                 'get_lvs_listeners', return_value=[LISTENER_ID])
  333     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  334                 'get_os_init_system', return_value=consts.INIT_SYSTEMD)
  335     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  336                 'get_keepalivedlvs_pid', return_value="12345")
  337     @mock.patch('subprocess.check_output')
  338     @mock.patch('os.remove')
  339     @mock.patch('os.path.exists')
  340     def test_delete_lvs_listener(self, m_exist, m_remove, m_check_output,
  341                                  mget_pid, m_init_sys, mget_lvs_listeners):
  342         m_exist.return_value = True
  343         res = self.test_keepalivedlvs.delete_lvs_listener(self.FAKE_ID)
  344 
  345         cmd1 = ("/usr/sbin/service "
  346                 "octavia-keepalivedlvs-{0} stop".format(self.FAKE_ID))
  347         cmd2 = ("systemctl disable "
  348                 "octavia-keepalivedlvs-{list}".format(list=self.FAKE_ID))
  349         calls = [
  350             mock.call(cmd1.split(), stderr=subprocess.STDOUT),
  351             mock.call(cmd2.split(), stderr=subprocess.STDOUT)
  352         ]
  353         m_check_output.assert_has_calls(calls)
  354         self.assertEqual(200, res.status_code)
  355 
  356     @mock.patch.object(keepalivedlvs, "webob")
  357     @mock.patch('os.path.exists')
  358     def test_delete_lvs_listener_not_exist(self, m_exist, m_webob):
  359         m_exist.return_value = False
  360         self.test_keepalivedlvs.delete_lvs_listener(self.FAKE_ID)
  361         calls = [
  362             mock.call(
  363                 json=dict(message='UDP Listener Not Found',
  364                           details="No UDP listener with UUID: "
  365                                   "{0}".format(self.FAKE_ID)), status=404),
  366             mock.call(json={'message': 'OK'})
  367         ]
  368         m_webob.Response.assert_has_calls(calls)
  369 
  370     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  371                 'get_keepalivedlvs_pid', return_value="12345")
  372     @mock.patch('subprocess.check_output')
  373     @mock.patch('os.path.exists')
  374     def test_delete_lvs_listener_stop_service_fail(self, m_exist,
  375                                                    m_check_output, mget_pid):
  376         m_exist.return_value = True
  377         m_check_output.side_effect = subprocess.CalledProcessError(1,
  378                                                                    'Woops!')
  379         res = self.test_keepalivedlvs.delete_lvs_listener(self.FAKE_ID)
  380         self.assertEqual(500, res.status_code)
  381         self.assertEqual({'message': 'Error stopping keepalivedlvs',
  382                           'details': None}, res.json)
  383 
  384     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  385                 'get_os_init_system', return_value=consts.INIT_SYSVINIT)
  386     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  387                 'get_keepalivedlvs_pid', return_value="12345")
  388     @mock.patch('subprocess.check_output')
  389     @mock.patch('os.remove')
  390     @mock.patch('os.path.exists')
  391     def test_delete_lvs_listener_disable_service_fail(self, m_exist, m_remove,
  392                                                       m_check_output,
  393                                                       mget_pid,
  394                                                       m_init_sys):
  395         m_exist.return_value = True
  396         m_check_output.side_effect = [True,
  397                                       subprocess.CalledProcessError(
  398                                           1, 'Woops!')]
  399         res = self.test_keepalivedlvs.delete_lvs_listener(self.FAKE_ID)
  400         self.assertEqual(500, res.status_code)
  401         self.assertEqual({
  402             'message': 'Error disabling '
  403                        'octavia-keepalivedlvs-%s service' % self.FAKE_ID,
  404             'details': None}, res.json)
  405 
  406     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  407                 'get_os_init_system')
  408     @mock.patch('octavia.amphorae.backends.agent.api_server.util.'
  409                 'get_keepalivedlvs_pid', return_value="12345")
  410     @mock.patch('subprocess.check_output')
  411     @mock.patch('os.remove')
  412     @mock.patch('os.path.exists')
  413     def test_delete_lvs_listener_unsupported_sysinit(self, m_exist, m_remove,
  414                                                      m_check_output, mget_pid,
  415                                                      m_init_sys):
  416         m_exist.return_value = True
  417         self.assertRaises(
  418             util.UnknownInitError,
  419             self.test_keepalivedlvs.delete_lvs_listener,
  420             self.FAKE_ID)