def load_configurations( self, reload_without_version_control = False ):

        d_configurations 	= {}

        l_bad_configurations	= []

        # Obtention d'un resolveur base sur le resolv_conf fouri
        self._resolver		= dns.resolver.Resolver( self._resolver_conf )
        self._resolver.query    = shared_infrastructure.catch_NoNamesservers( self._resolver.query )

        BLOCKSIZE 		= 65536

        def get_hook_server_filehash( filename ):
            hasher 		= hashlib.sha1()
            with closing( open( filename ) ) as f:
                buf = f.read( BLOCKSIZE )
                while len( buf ) > 0:
                    hasher.update( buf )
                    buf = f.read(BLOCKSIZE)
            return hasher.hexdigest()

        # Recherche des serveurs
        for server in [
                       s
                       for s
                       in os.listdir( self._root_configuration )
                       if os.path.isdir( self._root_configuration.rstrip( os.sep ) + os.sep + s )
                      ]:

            # Si le nom ne correspond pas a un nom resolvable
            # la configuration n'est pas prise en compte
            if not self._resolver.query( server, 'A' ) and not self._resolver.query( server, 'AAAA' ):
                l_bad_configurations.append( ( '%s not resolvable' % ( server ), self._root_configuration, server, ) )
                continue

            try:
                if not os.listdir( self._root_configuration.rstrip( os.sep ) + os.sep + server ):
                    l_bad_configurations.append( ( '%s no port definition' % ( server ), self._root_configuration, server, ) )
                    continue
            except:
                # En cas de suppression de la racine
                # entre le listdir dans la boucle
                # et l'usage du server dans la cronstrcuion
                # de chemin, le repertoire server
                # peut avoir disparu.
                continue

            # Recherche des ports
            for port in os.listdir( self._root_configuration.rstrip( os.sep ) + os.sep + server ):

                # Si le repertoire ne correspond pas au format d'un nom de port
                # la configuration n'est pas prise en compte
                try:
                   if not( re.match( '\d{1,5}', port ) and int( port ) <= 65535 ):
                        raise Exception()
                except:
                        l_bad_configurations.append( ( '%s unvalid port format' % ( port ), self._root_configuration, server, port ) )
                        continue

                d_configurations.setdefault(
                    server,
                    {}
                ).setdefault(
                    port,
                    dict(
                        [
                            (
                                hook_server_name
                                ,
                                {
                                    'path':
                                        hook_server_filepath
                                    ,
                                    'hash':
                                        get_hook_server_filehash( hook_server_filepath )
                                }
                            )
                            for hook_server_name, hook_server_filepath
                            in map(
                               lambda hook_server_name:
                                   (
                                       hook_server_name
                                       ,
                                       self._root_configuration.rstrip( os.sep ) 	+ 	\
                                       os.sep 						+ 	\
                                       server 						+ 	\
                                       os.sep 						+	\
                                       port						+ 	\
                                       os.sep 						+ 	\
                                       hook_server_name
                                   )
                               ,
                               sorted(
                                   self._l_hook_server_filenames
                               )
                            )
                            if (
                                True
                                if
                                   os.path.isfile( hook_server_filepath )
                                else
                                (
                                    l_bad_configurations.append( ( '%s is present but is not a file' % ( hook_server_name, ), self._root_configuration, server, port ) )
                                    if
                                       os.path.exists( hook_server_filepath )
                                    else
                                       False
                                )
                            )
                        ]
                    )
                )


        if  													\
                 reload_without_version_control 								\
             or													\
                 self.get_version_configurations( d_configurations ) <> self.current_version_configurations	\
             or													\
                 hashlib.sha1( repr( l_bad_configurations ) ).hexdigest() <> hashlib.sha1( repr( self._l_bad_configurations ) ).hexdigest():

            self._d_configurations         =       d_configurations
            self._l_bad_configurations     =       l_bad_configurations
            shared_infrastructure.cache_container_hook_server_configuration.clear()
            shared_infrastructure.cache_container_nginx_fs.clear()

            return True

        return False
    def __init__(
        self,
        agnostic_configuration,
        root_nginx_configuration,
        uid_owner,
        gid_owner,
        resolver_conf,
        mount_filename,
        unmount_filename,
        redirect_filename,
        error_status_filename,
        restart_nginx,
        ssl_configuration,
        url2entity_configuration,
        url2entity_filename,
        hook_server_configuration,
    ):

        self._agnostic_configuration	= agnostic_configuration
        self._root_nginx_configuration	= root_nginx_configuration
        self._uid_owner			= uid_owner
        self._gid_owner			= gid_owner
        self._resolver_conf		= resolver_conf
        self._resolver			= dns.resolver.Resolver( self._resolver_conf )
        self._resolver.query    	= shared_infrastructure.catch_NoNamesservers( self._resolver.query )
        self._mount_filename		= mount_filename
        self._unmount_filename		= unmount_filename
        self._redirect_filename		= redirect_filename
        self._error_status_filename	= error_status_filename
        self._restart_nginx		= restart_nginx
        self._ssl_configuration		= ssl_configuration
        self._url2entity_configuration	= url2entity_configuration
        self._url2entity_filename		= url2entity_filename
        self._hook_server_configuration	= hook_server_configuration

        self._extra_from_distrib        =                               \
            extra_from_distrib.ExtraFromDistrib(
                self._restart_nginx
            )

        self._extra_from_distrib.register_cache_to_clear(
            shared_infrastructure.cache_container_nginx_fs
        )

        self._l_bad_configurations	= []

        self._l_configurations 	= 					\
            (								\
                self._agnostic_configuration,				\
                self._url2entity_configuration,				\
                self._hook_server_configuration,			\
            )

        self._pattern_converted_conf_filenames	= \
           '^(?P<server>.*)-(?P<port>\d+)\.conf$'

        self._pattern_converted_map_filenames	= \
            '^(?P<mapping_type>' + \
            '%s|%s|%s|%s' % (
                self._mount_filename, 
                self._unmount_filename, 
                self._redirect_filename, 
                self._url2entity_filename,
            ) + ')-(?P<server>.*)-(?P<port>\d+)\.map$'

        # Getion des templates de read
        # Creation de l'nevironement des templates
        self._env				= 	\
            Environment(
                loader	= 			  	\
                    ChoiceLoader(
                        [
                            PackageLoader(
                                __name__,
                                'templates'
                            )
                            ,
                            self._hook_server_configuration
                        ]
                    )
            )

        # Gestion des interactions cross mapping
        # Les tableaux configuration vers virtuel permettent de calculer
        # les dependances engendrer par les modificatinos dans les configurations
        self._d_id_server_configuration_2_virtual	= {}
        self._d_id_port_configuration_2_virtual		= {}
        self._d_id_mapping_type_configuration_2_virtual	= {
            self._mount_filename:    [
                self._mount_filename,
                self._redirect_filename
            ],
            self._redirect_filename: [
                self._redirect_filename,
                self._mount_filename
            ],
            self._unmount_filename: [
                self._unmount_filename,
                self._mount_filename
            ],
            self._url2entity_filename: [
                self._url2entity_filename,
            ],
        }

        # la gestion cross mapping dnas le sens virtuel a configuration
        # est plus compliquee
        # Au premier niveau, elle est contextualisee
        # NGINXConfigurationFS.__ATTR_CTX__ pour le cross mapping
        # concernant l'obtention des attributs de fichiers (getattr)
        # NGINXConfigurationFS.__READ_CTX__ pour le crosss mapping
        # concernant la lecture (read)
        # Elle est ensuite categorisee par id (server, port, mapping_ype).
        # Puis les cross mappings eux-memes sont exprimes
        self._d_id_virtual_2_configuration			= {
            NGINXConfigurationFS.__ATTR_CTX__:			\
	        {
                     NGINXConfigurationFS.__ID_SERVER__:	\
                         {
                         },
                     NGINXConfigurationFS.__ID_PORT__:		\
                         {
                         },
                     NGINXConfigurationFS.__ID_MAPPING_TYPE__:	\
                         {
                             self._mount_filename:		\
                                 [
                                     self._mount_filename,
                                     self._redirect_filename,
                                     self._unmount_filename,
                                 ],
                             self._redirect_filename: 		\
                                 [
                                     self._redirect_filename,
                                     self._mount_filename
                                 ],
                             self._unmount_filename: 		\
                                 [ self._unmount_filename ],
                             self._url2entity_filename:		\
                                 [ self._url2entity_filename ],
                         },
                },
            NGINXConfigurationFS.__READ_CTX__:			\
	        {
                     NGINXConfigurationFS.__ID_SERVER__:	\
                         {
                         },
                     NGINXConfigurationFS.__ID_PORT__:		\
                         {
                         },
                     NGINXConfigurationFS.__ID_MAPPING_TYPE__:	\
                         {
                             self._mount_filename:		\
                                 [ self._mount_filename ],
                             self._redirect_filename: 		\
                                 [ self._redirect_filename ],
                             self._unmount_filename: 		\
                                 [ self._unmount_filename ],
                             self._url2entity_filename: 		\
                                 [ self._url2entity_filename ],
                         },
                },
        }

        wm 					= pyinotify.WatchManager() 
	mask 					= pyinotify.IN_MODIFY

        # Gestion du repertoire des templates
        def get_template_dir( template_name ):
            try:
               return \
                    self._env.get_template(
                        template_name
                    ).filename[ :-len( template_name ) ] 
            except:
                return None

        def add_templates_watches():
            wm.add_watch( 
                list(
                    set(
                        filter(
                            None,
                            map(
                                get_template_dir,
                                self.list_template_names
                            )
                        )
                    )
                ),
                mask, 
                rec=True,
                auto_add=True
            )

        class TemplateEventHandler( pyinotify.ProcessEvent ):

             def process_evt( o, event ):

                 if not event.dir and 				\
                    not event.pathname[ 
                            event.pathname.rfind( 
                                os.sep + 'templates' + os.sep 
                            ) + 
                            len( 
                                os.sep + 'templates' + os.sep 
                            ): ] in self.list_template_names:
                        return None

                 self._l_bad_configurations 	= []

                 self._env.cache.clear()

                 shared_infrastructure.cache_container_nginx_fs.clear()

                 try:

                     subprocess.call( self._restart_nginx, shell = True )

                 except: 

                     self.l_bad_configurations.append( ( '%s error' % ( self._restart_nginx ), ) )

                     shared_infrastructure.cache_container_agnostic_configuration.clear()

                     shared_infrastructure.cache_container_ssl_configuration.clear()

                     shared_infrastructure.cache_container_url2entity_configuration.clear()

                     shared_infrastructure.cache_container_nginx_fs.clear()

             process_IN_MODIFY	= process_evt


        self._template_notifier 				= pyinotify.ThreadedNotifier( wm, TemplateEventHandler() )

        self._extra_from_distrib.register_notifier(
            self._template_notifier
        )

        self._template_notifier.coalesce_events()

        add_templates_watches()

        self._template_notifier.start()
	
        for configuration in self._l_configurations:
            configuration.notifier.start()

        self._ssl_configuration.notifier.start()
    def load_configurations( self, reload_without_version_control = False ):

        d_configurations 	= {}

        l_bad_configurations	= []

        # Obtention d'un resolveur base sur le resolv_conf fouri
        self._resolver		= dns.resolver.Resolver( self._resolver_conf )
        self._resolver.query	= shared_infrastructure.catch_NoNamesservers( self._resolver.query )

        # Recherche des serveurs
        for server in [ 
                       s 
                       for s 
                       in os.listdir( self._root_configuration )
                       if os.path.isdir( self._root_configuration.rstrip( os.sep ) + os.sep + s )
                      ]:

            # Si le nom ne correspond pas a un nom resolvable
            # la configuration n'est pas prise en compte
	    if not self._resolver.query( server, 'A' ) and not self._resolver.query( server, 'AAAA' ):
                l_bad_configurations.append( ( '%s not resolvable' % ( server ), self._root_configuration, server, ) )
                continue

            # Si le repertoire ne contient pas de configuration
            # de port, la configuration n'est pas prise en compte
            try:
                if not os.listdir( self._root_configuration.rstrip( os.sep ) + os.sep + server ):
                    l_bad_configurations.append( ( '%s no port definition' % ( server ), self._root_configuration, server, ) )
                    continue
            except:
                    # En cas de suppression de la racine
                    # entre le listdir dans la boucle
                    # et l'usage du server dans la cronstrcuion
                    # de chemin, le repertoire server
                    # peut avoir disparu.
                    continue

            # Recherche des ports
            for port in os.listdir( self._root_configuration.rstrip( os.sep ) + os.sep + server ):

                # Si le repertoire ne correspond pas au format d'un nom de port
                # la configuration n'est pas prise en compte
                try:
                    if not( re.match( '\d{1,5}', port ) and int( port ) <= 65535 ):
                        raise Exception()
                except:
                        l_bad_configurations.append( ( '%s unvalid port format' % ( port ), self._root_configuration, server, port ) )
                        continue

                # Si aucun fichier de mapping
                # n'est present, la configuration n'est
                # pas prise en compte

                mount_filepath 		= 						\
                    self._root_configuration.rstrip( os.sep ) + os.sep + 		\
                    server + os.sep + 							\
                    port + os.sep + 							\
                    self._mount_filename

                unmount_filepath	= 						\
                    self._root_configuration.rstrip( os.sep ) + os.sep + 		\
                    server + os.sep + 							\
                    port + os.sep + 							\
                    self._unmount_filename

                redirect_filepath	= 						\
                    self._root_configuration.rstrip( os.sep ) + os.sep + 		\
                    server + os.sep + 							\
                    port + os.sep + 							\
                    self._redirect_filename


                def add_to_configuration(
                    mapping_type,
                    filepath,
                    pattern,
                    ):
                    try:
                        with closing( 
                            open( filepath )
                        ) as f:
        
                            for line in [ l.rstrip() for l in f.readlines() ]:
                                if re.match( AgnosticConfiguration._comment_pattern, line ):
                                    continue
        
                                m = re.match( pattern, line )
                                if not m:
                                    l_bad_configurations.append( 
                                        ( 
                                            'invalid format %s' % ( line ), 
                                            self._root_configuration,
                                            server, 
                                            port, 
                                            mapping_type 
                                        ) 
                                    )
                                    continue
                               
                                try:
                                    self._d_l_process_uri[ mapping_type ]( 
                                        self,
                                        m.groupdict(),
                                        filepath,
                                        line,
                                        server,
                                        port, 
                                        mapping_type,
                                        d_configurations, 
                                        l_bad_configurations, 
                                    )
                                except:
                                    import traceback
                                    traceback.print_exc()
                                    continue

                                
                    except:
                        pass

                try:
                    if \
                        not os.path.isfile( mount_filepath ) 			and	\
                        not os.path.isfile( unmount_filepath ) 			and 	\
                        not os.path.isfile( redirect_filepath ):
                       l_bad_configurations.append( 
                           ( 
                               'no %s or %s or %s file' % \
                                   ( 
                                       self._mount_filename, 
                                       self._unmount_filename, 
                                       self._redirect_filename 
                                   ), 
                               self._root_configuration,
                               server, 
                               port 
                           ) 
                       )
                       continue
                except:
                    # En cas de suppression de la racine
                    # entre le listdir dans la boucle
                    # et l'usage du server dans la cronstrcuion
                    # de chemin, le repertoire server
                    # peut avoir disparu.
                    continue

                add_to_configuration( 
                    self._mount_filename, 	
                    mount_filepath, 	
                    AgnosticConfiguration._mount_pattern, 		
                )

                add_to_configuration( 
                    self._unmount_filename, 	
                    unmount_filepath,	
                    AgnosticConfiguration._unmount_pattern, 	
                )

                add_to_configuration( 
                    self._redirect_filename, 	
                    redirect_filepath, 	
                    AgnosticConfiguration._redirect_pattern, 	
                )

        if len( d_configurations ) == 0:
            l_bad_configurations.append( ( 'no configuration available', self._root_configuration, ) )

        if  													\
                 reload_without_version_control 								\
             or													\
                 self.get_version_configurations( d_configurations ) <> self.current_version_configurations 	\
             or													\
                 hashlib.sha1( repr( l_bad_configurations ) ).hexdigest() <> hashlib.sha1( repr( self._l_bad_configurations ) ).hexdigest():

            self._d_configurations         =       d_configurations
            self._l_bad_configurations     =       l_bad_configurations
            shared_infrastructure.cache_container_agnostic_configuration.clear()
            shared_infrastructure.cache_container_nginx_fs.clear()

            #pprint.pprint( self._d_configurations )

            return True

        return False
    def load_configurations( self, reload_without_version_control = False ):

        d_configurations 	= {}

        l_bad_configurations	= []

        # Obtention d'un resolveur base sur le resolv_conf fouri
        self._resolver		= dns.resolver.Resolver( self._resolver_conf )
        self._resolver.query    = shared_infrastructure.catch_NoNamesservers( self._resolver.query )

        # Recherche des serveurs
        for server in [ 
                       s 
                       for s 
                       in os.listdir( self._root_ssl_configuration )
                       if os.path.isdir( self._root_ssl_configuration.rstrip( os.sep ) + os.sep + s )
                      ]:

            # Si le nom ne correspond pas a un nom resolvable
            # la configuration n'est pas prise en compte
            if not self._resolver.query( server, 'A' ) and not self._resolver.query( server, 'AAAA' ):
                l_bad_configurations.append( ( '%s not resolvable' % ( server ), self._root_ssl_configuration, server, ) )
                continue

            try:
                if not os.listdir( self._root_ssl_configuration.rstrip( os.sep ) + os.sep + server ):
                    l_bad_configurations.append( ( '%s no port definition' % ( server ), self._root_ssl_configuration, server, ) )
                    continue
            except:
                # En cas de suppression de la racine
                # entre le listdir dans la boucle
                # et l'usage du server dans la cronstrcuion
                # de chemin, le repertoire server
                # peut avoir disparu.
                continue

            # Recherche des ports
            for port in os.listdir( self._root_ssl_configuration.rstrip( os.sep ) + os.sep + server ):

                # Si le repertoire ne correspond pas au format d'un nom de port
                # la configuration n'est pas prise en compte
                try:
                   if not( re.match( '\d{1,5}', port ) and int( port ) <= 65535 ):
                        raise Exception()
                except:
                        l_bad_configurations.append( ( '%s unvalid port format' % ( port ), self._root_ssl_configuration, server, port ) )
                        continue

                # Les 3 fichiers de configuration doivent etre present
                # n'est present, la configuration n'est
                # pas prise en compte

                ssl_certificate_filepath	=					\
                    self._root_ssl_configuration.rstrip( os.sep ) + os.sep + 		\
                    server + os.sep + 							\
                    port + os.sep + 							\
                    self._ssl_certificate_filename

                ssl_certificate_key_filepath	= 					\
                    self._root_ssl_configuration.rstrip( os.sep ) + os.sep + 		\
                    server + os.sep + 							\
                    port + os.sep + 							\
                    self._ssl_certificate_key_filename

                try:
                    if \
                        not ( 								\
                             os.path.isfile( ssl_certificate_filepath ) 	and	\
                             os.path.isfile( ssl_certificate_key_filepath )
                       ):
                       l_bad_configurations.append( 
                           ( 
                               '%s AND %s must be present' % \
                                   ( 
                                       self._ssl_certificate_filename, 
                                       self._ssl_certificate_key_filename, 
                                   ), 
                               self._root_ssl_configuration, 
                               server, 
                               port 
                           ) 
                       )
                       continue
                except:
                    # En cas de suppression de la racine
                    # entre le listdir dans la boucle
                    # et l'usage du server dans la cronstrcuion
                    # de chemin, le repertoire server
                    # peut avoir disparu.
                    continue

                st_certificate_key_filepath 	= os.stat( ssl_certificate_key_filepath )

                if \
                    bool( st_certificate_key_filepath.st_mode & stat.S_IROTH ) or	\
                    bool( st_certificate_key_filepath.st_mode & stat.S_IWOTH ) or	\
                    bool( st_certificate_key_filepath.st_mode & stat.S_IXOTH ) or	\
                    not bool( st_certificate_key_filepath.st_mode & stat.S_IRGRP )	\
                   :
                   l_bad_configurations.append( 
                       ( 
                           '%s must be -r--r-----' % \
                               ( 
                                   self._ssl_certificate_key_filename, 
                               ), 
                           self._root_ssl_configuration, 
                           server, 
                           port 
                       ) 
                   )
                   continue

                digest_ssl_certificate 		= None
                digest_ssl_certificate_key 	= None

                try:
                    with closing( open( ssl_certificate_filepath ) ) as ssl_certificates:
                        digest_ssl_certificate	= 		\
                            load_certificate(
                                FILETYPE_PEM, 
                                ssl_certificates.read()
                            ).digest( 'sha1' )

                except Exception, e:
                   l_bad_configurations.append(
                       (
                           'ssl problem with %s (%s)' % \
                               (
                                   self._ssl_certificate_filename,
                                   repr( e )
                               ),
                           self._root_ssl_configuration,
                           server,
                           port
                       )
                   )
                   continue

                try:
                    with closing( open( ssl_certificate_key_filepath ) ) as ssl_certificate_key:
                        digest_ssl_certificate_key	= 		\
                            hashlib.sha1(
                                dump_privatekey(
                                    FILETYPE_PEM,
                                    load_privatekey(
                                        FILETYPE_PEM, 
                                        ssl_certificate_key.read()
                                    )
                                )
                            ).hexdigest()

                except Exception, e:
                   l_bad_configurations.append(
                       (
                           'problem with %s (%s)' % \
                               (
                                   self._ssl_certificate_key_filename,
                                   repr( e )
                               ),
                           self._root_ssl_configuration,
                           server,
                           port
                       )
                   )
                   continue

                d_configurations.setdefault(
                    server,
                    {}
                ).setdefault(
                    port,
                    {
                         'ssl_certificate_digest'		: digest_ssl_certificate,
                         'ssl_certificate_key_digest'		: digest_ssl_certificate_key,
                         'ssl_certificate_filepath'		: ssl_certificate_filepath,
                         'ssl_certificate_key_filepath'		: ssl_certificate_key_filepath,
                    }
                )