Esempio n. 1
0
def sources_network_info(source_id, auth_header):
    """
    Get additional sources context from Sources REST API.

    Additional details retrieved from the network includes:
        - Source Name
        - Source ID Type -> AWS, Azure, or OCP
        - Authentication: OCP -> Source uid; AWS -> Network call to Sources Authentication Store

    Details are stored in the Sources database table.

    Args:
        source_id (Integer): Source identifier
        auth_header (String): Authentication Header.

    Returns:
        None

    """
    sources_network = SourcesHTTPClient(auth_header, source_id)
    source_details = sources_network.get_source_details()
    source_name = source_details.get("name")
    source_type_id = int(source_details.get("source_type_id"))
    source_uuid = source_details.get("uid")
    source_type_name = sources_network.get_source_type_name(source_type_id)
    endpoint_id = sources_network.get_endpoint_id()

    if not endpoint_id and source_type_name != SOURCES_OCP_SOURCE_NAME:
        LOG.warning(f"Unable to find endpoint for Source ID: {source_id}")
        return

    source_type = SOURCE_PROVIDER_MAP.get(source_type_name)
    if not source_type:
        LOG.warning(f"Unexpected source type ID: {source_type_id}")
        return

    storage.add_provider_sources_network_info(source_id, source_uuid,
                                              source_name, source_type,
                                              endpoint_id)
    save_auth_info(auth_header, source_id)
Esempio n. 2
0
def cost_mgmt_msg_filter(msg_data):
    """Verify that message is for cost management."""
    event_type = msg_data.get("event_type")
    auth_header = msg_data.get("auth_header")

    if event_type in (KAFKA_APPLICATION_DESTROY, KAFKA_SOURCE_DESTROY):
        return msg_data

    if event_type in (KAFKA_AUTHENTICATION_CREATE,
                      KAFKA_AUTHENTICATION_UPDATE):
        sources_network = SourcesHTTPClient(auth_header)
        source_id = sources_network.get_source_id_from_endpoint_id(
            msg_data.get("resource_id"))
        msg_data["source_id"] = source_id
        if not sources_network.get_application_type_is_cost_management(
                source_id):
            LOG.info(
                f"Resource id {msg_data.get('resource_id')} not associated with cost-management."
            )
            return None
    else:
        source_id = msg_data.get("source_id")

    sources_network = SourcesHTTPClient(auth_header, source_id=source_id)
    source_details = sources_network.get_source_details()
    source_type_id = int(source_details.get("source_type_id"))
    source_type_name = sources_network.get_source_type_name(source_type_id)

    if source_type_name not in (
            SOURCES_OCP_SOURCE_NAME,
            SOURCES_AWS_SOURCE_NAME,
            SOURCES_AWS_LOCAL_SOURCE_NAME,
            SOURCES_AZURE_SOURCE_NAME,
            SOURCES_AZURE_LOCAL_SOURCE_NAME,
    ):
        LOG.debug(f"Filtering unexpected source type {source_type_name}.")
        return None
    return msg_data
Esempio n. 3
0
class SourceStatus:
    """Source Status."""
    def __init__(self, source_id):
        """Initialize source id."""
        self.source_id = source_id
        self.source = Sources.objects.get(source_id=source_id)
        if not source_settings_complete(
                self.source) or self.source.pending_delete:
            raise ObjectDoesNotExist(
                f"Source ID: {self.source_id} not ready for status")
        self.sources_client = SourcesHTTPClient(self.source.auth_header,
                                                source_id=source_id)

    @property
    def sources_response(self):
        return self.sources_client.build_source_status(self.status())

    def _set_provider_active_status(self, active_status):
        """Set provider active status."""
        if self.source.koku_uuid:
            try:
                provider = Provider.objects.get(uuid=self.source.koku_uuid)
                provider.active = active_status
                provider.save()
            except Provider.DoesNotExist:
                LOG.info(
                    f"No provider found for Source ID: {self.source.source_id}"
                )

    def determine_status(self, provider_type, source_authentication,
                         source_billing_source):
        """Check cloud configuration status."""
        interface = ProviderAccessor(provider_type)
        error_obj = None
        try:
            if self.source.account_id not in settings.DEMO_ACCOUNTS:
                interface.cost_usage_source_ready(source_authentication,
                                                  source_billing_source)
            self._set_provider_active_status(True)
        except ValidationError as validation_error:
            self._set_provider_active_status(False)
            error_obj = validation_error
        self.source.refresh_from_db()
        return error_obj

    def status(self):
        """Find the source's availability status."""
        source_billing_source = self.source.billing_source.get(
            "data_source") or {}
        source_authentication = self.source.authentication.get(
            "credentials") or {}
        provider_type = self.source.source_type
        return self.determine_status(provider_type, source_authentication,
                                     source_billing_source)

    @transaction.atomic
    def update_source_name(self):
        """Update source name if it is out of sync with platform."""
        source_details = self.sources_client.get_source_details()
        if source_details.get("name") != self.source.name:
            self.source.name = source_details.get("name")
            self.source.save()
            builder = SourcesProviderCoordinator(self.source_id,
                                                 self.source.auth_header)
            builder.update_account(self.source)

    def push_status(self):
        """Push status_msg to platform sources."""
        try:
            status_obj = self.status()
            if self.source.source_type in (Provider.PROVIDER_GCP,
                                           Provider.PROVIDER_GCP_LOCAL):
                builder = SourcesProviderCoordinator(self.source.source_id,
                                                     self.source.auth_header)
                if not status_obj:
                    if self.source.koku_uuid:
                        builder.update_account(self.source)
                    elif self.source.billing_source.get("data_source",
                                                        {}).get("table_id"):
                        builder.create_account(self.source)
            self.sources_client.set_source_status(status_obj)
            self.update_source_name()
            LOG.info(
                f"Source status for Source ID: {str(self.source_id)}: Status: {str(status_obj)}"
            )
        except SkipStatusPush as error:
            LOG.info(
                f"Platform sources status push skipped. Reason: {str(error)}")
        except SourcesHTTPClientError as error:
            err_msg = "Unable to push source status. Reason: {}".format(
                str(error))
            LOG.warning(err_msg)