def test_add_successfully_adds_network(self):
        pool = IPPool(network='192.168.1.1/32')
        db.session.add(pool)
        db.session.commit()
        res = ippool.IpAddrPool().get()
        first_net = {
            'allocation': [('192.168.1.1', None, 'free')],
            'blocked_list': [],
            'free_hosts': ['192.168.1.1'],
            'id': u'192.168.1.1/32',
            'ipv6': False,
            'network': u'192.168.1.1/32',
            'node': None,
            'page': 1,
            'pages': 1,
        }
        self.assertEqual(res, [first_net])
        pool = IPPool(network='192.168.1.2/32')
        db.session.add(pool)
        db.session.commit()
        res = ippool.IpAddrPool().get()
        self.assertEqual(len(res), 2)

        res = ippool.IpAddrPool().get(net='192.168.1.3/32')
        self.assertIsNone(res)

        res = ippool.IpAddrPool().get(net='192.168.1.1/32')
        self.assertEqual(res, first_net)

        res = ippool.IpAddrPool().get(net='192.168.1.1/32', page=1000)
        self.assertEqual(res, first_net)
    def test_create_correctly_excludes_blocks(self):
        pool = IPPool(network='192.168.1.1/32')
        db.session.add(pool)
        db.session.commit()

        expected_block_ips = {u'192.168.2.1', u'192.168.2.3', u'192.168.2.4',
                              u'192.168.2.5', u'192.168.2.7'}

        block = '192.168.2.1,192.168.2.3-192.168.2.5,192.168.2.7'

        data = {
            'network': u'192.168.2.0/24',
            'autoblock': block,
            'node': self.node.hostname,
        }
        pool = ippool.IpAddrPool().create(data)
        self.assertEqual({
            'network': pool.network,
            'blocked_list': pool.get_blocked_set()
        }, {
            'network': data['network'],
            'blocked_list': expected_block_ips,
        })

        invalid_block = 'qwerty'
        data = {
            'network': '192.168.4.0/24',
            'autoblock': invalid_block
        }
        with self.assertRaises(APIError):
            ippool.IpAddrPool().create(data)

        networks = db.session.query(IPPool).order_by(IPPool.network)
        self.assertEqual(
            [item.network for item in networks],
            [u'192.168.1.1/32', u'192.168.2.0/24'],
        )
    def test_start_pod_suspend(self, _run, mock_update):
        user = self.user
        url = self.item_url(self.user.id)

        ippool = IPPool(network='192.168.1.252/30')
        ippool.block_ip([u'192.168.1.252', u'192.168.1.255'])
        ippool.save()
        min_pod = {
            'restartPolicy':
            'Always',
            'kube_type':
            0,
            'containers': [{
                'image':
                'nginx',
                'name':
                'fk8i0gai',
                'args': ['nginx', '-g', 'daemon off;'],
                'ports': [{
                    'protocol': 'tcp',
                    'isPublic': True,
                    'containerPort': 80
                }],
            }]
        }

        # pod
        res = PodCollection(user).add(dict(min_pod, name='pod-1'),
                                      skip_check=False)

        data = {'command': 'start'}
        pod_url = '/'.join(['podapi', res['id']])
        response = self.open(url=pod_url,
                             method='PUT',
                             auth=self.userauth,
                             json=data)
        self.assert200(response)
        check_data = check_change_pod_data(data)
        mock_update.assert_called_once_with(res['id'], check_data)

        data = {'suspended': True}
        response = self.admin_open(url=url, method='PUT', json=data)
        self.assert200(response)

        mock_update.called = False
        response = self.open(url=pod_url,
                             method='PUT',
                             auth=self.userauth,
                             json={'command': 'start'})
        self.assertAPIError(response, 403, "PermissionDenied")
        assert mock_update.not_called
    def test_delete(self, network_check_mock):
        """Test IpAddrPool.delete method."""
        network = u'192.168.1.0/24'
        with self.assertRaises(APIError) as err:
            ippool.IpAddrPool().delete(network)
        self.assertEqual(err.exception.status_code, 404)

        pool = IPPool(network=network)
        db.session.add(pool)
        db.session.commit()

        network_check_mock.side_effect = APIError()
        with self.assertRaises(APIError):
            ippool.IpAddrPool().delete(network)

        network_check_mock.side_effect = None
        ippool.IpAddrPool().delete(network)
        all_ = IPPool.query.all()
        self.assertEqual(all_, [])
    def test_suspend(self, _run):
        """AC-1608 In case of unsuspend, return all public IPs"""

        # Disable as otherwise test breaks. Was created before introducing
        # this feature
        current_app.config['FIXED_IP_POOLS'] = False

        user = self.user
        url = self.item_url(self.user.id)

        ippool = IPPool(network='192.168.1.252/30')
        ippool.block_ip([u'192.168.1.252', u'192.168.1.255'])
        ippool.save()
        min_pod = {
            'restartPolicy':
            'Always',
            'kube_type':
            0,
            'containers': [{
                'image':
                'nginx',
                'name':
                'fk8i0gai',
                'args': ['nginx', '-g', 'daemon off;'],
                'ports': [{
                    'protocol': 'tcp',
                    'isPublic': True,
                    'containerPort': 80
                }],
            }]
        }

        # pod-1
        res = PodCollection(user).add(dict(min_pod, name='pod-1'),
                                      skip_check=False)
        pod_1 = Pod.query.get(res['id'])
        pod_1.with_ip_conf = {
            'public_ip': res['public_ip'],
            'containers': [{
                'ports': [{
                    'isPublic': True
                }]
            }],
        }
        pod_1.without_ip_conf = {
            'public_ip_before_freed': res['public_ip'],
            'containers': [{
                'ports': [{
                    'isPublic_before_freed': True
                }]
            }],
        }

        # pod-2
        res = PodCollection(user).add(dict(min_pod, name='pod-2'),
                                      skip_check=False)
        pod_2 = Pod.query.get(res['id'])
        pod_2.with_ip_conf = {
            'public_ip': res['public_ip'],
            'containers': [{
                'ports': [{
                    'isPublic': True
                }]
            }],
        }
        pod_2.without_ip_conf = {
            'public_ip_before_freed': res['public_ip'],
            'containers': [{
                'ports': [{
                    'isPublic_before_freed': True
                }]
            }],
        }

        # helpers
        def _has_public_ip(pod):
            podip = PodIP.query.filter_by(pod_id=pod.id).first()
            conf = pod.get_dbconfig()
            port = conf['containers'][0]['ports'][0]
            if podip is None:
                self.assertFalse(port.get('isPublic'))
                self.assertFalse(conf.get('public_ip'))
                self.assertTrue(port.get('isPublic_before_freed'))
                self.assertTrue(conf.get('public_ip_before_freed'))
                return False
            self.assertFalse(port.get('isPublic_before_freed'))
            self.assertFalse(conf.get('public_ip_before_freed'))
            self.assertTrue(port.get('isPublic'))
            self.assertEqual(conf.get('public_ip'),
                             unicode(ip_address(podip.ip_address)))
            return True

        def _count_pods_with_public_ip():
            return _has_public_ip(pod_1) + _has_public_ip(pod_2)

        # suspend user. Both ip must be freed
        self.assertEqual(_count_pods_with_public_ip(), 2,
                         'all pods must have public ip in the beginning')
        data = {'suspended': True}
        response = self.admin_open(url=url, method='PUT', json=data)
        self.assert200(response)

        self.assertEqual(_count_pods_with_public_ip(), 0,
                         'all pods must lose public ip')

        # unsuspend must be atomic, so if one pod cannot get public ip,
        # all won't
        ippool.block_ip(ippool.free_hosts(as_int=True)[0])
        db.session.commit()

        data = {'suspended': False}
        response = self.admin_open(url=url, method='PUT', json=data)
        self.assertAPIError(response, 400, 'NoFreeIPs')
        self.assertEqual(
            _count_pods_with_public_ip(), 0,
            "operation must be  atomic, so if one pod can't get "
            "public ip, all won't")

        # unblock ip in ippool to be able to unsuspend user
        ippool.unblock_ip(ippool.get_blocked_set(as_int=True).pop())
        db.session.commit()

        data = {'suspended': False}
        response = self.admin_open(url=url, method='PUT', json=data)
        self.assert200(response)
        self.assertEqual(_count_pods_with_public_ip(), 2,
                         'all pods must get their ip back')
 def test_add_raises_if_pool_network_is_incorrect(self):
     pool = IPPool(network='somegarbage')
     db.session.add(pool)
     db.session.commit()
     with self.assertRaises(ValueError):
         ippool.IpAddrPool().get()
    def test_is_ip_available(self):
        block = '["192.168.2.1","192.168.2.3","192.168.2.7"]'
        pool1 = IPPool(network='192.168.1.1/32')
        pool2 = IPPool(
            network='192.168.2.0/24', blocked_list=block, node=self.node)
        db.session.add(pool1)
        db.session.add(pool2)
        db.session.commit()

        self.assertTrue(pool1.is_ip_available(ip=u'192.168.1.1'))
        self.assertFalse(pool1.is_ip_available(ip=u'192.168.1.2'))
        self.assertFalse(pool1.is_ip_available(ip=u'192.168.2.2'))
        self.assertTrue(pool2.is_ip_available(ip='192.168.2.2'))
        self.assertFalse(pool2.is_ip_available(ip='192.168.2.7'))
        self.assertTrue(pool1.is_ip_available(
            ip=u'192.168.1.1', node_hostname=self.node.hostname))
        self.assertTrue(pool2.is_ip_available(
            ip=u'192.168.2.6', node_hostname=self.node.hostname))
        self.assertFalse(pool2.is_ip_available(
            ip=u'192.168.2.7', node_hostname=self.node.hostname))
        self.assertFalse(pool2.is_ip_available(
            ip=u'192.168.2.6', node_hostname="some_other_node"))
    def test_update(self, remove_public_mock):
        """Test IpAddrPool.update method."""
        network = u'192.168.2.0/24'
        with self.assertRaises(APIError):
            ippool.IpAddrPool().update(network, None)

        pool = IPPool(network='192.168.1.0/24')
        node = self.node

        db.session.add(pool)
        db.session.commit()

        block = '192.168.2.1,192.168.2.3-192.168.2.5,192.168.2.7'
        data = {
            'network': network,
            'autoblock': block,
            'node': node.hostname,
        }
        ippool.IpAddrPool().create(data)

        pool = ippool.IpAddrPool().update(network, None)
        self.assertIsNotNone(pool)
        blocked_list1 = pool.get_blocked_set()
        self.assertEqual(pool.network, network)

        # add already blocked ip
        block_ip = u'192.168.2.1'
        params = {'block_ip': block_ip}
        with self.assertRaises(APIError):
            ippool.IpAddrPool().update(network, params)

        # block new ip
        block_ip1 = u'192.168.2.111'
        params = {'block_ip': block_ip1}
        blocked_list = ippool.IpAddrPool().update(network, params)\
            .get_blocked_set()
        self.assertEqual(
            blocked_list,
            blocked_list1 | {block_ip1}
        )

        # and one else
        block_ip2 = u'192.168.2.112'
        params = {'block_ip': block_ip2}
        blocked_list = ippool.IpAddrPool().update(network, params)\
            .get_blocked_set()
        self.assertEqual(
            blocked_list,
            blocked_list1 | {block_ip1, block_ip2}
        )

        unblock_ip = block_ip1
        params = {'unblock_ip': unblock_ip}
        blocked_list = ippool.IpAddrPool().update(network, params)\
            .get_blocked_set()
        self.assertEqual(
            blocked_list,
            blocked_list1 | {block_ip2}
        )

        self.assertFalse(remove_public_mock.called)

        unbind_ip = '192.168.2.222'
        params = {'unbind_ip': unbind_ip}
        blocked_list = ippool.IpAddrPool().update(network, params)\
            .get_blocked_set()
        self.assertEqual(
            blocked_list,
            blocked_list1 | {block_ip2}
        )
        remove_public_mock.assert_called_once_with(ip=unbind_ip)

        pool = ippool.IpAddrPool().update(network, {'node': node.hostname})
        self.assertEqual(pool.node, node)
 def test_get_free_host_returns_first_ip_of_a_net_if_all_are_free(self):
     pool = IPPool(network='192.168.1.0/24')
     db.session.add(pool)
     db.session.commit()
     res = ippool.IpAddrPool().get_free()
     self.assertEqual(res, '192.168.1.0')