Ejemplo n.º 1
0
#
# License:
#  GPL-2: http://www.gnu.org/licenses/gpl-2.0.html
#
# See the LICENSE file in the project's top-level directory for details.

from clacks.agent.objects.filter import ElementFilter
from clacks.agent.objects.backend.registry import ObjectBackendRegistry
from clacks.common.error import ClacksErrorHandler as C
from clacks.common.utils import N_


# Register the errors handled  by us
C.register_codes(dict(
    PARAMETER_NOT_NUMERIC=N_("Parameter for '%(target)s' have to be numeric"),
    BACKEND_TOO_MANY=N_("Too many backends for %(target)s specified"),
    POSIX_ID_POOL_EMPTY=N_("ID pool for attribute %(target)s is empty [> %(max)s]")
))


class PosixException(Exception):
    pass


class GenerateIDs(ElementFilter):
    """
    Generate gid/uidNumbers on demand
    """
    def __init__(self, obj):
        super(GenerateIDs, self).__init__(obj)
Ejemplo n.º 2
0
# Copyright:
#  (C) 2010-2012 GONICUS GmbH, Germany, http://www.gonicus.de
#
# License:
#  GPL-2: http://www.gnu.org/licenses/gpl-2.0.html
#
# See the LICENSE file in the project's top-level directory for details.

__import__('pkg_resources').declare_namespace(__name__)
import pkg_resources
from clacks.common.utils import N_
from clacks.common.error import ClacksErrorHandler as C


C.register_codes(dict(
    COMPARATOR_NO_INSTANCE=N_("No comparator instance for '%(comparator)s' found")
    ))


def get_comparator(name):
    for entry in pkg_resources.iter_entry_points("object.comparator"):

        module = entry.load()
        if module.__name__ == name:
            return module

    raise KeyError(C.make_error("COMPARATOR_NO_INSTANCE", comparator=name))


class ElementComparator(object):
Ejemplo n.º 3
0
#  (C) 2010-2012 GONICUS GmbH, Germany, http://www.gonicus.de
#
# License:
#  GPL-2: http://www.gnu.org/licenses/gpl-2.0.html
#
# See the LICENSE file in the project's top-level directory for details.

__import__('pkg_resources').declare_namespace(__name__)
import pkg_resources
from clacks.common.utils import N_
from clacks.common.error import ClacksErrorHandler as C


# Register the errors handled  by us
C.register_codes(dict(
    OPERATOR_NO_INSTANCE=N_("No operator instance for '%(operator)s' found")
    ))


def get_operator(name):
    for entry in pkg_resources.iter_entry_points("object.operator"):
        module = entry.load()
        if module.__name__ == name:
            return module

    raise KeyError(C.make_error("OPERATOR_NO_INSTANCE", operator=name))


class ElementOperator(object):

    def __init(self, obj):
Ejemplo n.º 4
0
# Copyright:
#  (C) 2010-2012 GONICUS GmbH, Germany, http://www.gonicus.de
#
# License:
#  GPL-2: http://www.gnu.org/licenses/gpl-2.0.html
#
# See the LICENSE file in the project's top-level directory for details.

import pkg_resources
from clacks.common.utils import N_
from clacks.common.error import ClacksErrorHandler as C


# Register the errors handled  by us
C.register_codes(dict(
    BACKEND_NOT_FOUND=N_("Backend '%(topic)s' not found"),
    ))


class ObjectBackendRegistry(object):
    instance = None
    backends = {}
    uuidAttr = "entryUUID"

    def __init__(self):
        # Load available backends
        for entry in pkg_resources.iter_entry_points("object.backend"):
            clazz = entry.load()
            ObjectBackendRegistry.backends[clazz.__name__] = clazz()

    def dn2uuid(self, backend, dn):
Ejemplo n.º 5
0
__import__('pkg_resources').declare_namespace(__name__)
import ldap
from itertools import permutations
from clacks.common.utils import N_
from clacks.common.error import ClacksErrorHandler as C
from clacks.agent.exceptions import DNGeneratorError


# Register the errors handled  by us
C.register_codes(dict(
    GENERATOR_RDN_ATTRIBUTE_MISSING=N_("Attribute '%(topic)s needed to generate a RDN is missing"),
    RDN_NOT_SPECIFIED=N_("No 'RDN' backend parameter specified"),
    NO_UNIQUE_DN=N_("Cannot generate a unique DN in '%(base)s' using a combination of %(rdns)s"),
    TARGET_EXISTS=N_("Target DN '%(target)s' already exists"),
    DB_CONFIG_MISSING=N_("No database configuration found for '%(target)s'"),
    BACKEND_ATTRIBUTE_CONFIG_MISSING=N_("Attribute '%s' uses the ObjectHandler backend but there is no config for it"),
    SOURCE_OBJECT_NOT_FOUND=N_("Cannot find source object '%(object)s'"),
    NO_UNIQUE_ENTRY=N_("No unique '%(object)s' object which matches '%(attribute)s == %(value)s'"),
    ID_GENERATION_FAILED=N_("Failed to generate a unique ID"),
    ENTRY_UUID_NOT_FOUND=N_("Entry '%(uuid)s' not found"),
    ENTRY_UUID_NOT_UNIQUE=N_("Entry '%(uuid)s' not unique"),
    ))


class ObjectBackend(object):

    def dn2uuid(self, dn):
        """
        Convert DN to uuid.
        """
        raise NotImplementedError(C.make_error("NOT_IMPLEMENTED", dn, method="dn2uuid"))
Ejemplo n.º 6
0
------
"""
import ldapurl
import ldap.sasl
import types
import logging
from contextlib import contextmanager
from clacks.common import Environment
from clacks.common.utils import N_
from clacks.common.error import ClacksErrorHandler as C
from clacks.agent.exceptions import LDAPException


C.register_codes(dict(
    NO_SASL_SUPPORT=N_("No SASL support in the installed python-ldap detected"),
    LDAP_NO_CONNECTIONS=N_("No LDAP connection available"),
    ))


class LDAPHandler(object):
    """
    The LDAPHandler provides a connection pool with automatically reconnecting
    LDAP connections and is accessible thru the
    :meth:`clacks.agent.ldap_utils.LDAPHandler.get_instance` method.

    Example::

        >>> from clacks.agent.ldap_utils import LDAPHandler
        >>> from ldap.filter import filter_format
        >>> lh = LDAPHandler.get_instance()
        >>> uuid = 'you-will-not-find-anything'
Ejemplo n.º 7
0
# Copyright:
#  (C) 2010-2012 GONICUS GmbH, Germany, http://www.gonicus.de
#
# License:
#  GPL-2: http://www.gnu.org/licenses/gpl-2.0.html
#
# See the LICENSE file in the project's top-level directory for details.

__import__('pkg_resources').declare_namespace(__name__)
import pkg_resources
from clacks.common.utils import N_
from clacks.common.error import ClacksErrorHandler as C


C.register_codes(dict(
    FILTER_NO_INSTANCE=N_("No filter instance for '%(filter)s' found")
    ))


def get_filter(name):
    for entry in pkg_resources.iter_entry_points("object.filter"):
        module = entry.load()
        if module.__name__ == name:
            return module

    raise KeyError(C.make_error("FILTER_NO_INSTANCE", name))


class ElementFilter(object):

    def __init__(self, obj):
Ejemplo n.º 8
0
# Copyright:
#  (C) 2010-2012 GONICUS GmbH, Germany, http://www.gonicus.de
#
# License:
#  GPL-2: http://www.gnu.org/licenses/gpl-2.0.html
#
# See the LICENSE file in the project's top-level directory for details.

import smbpasswd #@UnresolvedImport
from clacks.agent.objects.filter import ElementFilter
from clacks.common.error import ClacksErrorHandler as C
from clacks.common.utils import N_


# Register the errors handled  by us
C.register_codes(dict(
    TYPE_UNKNOWN=N_("Filter '%(target)s' does not support input type '%(type)s'")))


class SambaHash(ElementFilter):
    """
    An object filter which generates samba NT/LM Password hashes for the incoming value.
    """
    def __init__(self, obj):
        super(SambaHash, self).__init__(obj)

    def process(self, obj, key, valDict):
        if len(valDict[key]['value']) and type(valDict[key]['value'][0]) in [str, unicode]:
            lm, nt = smbpasswd.hash(valDict[key]['value'][0])
            valDict['sambaNTPassword']['value'] = [nt]
            valDict['sambaLMPassword']['value'] = [lm]
        else:
Ejemplo n.º 9
0
import logging
import tornado.wsgi
import tornado.web
from tornado.ioloop import IOLoop
from tornado.httpserver import HTTPServer
from zope.interface import implements
from webob import exc #@UnresolvedImport
from clacks.common import Environment
from clacks.common.handler import IInterfaceHandler
from clacks.common.utils import N_
from clacks.common.error import ClacksErrorHandler as C
from clacks.agent.exceptions import HTTPException


C.register_codes(dict(
    HTTP_PATH_ALREADY_REGISTERED=N_("'%(path)s' has already been registered")
    ))


class HTTPDispatcher(object):
    """
    The *HTTPDispatcher* can be used to register WSGI applications
    to a given path. It will inspect the path of an incoming request
    and decides which registered application it gets.

    Analyzing the path can be configured to detect a *subtree* match
    or an *exact* match. If you need subtree matches, just add the
    class variable ``http_subtree`` to the WSGI class and set it to
    *True*.
    """
Ejemplo n.º 10
0
STATUS_OCCUPIED = "B"
STATUS_LOCKED = "L"
STATUS_BOOTING = "b"
STATUS_NEEDS_INITIAL_CONFIG = "P"
STATUS_NEEDS_REMOVE_CONFIG = "R"
STATUS_NEEDS_CONFIG = "c"
STATUS_NEEDS_INSTALL = "N"


# Register the errors handled  by us
C.register_codes(dict(
    DEVICE_EXISTS=N_("Device with hardware address '%(topic)s' already exists"),
    USER_NOT_UNIQUE=N_("User '%(topic)s' is not unique"),
    CLIENT_NOT_FOUND=N_("Client '%(topic)s' not found"),
    CLIENT_OFFLINE=N_("Client '%(topic)s' is offline"),
    CLIENT_METHOD_NOT_FOUND=N_("Client '%(topic)s' has no method %(method)s"),
    CLIENT_DATA_INVALID=N_("Invalid data '%(entry)s:%(data)s' for client '%(target)s provided'"),
    CLIENT_TYPE_INVALID=N_("Device type '%(type)s' for client '%(target)s' is invalid [terminal, workstation, server, sipphone, switch, router, printer, scanner]"),
    CLIENT_OWNER_NOT_FOUND=N_("Owner '%(owner)s' for client '%(target)s' not found"),
    CLIENT_UUID_INVALID=N_("Invalid client UUID '%(target)s'"),
    CLIENT_STATUS_INVALID=N_("Invalid status '%(status)s' for client '%(target)s'")))


class GOtoException(Exception):
    pass


class ClientService(Plugin):
    """
    Plugin to register clients and expose their functionality
    to the users.
Ejemplo n.º 11
0
from clacks.common.components import Command
from clacks.common.components import Plugin
from clacks.common.utils import N_
from clacks.common.components import PluginRegistry
from clacks.agent.objects import ObjectProxy
from clacks.agent.objects.factory import ObjectFactory
import clacks.agent.objects.renderer
from clacks.common.handler import IInterfaceHandler
from json import loads, dumps
from clacks.common.error import ClacksErrorHandler as C


# Register the errors handled  by us
C.register_codes(dict(
    INVALID_SEARCH_SCOPE=N_("Invalid scope '%(scope)s' [SUB, BASE, ONE, CHILDREN]"),
    INVALID_SEARCH_DATE=N_("Invalid date specification '%(date)s' [hour, day, week, month, year, all]"),
    UNKNOWN_USER=N_("Unknown user '%(target)s'"),
    BACKEND_PARAMETER_MISSING=N_("Backend parameter for '%(extension)s.%(attribute)s' is missing")))


class GOsaException(Exception):
    pass


class GuiMethods(Plugin):
    """
    Key for configuration section **gosa**

    +------------------+------------+-------------------------------------------------------------+
    + Key              | Format     +  Description                                                |
    +==================+============+=============================================================+
Ejemplo n.º 12
0
#  GPL-2: http://www.gnu.org/licenses/gpl-2.0.html
#
# See the LICENSE file in the project's top-level directory for details.

import re
from clacks.common.utils import N_
from clacks.common import Environment
from clacks.agent.objects.filter import ElementFilter
from clacks.common.components import PluginRegistry
from clacks.agent.objects.comparator import ElementComparator
from clacks.common.error import ClacksErrorHandler as C


# Register the errors handled  by us
C.register_codes(dict(
    SAMBA_DOMAIN_WITHOUT_SID=N_("Domain %(target)s has no SID"),
    SAMBA_NO_SID_TYPE=N_("Invalid type '%(type)s' for SID generator [user, group]")
))


class SambaException(Exception):
    pass


class CheckSambaSIDList(ElementComparator):
    """
    Checks whether the given sambaSIDList can be saved or if it
    will produce recursions.
    """
    def __init__(self, obj):
        super(CheckSambaSIDList, self).__init__()
Ejemplo n.º 13
0
from qpid.messaging.message import Disposition
from qpid.messaging.constants import RELEASED
from qpid.messaging.exceptions import NotFound
from clacks.common.gjson import loads, dumps
from clacks.common.components.jsonrpc_utils import ServiceRequestNotTranslatable, BadServiceRequest
from clacks.common.handler import IInterfaceHandler
from clacks.common.components import PluginRegistry, AMQPWorker, ZeroconfService
from clacks.common.utils import parseURL, repr2json, N_
from clacks.common import Environment
from clacks.common.error import ClacksErrorHandler as C
from avahi import dict_to_txt_array


# Register the errors handled  by us
C.register_codes(dict(
    AMQP_MESSAGE_WITHOUT_UID=N_("Incoming message has no user_id field"),
    AMQP_BAD_PARAMETERS=N_("Bad parameters - list or dict expected")
    ))


class AMQPService(object):
    """
    Class to serve all available queues and commands to the AMQP broker. It
    makes use of a couple of configuration flags provided by the clacks
    configurations file ``[amqp]`` section:

    ============== =============
    Key            Description
    ============== =============
    url            AMQP URL to connect to the broker
    id             User name to connect with
    key            Password to connect with
Ejemplo n.º 14
0
from clacks.common.gjson import loads, dumps
from webob import exc, Request, Response #@UnresolvedImport
from paste.auth.cookie import AuthCookieHandler #@UnresolvedImport
from clacks.common.utils import f_print, N_
from clacks.common.error import ClacksErrorHandler as C
from clacks.common.handler import IInterfaceHandler
from clacks.common import Environment
from clacks.common.components import PluginRegistry, ZeroconfService, JSONRPCException
from clacks.agent import __version__ as VERSION
from avahi import dict_to_txt_array


# Register the errors handled  by us
C.register_codes(dict(
    INVALID_JSON=N_("Invalid JSON string '%(data)s'"),
    JSON_MISSING_PARAMETER=N_("Parameter missing in JSON body"),
    PARAMETER_LIST_OR_DICT=N_("Parameter must be list or dictionary"),
    REGISTRY_NOT_READY=N_("Registry is not ready")
    ))


class JSONRPCService(object):
    """
    This is the JSONRPC clacks agent plugin which is registering an
    instance of :class:`clacks.agent.jsonrpc_service.JsonRpcApp` into the
    :class:`clacks.agent.httpd.HTTPService`.

    It is configured thru the ``[jsonrpc]`` section of your clacks
    configuration:

    =============== ============
    Key             Description
Ejemplo n.º 15
0
from clacks.common.utils import N_
from zope.interface import implements
from clacks.common.handler import IInterfaceHandler
from clacks.agent.objects.proxy import ObjectProxy
from clacks.common.components import PluginRegistry
from clacks.common import Environment
from clacks.agent.exceptions import ACLException
from clacks.common.error import ClacksErrorHandler as C


# Register the errors handled  by us
C.register_codes(
    dict(
        PASSWORD_METHOD_UNKNOWN=N_("Cannot detect password method"),
        PASSWORD_UNKNOWN_HASH=N_("No password method to generate hash of type '%(type)s' available"),
        PASSWORD_INVALID_HASH=N_("Invalid hash type for password method '%(method)s'"),
        PASSWORD_NO_ATTRIBUTE=N_("Object has no 'userPassword' attribute"),
        PASSWORD_NOT_AVAILABLE=N_("No password to lock."),
    )
)


class PasswordException(Exception):
    pass


class PasswordManager(Plugin):
    """
    Manager password changes
    """
Ejemplo n.º 16
0
try:
        from cStringIO import StringIO
except ImportError:
        from StringIO import StringIO


# Register the errors handled  by us
C.register_codes(dict(
    OBJECT_UNKNOWN_TYPE=N_("Unknown object type '%(type)s'"),
    OBJECT_EXTENSION_NOT_ALLOWED=N_("Extension '%(extension)s' not allowed"),
    OBJECT_EXTENSION_DEFINED=N_("Extension '%(extension)s' already there"),
    OBJECT_EXTENSION_DEPENDS=N_("Extension '%(extension)s' depends on '%(missing)s'"),
    PERMISSION_EXTEND=N_("No permission to extend %(target)s with %(extension)s"),
    OBJECT_NO_SUCH_EXTENSION=N_("Extension '%(extension)s' already retracted"),
    OBJECT_EXTENSION_IN_USE=N_("Extension '%(extension)s' is required by '%(origin)s'"),
    PERMISSION_RETRACT=N_("No permission to retract '%(extension)s' from '%(target)s'"),
    PERMISSION_MOVE=N_("No permission to move '%(source)s' to '%(target)s'"),
    OBJECT_HAS_CHILDREN=N_("Object '%(target)s' has children"),
    PERMISSION_REMOVE=N_("No permission to remove '%(target)s'"),
    PERMISSION_CREATE=N_("No permission to create '%(target)s'"),
    PERMISSION_ACCESS=N_("No permission to access '%(topic)s' on '%(target)s'"),
    OBJECT_UUID_MISMATCH=N_("UUID of base (%(b_uuid)s) and extension (%(e_uuid)s) differ")
    ))


class ObjectProxy(object):
    _no_pickle_ = True
    dn = None
    uuid = None
    __env = None
    __log = None
Ejemplo n.º 17
0
import datetime
from types import MethodType
from zope.interface import implements
from clacks.common.utils import N_
from clacks.common import Environment
from clacks.common.error import ClacksErrorHandler as C
from clacks.common.handler import IInterfaceHandler
from clacks.common.components import Command, PluginRegistry, ObjectRegistry, AMQPServiceProxy, Plugin
from clacks.agent.objects import ObjectProxy


# Register the errors handled  by us
C.register_codes(dict(
    REFERENCE_NOT_FOUND=N_("Reference '%(ref)s' not found"),
    PROPERTY_NOT_FOUND=N_("Property '%(property)s' not found"),
    METHOD_NOT_FOUND=N_("Method '%(method)s' not found"),
    OBJECT_LOCKED=N_("Object '%(object)s' has been locked by '%(user)s' on %(when)s"),
    OID_NOT_FOUND=N_("Object OID '%(oid)s' not found"),
    NOT_OBJECT_OWNER=N_("Caller does not own the referenced object")
    ))


class JSONRPCObjectMapper(Plugin):
    """
    The *JSONRPCObjectMapper* is a clacks agent plugin that implements a stack
    which can handle object instances. These can be passed via JSONRPC using
    the *__jsonclass__* helper attribute and allows remote proxies to emulate
    the object on the stack. The stack can hold objects that have been
    retrieved by their *OID* using the :class:`clacks.common.components.objects.ObjectRegistry`.

    Example::
Ejemplo n.º 18
0
from clacks.common import Environment
from clacks.common.utils import N_
from clacks.common.event import EventMaker
from clacks.common.handler import IInterfaceHandler
from clacks.common.components import Command, Plugin, PluginRegistry
from clacks.common.components.amqp import EventConsumer
from clacks.common.error import ClacksErrorHandler as C
from clacks.agent.objects import ObjectFactory, ObjectProxy, ObjectChanged
from clacks.agent.exceptions import ProxyException, ObjectException, FilterException, IndexException
from clacks.agent.lock import GlobalLock


# Register the errors handled  by us
C.register_codes(dict(
    OBJECT_EXISTS=N_("Object with UUID %(uuid)s already exists"),
    OBJECT_NOT_FOUND=N_("Cannot find object %(id)s"),
    INDEXING=N_("index rebuild in progress - try again later")
))


class IndexScanFinished():
    pass


class ObjectIndex(Plugin):
    """
    The *ObjectIndex* keeps track of objects and their indexed attributes. It
    is the search engine that allows quick querries on the data set with
    paged results and wildcards.
    """
    implements(IInterfaceHandler)
Ejemplo n.º 19
0
# License:
#  GPL-2: http://www.gnu.org/licenses/gpl-2.0.html
#
# See the LICENSE file in the project's top-level directory for details.

import inspect
from clacks.common.utils import N_
from clacks.common.error import ClacksErrorHandler as C
from clacks.agent.exceptions import ConversationNotSupported
__import__('pkg_resources').declare_namespace(__name__)


# Register the errors handled  by us
C.register_codes(dict(
    TYPE_NO_CHECK=N_("Cannot check value of type %(type)s"),
    TYPE_NO_MATCH=N_("Cannot match value of type %(type)s"),
    TYPE_NO_CONVERT=N_("Cannot convert from '%(source)s' type to '%(target)s' type"),
    ))


class AttributeType(object):

    __alias__ = ""

    def _cnv_topic(self):
        fname = inspect.stack()[1][3]
        if fname[:12:] == "_convert_to_":
            return self.__alias__.lower(), fname[12:].replace("_", " ")
        else:
            return self.__alias__.lower(), fname[14:].replace("_", " ")
Ejemplo n.º 20
0
#  GPL-2: http://www.gnu.org/licenses/gpl-2.0.html
#
# See the LICENSE file in the project's top-level directory for details.

import Image
import ImageOps #@UnresolvedImport
from bson.binary import Binary
from clacks.common import Environment
from clacks.agent.objects.filter import ElementFilter
from clacks.agent.exceptions import ElementFilterException
from clacks.common.error import ClacksErrorHandler as C
from clacks.common.utils import N_


# Register the errors handled  by us
C.register_codes(dict(
    USER_IMAGE_SIZE_MISSING=N_("Image sizes not specified")))


try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO


class ImageProcessor(ElementFilter):
    """
    Generate a couple of pre-sized images and place them in the cache.
    """
    def __init__(self, obj):
        super(ImageProcessor, self).__init__(obj)
Ejemplo n.º 21
0
import time
import datetime
from itertools import permutations
from logging import getLogger
from clacks.common import Environment
from clacks.common.utils import is_uuid, N_
from clacks.common.components.jsonrpc_utils import Binary
from clacks.agent.ldap_utils import LDAPHandler
from clacks.common.error import ClacksErrorHandler as C
from clacks.agent.objects.backend import ObjectBackend
from clacks.agent.exceptions import EntryNotFound, RDNNotSpecified, DNGeneratorError


# Register the errors handled  by us
C.register_codes(dict(
    NO_POOL_ID=N_("No ID pool found"),
    MULTIPLE_ID_POOLS=N_("Multiple ID pools found")
    ))


class LDAP(ObjectBackend):

    def __init__(self):
        # Load LDAP handler class
        self.env = Environment.getInstance()
        self.log = getLogger(__name__)

        self.lh = LDAPHandler.get_instance()
        self.con = self.lh.get_connection()
        self.uuid_entry = self.env.config.get("backend-ldap.uuid-attribute", "entryUUID")
        self.create_ts_entry = self.env.config.get("backend-ldap.create-attribute", "createTimestamp")
        self.modify_ts_entry = self.env.config.get("backend-ldap.modify-attribute", "modifyTimestamp")
Ejemplo n.º 22
0
import logging
from zope.interface import implements
from clacks.common import Environment
from clacks.common.utils import xml2dict
from clacks.common.components import Plugin
from clacks.common.handler import IInterfaceHandler
from clacks.common.components.amqp import EventConsumer
from clacks.common.components.registry import PluginRegistry
from clacks.common.error import ClacksErrorHandler as C
from clacks.common.utils import N_


# Register the errors handled  by us
C.register_codes(dict(
        INVENTORY_CLIENT_MISMATCH=N_("No client UUID for hardware UUID '%(target)s' found"),
        INVENTORY_CHECKSUM_MISMATCH=N_("No hardware checksum found for client %(target)s"),
        INVENTORY_DATA_INVALID=N_("Inventory data invalid")))


class InventoryException(Exception):
    pass


class InventoryConsumer(Plugin):
    """
    Consumer for inventory events emitted from clients.
    """
    implements(IInterfaceHandler)

    # Leave this in core as long we've no @Command
    _target_ = 'core'