Esempio n. 1
0
    def run_playbook(self, ansible_vars):
        """
        Run the playbook to perform the server reconfiguration.

        This is factored out into a separate method so it can be mocked out in the tests.
        """
        if settings.DISABLE_LOAD_BALANCER_CONFIGURATION:
            self.logger.info(
                'Direct load balancer reconfiguration disabled. Skipping %s configuration...',
                self)
            return

        playbook_path = pathlib.Path(
            settings.SITE_ROOT
        ) / "playbooks/load_balancer_conf/load_balancer_conf.yml"
        returncode = ansible.capture_playbook_output(
            requirements_path=str(playbook_path.parent / "requirements.txt"),
            inventory_str=self.domain,
            vars_str=ansible_vars,
            playbook_path=str(playbook_path),
            username=self.ssh_username,
            logger_=self.logger,
        )
        if returncode != 0:
            self.logger.error(
                "Playbook to reconfigure load-balancing server %s failed.",
                self)
            raise ReconfigurationFailed
Esempio n. 2
0
    def run_cleanup(self):
        """Run the actual cleanup"""
        logger.info("\n --- Starting Load balancer fragments cleanup ---")

        if self.dry_run:
            logger.info("Running in DRY_RUN mode, no actions will be taken")

        playbook_path = pathlib.Path(
            os.path.abspath(os.path.dirname(__file__))
        ) / "playbooks/load_balancer_cleanup.yml"

        ansible_vars = (
            "DAYS_OLDER_THAN: {age_limit}\n"
            "FRAGMENT_PATTERN: {fragment_prefix}*\n"
            "REMOVE_FRAGMENTS: {remove_fragments}\n"
        ).format(
            age_limit=self.age_limit,
            fragment_prefix=self.fragment_prefix,
            remove_fragments='true' if self.dry_run else 'false'
        )

        return_code = ansible.capture_playbook_output(
            requirements_path=str(playbook_path.parent / "requirements.txt"),
            playbook_path=str(playbook_path),
            inventory_str=self.load_balancer_address,
            vars_str=ansible_vars,
            username='******',
            logger_=logger,
        )
        if return_code != 0:
            raise Exception("Playbook to remove stale load balancer fragments failed")
    def get_elasticsearch_hits_data_summary(self, playbook_output_dir, name_prefix, start_date, end_date):
        """ Execute the collect_elasticsearch_data playbook to gather statistics """
        if not settings.INSTANCE_LOGS_SERVER_HOST:
            self.stderr.write(self.style.WARNING(
                'Skipping Elasticsearch data collection because '
                'INSTANCE_LOGS_SERVER_HOST is unset'
            ))
            return

        inventory = '[apps]\n{server}'.format(server=settings.INSTANCE_LOGS_SERVER_HOST)
        playbook_path = os.path.join(
            settings.SITE_ROOT,
            'playbooks/collect_instance_statistics/collect_elasticsearch_data.yml'
        )

        def log_line(line):
            """Helper to pass to capture_playbook_output()."""
            self.stderr.write(self.style.SUCCESS(line))
        log_line.info = log_line
        log_line.error = log_line

        # Launch the collect_elasticsearch_data playbook, which places a file into the `playbook_output_dir`
        # on this host.
        ansible.capture_playbook_output(
            requirements_path=os.path.join(
                os.path.dirname(playbook_path),
                'requirements.txt'
            ),
            inventory_str=inventory,
            vars_str=(
                'local_output_dir: {output_dir}\n'
                'remote_output_filename: /tmp/activity_report\n'
                'server_name_prefix: {server_name_prefix}\n'
                'start_date: {start_date}\n'
                'end_date: {end_date}'
            ).format(
                output_dir=playbook_output_dir,
                server_name_prefix=name_prefix,
                start_date=start_date,
                end_date=end_date
            ),
            playbook_path=playbook_path,
            username=settings.INSTANCE_LOGS_SERVER_SSH_USERNAME,
            logger_=log_line,
        )
Esempio n. 4
0
 def _run_playbook(self, working_dir, playbook):
     """
     Run a playbook against the AppServer's VM
     """
     return ansible.capture_playbook_output(
         requirements_path=os.path.join(working_dir, playbook.requirements_path),
         inventory_str=self.inventory_str,
         vars_str=playbook.variables,
         playbook_path=os.path.join(working_dir, playbook.playbook_path),
         username=settings.OPENSTACK_SANDBOX_SSH_USERNAME,
         logger_=self.logger,
         collect_logs=True,
     )
Esempio n. 5
0
 def _run_playbook(self, working_dir, playbook):
     """
     Run a playbook against the AppServer's VM
     """
     return ansible.capture_playbook_output(
         requirements_path=os.path.join(working_dir, playbook.requirements_path),
         inventory_str=self.inventory_str,
         vars_str=playbook.variables,
         playbook_path=os.path.join(working_dir, playbook.playbook_path),
         username=settings.OPENSTACK_SANDBOX_SSH_USERNAME,
         logger_=self.logger,
         collect_logs=True,
     )
    def get_instance_usage_data(self, playbook_output_dir, name_prefix, public_ip):
        """ Execute the collect_activity playbook to gather statistics """
        inventory = '[apps]\n{server}'.format(server=public_ip)
        playbook_path = os.path.join(
            settings.SITE_ROOT,
            'playbooks/collect_activity/collect_activity.yml'
        )

        def log_line(line):
            """Helper to pass to capture_playbook_output()."""
            self.stderr.write(self.style.SUCCESS(line))
        log_line.info = log_line
        log_line.error = log_line

        playbook_extra_script_arguments = '--skip-hit-statistics' if settings.INSTANCE_LOGS_SERVER_HOST else ''

        # Launch the collect_activity playbook, which places a file into the `playbook_output_dir`
        # on this host.
        ansible.capture_playbook_output(
            requirements_path=os.path.join(os.path.dirname(playbook_path), 'requirements.txt'),
            inventory_str=inventory,
            vars_str=(
                'local_output_dir: {output_dir}\n'
                'local_output_filename: user_statistics\n'
                'remote_output_filename: /tmp/activity_report\n'
                'config_section: {config_section}\n'
                'extra_script_arguments: {extra_script_arguments}'
            ).format(
                output_dir=playbook_output_dir,
                config_section=name_prefix,
                extra_script_arguments=playbook_extra_script_arguments
            ),
            playbook_path=playbook_path,
            username=settings.INSTANCE_LOGS_SERVER_SSH_USERNAME,
            logger_=log_line,
        )
Esempio n. 7
0
    def run_playbook(self, ansible_vars):
        """
        Run the playbook to perform the server reconfiguration.

        This is factored out into a separate method so it can be mocked out in the tests.
        """
        playbook_path = pathlib.Path(settings.SITE_ROOT) / "playbooks/load_balancer_conf/load_balancer_conf.yml"
        with cache.lock("load_balancer_reconfigure:{}".format(self.domain), timeout=900):
            returncode = ansible.capture_playbook_output(
                requirements_path=str(playbook_path.parent / "requirements.txt"),
                inventory_str=self.domain,
                vars_str=ansible_vars,
                playbook_path=str(playbook_path),
                username=self.ssh_username,
                logger_=self.logger,
            )
        if returncode != 0:
            self.logger.error("Playbook to reconfigure load-balancing server %s failed.", self)
            raise ReconfigurationFailed
Esempio n. 8
0
    def activity_csv(self, out):
        """Generate the activity CSV."""
        active_appservers = self.get_active_appservers()
        if not active_appservers:
            self.stderr.write(
                self.style.SUCCESS('There are no active app servers! Nothing to do.')
            )
            sys.exit(0)

        self.stderr.write(self.style.SUCCESS('Running playbook...'))

        with ansible.create_temp_dir() as playbook_output_dir:
            inventory = '[apps]\n{servers}'.format(servers='\n'.join(active_appservers.keys()))
            playbook_path = os.path.join(settings.SITE_ROOT, 'playbooks/collect_activity/collect_activity.yml')

            def log_line(line):
                """Helper to pass to capture_playbook_output()."""
                self.stderr.write(self.style.SUCCESS(line))
            log_line.info = log_line
            log_line.error = log_line

            # Launch the collect_activity playbook, which places a set of files into the `playbook_output_dir`
            # on this host.
            ansible.capture_playbook_output(
                requirements_path=os.path.join(os.path.dirname(playbook_path), 'requirements.txt'),
                inventory_str=inventory,
                vars_str=(
                    'local_output_dir: {output_dir}\n'
                    'remote_output_filename: /tmp/activity_report'
                ).format(output_dir=playbook_output_dir),
                playbook_path=playbook_path,
                username=settings.OPENSTACK_SANDBOX_SSH_USERNAME,
                logger_=log_line,
            )

            csv_writer = csv.writer(out, quoting=csv.QUOTE_NONNUMERIC)
            csv_writer.writerow([
                'Appserver IP', 'Internal LMS Domain', 'Name', 'Contact Email', 'Unique Hits', 'Total Users',
                'Total Courses', 'Age (Days)'
            ])

            filenames = [os.path.join(playbook_output_dir, f) for f in os.listdir(playbook_output_dir)]
            data = ConfigParser()
            data.read(filenames)

            for public_ip, instance in sorted(active_appservers.items(), key=lambda tup: tup[1].id):
                try:
                    section = data[public_ip]
                except KeyError:
                    # Fill in stats for any instaces that failed with "N/A"
                    section = {'hits': 'N/A', 'users': 'N/A', 'courses': 'N/A'}

                instance_age = datetime.now(instance.created.tzinfo) - instance.created

                try:
                    email = instance.betatestapplication_set.get().user.email
                except BetaTestApplication.DoesNotExist:
                    email = 'N/A'

                csv_writer.writerow([
                    public_ip, instance.internal_lms_domain, instance.ref.name, email,
                    section['hits'], section['users'], section['courses'],
                    instance_age.days
                ])

            self.stderr.write(self.style.SUCCESS('Done generating CSV output.'))
Esempio n. 9
0
    def activity_csv(self, out):  # pylint: disable=missing-docstring
        # Produce a mapping of public IPs (of active app servers) to parent instances.
        active_appservers = {
            instance.active_appserver.server.public_ip: instance for instance in OpenEdXInstance.objects.all()
            if not (instance.active_appserver is None or instance.active_appserver.server.public_ip is None)
        }

        if not active_appservers:
            self.stderr.write(
                self.style.SUCCESS('There are no active app servers! Nothing to do.')  # pylint: disable=no-member
            )
            sys.exit(0)

        self.stderr.write(self.style.SUCCESS('Running playbook...'))  # pylint: disable=no-member

        with ansible.create_temp_dir() as playbook_output_dir:
            inventory = '[apps]\n{servers}'.format(servers='\n'.join(active_appservers.keys()))
            playbook_path = os.path.join(settings.SITE_ROOT, 'playbooks/collect_activity/collect_activity.yml')

            def log_line(line):
                """Helper to pass to capture_playbook_output()."""
                self.stderr.write(self.style.SUCCESS(line))  # pylint: disable=no-member
            log_line.info = log_line
            log_line.error = log_line

            # Launch the collect_activity playbook, which places a set of files into the `playbook_output_dir`
            # on this host.
            ansible.capture_playbook_output(
                requirements_path=os.path.join(os.path.dirname(playbook_path), 'requirements.txt'),
                inventory_str=inventory,
                vars_str=(
                    'local_output_dir: {output_dir}\n'
                    'remote_output_filename: /tmp/activity_report'
                ).format(output_dir=playbook_output_dir),
                playbook_path=playbook_path,
                username=settings.OPENSTACK_SANDBOX_SSH_USERNAME,
                logger_=log_line,
            )

            csv_writer = csv.writer(out, quoting=csv.QUOTE_NONNUMERIC)
            csv_writer.writerow([
                'Appserver IP', 'Internal LMS Domain', 'Name', 'Contact Email', 'Unique Hits', 'Total Users',
                'Total Courses', 'Age (Days)'
            ])

            filenames = [os.path.join(playbook_output_dir, f) for f in os.listdir(playbook_output_dir)]
            data = ConfigParser()
            data.read(filenames)

            for public_ip in active_appservers.keys():
                try:
                    section = data[public_ip]
                except KeyError:
                    # Fill in stats for any instaces that failed with "N/A"
                    section = {'hits': 'N/A', 'users': 'N/A', 'courses': 'N/A'}

                instance = active_appservers[public_ip]
                instance_age = datetime.now(instance.created.tzinfo) - instance.created

                try:
                    email = instance.betatestapplication_set.get().user.email
                except BetaTestApplication.DoesNotExist:
                    email = 'N/A'

                csv_writer.writerow([
                    public_ip, instance.internal_lms_domain, instance.ref.name, email,
                    section['hits'], section['users'], section['courses'],
                    instance_age.days
                ])

            self.stderr.write(self.style.SUCCESS('Done generating CSV output.'))  # pylint: disable=no-member