# # 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)
# 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):
# (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):
# 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):
__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"))
------ """ 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'
# 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):
# 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:
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*. """
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.
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 | +==================+============+=============================================================+
# 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__()
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
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
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 """
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
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::
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)
# 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("_", " ")
# 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)
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")
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'