| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 1 | #    Copyright 2017 Mirantis, Inc. | 
 | 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 pytest | 
 | 16 |  | 
 | 17 | from devops.helpers import helpers | 
 | 18 |  | 
 | 19 | from tcp_tests import logger | 
 | 20 | from tcp_tests.helpers import netchecker | 
 | 21 |  | 
 | 22 | LOG = logger.logger | 
 | 23 |  | 
 | 24 |  | 
 | 25 | class TestMCPCalico(object): | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 26 |     """Test class for Calico network provider in k8s. | 
 | 27 |        Common calico tests requirements: | 
 | 28 |             KUBERNETES_NETCHECKER_ENABLED=true | 
 | 29 |     """ | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 30 |  | 
 | 31 |     @pytest.mark.fail_snapshot | 
 | 32 |     def test_k8s_netchecker_calico(self, show_step, config, k8s_deployed): | 
 | 33 |         """Test for deploying k8s environment with Calico plugin and check | 
 | 34 |            network connectivity between different pods by k8s-netchecker | 
 | 35 |  | 
 | 36 |         Scenario: | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 37 |             1. Check k8s installation. | 
 | 38 |             2. Get network verification status. Excepted status is 'OK'. | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 39 |  | 
 | 40 |         Duration: 3000 seconds | 
 | 41 |         """ | 
 | 42 |  | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 43 |         show_step(1) | 
 | 44 |         k8sclient = k8s_deployed.api | 
 | 45 |         assert k8sclient.nodes.list() is not None, "Can not get nodes list" | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 46 |         netchecker_port = netchecker.get_service_port(k8sclient) | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 47 |  | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 48 |         show_step(2) | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 49 |         netchecker.wait_check_network(k8sclient, works=True, timeout=300, | 
 | 50 |                                       netchecker_pod_port=netchecker_port) | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 51 |  | 
 | 52 |     @pytest.mark.fail_snapshot | 
| Artem Panchenko | 0872ec0 | 2017-06-29 17:14:12 +0300 | [diff] [blame] | 53 |     @pytest.mark.calico_ci | 
| Tatyana Leontovich | 071ce6a | 2017-10-24 18:08:10 +0300 | [diff] [blame] | 54 |     @pytest.mark.cz8116 | 
| Dennis Dmitriev | 0f624a8 | 2018-06-11 12:57:13 +0300 | [diff] [blame] | 55 |     @pytest.mark.k8s_calico | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 56 |     def test_calico_route_recovery(self, show_step, config, underlay, | 
 | 57 |                                    k8s_deployed): | 
 | 58 |         """Test for deploying k8s environment with Calico plugin and check | 
 | 59 |            that local routes are recovered by felix after removal | 
 | 60 |  | 
 | 61 |         Scenario: | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 62 |             1. Check k8s installation. | 
| Dmitry Tyzhnenko | e20367c | 2017-10-27 19:16:45 +0300 | [diff] [blame] | 63 |             2. Check netchecker-server service. | 
 | 64 |             3. Check netchecker-agent daemon set. | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 65 |             4. Get network verification status. Excepted status is 'OK'. | 
 | 66 |             5. Get metrics from netchecker. | 
 | 67 |             6. Remove local route to netchecker-agent pod on the first node. | 
 | 68 |             7. Check that the route is automatically recovered. | 
 | 69 |             8. Get network verification status. Excepted status is 'OK'. | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 70 |  | 
 | 71 |         Duration: 3000 seconds | 
 | 72 |         """ | 
 | 73 |  | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 74 |         show_step(1) | 
 | 75 |         k8sclient = k8s_deployed.api | 
 | 76 |         assert k8sclient.nodes.list() is not None, "Can not get nodes list" | 
| Dmitry Tyzhnenko | e20367c | 2017-10-27 19:16:45 +0300 | [diff] [blame] | 77 |         netchecker_port = netchecker.get_service_port(k8sclient) | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 78 |  | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 79 |         show_step(2) | 
| Dmitry Tyzhnenko | e20367c | 2017-10-27 19:16:45 +0300 | [diff] [blame] | 80 |         netchecker.get_netchecker_pod_status(k8s=k8s_deployed, | 
 | 81 |                                              namespace='netchecker') | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 82 |  | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 83 |         show_step(3) | 
| Dmitry Tyzhnenko | e20367c | 2017-10-27 19:16:45 +0300 | [diff] [blame] | 84 |         netchecker.get_netchecker_pod_status(k8s=k8s_deployed, | 
 | 85 |                                              pod_name='netchecker-agent', | 
 | 86 |                                              namespace='netchecker') | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 87 |  | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 88 |         show_step(4) | 
| Dmitry Tyzhnenko | e20367c | 2017-10-27 19:16:45 +0300 | [diff] [blame] | 89 |         netchecker.wait_check_network(k8sclient, namespace='netchecker', | 
 | 90 |                                       netchecker_pod_port=netchecker_port) | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 91 |  | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 92 |         show_step(5) | 
| Dmitry Tyzhnenko | e20367c | 2017-10-27 19:16:45 +0300 | [diff] [blame] | 93 |         res = netchecker.get_metric(k8sclient, | 
 | 94 |                                     netchecker_pod_port=netchecker_port, | 
 | 95 |                                     namespace='netchecker') | 
 | 96 |  | 
 | 97 |         assert res.status_code == 200, 'Unexpected response code {}'\ | 
 | 98 |             .format(res) | 
 | 99 |         metrics = ['ncagent_error_count_total', 'ncagent_http_probe_code', | 
 | 100 |                    'ncagent_http_probe_connect_time_ms', | 
 | 101 |                    'ncagent_http_probe_connection_result', | 
 | 102 |                    'ncagent_http_probe_content_transfer_time_ms', | 
 | 103 |                    'ncagent_http_probe_dns_lookup_time_ms', | 
 | 104 |                    'ncagent_http_probe_server_processing_time_ms', | 
 | 105 |                    'ncagent_http_probe_tcp_connection_time_ms', | 
 | 106 |                    'ncagent_http_probe_total_time_ms', | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 107 |                    'ncagent_report_count_total'] | 
| Dmitry Tyzhnenko | e20367c | 2017-10-27 19:16:45 +0300 | [diff] [blame] | 108 |         for metric in metrics: | 
 | 109 |             assert metric in res.text.strip(), \ | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 110 |                 'Mandatory metric {0} is missing in {1}'.format( | 
| Dmitry Tyzhnenko | e20367c | 2017-10-27 19:16:45 +0300 | [diff] [blame] | 111 |                     metric, res.text) | 
 | 112 |  | 
| Dmitry Tyzhnenko | e20367c | 2017-10-27 19:16:45 +0300 | [diff] [blame] | 113 |         show_step(6) | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 114 |         first_node = k8sclient.nodes.list()[0] | 
 | 115 |         first_node_ips = [addr.address for addr in first_node.status.addresses | 
 | 116 |                           if 'IP' in addr.type] | 
 | 117 |         assert len(first_node_ips) > 0, "Couldn't find first k8s node IP!" | 
 | 118 |         first_node_names = [name for name in underlay.node_names() | 
 | 119 |                             if name.startswith(first_node.name)] | 
 | 120 |         assert len(first_node_names) == 1, "Couldn't find first k8s node " \ | 
 | 121 |                                            "hostname in SSH config!" | 
 | 122 |         first_node_name = first_node_names.pop() | 
 | 123 |  | 
 | 124 |         target_pod_ip = None | 
 | 125 |  | 
| Dmitry Tyzhnenko | e20367c | 2017-10-27 19:16:45 +0300 | [diff] [blame] | 126 |         for pod in k8sclient.pods.list(namespace='netchecker'): | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 127 |             LOG.debug('NC pod IP: {0}'.format(pod.status.pod_ip)) | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 128 |             if pod.status.host_ip not in first_node_ips: | 
 | 129 |                 continue | 
 | 130 |             # TODO: get pods by daemonset with name 'netchecker-agent' | 
 | 131 |             if 'netchecker-agent-' in pod.name and 'hostnet' not in pod.name: | 
 | 132 |                 target_pod_ip = pod.status.pod_ip | 
 | 133 |  | 
 | 134 |         assert target_pod_ip is not None, "Could not find netchecker pod IP!" | 
 | 135 |  | 
 | 136 |         route_del_cmd = 'ip route delete {0}'.format(target_pod_ip) | 
 | 137 |         underlay.sudo_check_call(cmd=route_del_cmd, node_name=first_node_name) | 
 | 138 |         LOG.debug('Removed local route to pod IP {0} on node {1}'.format( | 
 | 139 |             target_pod_ip, first_node.name | 
 | 140 |         )) | 
 | 141 |  | 
| Dmitry Tyzhnenko | e20367c | 2017-10-27 19:16:45 +0300 | [diff] [blame] | 142 |         show_step(7) | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 143 |         route_chk_cmd = 'ip route list | grep -q "{0}"'.format(target_pod_ip) | 
 | 144 |         helpers.wait_pass( | 
 | 145 |             lambda: underlay.sudo_check_call(cmd=route_chk_cmd, | 
 | 146 |                                              node_name=first_node_name), | 
| Valentyn Yakovlev | 13a0fc2 | 2017-08-01 11:21:57 +0300 | [diff] [blame] | 147 |             timeout=120, | 
 | 148 |             interval=2 | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 149 |         ) | 
| Dmitry Tyzhnenko | e20367c | 2017-10-27 19:16:45 +0300 | [diff] [blame] | 150 |         pod_ping_cmd = 'sleep 120 && ping -q -c 1 -w 3 {0}'.format( | 
 | 151 |             target_pod_ip) | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 152 |         underlay.sudo_check_call(cmd=pod_ping_cmd, node_name=first_node_name) | 
 | 153 |         LOG.debug('Local route to pod IP {0} on node {1} is ' | 
| Dina Belova | e6fdffb | 2017-09-19 13:58:34 -0700 | [diff] [blame] | 154 |                   'recovered'.format(target_pod_ip, first_node.name)) | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 155 |  | 
| Dmitry Tyzhnenko | e20367c | 2017-10-27 19:16:45 +0300 | [diff] [blame] | 156 |         show_step(8) | 
 | 157 |         netchecker.wait_check_network(k8sclient, namespace='netchecker', | 
 | 158 |                                       netchecker_pod_port=netchecker_port, | 
 | 159 |                                       works=True) | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 160 |  | 
 | 161 |     @pytest.mark.fail_snapshot | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 162 |     @pytest.mark.calico_ci | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 163 |     def test_calico_network_policies(self, show_step, config, underlay, | 
 | 164 |                                      k8s_deployed): | 
 | 165 |         """Test for deploying k8s environment with Calico and check | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 166 |            that network policies work as expected. | 
 | 167 |            Policy test additional requirement: | 
 | 168 |                 KUBERNETES_CALICO_POLICY_ENABLED=true | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 169 |  | 
 | 170 |         Scenario: | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 171 |             1. Check k8s installation. | 
 | 172 |             2. Get network verification status. Excepted status is 'OK'. | 
 | 173 |             3. Enable network isolation for 'netchecker' namespace. | 
 | 174 |             4. Allow connections to netchecker-server from tests. | 
 | 175 |             5. Get network verification status. Excepted status is 'FAIL' | 
 | 176 |                because no netcheker-agent pods should be able to reach | 
 | 177 |                netchecker-service pod. | 
 | 178 |             6. Add kubernetes network policies which allow connections | 
 | 179 |                from netchecker-agent pods (including ones with host network). | 
 | 180 |             7. Get network verification status. Excepted status is 'OK'. | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 181 |  | 
 | 182 |         Duration: 3000 seconds | 
 | 183 |         """ | 
 | 184 |  | 
 | 185 |         show_step(1) | 
 | 186 |         k8sclient = k8s_deployed.api | 
 | 187 |         assert k8sclient.nodes.list() is not None, "Can not get nodes list" | 
 | 188 |         kube_master_nodes = k8s_deployed.get_k8s_masters() | 
 | 189 |         assert kube_master_nodes, "No k8s masters found in pillars!" | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 190 |         netchecker_port = netchecker.get_service_port(k8sclient) | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 191 |  | 
 | 192 |         show_step(2) | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 193 |         netchecker.wait_check_network(k8sclient, namespace='netchecker', | 
 | 194 |                                       works=True, timeout=300, | 
 | 195 |                                       netchecker_pod_port=netchecker_port) | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 196 |  | 
 | 197 |         show_step(3) | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 198 |         netchecker.kubernetes_block_traffic_namespace(underlay, | 
 | 199 |                                                       kube_master_nodes[0], | 
 | 200 |                                                       'netchecker') | 
 | 201 |  | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 202 |         show_step(4) | 
 | 203 |         netchecker.calico_allow_netchecker_connections(underlay, k8sclient, | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 204 |                                                        kube_master_nodes[0], | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 205 |                                                        'netchecker') | 
 | 206 |  | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 207 |         show_step(5) | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 208 |         netchecker.wait_check_network(k8sclient, namespace='netchecker', | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 209 |                                       works=False, timeout=500, | 
 | 210 |                                       netchecker_pod_port=netchecker_port) | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 211 |  | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 212 |         show_step(6) | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 213 |         netchecker.kubernetes_allow_traffic_from_agents(underlay, | 
 | 214 |                                                         kube_master_nodes[0], | 
 | 215 |                                                         'netchecker') | 
 | 216 |  | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 217 |         show_step(7) | 
| Artem Panchenko | 501e67e | 2017-06-14 14:59:18 +0300 | [diff] [blame] | 218 |         netchecker.wait_check_network(k8sclient, namespace='netchecker', | 
| Aleksei Kasatkin | 99dd786 | 2018-05-23 17:58:07 +0200 | [diff] [blame] | 219 |                                       works=True, timeout=300, | 
 | 220 |                                       netchecker_pod_port=netchecker_port) |