def test_read_stored_settings(self):
        """
        Test to see that keys from the configuration dict is updated with
        the value from the configuration file after store.
        """
        initial_configurations = self.settings_service.configurable_keys
        to_store_data = {
            key: value['value']
            for key, value in initial_configurations.items()
        }
        for key, value in self.TEST_SETTINGS.items():
            to_store_data[key] = value

        is_changed, shoud_reset = self.settings_service.save_settings(
            **to_store_data)
        assert shoud_reset and is_changed

        # enforce keys to get repopulated:
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)
        self.settings_service = SettingsService()

        updated_configurations = self.settings_service.configurable_keys
        for key, value in updated_configurations.items():
            if key in self.TEST_SETTINGS:
                assert self.TEST_SETTINGS[key] == value['value']
            elif key == SettingsService.KEY_ADMIN_PWD:
                assert TvbProfile.current.web.admin.ADMINISTRATOR_PASSWORD == value[
                    'value']
                assert TvbProfile.current.web.admin.ADMINISTRATOR_BLANK_PWD == initial_configurations[
                    key]['value']
            else:
                assert initial_configurations[key]['value'] == value['value']
    def test_update_settings(self):
        """
        Test update of settings: correct flags should be returned, and check storage folder renamed
        """
        # 1. save on empty config-file:
        to_store_data = {
            key: value['value']
            for key, value in self.settings_service.configurable_keys.items()
        }
        for key, value in self.TEST_SETTINGS.items():
            to_store_data[key] = value

        is_changed, shoud_reset = self.settings_service.save_settings(
            **to_store_data)
        assert shoud_reset and is_changed

        # 2. Reload and save with the same values (is_changed expected to be False)
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)
        self.settings_service = SettingsService()
        to_store_data = {
            key: value['value']
            for key, value in self.settings_service.configurable_keys.items()
        }

        is_changed, shoud_reset = self.settings_service.save_settings(
            **to_store_data)
        assert not is_changed
        assert not shoud_reset

        # 3. Reload and check that changing TVB_STORAGE is done correctly
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)
        self.settings_service = SettingsService()
        to_store_data = {
            key: value['value']
            for key, value in self.settings_service.configurable_keys.items()
        }
        to_store_data[SettingsService.KEY_STORAGE] = os.path.join(
            TvbProfile.current.TVB_STORAGE, 'RENAMED')

        # Write a test-file and check that it is moved
        file_writer = open(
            os.path.join(TvbProfile.current.TVB_STORAGE, "test_rename-xxx43"),
            'w')
        file_writer.write('test-content')
        file_writer.close()

        is_changed, shoud_reset = self.settings_service.save_settings(
            **to_store_data)
        assert is_changed
        assert not shoud_reset
        # Check that the file was correctly moved:
        data = open(
            os.path.join(TvbProfile.current.TVB_STORAGE, 'RENAMED',
                         "test_rename-xxx43"), 'r').read()
        assert data == 'test-content'

        shutil.rmtree(os.path.join(TvbProfile.current.TVB_STORAGE, 'RENAMED'))
        os.remove(
            os.path.join(TvbProfile.current.TVB_STORAGE, "test_rename-xxx43"))
Example #3
0
    def setup_method(self):
        """
        Prepare the usage of a different config file for this class only.
        """
        StorageInterface.remove_files([TEST_CONFIG_FILE, TestSQLiteProfile.DEFAULT_STORAGE])

        self.old_config_file = TvbProfile.current.TVB_CONFIG_FILE
        TvbProfile.current.__class__.TVB_CONFIG_FILE = TEST_CONFIG_FILE
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)
        self.settings_service = SettingsService()
Example #4
0
    def setup_method(self):
        """
        Prepare the usage of a different config file for this class only.
        """
        if os.path.exists(TEST_CONFIG_FILE):
            os.remove(TEST_CONFIG_FILE)

        self.old_config_file = TvbProfile.current.TVB_CONFIG_FILE
        TvbProfile.current.__class__.TVB_CONFIG_FILE = TEST_CONFIG_FILE
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)
        self.settings_service = SettingsService()
Example #5
0
def command_initializer(persist_settings=True, skip_import=False):
    if persist_settings and TvbProfile.is_first_run():
        settings_service = SettingsService()
        settings = {}
        # Save default settings
        for key, setting in settings_service.configurable_keys.items():
            settings[key] = setting['value']
        settings_service.save_settings(**settings)
    TvbProfile.set_profile(TvbProfile.COMMAND_PROFILE)
    # Build new db engine in case DB URL value changed
    new_db_engine = build_db_engine()
    SA_SESSIONMAKER.configure(bind=new_db_engine)

    # Initialize application
    initialize(skip_import)
    def test_read_stored_settings(self):
        """
        Test to see that keys from the configuration dict is updated with
        the value from the configuration file after store.
        """
        initial_configurations = self.settings_service.configurable_keys
        to_store_data = {key: value['value'] for key, value in initial_configurations.iteritems()}
        for key, value in self.TEST_SETTINGS.iteritems():
            to_store_data[key] = value

        is_changed, shoud_reset = self.settings_service.save_settings(**to_store_data)
        assert shoud_reset and is_changed

        # enforce keys to get repopulated:
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)
        self.settings_service = SettingsService()

        updated_configurations = self.settings_service.configurable_keys
        for key, value in updated_configurations.iteritems():
            if key in self.TEST_SETTINGS:
                assert self.TEST_SETTINGS[key] == value['value']
            elif key == SettingsService.KEY_ADMIN_PWD:
                assert TvbProfile.current.web.admin.ADMINISTRATOR_PASSWORD == value['value']
                assert TvbProfile.current.web.admin.ADMINISTRATOR_BLANK_PWD == initial_configurations[key]['value']
            else:
                assert initial_configurations[key]['value'] == value['value']
class SettingsController(UserController):
    """
    Controller for TVB-Settings web page.
    Inherit from UserController, to have the same fill_default_attributes method (with versionInfo).
    """

    def __init__(self):
        UserController.__init__(self)
        self.settingsservice = SettingsService()


    @cherrypy.expose
    @using_template('user/base_user')
    @admin()
    def settings(self, save_settings=False, **data):
        """Main settings page submit and get"""
        template_specification = dict(mainContent="../settings/system_settings", title="System Settings")
        if save_settings:
            try:
                form = SettingsForm()
                data = form.to_python(data)
                isrestart, isreset = self.settingsservice.save_settings(**data)
                if isrestart:
                    thread = threading.Thread(target=self._restart_services, kwargs={'should_reset': isreset})
                    thread.start()
                    bc.add2session(bc.KEY_IS_RESTART, True)
                    bc.set_info_message('Please wait until TVB is restarted properly!')
                    raise cherrypy.HTTPRedirect('/tvb')
                # Here we will leave the same settings page to be displayed.
                # It will continue reloading when CherryPy restarts.
            except formencode.Invalid, excep:
                template_specification[bc.KEY_ERRORS] = excep.unpack_errors()
            except InvalidSettingsException, excep:
                self.logger.error('Invalid settings!  Exception %s was raised' % (str(excep)))
                bc.set_error_message(excep.message)
Example #8
0
def initialize(introspected_modules, load_xml_events=True):
    """
    Initialize when Application is starting.
    Check for new algorithms or new DataTypes.
    """
    SettingsService().check_db_url(TvbProfile.current.db.DB_URL)

    ## Initialize DB
    is_db_empty = initialize_startup()

    ## Create Projects storage root in case it does not exist.
    initialize_storage()

    ## Populate DB algorithms, by introspection
    event_folders = []
    start_introspection_time = datetime.datetime.now()
    for module in introspected_modules:
        introspector = Introspector(module)
        # Introspection is always done, even if DB was not empty.
        introspector.introspect(True)
        event_path = introspector.get_events_path()
        if event_path:
            event_folders.append(event_path)

    # Now remove or mark as removed any unverified Algo-Group, Algo-Category or Portlet
    to_invalidate, to_remove = dao.get_non_validated_entities(
        start_introspection_time)
    for entity in to_invalidate:
        entity.removed = True
    dao.store_entities(to_invalidate)
    for entity in to_remove:
        dao.remove_entity(entity.__class__, entity.id)

    ## Populate events
    if load_xml_events:
        read_events(event_folders)

    if not TvbProfile.is_first_run():
        ## Create default users.
        if is_db_empty:
            dao.store_entity(
                model.User(TvbProfile.current.web.admin.SYSTEM_USER_NAME, None,
                           None, True, None))
            UserService().create_user(
                username=TvbProfile.current.web.admin.ADMINISTRATOR_NAME,
                password=TvbProfile.current.web.admin.ADMINISTRATOR_PASSWORD,
                email=TvbProfile.current.web.admin.ADMINISTRATOR_EMAIL,
                role=model.ROLE_ADMINISTRATOR)

        ## In case actions related to latest code-changes are needed, make sure they are executed.
        CodeUpdateManager().run_all_updates()

        ## In case the H5 version changed, run updates on all DataTypes
        if TvbProfile.current.version.DATA_CHECKED_TO_VERSION < TvbProfile.current.version.DATA_VERSION:
            thread = threading.Thread(
                target=FilesUpdateManager().run_all_updates)
            thread.start()

        ## Clean tvb-first-time-run temporary folder, as we are no longer at the first run:
        shutil.rmtree(TvbProfile.current.FIRST_RUN_STORAGE, True)
 def deco(*a, **b):
     """ Decorator for public method"""
     if hasattr(cherrypy, basecontroller.KEY_SESSION):
         user = basecontroller.get_logged_user()
         if (user is not None and user.is_administrator()) or SettingsService.is_first_run():
             return func(*a, **b)
     basecontroller.set_error_message('Only Administrators can access this application area!')
     raise cherrypy.HTTPRedirect('/tvb')
    def setup_method(self):
        """
        Prepare the usage of a different config file for this class only.
        """
        if os.path.exists(TEST_CONFIG_FILE):
            os.remove(TEST_CONFIG_FILE)

        self.old_config_file = TvbProfile.current.TVB_CONFIG_FILE
        TvbProfile.current.__class__.TVB_CONFIG_FILE = TEST_CONFIG_FILE
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)
        self.settings_service = SettingsService()
    def test_update_settings(self):
        """
        Test update of settings: correct flags should be returned, and check storage folder renamed
        """
        # 1. save on empty config-file:
        to_store_data = {key: value['value'] for key, value in self.settings_service.configurable_keys.iteritems()}
        for key, value in self.TEST_SETTINGS.iteritems():
            to_store_data[key] = value

        is_changed, shoud_reset = self.settings_service.save_settings(**to_store_data)
        assert shoud_reset and is_changed

        # 2. Reload and save with the same values (is_changed expected to be False)
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)
        self.settings_service = SettingsService()
        to_store_data = {key: value['value'] for key, value in self.settings_service.configurable_keys.iteritems()}

        is_changed, shoud_reset = self.settings_service.save_settings(**to_store_data)
        assert not is_changed
        assert not shoud_reset

        # 3. Reload and check that changing TVB_STORAGE is done correctly
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)
        self.settings_service = SettingsService()
        to_store_data = {key: value['value'] for key, value in self.settings_service.configurable_keys.iteritems()}
        to_store_data[SettingsService.KEY_STORAGE] = os.path.join(TvbProfile.current.TVB_STORAGE, 'RENAMED')

        # Write a test-file and check that it is moved
        file_writer = open(os.path.join(TvbProfile.current.TVB_STORAGE, "test_rename-xxx43"), 'w')
        file_writer.write('test-content')
        file_writer.close()

        is_changed, shoud_reset = self.settings_service.save_settings(**to_store_data)
        assert is_changed
        assert not shoud_reset
        # Check that the file was correctly moved:
        data = open(os.path.join(TvbProfile.current.TVB_STORAGE, 'RENAMED', "test_rename-xxx43"), 'r').read()
        assert data == 'test-content'

        shutil.rmtree(os.path.join(TvbProfile.current.TVB_STORAGE, 'RENAMED'))
        os.remove(os.path.join(TvbProfile.current.TVB_STORAGE, "test_rename-xxx43"))
Example #12
0
def initialize(skip_import=False, skip_updates=False):
    """
    Initialize when Application is starting.
    Check for new algorithms or new DataTypes.
    """
    SettingsService().check_db_url(TvbProfile.current.db.DB_URL)

    # Initialize DB
    is_db_empty = initialize_startup()

    # Create Projects storage root in case it does not exist.
    initialize_storage()

    # Populate DB algorithms, by introspection
    start_introspection_time = datetime.now()
    # Introspection is always done, even if DB was not empty.
    introspector = Introspector()
    introspector.introspect()

    to_invalidate = dao.get_non_validated_entities(start_introspection_time)
    for entity in to_invalidate:
        entity.removed = True
    dao.store_entities(to_invalidate)

    if not TvbProfile.is_first_run() and not skip_updates:
        # Create default users.
        if is_db_empty:
            dao.store_entity(
                User(TvbProfile.current.web.admin.SYSTEM_USER_NAME, TvbProfile.current.web.admin.SYSTEM_USER_NAME, None,
                     None, True, None))
            UserService().create_user(username=TvbProfile.current.web.admin.ADMINISTRATOR_NAME,
                                      display_name=TvbProfile.current.web.admin.ADMINISTRATOR_DISPLAY_NAME,
                                      password=TvbProfile.current.web.admin.ADMINISTRATOR_PASSWORD,
                                      email=TvbProfile.current.web.admin.ADMINISTRATOR_EMAIL,
                                      role=ROLE_ADMINISTRATOR, skip_import=skip_import)

        # In case actions related to latest code-changes are needed, make sure they are executed.
        CodeUpdateManager().run_all_updates()

        # In case the H5 version changed, run updates on all DataTypes
        thread = None
        if TvbProfile.current.version.DATA_CHECKED_TO_VERSION < TvbProfile.current.version.DATA_VERSION:
            thread = threading.Thread(target=FilesUpdateManager().run_all_updates)
            thread.start()

        # Clean tvb-first-time-run temporary folder, as we are no longer at the first run:
        shutil.rmtree(TvbProfile.current.FIRST_RUN_STORAGE, True)
        return thread
 def create_user(self, username=None, password=None, password2=None,
                 role=None, email=None, comment=None, email_msg=None, validated=False):
     """
     Service Layer for creating a new user.
     """
     #Basic fields validation.
     if (username is None) or len(username) < 1:
         raise UsernameException("Empty UserName!")
     if (password is None) or len(password) < 1:
         raise UsernameException("Empty password!")
     if password2 is None:
         password2 = password
     if password != password2:
         raise UsernameException("Passwords do not match!")
     try:
         user_validated = (role == 'ADMINISTRATOR') or validated
         user = model.User(username, password, email, user_validated, role)
         if email_msg is None:
             email_msg = 'Hello ' + username + TEXT_CREATE
         admin_msg = (TEXT_CREATE_TO_ADMIN + username + ' :\n ' + cfg.BASE_URL +
                      'user/validate/' + username + '\n\n"' + str(comment) + '"')
         self.logger.info("Registering user " + username + " !")
         if role != 'ADMINISTRATOR' and email is not None:
             admins = UserService.get_administrators()
             admin = admins[randint(0, len(admins) - 1)]
             if admin.email is not None and (admin.email != cfg.DEFAULT_ADMIN_EMAIL or
                                             cfg.SERVER_IP != cfg.LOCALHOST):
                 # Do not send validation email in case default admin email
                 # remained unchanged but TVB in locally deployed....
                 email_sender.send(FROM_ADDRESS, admin.email, SUBJECT_REGISTER, admin_msg)
                 self.logger.debug("Email sent to:" + admin.email + " for validating user:"******" !")
             email_sender.send(FROM_ADDRESS, email, SUBJECT_REGISTER, email_msg)
             self.logger.debug("Email sent to:" + email + " for notifying new user:"******" !")
         user = dao.store_entity(user)
         if not SettingsService.is_first_run():
             handle_event(".".join([self.__class__.__name__, stack()[0][3]]), user)
         return TEXT_DISPLAY
     except Exception, excep:
         self.logger.error("Could not create user!")
         self.logger.exception(excep)
         raise UsernameException(excep.message)
Example #14
0
class SettingsController(UserController):
    """
    Controller for TVB-Settings web page.
    Inherit from UserController, to have the same fill_default_attributes method (with versionInfo).
    """
    def __init__(self):
        UserController.__init__(self)
        self.settingsservice = SettingsService()

    @cherrypy.expose
    @handle_error(redirect=True)
    @using_template('user/base_user')
    @check_admin
    def settings(self, save_settings=False, **data):
        """Main settings page submit and get"""
        template_specification = dict(
            mainContent="../settings/system_settings", title="System Settings")
        if save_settings:
            try:
                form = SettingsForm()
                data = form.to_python(data)
                isrestart, isreset = self.settingsservice.save_settings(**data)
                if isrestart:
                    thread = threading.Thread(target=self._restart_services,
                                              kwargs={'should_reset': isreset})
                    thread.start()
                    common.add2session(common.KEY_IS_RESTART, True)
                    common.set_important_message(
                        'Please wait until TVB is restarted properly!')
                    raise cherrypy.HTTPRedirect('/tvb')
                # Here we will leave the same settings page to be displayed.
                # It will continue reloading when CherryPy restarts.
            except formencode.Invalid, excep:
                template_specification[
                    common.KEY_ERRORS] = excep.unpack_errors()
            except InvalidSettingsException, excep:
                self.logger.error(
                    'Invalid settings!  Exception %s was raised' %
                    (str(excep)))
                common.set_error_message(excep.message)
 def deco(*a, **b):
     """ Decorator for public method"""
     if not SettingsService.is_first_run():
         return func(*a, **b)
     raise cherrypy.HTTPRedirect('/settings/settings')
Example #16
0
class SettingsController(UserController):
    """
    Controller for TVB-Settings web page.
    Inherit from UserController, to have the same fill_default_attributes method (with versionInfo).
    """

    def __init__(self):
        UserController.__init__(self)
        self.settingsservice = SettingsService()

    @cherrypy.expose
    @handle_error(redirect=True)
    @using_template('user/base_user')
    @check_admin
    def settings(self, save_settings=False, **data):
        """Main settings page submit and get"""
        template_specification = dict(mainContent="settings/system_settings", title="System Settings")
        if save_settings:
            try:
                form = SettingsForm()
                data = form.to_python(data)
                isrestart, isreset = self.settingsservice.save_settings(**data)
                if isrestart:
                    thread = threading.Thread(target=self._restart_services, kwargs={'should_reset': isreset})
                    thread.start()
                    common.add2session(common.KEY_IS_RESTART, True)
                    common.set_important_message('Please wait until TVB is restarted properly!')
                    raise cherrypy.HTTPRedirect('/tvb')
                # Here we will leave the same settings page to be displayed.
                # It will continue reloading when CherryPy restarts.
            except formencode.Invalid as excep:
                template_specification[common.KEY_ERRORS] = excep.unpack_errors()
            except InvalidSettingsException as excep:
                self.logger.error('Invalid settings!  Exception %s was raised' % (str(excep)))
                common.set_error_message(excep.message)
        template_specification.update({'keys_order': self.settingsservice.KEYS_DISPLAY_ORDER,
                                       'config_data': self.settingsservice.configurable_keys,
                                       common.KEY_FIRST_RUN: TvbProfile.is_first_run()})
        return self.fill_default_attributes(template_specification)

    def _restart_services(self, should_reset):
        """
        Restart CherryPy Backend.
        """
        cherrypy.engine.exit()

        self.logger.info("Waiting for CherryPy to shut down ... ")

        sleep(5)

        python_path = TvbProfile.current.PYTHON_INTERPRETER_PATH
        try:
            import tvb_bin
            proc_params = [python_path, '-m', 'tvb_bin.app', 'start', TvbProfile.CURRENT_PROFILE_NAME]
            if should_reset:
                proc_params.append('-reset')
            subprocess.Popen(proc_params, shell=False)
        except ImportError:
            proc_params = [python_path, '-m', 'tvb.interfaces.web.run', TvbProfile.CURRENT_PROFILE_NAME, "tvb.config"]
            if should_reset:
                proc_params.append('reset')
            subprocess.Popen(proc_params, shell=False).communicate()

        self.logger.info("Starting CherryPy again ... ")

    @cherrypy.expose
    @handle_error(redirect=False)
    @jsonify
    def check_db_url(self, **data):
        """
        Action on DB-URL validate button.
        """
        try:
            storage_path = data[self.settingsservice.KEY_STORAGE]
            if os.path.isfile(storage_path):
                raise InvalidSettingsException('TVB Storage should be set to a folder and not a file.')
            if not os.path.isdir(storage_path):
                try:
                    os.mkdir(storage_path)
                except OSError:
                    return {'status': 'not ok',
                            'message': 'Could not create root storage for TVB. Please check write permissions!'}
            self.settingsservice.check_db_url(data[self.settingsservice.KEY_DB_URL])
            return {'status': 'ok', 'message': 'The database URL is valid.'}
        except InvalidSettingsException as excep:
            self.logger.error(excep)
            return {'status': 'not ok', 'message': 'The database URL is not valid.'}

    @cherrypy.expose
    @handle_error(redirect=False)
    @jsonify
    def validate_matlab_path(self, **data):
        """
        Check if the set path from the ui actually corresponds to a matlab executable.
        """
        submitted_path = data[self.settingsservice.KEY_MATLAB_EXECUTABLE]
        if len(submitted_path) == 0:
            return {'status': 'ok',
                    'message': 'No Matlab/Ocatve path was given. Some analyzers will not be available.'}

        if os.path.isfile(submitted_path):
            version = check_matlab_version(submitted_path)
            if version:
                return {'status': 'ok', 'message': "Valid Matlab/Octave. Found version: '%s'." % (version,)}
            else:
                return {'status': 'not ok', 'message': "Invalid Matlab/Octave. Found version: '%s' ." % (version,)}
        else:
            return {'status': 'not ok', 'message': 'Invalid Matlab/Octave path.'}
Example #17
0
 def __init__(self):
     UserController.__init__(self)
     self.settingsservice = SettingsService()
class TestSettingsService(BaseTestCase):
    """
    This class contains tests for the tvb.core.services.settings_service module.
    """
    TEST_SETTINGS = {
        SettingsService.KEY_ADMIN_NAME: 'test_name',
        SettingsService.KEY_ADMIN_EMAIL: '*****@*****.**',
        SettingsService.KEY_PORT: 8081,
        SettingsService.KEY_MAX_DISK_SPACE_USR: 2**8
    }

    def setup_method(self):
        """
        Prepare the usage of a different config file for this class only.
        """
        if os.path.exists(TEST_CONFIG_FILE):
            os.remove(TEST_CONFIG_FILE)
        if os.path.exists(TestSQLiteProfile.DEFAULT_STORAGE):
            shutil.rmtree(TestSQLiteProfile.DEFAULT_STORAGE)

        self.old_config_file = TvbProfile.current.TVB_CONFIG_FILE
        TvbProfile.current.__class__.TVB_CONFIG_FILE = TEST_CONFIG_FILE
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)
        self.settings_service = SettingsService()

    def teardown_method(self):
        """
        Restore configuration file
        """
        if os.path.exists(TEST_CONFIG_FILE):
            os.remove(TEST_CONFIG_FILE)

        TvbProfile.current.__class__.TVB_CONFIG_FILE = self.old_config_file
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)

    def test_check_db_url_invalid(self):
        """
        Make sure a proper exception is raised in case an invalid database url is passed.
        """
        with pytest.raises(InvalidSettingsException):
            self.settings_service.check_db_url("this-url-should-be-invalid")

    def test_get_free_disk_space(self):
        """
        Check that no exception is raised during the query for free disk space.
        Also do a check that returned value is greater than 0.
        Not most precise check but other does not seem possible so far.
        """
        disk_space = self.settings_service.get_disk_free_space(
            TvbProfile.current.TVB_STORAGE)
        assert disk_space > 0, "Disk space should never be negative."

    def test_first_run_save(self):
        """
        Check that before setting something, all flags are pointing towards empty.
        After storing some configurations, check that flags are changed.
        """
        initial_configurations = self.settings_service.configurable_keys
        first_run = TvbProfile.is_first_run()
        assert first_run, "Invalid First_Run flag!!"
        assert not os.path.exists(TEST_CONFIG_FILE)
        assert len(TvbProfile.current.manager.stored_settings) == 0

        to_store_data = {
            key: value['value']
            for key, value in initial_configurations.items()
        }
        for key, value in self.TEST_SETTINGS.items():
            to_store_data[key] = value
        _, shoud_reset = self.settings_service.save_settings(**to_store_data)

        assert shoud_reset
        first_run = TvbProfile.is_first_run()
        assert not first_run, "Invalid First_Run flag!!"
        assert os.path.exists(TEST_CONFIG_FILE)
        assert not len(TvbProfile.current.manager.stored_settings) == 0

    def test_read_stored_settings(self):
        """
        Test to see that keys from the configuration dict is updated with
        the value from the configuration file after store.
        """
        initial_configurations = self.settings_service.configurable_keys
        to_store_data = {
            key: value['value']
            for key, value in initial_configurations.items()
        }
        for key, value in self.TEST_SETTINGS.items():
            to_store_data[key] = value

        is_changed, shoud_reset = self.settings_service.save_settings(
            **to_store_data)
        assert shoud_reset and is_changed

        # enforce keys to get repopulated:
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)
        self.settings_service = SettingsService()

        updated_configurations = self.settings_service.configurable_keys
        for key, value in updated_configurations.items():
            if key in self.TEST_SETTINGS:
                assert self.TEST_SETTINGS[key] == value['value']
            elif key == SettingsService.KEY_ADMIN_PWD:
                assert TvbProfile.current.web.admin.ADMINISTRATOR_PASSWORD == value[
                    'value']
                assert TvbProfile.current.web.admin.ADMINISTRATOR_BLANK_PWD == initial_configurations[
                    key]['value']
            else:
                assert initial_configurations[key]['value'] == value['value']

    def test_update_settings(self):
        """
        Test update of settings: correct flags should be returned, and check storage folder renamed
        """
        # 1. save on empty config-file:
        to_store_data = {
            key: value['value']
            for key, value in self.settings_service.configurable_keys.items()
        }
        for key, value in self.TEST_SETTINGS.items():
            to_store_data[key] = value

        is_changed, shoud_reset = self.settings_service.save_settings(
            **to_store_data)
        assert shoud_reset and is_changed

        # 2. Reload and save with the same values (is_changed expected to be False)
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)
        self.settings_service = SettingsService()
        to_store_data = {
            key: value['value']
            for key, value in self.settings_service.configurable_keys.items()
        }

        is_changed, shoud_reset = self.settings_service.save_settings(
            **to_store_data)
        assert not is_changed
        assert not shoud_reset

        # 3. Reload and check that changing TVB_STORAGE is done correctly
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)
        self.settings_service = SettingsService()
        to_store_data = {
            key: value['value']
            for key, value in self.settings_service.configurable_keys.items()
        }
        to_store_data[SettingsService.KEY_STORAGE] = os.path.join(
            TvbProfile.current.TVB_STORAGE, 'RENAMED')

        # Write a test-file and check that it is moved
        file_writer = open(
            os.path.join(TvbProfile.current.TVB_STORAGE, "test_rename-xxx43"),
            'w')
        file_writer.write('test-content')
        file_writer.close()

        is_changed, shoud_reset = self.settings_service.save_settings(
            **to_store_data)
        assert is_changed
        assert not shoud_reset
        # Check that the file was correctly moved:
        data = open(
            os.path.join(TvbProfile.current.TVB_STORAGE, 'RENAMED',
                         "test_rename-xxx43"), 'r').read()
        assert data == 'test-content'

        shutil.rmtree(os.path.join(TvbProfile.current.TVB_STORAGE, 'RENAMED'))
        os.remove(
            os.path.join(TvbProfile.current.TVB_STORAGE, "test_rename-xxx43"))
from tvb.interfaces.web.controllers.flow_controller import FlowController
from tvb.interfaces.web.controllers.settings_controller import SettingsController
from tvb.interfaces.web.controllers.burst.burst_controller import BurstController
from tvb.interfaces.web.controllers.burst.exploration_controller import ParameterExplorationController
from tvb.interfaces.web.controllers.spatial.base_spatio_temporal_controller import SpatioTemporalController
from tvb.interfaces.web.controllers.spatial.region_model_parameters_controller import RegionsModelParametersController
from tvb.interfaces.web.controllers.spatial.surface_model_parameters_controller import SurfaceModelParametersController
from tvb.interfaces.web.controllers.spatial.region_stimulus_controller import RegionStimulusController
from tvb.interfaces.web.controllers.spatial.surface_stimulus_controller import SurfaceStimulusController
from tvb.interfaces.web.controllers.spatial.local_connectivity_controller import LocalConnectivityController
from tvb.interfaces.web.controllers.spatial.noise_configuration_controller import NoiseConfigurationController
from tvb.interfaces.web.controllers.api.simulator_controller import SimulatorController


LOGGER = get_logger('tvb.interface.web.run')
CONFIG_EXISTS = not SettingsService.is_first_run()
PARAM_RESET_DB = "reset"

### Ensure Python is using UTF-8 encoding.
### While running distribution/console, default encoding is ASCII
reload(sys)
sys.setdefaultencoding('utf-8')
LOGGER.info("TVB application running using encoding: " + sys.getdefaultencoding())



def init_cherrypy(arguments=None):
    #### Mount static folders from modules marked for introspection
    arguments = arguments or []
    CONFIGUER = TVBSettings.CHERRYPY_CONFIGURATION
    for module in arguments:
class TestSettingsService(BaseTestCase):
    """
    This class contains tests for the tvb.core.services.settings_service module.
    """
    TEST_SETTINGS = {SettingsService.KEY_ADMIN_NAME: 'test_name',
                     SettingsService.KEY_ADMIN_EMAIL: '*****@*****.**',
                     SettingsService.KEY_PORT: 8081,
                     SettingsService.KEY_URL_WEB: "http://192.168.123.11:8081/",
                     SettingsService.KEY_MAX_DISK_SPACE_USR: 2 ** 8}


    def setup_method(self):
        """
        Prepare the usage of a different config file for this class only.
        """
        if os.path.exists(TEST_CONFIG_FILE):
            os.remove(TEST_CONFIG_FILE)

        self.old_config_file = TvbProfile.current.TVB_CONFIG_FILE
        TvbProfile.current.__class__.TVB_CONFIG_FILE = TEST_CONFIG_FILE
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)
        self.settings_service = SettingsService()
        
            
    def teardown_method(self):
        """
        Restore configuration file
        """
        if os.path.exists(TEST_CONFIG_FILE):
            os.remove(TEST_CONFIG_FILE)

        TvbProfile.current.__class__.TVB_CONFIG_FILE = self.old_config_file
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)
    


    def test_check_db_url_invalid(self):
        """
        Make sure a proper exception is raised in case an invalid database url is passed.
        """
        with pytest.raises(InvalidSettingsException):
            self.settings_service.check_db_url("this-url-should-be-invalid")
        
    
    def test_get_free_disk_space(self):
        """
        Check that no exception is raised during the query for free disk space.
        Also do a check that returned value is greater than 0.
        Not most precise check but other does not seem possible so far.
        """
        disk_space = self.settings_service.get_disk_free_space(TvbProfile.current.TVB_STORAGE)
        assert disk_space > 0, "Disk space should never be negative."
    
            
    def test_first_run_save(self):
        """
        Check that before setting something, all flags are pointing towards empty.
        After storing some configurations, check that flags are changed.
        """
        initial_configurations = self.settings_service.configurable_keys
        first_run = TvbProfile.is_first_run()
        assert first_run, "Invalid First_Run flag!!"
        assert not os.path.exists(TEST_CONFIG_FILE)
        assert len(TvbProfile.current.manager.stored_settings) == 0

        to_store_data = {key: value['value'] for key, value in initial_configurations.iteritems()}
        for key, value in self.TEST_SETTINGS.iteritems():
            to_store_data[key] = value
        _, shoud_reset = self.settings_service.save_settings(**to_store_data)

        assert shoud_reset
        first_run = TvbProfile.is_first_run()
        assert not first_run, "Invalid First_Run flag!!"
        assert os.path.exists(TEST_CONFIG_FILE)
        assert not len(TvbProfile.current.manager.stored_settings) == 0
        
        
    def test_read_stored_settings(self):
        """
        Test to see that keys from the configuration dict is updated with
        the value from the configuration file after store.
        """
        initial_configurations = self.settings_service.configurable_keys
        to_store_data = {key: value['value'] for key, value in initial_configurations.iteritems()}
        for key, value in self.TEST_SETTINGS.iteritems():
            to_store_data[key] = value

        is_changed, shoud_reset = self.settings_service.save_settings(**to_store_data)
        assert shoud_reset and is_changed

        # enforce keys to get repopulated:
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)
        self.settings_service = SettingsService()

        updated_configurations = self.settings_service.configurable_keys
        for key, value in updated_configurations.iteritems():
            if key in self.TEST_SETTINGS:
                assert self.TEST_SETTINGS[key] == value['value']
            elif key == SettingsService.KEY_ADMIN_PWD:
                assert TvbProfile.current.web.admin.ADMINISTRATOR_PASSWORD == value['value']
                assert TvbProfile.current.web.admin.ADMINISTRATOR_BLANK_PWD == initial_configurations[key]['value']
            else:
                assert initial_configurations[key]['value'] == value['value']

                    
    def test_update_settings(self):
        """
        Test update of settings: correct flags should be returned, and check storage folder renamed
        """
        # 1. save on empty config-file:
        to_store_data = {key: value['value'] for key, value in self.settings_service.configurable_keys.iteritems()}
        for key, value in self.TEST_SETTINGS.iteritems():
            to_store_data[key] = value

        is_changed, shoud_reset = self.settings_service.save_settings(**to_store_data)
        assert shoud_reset and is_changed

        # 2. Reload and save with the same values (is_changed expected to be False)
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)
        self.settings_service = SettingsService()
        to_store_data = {key: value['value'] for key, value in self.settings_service.configurable_keys.iteritems()}

        is_changed, shoud_reset = self.settings_service.save_settings(**to_store_data)
        assert not is_changed
        assert not shoud_reset

        # 3. Reload and check that changing TVB_STORAGE is done correctly
        TvbProfile._build_profile_class(TvbProfile.CURRENT_PROFILE_NAME)
        self.settings_service = SettingsService()
        to_store_data = {key: value['value'] for key, value in self.settings_service.configurable_keys.iteritems()}
        to_store_data[SettingsService.KEY_STORAGE] = os.path.join(TvbProfile.current.TVB_STORAGE, 'RENAMED')

        # Write a test-file and check that it is moved
        file_writer = open(os.path.join(TvbProfile.current.TVB_STORAGE, "test_rename-xxx43"), 'w')
        file_writer.write('test-content')
        file_writer.close()

        is_changed, shoud_reset = self.settings_service.save_settings(**to_store_data)
        assert is_changed
        assert not shoud_reset
        # Check that the file was correctly moved:
        data = open(os.path.join(TvbProfile.current.TVB_STORAGE, 'RENAMED', "test_rename-xxx43"), 'r').read()
        assert data == 'test-content'

        shutil.rmtree(os.path.join(TvbProfile.current.TVB_STORAGE, 'RENAMED'))
        os.remove(os.path.join(TvbProfile.current.TVB_STORAGE, "test_rename-xxx43"))
class SettingsController(UserController):
    """
    Controller for TVB-Settings web page.
    Inherit from UserController, to have the same fill_default_attributes method (with versionInfo).
    """

    def __init__(self):
        UserController.__init__(self)
        self.settingsservice = SettingsService()


    @cherrypy.expose
    @handle_error(redirect=True)
    @using_template('user/base_user')
    @check_admin
    def settings(self, save_settings=False, **data):
        """Main settings page submit and get"""
        template_specification = dict(mainContent="../settings/system_settings", title="System Settings")
        if save_settings:
            try:
                form = SettingsForm()
                data = form.to_python(data)
                isrestart, isreset = self.settingsservice.save_settings(**data)
                if isrestart:
                    thread = threading.Thread(target=self._restart_services, kwargs={'should_reset': isreset})
                    thread.start()
                    common.add2session(common.KEY_IS_RESTART, True)
                    common.set_important_message('Please wait until TVB is restarted properly!')
                    raise cherrypy.HTTPRedirect('/tvb')
                # Here we will leave the same settings page to be displayed.
                # It will continue reloading when CherryPy restarts.
            except formencode.Invalid as excep:
                template_specification[common.KEY_ERRORS] = excep.unpack_errors()
            except InvalidSettingsException as excep:
                self.logger.error('Invalid settings!  Exception %s was raised' % (str(excep)))
                common.set_error_message(excep.message)
        template_specification.update({'keys_order': self.settingsservice.KEYS_DISPLAY_ORDER,
                                       'config_data': self.settingsservice.configurable_keys,
                                       common.KEY_FIRST_RUN: TvbProfile.is_first_run()})
        return self.fill_default_attributes(template_specification)


    def _restart_services(self, should_reset):
        """
        Restart CherryPy Backend.
        """
        cherrypy.engine.exit()

        self.logger.info("Waiting for Cherrypy to shut down ... ")

        sleep(5)

        python_path = TvbProfile.current.PYTHON_INTERPRETER_PATH
        proc_params = [python_path, '-m', 'tvb_bin.app', 'start', TvbProfile.CURRENT_PROFILE_NAME]
        if should_reset:
            proc_params.append('-reset')

        self.logger.info("Starting CherryPy again ... ")
        subprocess.Popen(proc_params, shell=False)


    @cherrypy.expose
    @handle_error(redirect=False)
    @jsonify
    def check_db_url(self, **data):
        """
        Action on DB-URL validate button.
        """
        try:
            storage_path = data[self.settingsservice.KEY_STORAGE]
            if os.path.isfile(storage_path):
                raise InvalidSettingsException('TVB Storage should be set to a folder and not a file.')
            if not os.path.isdir(storage_path):
                try:
                    os.mkdir(storage_path)
                except OSError:
                    return {'status': 'not ok',
                            'message': 'Could not create root storage for TVB. Please check write permissions!'}
            self.settingsservice.check_db_url(data[self.settingsservice.KEY_DB_URL])
            return {'status': 'ok', 'message': 'The database URL is valid.'}
        except InvalidSettingsException as excep:
            self.logger.error(excep)
            return {'status': 'not ok', 'message': 'The database URL is not valid.'}


    @cherrypy.expose
    @handle_error(redirect=False)
    @jsonify
    def validate_matlab_path(self, **data):
        """
        Check if the set path from the ui actually corresponds to a matlab executable.
        """
        submitted_path = data[self.settingsservice.KEY_MATLAB_EXECUTABLE]
        if len(submitted_path) == 0:
            return {'status': 'ok',
                    'message': 'No Matlab/Ocatve path was given. Some analyzers will not be available.'}

        if os.path.isfile(submitted_path):
            version = check_matlab_version(submitted_path)
            if version:
                return {'status': 'ok', 'message': "Valid Matlab/Octave. Found version: '%s'." % (version,)}
            else:
                return {'status': 'not ok', 'message': "Invalid Matlab/Octave. Found version: '%s' ." % (version,)}
        else:
            return {'status': 'not ok', 'message': 'Invalid Matlab/Octave path.'}
 def __init__(self):
     UserController.__init__(self)
     self.settingsservice = SettingsService()