def _get_service_charging_by_diffs(self, pricing_service, **kwargs):
        """
        Calculates total cost of diffs (between real and calculated costs) of
        selected pricing services.

        :param pricing_service: day for which calculate extra costss
        :returns: dict with difference between real and calculated by specific
            pricing service plugin, grouped by pricing service id (key is
            another pricing service id, value is costs difference)
        :rtype dict:
        """
        result = {}
        for ps in pricing_service.charged_by_diffs.all():
            args = dict(type='total_cost',
                        pricing_service=ps,
                        for_all_service_environments=True,
                        **kwargs)
            try:
                # first run valid pricing service plugin to get "offical" costs
                ps_cost = plugin_runner.run('scrooge_costs',
                                            ps.get_plugin_name(), **args)

                # then call universal plugin to get real cost
                ps_real_cost = plugin_runner.run('scrooge_costs',
                                                 'pricing_service_plugin',
                                                 **args)
            except (KeyError, AttributeError):
                logger.warning('Invalid call for {0} total cost diff'.format(
                    ps.name))
            else:
                # calculate difference between real cost and calculated cost
                diff = ps_real_cost.values()[0][0] - ps_cost.values()[0][0]
                result[ps.id] = diff, {}
        return result
 def handle(self, today, run_only, *args, **options):
     from ralph_pricing import plugins  # noqa
     if today:
         today = datetime.datetime.strptime(today, '%Y-%m-%d').date()
     else:
         today = datetime.date.today()
     print('Synchronizing for {0}.'.format(today.isoformat()))
     if run_only:
         print('Running only {0}...'.format(run_only))
         success, message, context = plugin.run(
             'pricing',
             run_only,
             today=today,
         )
         print('{1}: {0}'.format(message, 'Done' if success else 'Failed'))
         return
     done = set()
     tried = set()
     while True:
         to_run = plugin.next('pricing', done) - tried
         if not to_run:
             break
         name = plugin.highest_priority('pricing', to_run)
         tried.add(name)
         print('Running {0}...'.format(name))
         success, message, context = plugin.run(
             'pricing',
             name,
             today=today,
         )
         print('{1}: {0}'.format(message, 'Done' if success else 'Failed'))
         if success:
             done.add(name)
 def handle(self, today, run_only, *args, **options):
     from ralph_pricing import plugins  # noqa
     if today:
         today = datetime.datetime.strptime(today, '%Y-%m-%d').date()
     else:
         today = datetime.date.today()
     print('Synchronizing for {0}.'.format(today.isoformat()))
     if run_only:
         print('Running only {0}...'.format(run_only))
         success, message, context = plugin.run(
             'pricing',
             run_only,
             today=today,
         )
         print('{1}: {0}'.format(message, 'Done' if success else 'Failed'))
         return
     done = set()
     tried = set()
     while True:
         to_run = plugin.next('pricing', done) - tried
         if not to_run:
             break
         name = plugin.highest_priority('pricing', to_run)
         tried.add(name)
         print('Running {0}...'.format(name))
         success, message, context = plugin.run(
             'pricing', name, today=today,
         )
         print('{1}: {0}'.format(message, 'Done' if success else 'Failed'))
         if success:
             done.add(name)
Exemple #4
0
    def _get_dependent_services_cost(
        self,
        start,
        end,
        service,
        forecast,
        ventures
    ):
        """
        Calculates cost of dependent services used by service.
        """
        dependent_costs = 0
        for dependent in service.dependency.exclude(id=service.id):
            try:
                dependent_schema = plugin_runner.run(
                    'reports',
                    dependent.get_plugin_name(),
                    service=dependent,
                    type='schema'
                )
                # find total cost column in schema
                total_cost_key = None
                for column_key, column_description in dependent_schema.items():
                    if column_description.get('total_cost'):
                        total_cost_key = column_key
                        break

                if total_cost_key:
                    # do report of usages for service (and it's ventures)
                    dependent_usages = plugin_runner.run(
                        'reports',
                        dependent.get_plugin_name(),
                        service=dependent,
                        ventures=ventures,
                        start=start,
                        end=end,
                        forecast=forecast,
                        type='costs',
                    )

                    for venture, venture_data in dependent_usages.items():
                        dependent_costs += venture_data[total_cost_key]
                else:
                    logger.warning(
                        'No total cost column for {0} dependency'.format(
                            dependent.name
                        )
                    )
            except (KeyError, AttributeError):
                logger.warning('Invalid plugin for {0} dependency'.format(
                    dependent.name
                ))
        return dependent_costs
Exemple #5
0
def run_deployment(deployment):
    if deployment.is_running:
        return
    deployment.is_running = True
    deployment.save()
    try:
        done = set(name.strip() for name in deployment.done_plugins.split(',')
                   if name.strip())
        tried = set(done)
        while True:
            plugins = plugin.next('deployment', done) - tried
            if not plugins:
                break
            name = plugin.highest_priority('deployment', plugins)
            tried.add(name)
            try:
                success = plugin.run(
                    'deployment',
                    name,
                    deployment_id=deployment.id,
                )
            except Exception:
                traceback.print_exc()
            else:
                if success:
                    done.add(name)
        # The plugins might have changed the deployment object.
        deployment = Deployment.objects.get(id=deployment.id)
        deployment.done_plugins = ', '.join(done)
        deployment.save()
    finally:
        deployment.is_running = False
        deployment.save()
Exemple #6
0
    def _get_service_extra_cost(
        self,
        start,
        end,
        ventures,
    ):
        """
        Calculates total cost of extra costs for given service.

        :param datatime start: Begin of time interval
        :param datatime end: End of time interval
        :param list ventures: List of ventures
        :returns decimal: price
        :rtype decimal:
        """
        try:
            return plugin_runner.run(
                'reports',
                'extra_cost_plugin',
                type='total_cost',
                start=start,
                end=end,
                ventures=ventures,
            )
        except (KeyError, AttributeError):
            logger.warning('Invalid call for total extra cost')
            return D(0)
    def _get_service_dynamic_extra_cost(
        self,
        date,
        forecast,
        service_environments,
    ):
        """
        Calculates total cost of dynamic extra costs for given pricing_service.

        :param datatime date: day for which calculate extra costs
        :param list service_environments: List of service_environments
        :returns decimal: price
        :rtype decimal:
        """
        result = {}
        for dynamic_extra_cost_type in DynamicExtraCostType.objects.all():
            try:
                dynamic_extra_cost = plugin_runner.run(
                    'scrooge_costs',
                    'dynamic_extra_cost_plugin',
                    type='total_cost',
                    date=date,
                    forecast=forecast,
                    dynamic_extra_cost_type=dynamic_extra_cost_type,
                    service_environments=service_environments,
                )
                if dynamic_extra_cost != 0:
                    result.update(dynamic_extra_cost)
            except (KeyError, AttributeError):
                logger.warning('Invalid call for {0} total cost'.format(
                    dynamic_extra_cost_type.name))
        return result
 def _get_dependent_services_cost(
     self,
     date,
     pricing_service,
     forecast,
     service_environments,
 ):
     """
     Calculates cost of dependent services used by pricing_service.
     """
     result = {}
     exclude = [pricing_service]
     dependent_services = pricing_service.get_dependent_services(
         date,
         exclude,
     )
     for dependent in dependent_services:
         try:
             dependent_cost = plugin_runner.run(
                 'scrooge_costs',
                 dependent.get_plugin_name(),
                 pricing_service=dependent,
                 type='total_cost',
                 date=date,
                 forecast=forecast,
                 service_environments=service_environments,
             )
             result.update(dependent_cost)
         except (KeyError, AttributeError):
             logger.warning('Invalid call for {0} total cost'.format(
                 dependent.name))
     return result
 def _get_service_teams_cost(
     self,
     date,
     forecast,
     service_environments,
 ):
     """
     Calculates total cost of teams for given pricing service, using
     real or forecast prices/costs. Total cost is calculated for period of
     time (between start and end) and for specified service environments.
     """
     result = {}
     for team in Team.objects.all():
         try:
             team_cost = plugin_runner.run(
                 'scrooge_costs',
                 'team_plugin',
                 type='total_cost',
                 date=date,
                 team=team,
                 forecast=forecast,
                 service_environments=service_environments,
             )
             if team_cost != 0:
                 result[team.id] = team_cost, {}
         except (KeyError, AttributeError):
             logger.warning('Invalid call for {0} total cost'.format(
                 team.name))
     return result
Exemple #10
0
    def get_header(cls, start, end, usage_types, **kwargs):
        """
        Return all headers for daily usages report.

        :returns list: Complete collection of headers for report
        :rtype list:
        """
        logger.debug("Getting headers for report")
        header = [
            [
                (_('Service'), {
                    'rowspan': 2
                }),
                (_('Environment'), {
                    'rowspan': 2
                }),
            ],
            [],
        ]
        usage_types_headers = []
        for usage_type in usage_types:
            usage_type_header = plugin_runner.run(
                'scrooge_reports',
                usage_type.get_plugin_name(),
                usage_type=usage_type,
                type='usages_schema',
            )
            usage_types_headers.append(usage_type_header)

        for day in rrule.rrule(rrule.DAILY, dtstart=start, until=end):
            header[0].append((day.date(), {'colspan': len(usage_types)}))
            header[1].extend(usage_types_headers)
        return header
    def get_header(cls, start, end, usage_types, **kwargs):
        """
        Return all headers for daily usages report.

        :returns list: Complete collection of headers for report
        :rtype list:
        """
        logger.debug("Getting headers for report")
        header = [
            [
                (_('Venture'), {'rowspan': 2})
            ],
            [],
        ]
        usage_types_headers = []
        for usage_type in usage_types:
            usage_type_header = plugin_runner.run(
                'reports',
                usage_type.get_plugin_name(),
                usage_type=usage_type,
                type='dailyusages_header',
            )
            usage_types_headers.append(usage_type_header)

        for day in rrule.rrule(rrule.DAILY, dtstart=start, until=end):
            header[0].append((day.date(), {'colspan': len(usage_types)}))
            header[1].extend(usage_types_headers)
        return header
Exemple #12
0
    def _get_report_data(cls, start, end, is_active, forecast, ventures):
        """
        Use plugins to get usages data for given ventures. Plugin logic can be
        so complicated but for this method, plugin must return value in
        format:

        data_from_plugin = {
            'venture_id': {
                'field1_name': value,
                'field2_name': value,
                ...
            },
            ...
        }

        :param datatime start: Start of time interval for report
        :param datatime end: End of time interval for report
        :param boolean forecast: Forecast prices or real
        :param list ventures: List of ventures for which data must be taken
        :returns dict: Complete report data for all ventures
        :rtype dict:
        """
        logger.debug("Getting report date")
        old_queries_count = len(connection.queries)
        data = {venture.id: {} for venture in ventures}
        for i, plugin in enumerate(cls.get_plugins()):
            try:
                plugin_old_queries_count = len(connection.queries)
                plugin_report = plugin_runner.run(
                    'reports',
                    plugin.plugin_name,
                    ventures=ventures,
                    start=start,
                    end=end,
                    forecast=forecast,
                    type='costs',
                    **plugin.get('plugin_kwargs', {})
                )
                for venture_id, venture_usage in plugin_report.iteritems():
                    if venture_id in data:
                        data[venture_id].update(venture_usage)
                plugin_queries_count = (
                    len(connection.queries) - plugin_old_queries_count
                )
                if settings.DEBUG:
                    logger.debug('Plugin SQL queries: {0}\n'.format(
                        plugin_queries_count
                    ))
            except KeyError:
                logger.warning(
                    "Usage '{0}' have no usage plugin".format(plugin.name)
                )
            except BaseException as e:
                logger.exception("Report generate error: {0}".format(e))
        queries_count = len(connection.queries) - old_queries_count
        if settings.DEBUG:
            logger.debug('Total SQL queries: {0}'.format(queries_count))
        return data
Exemple #13
0
    def _get_report_data(cls, start, end, is_active, forecast, ventures):
        """
        Use plugins to get usages data for given ventures. Plugin logic can be
        so complicated but for this method, plugin must return value in
        format:

        data_from_plugin = {
            'venture_id': {
                'field1_name': value,
                'field2_name': value,
                ...
            },
            ...
        }

        :param datatime start: Start of time interval for report
        :param datatime end: End of time interval for report
        :param boolean forecast: Forecast prices or real
        :param list ventures: List of ventures for which data must be taken
        :returns dict: Complete report data for all ventures
        :rtype dict:
        """
        logger.debug("Getting report date")
        old_queries_count = len(connection.queries)
        data = {venture.id: {} for venture in ventures}
        for i, plugin in enumerate(cls.get_plugins()):
            try:
                plugin_old_queries_count = len(connection.queries)
                plugin_report = plugin_runner.run('reports',
                                                  plugin.plugin_name,
                                                  ventures=ventures,
                                                  start=start,
                                                  end=end,
                                                  forecast=forecast,
                                                  type='costs',
                                                  **plugin.get(
                                                      'plugin_kwargs', {}))
                for venture_id, venture_usage in plugin_report.iteritems():
                    if venture_id in data:
                        data[venture_id].update(venture_usage)
                plugin_queries_count = (len(connection.queries) -
                                        plugin_old_queries_count)
                if settings.DEBUG:
                    logger.debug('Plugin SQL queries: {0}\n'.format(
                        plugin_queries_count))
            except KeyError:
                logger.warning("Usage '{0}' have no usage plugin".format(
                    plugin.name))
            except Exception as e:
                logger.exception(
                    "Error while generating the report: {0}".format(e))
                raise
        queries_count = len(connection.queries) - old_queries_count
        if settings.DEBUG:
            logger.debug('Total SQL queries: {0}'.format(queries_count))
        return data
Exemple #14
0
 def _costs(
     self,
     pricing_service,
     date,
     forecast=False,
     **kwargs
 ):
     logger.info(
         (
             "Calculating pricing service costs (using fixed "
             "prices): {0}"
         ).format(
             pricing_service.name,
         )
     )
     result_dict = defaultdict(dict)
     usage_types = pricing_service.usage_types.all()
     for usage_type in usage_types:
         try:
             # results per service environment (list of costs per pricing
             # object as a value)
             costs = plugin_runner.run(
                 'scrooge_costs',
                 usage_type.get_plugin_name(),
                 type='costs',
                 date=date,
                 usage_type=usage_type,
                 forecast=forecast,
             )
             # store costs in hierarchy service environment / pricing object
             # and calculate total cost of cloud per pricing object
             for se, se_costs in costs.items():
                 for cost in se_costs:
                     pricing_object_id = cost.get('pricing_object_id')
                     if pricing_object_id not in result_dict[se]:
                         result_dict[se][pricing_object_id] = {
                             'type_id': pricing_service.id,
                             'pricing_object_id': pricing_object_id,
                             'cost': D(0),
                             '_children': [],
                         }
                     result_dict[se][pricing_object_id]['_children'].append(
                         cost
                     )
                     result_dict[se][pricing_object_id]['cost'] += (
                         cost['cost']
                     )
         except (KeyError, AttributeError):
             logger.warning(
                 'Invalid call for {0} total cost'.format(usage_type.name)
             )
     # return data in format accepted by collector - costs per service
     # environment (without nested dict with pricing object)
     return {k: v.values() for k, v in result_dict.items()}
Exemple #15
0
 def _run_plugin(self, name, today):
     logger.info('Running {0}...'.format(name))
     try:
         success, message, context = plugin.run(
             'pricing',
             name,
             today=today,
         )
         if not success:
             raise PluginError(message)
         logger.info('{0}: Done'.format(message))
         return True
     except Exception as e:
         logger.exception("{0}: {1}".format(name, e))
Exemple #16
0
    def _collect_costs(
        self,
        date,
        forecast=False,
        plugins=None
    ):
        """
        Collects costs from all plugins and stores them per service environment
        """
        logger.debug("Getting report date")
        old_queries_count = len(connection.queries)
        data = defaultdict(list)
        for i, plugin in enumerate(plugins or self.get_plugins()):
            try:
                plugin_old_queries_count = len(connection.queries)
                plugin_report = plugin_runner.run(
                    'scrooge_costs',
                    plugin.plugin_name,
                    date=date,
                    forecast=forecast,
                    type='costs',
                    **{str(k): v for (k, v) in plugin['plugin_kwargs'].items()}
                )
                for service_id, service_usage in plugin_report.iteritems():
                    data[service_id].extend(service_usage)
                plugin_queries_count = (
                    len(connection.queries) - plugin_old_queries_count
                )
                if settings.DEBUG:
                    logger.debug('Plugin SQL queries: {0}\n'.format(
                        plugin_queries_count
                    ))
            except KeyError:
                logger.warning(
                    "Usage '{0}' has no usage plugin\n".format(plugin.name)
                )
            except NoPriceCostError:
                logger.warning('No costs defined\n')
            except MultiplePriceCostError:
                logger.warning('Multiple costs defined\n')
            except Exception as e:
                logger.exception(
                    "Error while generating the report: {0}\n".format(e)
                )
                raise

        queries_count = len(connection.queries) - old_queries_count
        if settings.DEBUG:
            logger.debug('Total SQL queries: {0}'.format(queries_count))
        return data
Exemple #17
0
 def _run_plugin(self, name, today):
     logger.info('Running {0}...'.format(name))
     try:
         success, message, context = plugin.run(
             'pricing',
             name,
             today=today,
         )
         if not success:
             raise PluginError(message)
         logger.info('{0}: Done'.format(message))
         return True
     except Exception as e:
         logger.exception("{0}: {1}".format(name, e))
Exemple #18
0
    def _get_report_data(cls, start, end, usage_types, service_environments):
        """
        Use plugins to get daily usages data for given service environments.
        Plugin should return data in following format:

        data_from_plugin = {
            'day': {
                'service_environment_1_id': value,
                'service_environment_2_id': value2,
            },
            ...
        }

        :param datatime start: Start of time interval for report
        :param datatime end: End of time interval for report
        :param list usage_types: Usage types to use
        :param list service_environments: List of service environments for
            which data must be taken
        :returns dict: Complete report data for service environments daily
            usages
        :rtype dict:
        """
        logger.debug("Getting services environments dailyusages report data")
        data = {
            day.date(): {}
            for day in rrule.rrule(rrule.DAILY, dtstart=start, until=end)
        }
        for usage_type in usage_types:
            plugin_name = usage_type.get_plugin_name()
            try:
                plugin_report = plugin_runner.run(
                    'scrooge_reports',
                    plugin_name,
                    type='usages',
                    start=start,
                    end=end,
                    usage_type=usage_type,
                    service_environments=service_environments,
                )
                for day, day_usages in plugin_report.iteritems():
                    data[day][usage_type.id] = day_usages
            except KeyError:
                logger.warning(
                    "Usage '{0}' has no usage plugin".format(plugin_name))
            except Exception as e:
                logger.exception(
                    "Error while generating the report: {0}".format(e))
                raise
        return data
    def _get_report_data(cls, start, end, usage_types, ventures):
        """
        Use plugins to get daily usages data for given ventures. Plugin return
        value format:

        data_from_plugin = {
            'day': {
                'venture_id': value,
                'venture_id2': value2,
            },
            ...
        }

        :param datatime start: Start of time interval for report
        :param datatime end: End of time interval for report
        :param list usage_types: Usage types to use
        :param list ventures: List of ventures for which data must be taken
        :returns dict: Complete report data for ventures daily usages
        :rtype dict:
        """
        logger.debug("Getting ventures dailyusages report data")
        data = {day.date(): {} for day in rrule.rrule(
            rrule.DAILY,
            dtstart=start,
            until=end
        )}
        for usage_type in usage_types:
            plugin_name = usage_type.get_plugin_name()
            try:
                plugin_report = plugin_runner.run(
                    'reports',
                    plugin_name,
                    ventures=ventures,
                    start=start,
                    end=end,
                    usage_type=usage_type,
                    type='dailyusages',
                )
                for day, day_usages in plugin_report.iteritems():
                    data[day][usage_type.symbol] = day_usages
            except KeyError:
                logger.warning(
                    "Usage '{0}' has no usage plugin".format(plugin_name)
                )
            except BaseException as e:
                logger.error("Report generate error: {0}".format(e))
        return data
    def _get_report_data(cls, start, end, usage_types, ventures):
        """
        Use plugins to get daily usages data for given ventures. Plugin return
        value format:

        data_from_plugin = {
            'day': {
                'venture_id': value,
                'venture_id2': value2,
            },
            ...
        }

        :param datatime start: Start of time interval for report
        :param datatime end: End of time interval for report
        :param list usage_types: Usage types to use
        :param list ventures: List of ventures for which data must be taken
        :returns dict: Complete report data for ventures daily usages
        :rtype dict:
        """
        logger.debug("Getting ventures dailyusages report data")
        data = {day.date(): {} for day in rrule.rrule(
            rrule.DAILY,
            dtstart=start,
            until=end
        )}
        for usage_type in usage_types:
            plugin_name = usage_type.get_plugin_name()
            try:
                plugin_report = plugin_runner.run(
                    'reports',
                    plugin_name,
                    ventures=ventures,
                    start=start,
                    end=end,
                    usage_type=usage_type,
                    type='dailyusages',
                )
                for day, day_usages in plugin_report.iteritems():
                    data[day][usage_type.symbol] = day_usages
            except KeyError:
                logger.warning(
                    "Usage '{0}' has no usage plugin".format(plugin_name)
                )
            except BaseException as e:
                logger.error("Report generate error: {0}".format(e))
        return data
Exemple #21
0
    def _get_report_data(cls, start, end, ventures, forecast, devices):
        """
        Use plugins to get usages data per device for given venture. Each
        plugin has to return value in following format:

        data_from_plugin = {
            'device_id': {
                'field1_name': value,
                'field2_name': value,
                ...
            },
            ...
        }

        :param date start: Start of date interval for report
        :param date end: End of date interval for report
        :param boolean forecast: Forecast prices or real
        :param Venture venture: Venture to generate report for
        :param list devices: List of devices to generate report for
        :returns dict: Complete report data for all ventures
        :rtype dict:
        """
        logger.debug("Getting devices report data")
        data = {device.id: {} for device in devices}
        for plugin in cls.get_plugins():
            try:
                plugin_report = plugin_runner.run(
                    'reports',
                    plugin.plugin_name,
                    ventures=ventures,
                    start=start,
                    end=end,
                    forecast=forecast,
                    type='costs_per_device',
                    **plugin.get('plugin_kwargs', {})
                )
                for device_id, device_usage in plugin_report.iteritems():
                    if device_id in data:
                        data[device_id].update(device_usage)
            except KeyError:
                logger.warning(
                    "Usage {0} has no plugin connected".format(plugin.name)
                )
            except Exception as e:
                logger.exception("Report generate error: {0}".format(e))
        return data
Exemple #22
0
def _run_plugin(context,
                chain,
                plugin_name,
                requirements,
                interactive,
                clear_down,
                done_requirements,
                outputs=None):
    if outputs:
        stdout, stdout_verbose, stderr = outputs
    else:
        stdout = output.get(interactive)
        stdout_verbose = output.get(interactive, verbose=True)
        stderr = output.get(interactive, err=True)

    message = "[{}] {}... ".format(plugin_name, context.get('ip', ''))
    pad = output.WIDTH - len(message)
    stdout(message, end='')
    try:
        new_context = {}
        is_up, message, new_context = plugin.run(chain, plugin_name, **context)
        if is_up:
            requirements.add(plugin_name)
    except plugin.Restart as e:
        stdout('needs to be restarted: {}'.format(unicode(e)), end='\n')
        raise
    except Exception:
        stdout('', end='\r')
        stderr("Exception in plugin '{}' for '{}': {}".format(
            plugin_name, context.get('ip', 'none'), traceback.format_exc()),
               end='\n')
    else:
        message = message or ''
        if clear_down and not is_up:
            end = '\r'
        else:
            end = '\n'
        pad -= len(message)
        message = message + (" " * pad)
        if is_up:
            stdout(message, end=end)
        else:
            stdout_verbose(message, end=end)
    finally:
        done_requirements.add(plugin_name)
    context.update(new_context)
Exemple #23
0
def _run_plugin(context, chain, plugin_name, requirements, interactive,
                clear_down, done_requirements, outputs=None):
    if outputs:
        stdout, stdout_verbose, stderr = outputs
    else:
        stdout = output.get(interactive)
        stdout_verbose = output.get(interactive, verbose=True)
        stderr = output.get(interactive, err=True)

    message = "[{}] {}... ".format(plugin_name, context.get('ip', ''))
    pad = output.WIDTH - len(message)
    stdout(message, end='')
    try:
        new_context = {}
        is_up, message, new_context = plugin.run(chain, plugin_name,
                                                 **context)
        if is_up:
            requirements.add(plugin_name)
    except plugin.Restart as e:
        stdout('needs to be restarted: {}'.format(unicode(e)), end='\n')
        raise
    except Exception:
        stdout('', end='\r')
        stderr("{}\nException in plugin '{}' for '{}'.".format(
            traceback.format_exc()),
            plugin_name,
            context.get('ip', 'none'),
            end='\n')
    else:
        message = message or ''
        if clear_down and not is_up:
            end = '\r'
        else:
            end = '\n'
        pad -= len(message)
        message = message + (" " * pad)
        if is_up:
            stdout(message, end=end)
        else:
            stdout_verbose(message, end=end)
    finally:
        done_requirements.add(plugin_name)
    context.update(new_context)
    context['successful_plugins'] = ', '.join(sorted(requirements))
Exemple #24
0
    def _get_report_data(cls, start, end, ventures, forecast, devices):
        """
        Use plugins to get usages data per device for given venture. Each
        plugin has to return value in following format:

        data_from_plugin = {
            'device_id': {
                'field1_name': value,
                'field2_name': value,
                ...
            },
            ...
        }

        :param date start: Start of date interval for report
        :param date end: End of date interval for report
        :param boolean forecast: Forecast prices or real
        :param Venture venture: Venture to generate report for
        :param list devices: List of devices to generate report for
        :returns dict: Complete report data for all ventures
        :rtype dict:
        """
        logger.debug("Getting devices report data")
        data = {device.id: {} for device in devices}
        for plugin in cls.get_plugins():
            try:
                plugin_report = plugin_runner.run('reports',
                                                  plugin.plugin_name,
                                                  ventures=ventures,
                                                  start=start,
                                                  end=end,
                                                  forecast=forecast,
                                                  type='costs_per_device',
                                                  **plugin.get(
                                                      'plugin_kwargs', {}))
                for device_id, device_usage in plugin_report.iteritems():
                    if device_id in data:
                        data[device_id].update(device_usage)
            except KeyError:
                logger.warning("Usage {0} has no plugin connected".format(
                    plugin.name))
            except Exception as e:
                logger.exception("Report generate error: {0}".format(e))
        return data
Exemple #25
0
def _run_plugin(name, today):
    logger.info('Running {0}...'.format(name))
    success, message = False, None
    sync_status = SyncStatus.objects.get_or_create(plugin=name, date=today)[0]
    try:
        success, message = plugin.run(
            'scrooge',
            name,
            today=today,
        )
        if not success:
            raise PluginError(message)
    except Exception as e:
        logger.exception("{0}: {1}".format(name, e))
        raise PluginError(e)
    finally:
        sync_status.success = success
        sync_status.remarks = message
        sync_status.save()
        logger.info('Done: {0}'.format(message))
Exemple #26
0
def _run_plugin(name, today):
    logger.info('Running {0}...'.format(name))
    success, message = False, None
    sync_status = SyncStatus.objects.get_or_create(plugin=name, date=today)[0]
    try:
        success, message = plugin.run(
            'scrooge',
            name,
            today=today,
        )
        if not success:
            raise PluginError(message)
    except Exception as e:
        logger.exception("{0}: {1}".format(name, e))
        raise PluginError(e)
    finally:
        sync_status.success = success
        sync_status.remarks = message
        sync_status.save()
        logger.info('Done: {0}'.format(message))
Exemple #27
0
def _run_plugin(context,
                chain,
                plugin_name,
                requirements,
                interactive,
                done_requirements,
                outputs=None):
    if outputs:
        stdout, stdout_verbose, stderr = outputs
    else:
        stdout = output.get(interactive)
        stderr = output.get(interactive, err=True)

    message = "[{}] {}... ".format(plugin_name, _get_uid(context))
    stdout(message, end='')
    new_context = {}
    try:
        is_up, message, new_context = plugin.run(chain, plugin_name, **context)
    except plugin.Restart as e:
        stdout('needs to be restarted: {}'.format(unicode(e)))
        raise
    except Exception:
        stdout('', end='\r')
        stderr(
            "{}\nException in plugin '{}' for '{}'.".format(
                traceback.format_exc(),
                plugin_name,
                _get_uid(context),
            ),
            end='\n',
        )
        raise
    else:
        if message:
            stdout(message, verbose=not is_up)
        if is_up:
            requirements.add(plugin_name)
            context['successful_plugins'] = ', '.join(sorted(requirements))
        context.update(new_context)
    finally:
        done_requirements.add(plugin_name)
 def _get_usage_type_costs(self, date, usage_type, forecast,
                           service_environments):
     """
     Calculates total cost of usage of given type for specified
     service environments in period of time (between start and end), using
     real or forecast price/cost.
     """
     try:
         return plugin_runner.run(
             'scrooge_costs',
             usage_type.get_plugin_name(),
             type='total_cost',
             date=date,
             usage_type=usage_type,
             forecast=forecast,
             service_environments=service_environments,
         )
     except (KeyError, AttributeError):
         logger.warning('Invalid call for {0} total cost'.format(
             usage_type.name))
         return D(0)
    def _get_schema(cls):
        """
        Use plugins to get full schema for report

        :returns dict: Complete schema for all columns in report
        :rtype dict:
        """
        logger.debug("Getting schema for report")
        header = []
        for plugin in cls.get_plugins():
            try:
                plugin_headers = plugin_runner.run('scrooge_reports',
                                                   plugin.plugin_name,
                                                   type=cls.schema_name,
                                                   **plugin.get(
                                                       'plugin_kwargs', {}))
                header.append(plugin_headers)
            except KeyError:
                logger.warning("Usage '{0}' has no schema plugin".format(
                    plugin.name))
        return header
Exemple #30
0
 def _get_usage_type_cost(self, start, end, usage_type, forecast, ventures):
     """
     Calculates total cost of usage of given type for specified ventures in
     period of time (between start and end), using real or forecast
     price/cost.
     """
     try:
         return plugin_runner.run(
             'reports',
             usage_type.get_plugin_name(),
             type='total_cost',
             start=start,
             end=end,
             usage_type=usage_type,
             forecast=forecast,
             ventures=ventures,
         )
     except (KeyError, AttributeError):
         logger.warning('Invalid call for {0} total cost'.format(
             usage_type.name))
         return D(0)
Exemple #31
0
def run_deployment(deployment):
    if deployment.is_running:
        return
    deployment.is_running = True
    deployment.save()
    try:
        done = set(name.strip() for name in deployment.done_plugins.split(','))
        tried = set(done)
        while True:
            plugins = plugin.next('deployment', done) - tried
            if not plugins:
                break
            name = plugin.highest_priority('deployment', plugins)
            tried.add(name)
            if plugin.run('deployment', name, deployment_id=deployment.id):
                done.add(name)
        deployment.done_plugins = ', '.join(done)
        deployment.save()
    finally:
        deployment.is_running = False
        deployment.save()
Exemple #32
0
 def _get_usage_type_cost(self, start, end, usage_type, forecast, ventures):
     """
     Calculates total cost of usage of given type for specified ventures in
     period of time (between start and end), using real or forecast
     price/cost.
     """
     try:
         return plugin_runner.run(
             'reports',
             usage_type.get_plugin_name(),
             type='total_cost',
             start=start,
             end=end,
             usage_type=usage_type,
             forecast=forecast,
             ventures=ventures,
         )
     except (KeyError, AttributeError):
         logger.warning(
             'Invalid call for {0} total cost'.format(usage_type.name)
         )
         return D(0)
Exemple #33
0
def _run_plugin(context, chain, plugin_name, requirements, interactive, clear_down, done_requirements, outputs=None):
    if outputs:
        stdout, stdout_verbose, stderr = outputs
    else:
        stdout = output.get(interactive)
        stdout_verbose = output.get(interactive, verbose=True)
        stderr = output.get(interactive, err=True)

    message = "[{}] {}... ".format(plugin_name, context["ip"])
    pad = output.WIDTH - len(message)
    stdout(message, end="")
    try:
        new_context = {}
        is_up, message, new_context = plugin.run(chain, plugin_name, **context)
        if is_up:
            requirements.add(plugin_name)
    except plugin.Restart as e:
        stdout("needs to be restarted: {}".format(unicode(e)), end="\n")
        raise
    except Exception:
        stdout("", end="\r")
        stderr(
            "Exception in plugin '{}' for '{}': {}".format(plugin_name, context["ip"], traceback.format_exc()), end="\n"
        )
    else:
        message = message or ""
        if clear_down and not is_up:
            end = "\r"
        else:
            end = "\n"
        pad -= len(message)
        message = message + (" " * pad)
        if is_up:
            stdout(message, end=end)
        else:
            stdout_verbose(message, end=end)
    finally:
        done_requirements.add(plugin_name)
    context.update(new_context)
    def _get_schema(cls):
        """
        Use plugins to get full schema for report

        :returns dict: Complete schema for all columns in report
        :rtype dict:
        """
        logger.debug("Getting schema for report")
        header = []
        for plugin in cls.get_plugins():
            try:
                plugin_headers = plugin_runner.run(
                    'reports',
                    plugin.plugin_name,
                    type=cls.schema_name,
                    **plugin.get('plugin_kwargs', {})
                )
                header.append(plugin_headers)
            except KeyError:
                logger.warning(
                    "Usage '{0}' has no schema plugin".format(plugin.name)
                )
        return header
Exemple #35
0
def run_deployment(deployment):
    if deployment.is_running:
        return
    deployment.is_running = True
    deployment.save()
    try:
        done = set(
            name.strip() for
            name in
            deployment.done_plugins.split(',')
            if name.strip()
        )
        tried = set(done)
        while True:
            plugins = plugin.next('deployment', done) - tried
            if not plugins:
                break
            name = plugin.highest_priority('deployment', plugins)
            tried.add(name)
            try:
                success = plugin.run(
                    'deployment',
                    name,
                    deployment_id=deployment.id,
                )
            except Exception:
                traceback.print_exc()
            else:
                if success:
                    done.add(name)
        # The plugins might have changed the deployment object.
        deployment = Deployment.objects.get(id=deployment.id)
        deployment.done_plugins = ', '.join(done)
        deployment.save()
    finally:
        deployment.is_running = False
        deployment.save()
Exemple #36
0
def _run_plugin(context, chain, plugin_name, requirements, interactive,
                done_requirements, outputs=None):
    if outputs:
        stdout, stdout_verbose, stderr = outputs
    else:
        stdout = output.get(interactive)
        stderr = output.get(interactive, err=True)

    message = "[{}] {}... ".format(plugin_name, _get_uid(context))
    stdout(message, end='')
    new_context = {}
    try:
        is_up, message, new_context = plugin.run(chain, plugin_name,
                                                 **context)
    except plugin.Restart as e:
        stdout('needs to be restarted: {}'.format(unicode(e)))
        raise
    except Exception:
        stdout('', end='\r')
        stderr(
            "{}\nException in plugin '{}' for '{}'.".format(
                traceback.format_exc(),
                plugin_name,
                _get_uid(context),
            ),
            end='\n',
        )
        raise
    else:
        if message:
            stdout(message, verbose=not is_up)
        if is_up:
            requirements.add(plugin_name)
            context['successful_plugins'] = ', '.join(sorted(requirements))
        context.update(new_context)
    finally:
        done_requirements.add(plugin_name)
    def _get_report_data(
        cls,
        start,
        end,
        is_active,
        forecast,
        service_environments,
    ):
        """
        Use plugins to get usages data for given ventures. Plugin logic can be
        so complicated but for this method, plugin must return value in
        format:

        data_from_plugin = {
            'venture_id': {
                'field1_name': value,
                'field2_name': value,
                ...
            },
            ...
        }

        :param datatime start: Start of time interval for report
        :param datatime end: End of time interval for report
        :param boolean forecast: Forecast prices or real
        :param list ventures: List of ventures for which data must be taken
        :returns dict: Complete report data for all ventures
        :rtype dict:
        """
        logger.debug("Getting report date")
        data = {se.id: {} for se in service_environments}
        plugins = cls.get_plugins()
        progress = 0
        step = 100 / len(plugins)
        for i, plugin in enumerate(plugins):
            try:
                logger.info('Calling plugin {} with base usage {}'.format(
                    plugin.plugin_name,
                    plugin.get('plugin_kwargs', {}).get('base_usage', '-'),
                ))
                plugin_report = plugin_runner.run('scrooge_reports',
                                                  plugin.plugin_name,
                                                  start=start,
                                                  end=end,
                                                  forecast=forecast,
                                                  type='costs',
                                                  **plugin.get(
                                                      'plugin_kwargs', {}))
                for service_id, service_usage in plugin_report.iteritems():
                    if service_id in data:
                        data[service_id].update(service_usage)

                progress += step
                yield progress, {}
            except KeyError:
                logger.warning("Usage '{0}' has no usage plugin".format(
                    plugin.name))
            except Exception as e:
                logger.exception(
                    "Error while generating the report: {0}".format(e))
                raise
        yield 100, data
    def _get_report_data(
        cls,
        start,
        end,
        is_active,
        forecast,
        service_environments,
    ):
        """
        Use plugins to get usages data for given ventures. Plugin logic can be
        so complicated but for this method, plugin must return value in
        format:

        data_from_plugin = {
            'venture_id': {
                'field1_name': value,
                'field2_name': value,
                ...
            },
            ...
        }

        :param datatime start: Start of time interval for report
        :param datatime end: End of time interval for report
        :param boolean forecast: Forecast prices or real
        :param list ventures: List of ventures for which data must be taken
        :returns dict: Complete report data for all ventures
        :rtype dict:
        """
        logger.debug("Getting report date")
        data = {se.id: {} for se in service_environments}
        plugins = cls.get_plugins()
        progress = 0
        step = 100 / len(plugins)
        for i, plugin in enumerate(plugins):
            try:
                logger.info('Calling plugin {} with base usage {}'.format(
                    plugin.plugin_name,
                    plugin.get('plugin_kwargs', {}).get('base_usage', '-'),
                ))
                plugin_report = plugin_runner.run(
                    'scrooge_reports',
                    plugin.plugin_name,
                    start=start,
                    end=end,
                    forecast=forecast,
                    type='costs',
                    **plugin.get('plugin_kwargs', {})
                )
                for service_id, service_usage in plugin_report.iteritems():
                    if service_id in data:
                        data[service_id].update(service_usage)

                progress += step
                yield progress, {}
            except KeyError:
                logger.warning(
                    "Usage '{0}' has no usage plugin".format(plugin.name)
                )
            except Exception as e:
                logger.exception(
                    "Error while generating the report: {0}".format(e)
                )
                raise
        yield 100, data