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

    def test_list_all_packages(self):
        packages = self.dc.list_packages()
        self.assertIsNotNone(packages)
        self.assertIsInstance(packages, list)
        self.assertGreater(packages.__len__(),0, 'no packages returned')
        for package in packages:
            self.assertIsInstance(package, Package)
            for attr in ['uuid', 'owner_uuids']:
                self.assertIsNotNone(package.__getattribute__(attr))

            self.assertGreater(package.owner_uuids.__len__(), 0, 'no owner_uuids found')


    def test_get_package_by_uuid(self):
        packages = self.dc.list_packages()
        package = packages.pop()

        package_ = self.dc.get_package(uuid=package.uuid)
        self.assertEqual(package, package_)
class TestLifeCycleNetwork(unittest.TestCase):
    def setUp(self):
        self.config = TestConfig()
        self.dc = DataCenter(sapi=self.config.sapi_ip, vmapi=self.config.vmapi_ip)

    def test_network_lifecycle(self):
        my_network = self.dc.create_network(
            name=self.config.network_name,
            owner_uuids=[self.config.user_uuid],
            subnet=self.config.subnet,
            gateway=self.config.gateway,
            provision_start_ip=self.config.provision_start_ip,
            provision_end_ip=self.config.provision_end_ip,
            vlan_id=self.config.vlan_id,
            nic_tag=self.config.nic_tag,
            resolvers=self.config.resolvers,
            routes=self.config.routes,
            description=self.config.network_description,
        )

        self.assertIsInstance(my_network, Network)
        self.assertIsNotNone(my_network.uuid)

        my_network_ = self.dc.get_network(uuid=my_network.uuid)
        self.assertEqual(my_network, my_network_)

        my_network.delete()
        my_network_ = self.dc.get_network(uuid=my_network.uuid)
        self.assertIsNone(my_network_, "network still exists")

    def test_smart_network_lifecycle(self):
        my_smart_network = self.dc.create_smart_network(
            name=self.config.network_name,
            owner_uuids=[self.config.user_uuid],
            description=self.config.network_description,
        )
        self.assertIsInstance(my_smart_network, Network)
        self.assertIsNotNone(my_smart_network.uuid)

        my_network_ = self.dc.get_network(uuid=my_smart_network.uuid)
        self.assertEqual(my_smart_network, my_network_)

        my_smart_network.delete()
        my_network_ = self.dc.get_network(uuid=my_smart_network.uuid)
        self.assertIsNone(my_network_, "network still exists")
class TestJob(unittest.TestCase):
    def verify_job_object(self, job):
        self.assertIsInstance(job, Job)
        self.assertIsNotNone(job.uuid)
        self.assertIsNotNone(job.workflow)
        self.assertIsNotNone(job.workflow_uuid)

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

    def test_retrieve_all_jobs(self):
        all_jobs = self.dc.list_jobs()

        self.assertNotEqual(0, all_jobs.__len__())
        self.assertIsInstance(all_jobs, list)
        for job in all_jobs:
            self.assertIsInstance(job, Job)

    def test_create_job_from_raw_data(self):
        all_jobs = self.dc.list_jobs()
        job_uuid = all_jobs.pop().uuid
        raw_job_data, _ = self.dc.request("GET", "workflow", "/jobs/" + job_uuid)
        my_job = Job(datacenter=self.dc, data=raw_job_data)
        self.verify_job_object(my_job)

    def test_create_job_from_uuid(self):
        all_jobs = self.dc.list_jobs()
        job_uuid = all_jobs.pop().uuid
        my_job = Job(datacenter=self.dc, uuid=job_uuid)
        self.verify_job_object(my_job)

    def test_retrieve_job_by_id(self):
        all_jobs = self.dc.list_jobs()
        test_job = all_jobs.pop()
        test_job_uuid = test_job.uuid
        verify_job = self.dc.get_job(uuid=test_job_uuid)
        self.assertEqual(test_job, verify_job)
 def setUp(self):
     self.config = TestConfig()
     self.dc = DataCenter(sapi=self.config.sapi_ip, vmapi=self.config.vmapi_ip)
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)
class TestLifeCycleVMandNetwork(unittest.TestCase):
    def setUp(self):
        self.config = TestConfig()
        self.dc = DataCenter(sapi=self.config.sapi_ip, vmapi=self.config.vmapi_ip)

    def test_attach_nics_to_machines(self):

        my_alias = uuid.uuid4().__str__()

        # setup vm
        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)


        # verify vm
        self.assertIsInstance(smartmachine, SmartMachine)
        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())

        # setup net
        my_network = self.dc.create_network(name=self.config.network_name,
                                            owner_uuids=[self.config.user_uuid],
                                            subnet=self.config.subnet,
                                            gateway=self.config.gateway,
                                            provision_start_ip=self.config.provision_start_ip,
                                            provision_end_ip=self.config.provision_end_ip,
                                            vlan_id=self.config.vlan_id,
                                            nic_tag=self.config.nic_tag,
                                            resolvers=self.config.resolvers,
                                            routes=self.config.routes,
                                            description=self.config.network_description)

        # verify net
        self.assertIsInstance(my_network, Network)
        self.assertIsNotNone(my_network.uuid)
        my_network_ = self.dc.get_network(uuid=my_network.uuid)
        self.assertEqual(my_network, my_network_)

        # add net to vm
        smartmachine.add_nic(my_network.uuid, ip=self.config.test_ip_1)
        time.sleep(30) # FIXME: add_nic has no blocking method
        smartmachine.refresh()

        self.assertTrue(smartmachine.is_attached_to_network(my_network.uuid))

        self.assertEqual(smartmachine.nics.__len__(), 2)
        self.assertEqual(smartmachine.nics[1].get('network_uuid'), my_network.uuid)
        self.assertEqual(smartmachine.nics[1].get('ip'), self.config.test_ip_1)


        smartmachine.remove_nic(mac_address=smartmachine.nics[1].get('mac'))
        time.sleep(30) # FIXME: add_nic has no blocking method
        smartmachine.refresh()

        self.assertFalse(smartmachine.is_attached_to_network(my_network.uuid))

        self.assertEqual(smartmachine.nics.__len__(), 1)

        # clean up
        my_network.delete()
        my_network_ = self.dc.get_network(uuid=my_network.uuid)
        self.assertIsNone(my_network_, 'network still exists')

        smartmachine.delete()
        smartmachine.poll_until(status=DataCenter.STATE_DESTROYED)
        self.assertEqual(smartmachine.status(), DataCenter.STATE_DESTROYED)
    def test_create_retrieve_save_delete(self):
        # John is a user who wants to use this library to manage kvm and smart machines on a SDC
        # he was given a user account which he should use as the owner of his systems:
        # user John, password: johnpass1, user-uuid: 9d5ae03c-d64a-ea5b-b020-9ae6e3b6bb9e
        user_uuid = TestConfig.user_uuid

        # John was also given:
        # the sapi URL
        sapi_ip = TestConfig.sapi_ip
        # and 2 package-uuids:
        package_small = TestConfig.package_small
        package_big = TestConfig.package_big

        # the image-uuid for a smartmachine:
        smartmachine_image = TestConfig.smartmachine_image
        kvm_image = TestConfig.kvm_image

        # and the external network:
        external_network_uuid = TestConfig.external_network_uuid


        # John, curious as he is, imports the library
        from sdcadmin.datacenter import DataCenter

        # John creates a datacenter with the sapi information he was provided
        dc = DataCenter(sapi=sapi_ip, vmapi=self.config.vmapi_ip)
        self.assertTrue(dc.healthcheck_vmapi())

        # John does not want his machines to be public. He looks around for other networks
        self.assertGreater(dc.list_networks().__len__(), 1)

        # John creates his own network
        my_network = dc.create_network(name='john_net', owner_uuids=[user_uuid],
                                       subnet=TestConfig.subnet,
                                       gateway=TestConfig.gateway,
                                       provision_start_ip=TestConfig.provision_start_ip,
                                       provision_end_ip=TestConfig.provision_end_ip,
                                       vlan_id=TestConfig.vlan_id,
                                       nic_tag=TestConfig.nic_tag,
                                       resolvers=TestConfig.resolvers,
                                       routes=TestConfig.routes,
                                       description='john_net for john')
        my_network_uuid = my_network.uuid
        self.assertIsNotNone(my_network)
        self.assertIsNotNone(my_network_uuid)


        # John retrieves his network
        my_network_ = dc.get_network(my_network_uuid)
        self.assertEqual(my_network, my_network_)



        # John sees no machines created yet for his user that are running
        all_my_vms = dc.list_machines(owner_uuid=user_uuid, state=dc.STATE_RUNNING)
        all_my_smart_machines = dc.list_smart_machines(owner_uuid=user_uuid, state=dc.STATE_RUNNING)
        all_my_kvm_machines = dc.list_kvm_machines(owner_uuid=user_uuid, state=dc.STATE_RUNNING)
        self.assertEqual(all_my_smart_machines.__len__() + all_my_kvm_machines.__len__(), 0, 'VMs for this Owner exist')


        # John creates a first smartmachine and is pleased
        my_first_smart_machine = dc.create_smart_machine(owner=user_uuid, networks=[external_network_uuid],
                                                         package=package_small, image=smartmachine_image,
                                                         alias='my_first_smart_machine')
        self.assertIsNotNone(my_first_smart_machine.status())
        self.assertIsNotNone(my_first_smart_machine.uuid)

        # John wonders if the machine is created, so he retrieves it another time
        my_first_smartmachine_ = dc.get_smart_machine(uuid=my_first_smart_machine.uuid)
        self.assertEqual(my_first_smart_machine, my_first_smartmachine_)

        # John realizes he was to fast, his machine is still provisioning
        self.assertNotEqual(dc.STATE_RUNNING, my_first_smart_machine.status())

        # John decides to call a method that waits until the provisioning is done
        my_first_smart_machine.poll_until(status=dc.STATE_RUNNING)
        self.assertEqual(dc.STATE_RUNNING, my_first_smart_machine.status())

        # John sees his smart machine created and is happy for a moment
        all_my_vms = dc.list_machines(owner_uuid=user_uuid, state=dc.STATE_RUNNING)
        all_my_smart_machines = dc.list_smart_machines(owner_uuid=user_uuid, state=dc.STATE_RUNNING)
        self.assertEqual(all_my_vms.__len__(), 1)
        self.assertEqual(all_my_smart_machines.__len__(), 1)

        # John wants to provision another machine, this time he wants to try a KVM machine
        # John provisions his second machine
        my_first_kvm_machine = dc.create_kvm_machine(user_uuid, [external_network_uuid], package_small, kvm_image,
                                                     'my_first_kvm_machine')
        self.assertIsNotNone(my_first_kvm_machine)

        # John calls the wait method again and waits patiently
        self.assertNotEqual(my_first_kvm_machine.status(), dc.STATE_RUNNING)
        my_first_kvm_machine.poll_until(dc.STATE_RUNNING)
        self.assertEqual(my_first_kvm_machine.status(), dc.STATE_RUNNING)

        # John gets exited as he sees his second machine, this time a KVM machine as well
        all_my_vms = dc.list_machines(owner_uuid=user_uuid, state=dc.STATE_RUNNING)
        all_my_kvm_machines = dc.list_kvm_machines(owner_uuid=user_uuid, state=dc.STATE_RUNNING)
        self.assertEqual(all_my_vms.__len__(), 2)
        self.assertEqual(all_my_kvm_machines.__len__(), 1)

        # John wants to give his machines access to his private network
        my_first_kvm_machine.add_nic(network_uuid=my_network_uuid, ip=TestConfig.test_ip_1)

        # John grabs a coffee
        time.sleep(30) # FIXME: add_nic has no blocking method

        self.assertTrue(my_first_kvm_machine.is_attached_to_network(my_network_uuid))
        my_first_kvm_machine.refresh()
        my_first_kvm_machine.remove_nic(my_first_kvm_machine.nics[1].get('mac'))
        time.sleep(30)  # FIXME: add_nic has no blocking method
        my_first_kvm_machine.refresh()
        self.assertFalse(my_first_kvm_machine.is_attached_to_network(my_network_uuid))


        my_first_smart_machine.add_nic(network_uuid=my_network_uuid, ip=TestConfig.test_ip_2)
        time.sleep(30)
        self.assertTrue(my_first_smart_machine.is_attached_to_network(my_network_uuid))

        # John does a quick refresh
        my_first_smart_machine.refresh()

        # John wants to remove the external network from his machine again.
        my_first_smart_machine.remove_nic(my_first_smart_machine.nics[1].get('mac'))

        # John grabs another coffee
        time.sleep(30)

        self.assertFalse(my_first_smart_machine.is_attached_to_network(my_network_uuid))


        # John now gets tired, he did provision 2 servers after all.
        # He decides to remove the kvm machine first
        my_first_kvm_machine.delete()

        # John calls the method to wait until it is gone.
        self.assertNotEqual(my_first_kvm_machine.status(), dc.STATE_DESTROYED)
        my_first_kvm_machine.poll_until(dc.STATE_DESTROYED)
        self.assertEqual(my_first_kvm_machine.status(), dc.STATE_DESTROYED)

        # John grins as the kvm machine is destroyed. to be sure that it is gone for sure, he lists his vms
        # and only sees the smart machine remaining
        all_my_vms = dc.list_machines(owner_uuid=user_uuid, state=dc.STATE_RUNNING)
        all_my_smart_machines = dc.list_smart_machines(owner_uuid=user_uuid, state=dc.STATE_RUNNING)
        all_my_kvm_machines = dc.list_kvm_machines(owner_uuid=user_uuid, state=dc.STATE_RUNNING)
        self.assertEqual(all_my_vms.__len__(), 1)
        self.assertEqual(all_my_smart_machines.__len__(), 1)
        self.assertEqual(all_my_kvm_machines.__len__(), 0)

        # John, with a tear in his eye, goes on to  destroy his beloved awesome smart machine.
        # goodbye sweet prince he whispers to himself
        my_first_smart_machine.delete()
        self.assertNotEqual(my_first_smart_machine.status(), dc.STATE_DESTROYED)
        my_first_smart_machine.poll_until(dc.STATE_DESTROYED)
        self.assertEqual(my_first_smart_machine.status(), dc.STATE_DESTROYED)


        # John realises what he has done and questions life and his very existence.
        # After a few moments of regret, he wants to be sure that all VMs are destroyed.
        all_my_vms = dc.list_machines(owner_uuid=user_uuid, state=dc.STATE_RUNNING)
        all_my_smart_machines = dc.list_smart_machines(owner_uuid=user_uuid, state=dc.STATE_RUNNING)
        all_my_kvm_machines = dc.list_kvm_machines(owner_uuid=user_uuid, state=dc.STATE_RUNNING)
        self.assertEqual(all_my_vms.__len__(), 0)
        self.assertEqual(all_my_smart_machines.__len__(), 0)
        self.assertEqual(all_my_kvm_machines.__len__(), 0)

        # John keeps on rampaging and deletes his john_net.
        my_network.delete()
        my_network = dc.get_network(uuid=my_network_uuid)
        self.assertIsNone(my_network)