def test_reboot_ready_server(self, mock_sleep): """ Reboot a server that has status 'ready' """ server = ReadyOpenStackServerFactory() server.reboot() self.assertEqual(server.status, ServerStatus.Booting) server.os_server.reboot.assert_called_once_with(reboot_type='SOFT') mock_sleep.assert_called_once_with(30)
def test_make_active(self, mock_run_playbook, mock_public_ip): """ POST /api/v1/openedx_appserver/:id/make_active/ - Make this OpenEdXAppServer active for its given instance. This can be done at any time; the AppServer must be healthy but "New", "WaitingForServer", etc. are all considered healthy states, so the AppServer does not necessarily have to be fully provisioned and online. """ self.api_client.login(username='******', password='******') instance = OpenEdXInstanceFactory(edx_platform_commit='1' * 40) server = ReadyOpenStackServerFactory() app_server = make_test_appserver(instance=instance, server=server) self.assertFalse(instance.get_active_appservers().exists()) response = self.api_client.post( '/api/v1/openedx_appserver/{pk}/make_active/'.format( pk=app_server.pk)) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data, {'status': 'App server activation initiated.'}) self.assertEqual(mock_run_playbook.call_count, 1) instance.refresh_from_db() self.assertEqual(list(instance.get_active_appservers().all()), [app_server]) app_server.refresh_from_db() self.assertTrue(app_server.is_active)
def setUp(self): with patch( 'instance.tests.models.factories.openedx_instance.OpenEdXInstance._write_metadata_to_consul', return_value=(1, True)): self.appserver = make_test_appserver() self.appserver.server = ReadyOpenStackServerFactory() self.appserver.is_active = True self.appserver.save()
def test_update_status_ready_to_booting(self, _mock_sleep, mock_is_port_open): """ Update status when the server is rebooted """ server = ReadyOpenStackServerFactory(os_server_fixture='openstack/api_server_2_active.json') # If server is in Status.Booting, update_status calls is_port_open # to determine if server should transition to Status.Ready. # When using a fixture for server.os_server, is_port_open will eventually return False, # but only after a delay of about two minutes. # So we mock out is_port_open here to speed up testing: mock_is_port_open.return_value = False self.assertEqual(server.status, ServerStatus.Ready) self.assertIsInstance(server.update_status(), ServerStatus.Ready) server.reboot() self.assertEqual(server.status, ServerStatus.Booting) self.assertIsInstance(server.update_status(), ServerStatus.Booting) self.assertEqual(server.status, ServerStatus.Booting)
def _create_appserver(self, is_active): """ Creates test instance and app server """ instance = OpenEdXInstanceFactory(edx_platform_commit='1' * 40) server = ReadyOpenStackServerFactory() app_server = make_test_appserver(instance=instance, server=server) self.assertFalse(instance.get_active_appservers().exists()) app_server.make_active(is_active) self.assertEqual(app_server.is_active, is_active) return instance, app_server
def test_inventory_str(self, os_server_manager): """ Ansible inventory - showing servers once they are in ready status """ instance = SingleVMOpenEdXInstanceFactory() self.assertEqual(instance.inventory_str, '[app]') # Server 0: 'pending' OpenStackServerFactory(instance=instance) self.assertEqual(instance.inventory_str, '[app]') # Server 1: 'building' BuildingOpenStackServerFactory(instance=instance) self.assertEqual(instance.inventory_str, '[app]') # Server 2: 'failed' server2 = BuildingOpenStackServerFactory(instance=instance) server2._status_to_build_failed() self.assertEqual(instance.inventory_str, '[app]') # Server 3: 'booting' server3 = BootingOpenStackServerFactory(instance=instance) os_server_manager.add_fixture(server3.openstack_id, 'openstack/api_server_2_active.json') self.assertEqual(instance.inventory_str, '[app]') # Server 4: 'terminated' server4 = ReadyOpenStackServerFactory(instance=instance) server4._status_to_terminated() os_server_manager.add_fixture(server4.openstack_id, 'openstack/api_server_2_active.json') self.assertEqual(instance.inventory_str, '[app]') # Server 5: 'ready' server5 = ReadyOpenStackServerFactory(instance=instance) os_server_manager.add_fixture(server5.openstack_id, 'openstack/api_server_2_active.json') self.assertEqual(instance.inventory_str, '[app]\n192.168.100.200') # Server 6: 'ready' server6 = ReadyOpenStackServerFactory(instance=instance) os_server_manager.add_fixture(server6.openstack_id, 'openstack/api_server_3_active.json') self.assertEqual(instance.inventory_str, '[app]\n192.168.100.200\n192.168.99.66')
def test_mark_active_on_success(self, provisioning_succeeds, mock_consul): """ Test that when mark_active_on_success=True, the spawn_appserver task will mark the newly provisioned AppServer as active, if provisioning succeeded. """ instance = OpenEdXInstanceFactory() server = ReadyOpenStackServerFactory() appserver = make_test_appserver(instance=instance, server=server) self.mock_spawn_appserver.return_value = appserver.pk if provisioning_succeeds else None tasks.spawn_appserver(instance.ref.pk, mark_active_on_success=True) self.assertEqual(self.mock_spawn_appserver.call_count, 1) if provisioning_succeeds: self.mock_make_appserver_active.assert_called_once_with(appserver.pk, active=True, deactivate_others=False) else: self.mock_make_appserver_active.assert_not_called()
def test_deactivate_old_appservers(self, provisioning_succeeds): """ If `mark_active_on_success` and `deactivate_old_appservers` are both passed in as `True`, the spawn appserver task will mark the newly provisioned AppServer as active, and deactivate old appservers, if provisioning succeeded. """ instance = OpenEdXInstanceFactory() server = ReadyOpenStackServerFactory() appserver = make_test_appserver(instance=instance, server=server) self.mock_spawn_appserver.return_value = appserver.pk if provisioning_succeeds else None tasks.spawn_appserver(instance.ref.pk, mark_active_on_success=True, deactivate_old_appservers=True) self.assertEqual(self.mock_spawn_appserver.call_count, 1) if provisioning_succeeds: self.mock_make_appserver_active.assert_called_once_with(appserver.pk, active=True, deactivate_others=True) else: self.mock_make_appserver_active.assert_not_called()
def test_make_inactive_unhealthy(self, mock_run_appserver_playbook, mock_run_playbook, mock_public_ip, mock_consul): """ POST /api/v1/openedx_appserver/:id/make_inactive/ - unheahtly AppServers can be deactivated """ self.api_client.login(username='******', password='******') instance = OpenEdXInstanceFactory(edx_platform_commit='1' * 40) server = ReadyOpenStackServerFactory() app_server = make_test_appserver(instance=instance, server=server) self.assertFalse(instance.get_active_appservers().exists()) # Make the server active response = self.api_client.post( '/api/v1/openedx_appserver/{pk}/make_active/'.format( pk=app_server.pk)) instance.refresh_from_db() self.assertEqual(list(instance.get_active_appservers().all()), [app_server]) app_server.refresh_from_db() self.assertTrue(app_server.is_active) self.assertEqual(mock_run_appserver_playbook.call_count, 1) # Move to unhealthy status app_server._status_to_waiting_for_server() app_server._status_to_error() # Returns false if playbook fails, but should enable deactivating # unhealthy/unaccessible appservers mock_run_appserver_playbook.return_value = ("", 2) # Make the server inactive response = self.api_client.post( '/api/v1/openedx_appserver/{pk}/make_inactive/'.format( pk=app_server.pk)) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data, {'status': 'App server deactivation initiated.'}) self.assertEqual(mock_run_playbook.call_count, 2) instance.refresh_from_db() self.assertFalse(instance.get_active_appservers().exists()) app_server.refresh_from_db() self.assertFalse(app_server.is_active) self.assertEqual(mock_run_appserver_playbook.call_count, 2)
def test_make_active_no_organization(self): """ POST - An instance manager user without an organization can't activate/deactivate servers (since they don't belong to the user's organization, because there isn't one). """ self.api_client.login(username='******', password='******') instance = OpenEdXInstanceFactory(edx_platform_commit='1' * 40) server = ReadyOpenStackServerFactory() app_server = make_test_appserver(instance=instance, server=server) response = self.api_client.post( '/api/v1/openedx_appserver/{pk}/make_active/'.format( pk=app_server.pk)) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) response = self.api_client.post( '/api/v1/openedx_appserver/{pk}/make_inactive/'.format( pk=app_server.pk)) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
def test_make_active_permission_denied(self, username, message): """ POST - Anonymous, basic, and staff users (without manage_own permission) can't make servers active/inactive. """ if username: self.api_client.login(username=username, password='******') instance = OpenEdXInstanceFactory(edx_platform_commit='1' * 40) server = ReadyOpenStackServerFactory() app_server = make_test_appserver(instance=instance, server=server) response = self.api_client.post( '/api/v1/openedx_appserver/{pk}/make_active/'.format( pk=app_server.pk)) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) self.assertEqual(response.data, {'detail': message}) response = self.api_client.post( '/api/v1/openedx_appserver/{pk}/make_inactive/'.format( pk=app_server.pk)) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) self.assertEqual(response.data, {'detail': message})
def test_make_inactive(self, mock_run_appserver_playbook, mock_run_playbook, mock_public_ip, mock_consul): """ POST /api/v1/openedx_appserver/:id/make_inactive/ - Make this OpenEdXAppServer inactive for its given instance. AppServer does not need to be healty to be deactivated. """ self.api_client.login(username='******', password='******') instance = OpenEdXInstanceFactory(edx_platform_commit='1' * 40) server = ReadyOpenStackServerFactory() app_server = make_test_appserver(instance=instance, server=server) self.assertFalse(instance.get_active_appservers().exists()) # Make the server active response = self.api_client.post( '/api/v1/openedx_appserver/{pk}/make_active/'.format( pk=app_server.pk)) instance.refresh_from_db() self.assertEqual(list(instance.get_active_appservers().all()), [app_server]) app_server.refresh_from_db() self.assertTrue(app_server.is_active) self.assertEqual(mock_run_appserver_playbook.call_count, 1) # Make the server inactive response = self.api_client.post( '/api/v1/openedx_appserver/{pk}/make_inactive/'.format( pk=app_server.pk)) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data, {'status': 'App server deactivation initiated.'}) self.assertEqual(mock_run_playbook.call_count, 2) instance.refresh_from_db() self.assertFalse(instance.get_active_appservers().exists()) app_server.refresh_from_db() self.assertFalse(app_server.is_active) self.assertEqual(mock_run_appserver_playbook.call_count, 2)
def test_make_active_different_org(self): """ POST - An instance manager can't activate/deactive a server in an organization they don't belong to. """ self.api_client.login(username='******', password='******') # user4 won't be able to access this instance because it belongs to user1's organization instance = OpenEdXInstanceFactory() instance.ref.creator = self.user1.profile instance.ref.owner = self.user1.profile.organization instance.save() server = ReadyOpenStackServerFactory() app_server = make_test_appserver(instance=instance, server=server) response = self.api_client.post( '/api/v1/openedx_appserver/{pk}/make_active/'.format( pk=app_server.pk)) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) response = self.api_client.post( '/api/v1/openedx_appserver/{pk}/make_inactive/'.format( pk=app_server.pk)) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
def setUp(self): self.appserver = make_test_appserver() self.appserver.server = ReadyOpenStackServerFactory() self.appserver.is_active = True self.appserver.save()