Ejemplo n.º 1
0
    def ready(self):
        # structure
        from .backend import ZabbixBackend
        SupportedServices.register_backend(ZabbixBackend)

        # templates
        from nodeconductor.template import TemplateRegistry
        from nodeconductor_zabbix.template import HostProvisionTemplateForm
        TemplateRegistry.register(HostProvisionTemplateForm)

        from . import handlers
        for index, resource_model in enumerate(
                structure_models.Resource.get_all_models()):
            signals.post_save.connect(
                handlers.update_hosts_visible_name_on_scope_name_change,
                sender=resource_model,
                dispatch_uid=
                'nodeconductor_zabbix.handlers.update_hosts_visible_name_on_scope_name_change_%s_%s'
                % (index, resource_model.__name__))

            signals.pre_delete.connect(
                handlers.delete_hosts_on_scope_deletion,
                sender=resource_model,
                dispatch_uid=
                'nodeconductor_zabbix.handlers.delete_hosts_on_scope_deletion_%s_%s'
                % (index, resource_model.__name__))
Ejemplo n.º 2
0
    def ready(self):
        # structure
        from .backend import SugarCRMBackend
        SupportedServices.register_backend(SugarCRMBackend)

        # cost tracking
        from .cost_tracking import SugarCRMCostTrackingBackend
        CostTrackingRegister.register(self.label, SugarCRMCostTrackingBackend)

        # template
        from .template import CRMProvisionTemplateForm
        TemplateRegistry.register(CRMProvisionTemplateForm)

        from . import handlers
        CRM = self.get_model('CRM')

        signals.post_save.connect(
            handlers.update_user_limit_count_quota_on_crm_quota_change,
            sender=Quota,
            dispatch_uid='nodeconductor_sugarcrm.handlers.update_user_limit_count_quota_on_crm_quota_change',
        )

        signals.pre_delete.connect(
            handlers.update_user_limit_count_quota_on_crm_deletion,
            sender=CRM,
            dispatch_uid='nodeconductor_sugarcrm.handlers.update_user_limit_count_quota_on_crm_deletion'
        )
Ejemplo n.º 3
0
 def __new__(mcs, name, bases, args):
     service_filter = super(ServiceFilterMetaclass,
                            mcs).__new__(mcs, name, bases, args)
     model = args['Meta'].model
     if not model._meta.abstract:
         SupportedServices.register_service_filter(args['Meta'].model,
                                                   service_filter)
     return service_filter
Ejemplo n.º 4
0
def get_field_type(field):
    """
    Returns field type/possible values.
    """
    if isinstance(field, core_filters.MappedMultipleChoiceFilter):
        return ' | '.join(['"%s"' % f for f in sorted(field.mapped_to_model)])
    if isinstance(field, OrderingFilter) or isinstance(field, ChoiceFilter):
        return ' | '.join(['"%s"' % f[0] for f in field.extra['choices']])
    if isinstance(field, ChoiceField):
        return ' | '.join(['"%s"' % f for f in sorted(field.choices)])
    if isinstance(field, HyperlinkedRelatedField):
        if field.view_name.endswith('detail'):
            return 'link to %s' % reverse(field.view_name,
                                          kwargs={
                                              '%s' % field.lookup_field:
                                              "'%s'" % field.lookup_field
                                          })
        return reverse(field.view_name)
    if isinstance(field, structure_filters.ServiceTypeFilter):
        return ' | '.join([
            '"%s"' % f for f in SupportedServices.get_filter_mapping().keys()
        ])
    if isinstance(field, ResourceTypeFilter):
        return ' | '.join([
            '"%s"' % f for f in SupportedServices.get_resource_models().keys()
        ])
    if isinstance(field, core_serializers.GenericRelatedField):
        links = []
        for model in field.related_models:
            detail_view_name = core_utils.get_detail_view_name(model)
            for f in field.lookup_fields:
                try:
                    link = reverse(detail_view_name,
                                   kwargs={'%s' % f: "'%s'" % f})
                except NoReverseMatch:
                    pass
                else:
                    links.append(link)
                    break
        path = ', '.join(links)
        if path:
            return 'link to any: %s' % path
    if isinstance(field, core_filters.ContentTypeFilter):
        return "string in form 'app_label'.'model_name'"
    if isinstance(field, ModelMultipleChoiceFilter):
        return get_field_type(field.field)
    if isinstance(field, ListSerializer):
        return 'list of [%s]' % get_field_type(field.child)
    if isinstance(field, ManyRelatedField):
        return 'list of [%s]' % get_field_type(field.child_relation)
    if isinstance(field, ModelField):
        return get_field_type(field.model_field)

    name = field.__class__.__name__
    for w in ('Filter', 'Field', 'Serializer'):
        name = name.replace(w, '')
    return FIELDS.get(name, name)
Ejemplo n.º 5
0
    def ready(self):
        OpenStackService = self.get_model('OpenStackService')
        OpenStackServiceProjectLink = self.get_model('OpenStackServiceProjectLink')
        Instance = self.get_model('Instance')
        FloatingIP = self.get_model('FloatingIP')

        # structure
        from nodeconductor.openstack.backend import OpenStackBackend
        SupportedServices.register_backend(OpenStackService, OpenStackBackend)

        # cost tracking
        from nodeconductor.openstack.cost_tracking import OpenStackCostTrackingBackend
        CostTrackingRegister.register(self.label, OpenStackCostTrackingBackend)

        # template
        from nodeconductor.template import TemplateRegistry
        from nodeconductor.openstack.template import InstanceProvisionTemplateForm
        TemplateRegistry.register(InstanceProvisionTemplateForm)

        signals.post_save.connect(
            handlers.create_initial_security_groups,
            sender=OpenStackServiceProjectLink,
            dispatch_uid='nodeconductor.openstack.handlers.create_initial_security_groups',
        )

        signals.post_save.connect(
            quotas_handlers.add_quotas_to_scope,
            sender=OpenStackServiceProjectLink,
            dispatch_uid='nodeconductor.openstack.handlers.add_quotas_to_service_project_link',
        )

        signals.pre_save.connect(
            handlers.set_spl_default_availability_zone,
            sender=OpenStackServiceProjectLink,
            dispatch_uid='nodeconductor.openstack.handlers.set_spl_default_availability_zone',
        )

        signals.post_save.connect(
            handlers.increase_quotas_usage_on_instance_creation,
            sender=Instance,
            dispatch_uid='nodeconductor.openstack.handlers.increase_quotas_usage_on_instance_creation',
        )

        signals.post_delete.connect(
            handlers.decrease_quotas_usage_on_instances_deletion,
            sender=Instance,
            dispatch_uid='nodeconductor.openstack.handlers.decrease_quotas_usage_on_instances_deletion',
        )

        signals.post_save.connect(
            handlers.change_floating_ip_quota_on_status_change,
            sender=FloatingIP,
            dispatch_uid='nodeconductor.openstack.handlers.change_floating_ip_quota_on_status_change',
        )
Ejemplo n.º 6
0
def service_settings_description():
    services = []
    for cls in BaseServiceSerializer.__subclasses__():
        if cls.Meta.model is NotImplemented:
            continue
        if not SupportedServices._is_active_model(cls.Meta.model):
            continue
        name = SupportedServices.get_name_for_model(cls.Meta.model)
        fields, extra_fields = get_fields(cls)
        services.append((name, {
            'fields': fields,
            'extra_fields': extra_fields
        }))
    return {'services': sorted(services)}
Ejemplo n.º 7
0
    def ready(self):
        from .backend import SaltStackBackend
        from .models import SaltStackProperty
        import handlers
        SupportedServices.register_backend(SaltStackBackend)

        from nodeconductor.structure.models import ServiceSettings
        from nodeconductor.quotas.fields import QuotaField, CounterQuotaField
        from ..exchange.models import ExchangeTenant

        ServiceSettings.add_quota_field(
            name='sharepoint_storage',
            quota_field=QuotaField(
                creation_condition=lambda service_settings: service_settings.
                type == SaltStackConfig.service_name, ),
        )

        ServiceSettings.add_quota_field(
            name='exchange_storage',
            quota_field=QuotaField(
                creation_condition=lambda service_settings: service_settings.
                type == SaltStackConfig.service_name, ),
        )

        ServiceSettings.add_quota_field(
            name='exchange_tenant_count',
            quota_field=CounterQuotaField(
                creation_condition=lambda service_settings: service_settings.
                type == SaltStackConfig.service_name,
                target_models=[ExchangeTenant],
                path_to_scope='service_project_link.service.settings',
            ))

        for index, model in enumerate(SaltStackProperty.get_all_models()):
            signals.post_save.connect(
                handlers.log_saltstack_property_created,
                sender=model,
                dispatch_uid=
                'nodeconductor_saltstack.saltstack.handlers.log_saltstack_property_created{}_{}'
                .format(model.__name__, index),
            )

            signals.post_delete.connect(
                handlers.log_saltstack_property_deleted,
                sender=model,
                dispatch_uid=
                'nodeconductor_saltstack.saltstack.handlers.log_saltstack_property_deleted{}_{}'
                .format(model.__name__, index),
            )
Ejemplo n.º 8
0
    def count(self, request):
        """
        Count resources by type. Example output:
        {
            "Amazon.Instance": 0,
            "GitLab.Project": 3,
            "Azure.VirtualMachine": 0,
            "IaaS.Instance": 10,
            "DigitalOcean.Droplet": 0,
            "OpenStack.Instance": 0,
            "GitLab.Group": 8
        }
        """
        types = request.query_params.getlist('resource_type', [])
        params = self.get_params(request)
        resources = SupportedServices.get_resources(request).items()

        result = {}
        for (type, url) in resources:
            if types != [] and type not in types:
                continue
            response = request_api(request, url, method='HEAD', params=params)
            if not response.success:
                raise APIException(response.data)
            result[type] = response.total
        return Response(result)
Ejemplo n.º 9
0
 def get_urls(self, request):
     types = request.query_params.getlist('resource_type', [])
     resources = SupportedServices.get_resources(request).items()
     if types != []:
         return [url for (type, url) in resources if type in types]
     else:
         return [url for (type, url) in resources]
Ejemplo n.º 10
0
def begin_recovering_erred_service_settings(settings_uuid, transition_entity=None):
    settings = models.ServiceSettings.objects.get(uuid=settings_uuid)

    try:
        backend = settings.get_backend()
        is_active = backend.ping()
    except ServiceBackendNotImplemented:
        is_active = False

    if is_active:
        settings.set_in_sync()
        settings.error_message = ''
        settings.save()
        logger.info('Service settings %s successfully recovered.' % settings.name)

        try:
            spl_model = SupportedServices.get_service_models()[settings.type]['service_project_link']
            erred_spls = spl_model.objects.filter(service__settings=settings,
                                                  state=SynchronizationStates.ERRED)
            recover_erred_services.delay([spl.to_string() for spl in erred_spls])
        except KeyError:
            logger.warning('Failed to recover service project links for settings %s', settings)
    else:
        settings.set_erred()
        settings.error_message = 'Failed to ping service settings %s' % settings.name
        settings.save()
        logger.info('Failed to recover service settings %s.' % settings.name)
Ejemplo n.º 11
0
def wait_for_provision(previous_task_data=None,
                       template_uuid=None,
                       token_key=None,
                       template_group_result_uuid=None,
                       success_state='Online',
                       erred_state='Erred'):
    template_group_result = models.TemplateGroupResult.objects.get(
        uuid=template_group_result_uuid)
    template = models.Template.objects.get(uuid=template_uuid)

    url = previous_task_data['url']
    resource_data = template.get_resource(url, token_key).json()

    resource_type = SupportedServices.get_name_for_model(
        template.resource_content_type.model_class())
    state = resource_data['state']
    if state == success_state:
        template_group_result.state_message = '%s has been successfully provisioned.' % resource_type
        template_group_result.provisioned_resources[resource_type] = url
        template_group_result.save()
        return resource_data
    elif state != erred_state:
        template_group_result.state_message = 'Waiting for %s provision (current state: %s). ' % (
            resource_type, state)
        template_group_result.save()
        return False
    else:
        message = 'Failed to provision %s.' % resource_type
        details = 'Resource with URL %s come to state "%s".' % (url, state)
        raise models.TemplateActionException(message, details)
Ejemplo n.º 12
0
    def _get_erred_resources_module(self):
        """
        Returns a list of links to resources which are in ERRED state and linked to a shared service settings.
        """
        result_module = modules.LinkList(title=_('Resources in erred state'))
        erred_state = structure_models.NewResource.States.ERRED
        children = []

        resource_models = SupportedServices.get_resource_models()
        resources_in_erred_state_overall = 0
        for resource_type, resource_model in resource_models.items():
            queryset = resource_model.objects.filter(
                service_project_link__service__settings__shared=True)
            erred_amount = queryset.filter(state=erred_state).count()
            if erred_amount:
                resources_in_erred_state_overall = resources_in_erred_state_overall + erred_amount
                link = self._get_erred_resource_link(resource_model,
                                                     erred_amount, erred_state)
                children.append(link)

        if resources_in_erred_state_overall:
            result_module.title = '%s (%s)' % (
                result_module.title, resources_in_erred_state_overall)
            result_module.children = children
        else:
            result_module.pre_content = _('Nothing found.')

        return result_module
Ejemplo n.º 13
0
    def clean(self):
        if not self.service:
            raise ValidationError(_('Service is not defined.'))

        if SupportedServices.is_public_service(self.service):
            raise ValidationError(
                _('Public service does not support price list items.'))

        resource = self.default_price_list_item.resource_content_type.model_class(
        )
        valid_resources = SupportedServices.get_related_models(
            self.service)['resources']

        if resource not in valid_resources:
            raise ValidationError(
                _('Service does not support required content type.'))
Ejemplo n.º 14
0
def debit_customers():
    """ Fetch a list of shared services (services based on shared settings).
        Calculate the amount of consumed resources "yesterday" (make sure this task executed only once a day)
        Reduce customer's balance accordingly
        Stop online resource if needed
    """

    date = datetime.now() - timedelta(days=1)
    start_date = date.replace(hour=0, minute=0, second=0, microsecond=0)
    end_date = start_date + timedelta(days=1, microseconds=-1)

    # XXX: it's just a placeholder, it doesn't work properly now nor implemented anyhow
    #      perhaps it should merely use price estimates..

    # TODO: remove once iaas has been deprecated
    from nodeconductor.iaas.models import Instance
    models = filter(lambda model: model != Instance,
                    SupportedServices.get_resource_models().values())

    for model in models:
        resources = model.objects.filter(
            service_project_link__service__settings__shared=True)

        for resource in resources:
            try:
                data = resource.get_cost(start_date, end_date)
            except NotImplementedError:
                continue
            else:
                resource.customer.debit_account(data['total_amount'])
Ejemplo n.º 15
0
 def create(self, validated_data):
     # XXX: This behavior is wrong for services with several resources, find a better approach
     resource_class = SupportedServices.get_related_models(
         validated_data['service'])['resources'][0]
     validated_data[
         'resource_content_type'] = ContentType.objects.get_for_model(
             resource_class)
     return super(PriceListItemSerializer, self).create(validated_data)
Ejemplo n.º 16
0
 def queryset(self, request, queryset):
     if self.value():
         model = SupportedServices.get_resource_models().get(
             self.value(), None)
         if model:
             return queryset.filter(resource_content_type=ContentType.
                                    objects.get_for_model(model))
     return queryset
Ejemplo n.º 17
0
 def get_links(self):
     """
     Get all service project links connected to current project
     """
     return [
         link for model in SupportedServices.get_service_models().values()
         for link in model['service_project_link'].objects.filter(
             project=self)
     ]
Ejemplo n.º 18
0
 def filter(self, qs, value):
     if value in EMPTY_VALUES:
         return qs
     resource_models = SupportedServices.get_resource_models()
     try:
         model = resource_models[value]
         ct = ContentType.objects.get_for_model(model)
         return super(ResourceTypeFilter, self).filter(qs, ct)
     except (ContentType.DoesNotExist, KeyError):
         return qs.none()
Ejemplo n.º 19
0
 def lookups(self, request, model_admin):
     resources = [
         (model, name)
         for name, model in SupportedServices.get_resource_models().items()
     ]
     others = [(model, model.__name__)
               for model in models.PriceEstimate.get_estimated_models()
               if not issubclass(model, structure_models.ResourceMixin)]
     estimated_models = [(core_utils.serialize_class(model), name)
                         for model, name in resources + others]
     return sorted(estimated_models, key=lambda x: x[1])
Ejemplo n.º 20
0
 def _find_service(self):
     service_type = self.request.query_params.get('service_type')
     service_uuid = self.request.query_params.get('service_uuid')
     if not service_type or not service_uuid:
         return
     rows = SupportedServices.get_service_models()
     if service_type not in rows:
         return
     service_class = rows.get(service_type)['service']
     try:
         return service_class.objects.get(uuid=service_uuid)
     except ObjectDoesNotExist:
         return None
Ejemplo n.º 21
0
    def ready(self):
        from nodeconductor.quotas.fields import LimitAggregatorQuotaField
        from nodeconductor.structure import SupportedServices

        # structure
        from .backend import SugarCRMBackend
        SupportedServices.register_backend(SugarCRMBackend)

        from nodeconductor.structure.models import ServiceSettings
        from . import handlers, signals as sugarcrm_signals
        CRM = self.get_model('CRM')
        SugarCRMServiceProjectLink = self.get_model(
            'SugarCRMServiceProjectLink')

        sugarcrm_signals.user_post_save.connect(
            handlers.log_user_post_save,
            sender=CRM,
            dispatch_uid='nodeconductor_sugarcrm.handlers.log_user_post_save')

        sugarcrm_signals.user_post_delete.connect(
            handlers.log_user_post_delete,
            sender=CRM,
            dispatch_uid='nodeconductor_sugarcrm.handlers.log_user_post_delete'
        )

        ServiceSettings.add_quota_field(
            name='sugarcrm_user_count',
            quota_field=LimitAggregatorQuotaField(
                creation_condition=lambda service_settings: service_settings.
                type == SugarCRMConfig.service_name,
                get_children=lambda service_settings:
                SugarCRMServiceProjectLink.objects.filter(service__settings=
                                                          service_settings),
                child_quota_name='user_limit_count',
            ),
        )
Ejemplo n.º 22
0
def connect_customer_to_shared_service_settings(sender,
                                                instance,
                                                created=False,
                                                **kwargs):
    if not created:
        return
    customer = instance

    for shared_settings in ServiceSettings.objects.filter(
            shared=True, state=SynchronizationStates.IN_SYNC):
        service_model = SupportedServices.get_service_models()[
            shared_settings.type]['service']
        service_model.objects.create(customer=customer,
                                     settings=shared_settings,
                                     name=shared_settings.name,
                                     available_for_all=True)
Ejemplo n.º 23
0
 def get_backend(self, service):
     # project_uuid can be supplied in order to get a list of resources
     # available for import (link) based on project, depends on backend implementation
     project_uuid = self.request.query_params.get('project_uuid')
     if project_uuid:
         spl_class = SupportedServices.get_related_models(
             service)['service_project_link']
         try:
             spl = spl_class.objects.get(project__uuid=project_uuid,
                                         service=service)
         except:
             raise NotFound("Can't find project %s" % project_uuid)
         else:
             return spl.get_backend()
     else:
         return service.get_backend()
Ejemplo n.º 24
0
    def create_service_project_link(self, customer, project):
        service_type, models = SupportedServices.get_service_models().items(
        )[0]

        class ServiceFactory(factory.DjangoModelFactory):
            class Meta(object):
                model = models['service']

        class ServiceProjectLinkFactory(factory.DjangoModelFactory):
            class Meta(object):
                model = models['service_project_link']

        settings = structure_factories.ServiceSettingsFactory(
            customer=customer, type=service_type, shared=False)
        service = ServiceFactory(customer=customer, settings=settings)
        return ServiceProjectLinkFactory(service=service, project=project)
Ejemplo n.º 25
0
    def _get_log_context(self, entity_name):
        context = super(ResourceMixin, self)._get_log_context(entity_name)
        # XXX: Add resource_full_name here, because event context does not support properties as fields
        context['resource_full_name'] = self.full_name
        # required for lookups in ElasticSearch by the client
        context['resource_type'] = SupportedServices.get_name_for_model(self)

        # XXX: a hack for IaaS / PaaS / SaaS tags
        # XXX: should be moved to itacloud assembly
        if self.tags.filter(name='IaaS').exists():
            context['resource_delivery_model'] = 'IaaS'
        elif self.tags.filter(name='PaaS').exists():
            context['resource_delivery_model'] = 'PaaS'
        elif self.tags.filter(name='SaaS').exists():
            context['resource_delivery_model'] = 'SaaS'

        return context
Ejemplo n.º 26
0
    def init_resource_count_quota(self):
        self.stdout.write('Drop current nc_resource_count quotas values ...')
        customer_ct = ContentType.objects.get_for_model(models.Customer)
        project_ct = ContentType.objects.get_for_model(models.Project)
        quotas_models.Quota.objects.filter(
            name='nc_resource_count',
            content_type__in=[project_ct, customer_ct]).update(usage=0)
        self.stdout.write('... Done')

        self.stdout.write(
            'Calculating new nc_resource_count quotas values ...')
        resource_models = SupportedServices.get_resource_models().values()
        for model in resource_models:
            for resource in model.objects.all():
                resource.service_project_link.project.add_quota_usage(
                    'nc_resource_count', 1)
        self.stdout.write('... Done')
Ejemplo n.º 27
0
def connect_customer_to_shared_service_settings(sender,
                                                instance,
                                                created=False,
                                                **kwargs):
    if not created:
        return
    customer = instance

    for shared_settings in ServiceSettings.objects.filter(shared=True):
        try:
            service_model = SupportedServices.get_service_models()[
                shared_settings.type]['service']
            service_model.objects.create(customer=customer,
                                         settings=shared_settings,
                                         available_for_all=True)
        except KeyError:
            logger.warning("Unregistered service of type %s" %
                           shared_settings.type)
Ejemplo n.º 28
0
    def provision_service(self, host):
        resource_type = SupportedServices.get_name_for_model(host.scope)
        description = self.service_triggers.get(resource_type)
        if not description:
            logger.warning(
                'Zabbix IT service is not created because trigger '
                'description for resource with type %s is missing',
                resource_type)
            return
        trigger_id = self._get_trigger_id(host.backend_id, description)

        service_name = self._get_service_name(host.scope.backend_id)
        service_id, created = self.get_or_create_service(
            service_name, host.agreed_sla, trigger_id)

        host.service_id = service_id
        host.trigger_id = trigger_id
        host.save(update_fields=['service_id', 'trigger_id'])
Ejemplo n.º 29
0
def connect_shared_service_settings_to_customers(sender, instance, name,
                                                 source, target, **kwargs):
    """ Connected service settings with all customers if they were created or become shared """
    service_settings = instance
    if (target != SynchronizationStates.IN_SYNC
            or source not in (SynchronizationStates.ERRED,
                              SynchronizationStates.CREATING)
            or not service_settings.shared):
        return

    service_model = SupportedServices.get_service_models()[
        service_settings.type]['service']
    for customer in Customer.objects.all():
        if not service_model.objects.filter(
                customer=customer, settings=service_settings).exists():
            service_model.objects.create(customer=customer,
                                         settings=service_settings,
                                         name=service_settings.name,
                                         available_for_all=True)
Ejemplo n.º 30
0
def schedule_provision(previous_task_data=None,
                       url=None,
                       template_uuid=None,
                       token_key=None,
                       additional_options=None,
                       template_group_result_uuid=None):
    template = models.Template.objects.get(uuid=template_uuid)
    response_data = template.schedule_provision(url, token_key,
                                                additional_options,
                                                previous_task_data).json()
    # update templates group result if it is defined
    if template_group_result_uuid is not None:
        template_group_result = models.TemplateGroupResult.objects.get(
            uuid=template_group_result_uuid)
        resource_type = SupportedServices.get_name_for_model(
            template.resource_content_type.model_class())
        template_group_result.state_message = '%s provision has been scheduled successfully.' % resource_type
        template_group_result.save()
    return response_data