class TestDataCenter(unittest.TestCase):
    def setUp(self):
        self.config = TestConfig()
        self.dc = DataCenter(sapi=self.config.sapi_ip, vmapi=self.config.vmapi_ip)


    def test_known_datacenter_apis_are_visible(self):
        self.assertEqual(DataCenter.APIS, ['sapi', 'vmapi', 'fwapi', 'imgapi', 'napi', 'papi', 'workflow', 'ufds'])

    def test_create_with_manual_urls(self):
        self.dc2 = DataCenter('sapi', 'vmapi', 'fwapi', 'imgapi', 'napi', 'papi', 'workflow', 'ufds')
        for api in DataCenter.APIS:
            self.assertEqual(getattr(self.dc2, api), 'http://' + api)

    def test_create_with_sapi_url_only(self):


        self.assertEqual(self.dc.vmapi, 'http://' + self.config.vmapi_ip)
        self.assertEqual(self.dc.fwapi, 'http://' + self.config.fwapi_ip)
        self.assertEqual(self.dc.imgapi, 'http://' + self.config.imgapi_ip)
        self.assertEqual(self.dc.napi, 'http://' + self.config.napi_ip)
        self.assertEqual(self.dc.papi, 'http://' + self.config.papi_ip)
        self.assertEqual(self.dc.workflow, 'http://' + self.config.workflow_ip)
        self.assertEqual(self.dc.ufds, 'http://' + self.config.ufds_ip)


    def test_health_check_vmapi(self):
        self.assertTrue(self.dc.healthcheck_vmapi())


    def test_list_smart_machines_has_correct_type(self):

        vms = self.dc.list_smart_machines()
        if not vms:
            # TODO: mocking
            pass
        self.assertIsInstance(vms.pop(), SmartMachine)

    def test_list_kvm_machines_has_correct_type(self):

        vms = self.dc.list_kvm_machines()
        if not vms:
            # TODO: mocking
            pass
        self.assertIsInstance(vms.pop(), KVMMachine)

    def test_list_machines_has_both_types(self):
        vms = self.dc.list_machines()
        if not vms:
            # TODO: mocking
            pass
        kvmFound = False
        smFound = False

        for vm in vms:
            if isinstance(vm, SmartMachine):
                smFound = True
            if isinstance(vm, KVMMachine):
                kvmFound = True

        self.assertTrue(kvmFound)
        self.assertTrue(smFound)

    def test_get_smart_machine(self):
        vms = self.dc.list_smart_machines()
        test_vm = vms.pop()
        verify_vm = self.dc.get_smart_machine(test_vm.uuid)
        self.assertEqual(test_vm, verify_vm)

    def test_get_kvm_machine(self):
        vms = self.dc.list_kvm_machines()
        test_vm = vms.pop()
        verify_vm = self.dc.get_kvm_machine(test_vm.uuid)
        self.assertEqual(test_vm, verify_vm)

    def test_get_machine(self):
        smart_machines = self.dc.list_smart_machines()
        kvm_machines = self.dc.list_kvm_machines()

        test_sm = smart_machines.pop()
        test_kvm = kvm_machines.pop()

        test_sm_ = self.dc.get_machine(test_sm.uuid)
        self.assertEqual(test_sm, test_sm_)

        test_kvm_ = self.dc.get_machine(test_kvm.uuid)
        self.assertEqual(test_kvm, test_kvm_)

    def test_list_networks(self):

        network_dummy_data = [{'uuid': 'foo'}, {'uuid': 'bar'}]
        self.dc.request = MagicMock()
        self.dc.request.return_value = (network_dummy_data, None)
        networks = self.dc.list_networks()
        self.dc.request.assert_called_once_with('GET', 'napi', '/networks')
        self.assertEqual(networks.__len__(), 2)
        self.assertEqual(networks.pop().uuid, 'bar')
        self.assertEqual(networks.pop().uuid, 'foo')


    def test_find_next_free_vlan(self):

        self.dc.request = MagicMock()

        raw_network_data = [
            {u'vlan_id': 0},
            {u'vlan_id': 0},
            {u'vlan_id': 1337}
        ]
        self.dc.request.return_value = ( raw_network_data, None )
        self.assertEqual(self.dc.next_free_vlan(), 2)

        raw_network_data = [
            {u'vlan_id': 0},
            {u'vlan_id': 1},
            {u'vlan_id': 2}
        ]
        self.dc.request.return_value = ( raw_network_data, None )
        self.assertEqual(self.dc.next_free_vlan(), 3)

        raw_network_data = [
            {u'vlan_id': 2},
            {u'vlan_id': 1},
            {u'vlan_id': 0}
        ]
        self.dc.request.return_value = ( raw_network_data, None )
        self.assertEqual(self.dc.next_free_vlan(), 3)

        raw_network_data = [
            {u'vlan_id': 3},
            {u'vlan_id': 1},
            {u'vlan_id': 2}
        ]
        self.dc.request.return_value = ( raw_network_data, None )
        self.assertEqual(self.dc.next_free_vlan(), 4)

        raw_network_data = [{u'vlan_id': i } for i in xrange(0,4096)]
        self.dc.request.return_value = ( raw_network_data, None )
        self.assertEqual(self.dc.next_free_vlan(), None)

    def test_find_next_free_network(self):

        self.dc.request = MagicMock()

        raw_network_data = [
            {u'subnet': u'192.168.2.0/24'},
            {u'subnet': u'10.0.0.0/24'},
            {u'subnet': u'10.0.1.0/24'},
            {u'subnet': u'10.0.2.0/24'}
        ]
        self.dc.request.return_value = ( raw_network_data, None )
        self.assertEqual(self.dc.next_free_network(24), '10.0.3.0/24')

        raw_network_data = [
            {u'subnet': u'192.168.2.0/24'},
            {u'subnet': u'10.0.2.0/24'},
            {u'subnet': u'10.0.1.0/24'},
            {u'subnet': u'10.0.0.0/24'}
        ]
        self.dc.request.return_value = ( raw_network_data, None )
        self.assertEqual(self.dc.next_free_network(24), '10.0.3.0/24')

        raw_network_data = [
            {u'subnet': u'192.168.2.0/24'},
            {u'subnet': u'10.0.0.0/23'},
            {u'subnet': u'10.0.2.0/25'}
        ]
        self.dc.request.return_value = ( raw_network_data, None )
        self.assertEqual(self.dc.next_free_network(25), '10.0.2.128/25')

        raw_network_data = [
            {u'subnet': u'192.168.2.0/24'},
            {u'subnet': u'10.0.0.0/23'},
            {u'subnet': u'10.0.1.0/24'}
        ]
        self.dc.request.return_value = ( raw_network_data, None )
        self.assertEqual(self.dc.next_free_network(24), '10.0.2.0/24')

        raw_network_data = [
            {u'subnet': u'192.168.2.0/24'},
            {u'subnet': u'10.0.0.0/22'}
        ]
        self.dc.request.return_value = ( raw_network_data, None )
        self.assertEqual(self.dc.next_free_network(24), '10.0.4.0/24')

        raw_network_data = [
            {u'subnet': u'192.168.2.0/24'},
            {u'subnet': u'10.0.0.0/25'}
        ]
        self.dc.request.return_value = ( raw_network_data, None )
        self.assertEqual(self.dc.next_free_network(24), '10.0.1.0/24')



    def test_get_keys(self):
        # FIXME: needs more testing
        admin_pubkeys = self.dc.get_pubkeys(user_uuid=self.config.admin_uuid, ignore_cert=True)
        self.assertGreater(admin_pubkeys.__len__(), 0)
class TestLifeCycleVM(unittest.TestCase):
    def setUp(self):
        self.config = TestConfig()
        self.dc = DataCenter(sapi=self.config.sapi_ip, vmapi=self.config.vmapi_ip)


    def test_smart_machine_lifecycle(self):
        my_alias = uuid.uuid4().__str__()

        smartmachine = self.dc.create_smart_machine(owner=self.config.user_uuid,
                                                    networks=[self.config.external_network_uuid],
                                                    package=self.config.package_small,
                                                    image=self.config.smartmachine_image,
                                                    alias=my_alias)

        self.assertIsInstance(smartmachine, SmartMachine)
        self.assertNotEqual(smartmachine.status(), DataCenter.STATE_RUNNING)
        self.assertFalse(smartmachine.is_running())
        smartmachine.poll_until(status=DataCenter.STATE_RUNNING)
        smartmachine.refresh()
        self.assertEqual(smartmachine.status(), DataCenter.STATE_RUNNING)
        self.assertTrue(smartmachine.is_running())
        self.assertGreater(smartmachine.customer_metadata.get('root_authorized_keys'),0)
        smartmachine.stop()
        self.assertFalse(smartmachine.is_stopped())
        smartmachine.poll_until(smartmachine.STATE_STOPPED)
        self.assertTrue(smartmachine.is_stopped())
        smartmachine.start()
        self.assertFalse(smartmachine.is_running())
        smartmachine.poll_until(smartmachine.STATE_RUNNING)
        self.assertTrue(smartmachine.is_running())
        self.assertFalse(smartmachine.is_destroyed())
        smartmachine.delete()
        smartmachine.poll_until(status=DataCenter.STATE_DESTROYED)
        self.assertEqual(smartmachine.status(), DataCenter.STATE_DESTROYED)

    def test_kvm_machine_lifecycle(self):
        my_alias = uuid.uuid4().__str__()

        kvm_machine = self.dc.create_kvm_machine(owner=self.config.user_uuid,
                                                 networks=[self.config.external_network_uuid],
                                                 package=self.config.package_small,
                                                 image=self.config.kvm_image,
                                                 alias=my_alias)

        self.assertIsInstance(kvm_machine, KVMMachine)
        self.assertNotEqual(kvm_machine.status(), DataCenter.STATE_RUNNING)
        kvm_machine.poll_until(status=DataCenter.STATE_RUNNING)
        kvm_machine.refresh()
        self.assertEqual(kvm_machine.status(), DataCenter.STATE_RUNNING)
        self.assertGreater(kvm_machine.customer_metadata.get('root_authorized_keys'),0)
        kvm_machine.stop()
        self.assertFalse(kvm_machine.is_stopped())
        kvm_machine.poll_until(kvm_machine.STATE_STOPPED)
        self.assertTrue(kvm_machine.is_stopped())
        kvm_machine.start()
        self.assertFalse(kvm_machine.is_running())
        kvm_machine.poll_until(kvm_machine.STATE_RUNNING)
        self.assertTrue(kvm_machine.is_running())

        kvm_machine.delete()
        kvm_machine.poll_until(status=DataCenter.STATE_DESTROYED)
        self.assertEqual(kvm_machine.status(), DataCenter.STATE_DESTROYED)

    # to test the generic dc.get_machine functions, should work for both sm and kvm.
    def test_both_combined_lifecycle_and_retrieval(self):
        my_smart_machine_alias = uuid.uuid4().__str__()
        my_kvm_machine_alias = uuid.uuid4().__str__()

        smart_machine = self.dc.create_smart_machine(owner=self.config.user_uuid,
                                                     networks=[self.config.external_network_uuid],
                                                     package=self.config.package_small,
                                                     image=self.config.smartmachine_image,
                                                     alias=my_smart_machine_alias,
                                                     user_script="touch /test-file")
        sm_uuid = smart_machine.uuid

        self.assertIsInstance(smart_machine, SmartMachine)
        self.assertNotEqual(smart_machine.status(), DataCenter.STATE_RUNNING)
        self.assertFalse(smart_machine.is_running())
        smart_machine.poll_until(status=DataCenter.STATE_RUNNING)
        self.assertGreater(smart_machine.customer_metadata.get('root_authorized_keys'),0)
        smart_machine.refresh()
        self.assertEqual(smart_machine.status(), DataCenter.STATE_RUNNING)
        self.assertTrue(smart_machine.is_running())
        self.assertFalse(smart_machine.is_destroyed())

        kvm_machine = self.dc.create_kvm_machine(owner=self.config.user_uuid,
                                                 networks=[self.config.external_network_uuid],
                                                 package=self.config.package_small,
                                                 image=self.config.kvm_image,
                                                 alias=my_kvm_machine_alias,
                                                 user_script="touch /test-file")
        kvm_uuid = kvm_machine.uuid

        self.assertIsInstance(kvm_machine, KVMMachine)
        self.assertNotEqual(kvm_machine.status(), DataCenter.STATE_RUNNING)
        kvm_machine.poll_until(status=DataCenter.STATE_RUNNING)
        self.assertEqual(kvm_machine.status(), DataCenter.STATE_RUNNING)
        self.assertGreater(kvm_machine.customer_metadata.get('root_authorized_keys'),0)
        kvm_machine.refresh()

        smart_machine = self.dc.get_machine(sm_uuid)
        self.assertIsInstance(smart_machine, SmartMachine)
        self.assertEqual(smart_machine, smart_machine)

        kvm_machine_ = self.dc.get_machine(kvm_uuid)
        self.assertIsInstance(kvm_machine_, KVMMachine)
        self.assertEqual(kvm_machine_, kvm_machine)

        smart_machine.delete()
        smart_machine.poll_until(status=DataCenter.STATE_DESTROYED)
        self.assertEqual(smart_machine.status(), DataCenter.STATE_DESTROYED)
        kvm_machine.delete()
        kvm_machine.poll_until(status=DataCenter.STATE_DESTROYED)
        self.assertEqual(kvm_machine.status(), DataCenter.STATE_DESTROYED)