From 047f95f0ffe6985446710edb9b6ba7467811ff60 Mon Sep 17 00:00:00 2001
From: petjere <none@none>
Date: Tue, 21 Jun 2022 07:38:14 +0200
Subject: [PATCH] Adding any untracked (non-dirty) files before git migration
 lk:31512102896748

---
 bin/leankit_mindmap.py              | 163 ++++++
 bin/redmine_create_repo.py          | 104 ++++
 bin/redmine_create_sc_projects.py   | 760 ++++++++++++++++++++++++++++
 bin/redmine_fetch_changeset.py      |  94 ++++
 bin/redmine_issue                   | 226 +++++++++
 bin/redmine_leankit_create_issue    |  32 +-
 bin/sid_user.py                     | 170 +++++--
 bin/synchronize_home_Users.pl       | 422 +++++++++++++++
 bin/synchronize_redmine_projects.py | 760 ++++++++++++++++++++++++++++
 bin/synchronize_redmine_users.py    |  80 +++
 10 files changed, 2768 insertions(+), 43 deletions(-)
 create mode 100755 bin/leankit_mindmap.py
 create mode 100755 bin/redmine_create_repo.py
 create mode 100755 bin/redmine_create_sc_projects.py
 create mode 100755 bin/redmine_fetch_changeset.py
 create mode 100755 bin/redmine_issue
 create mode 100755 bin/synchronize_home_Users.pl
 create mode 100755 bin/synchronize_redmine_projects.py
 create mode 100755 bin/synchronize_redmine_users.py

diff --git a/bin/leankit_mindmap.py b/bin/leankit_mindmap.py
new file mode 100755
index 0000000..a95d407
--- /dev/null
+++ b/bin/leankit_mindmap.py
@@ -0,0 +1,163 @@
+
+#!/opt/gvenv/venv_leankit/bin/python3
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from __future__ import absolute_import, print_function
+
+import os
+import sys
+
+import configparser as ConfigParser
+import logging
+import argparse
+import inspect
+import traceback
+import shlex
+import re
+from subprocess import check_output, STDOUT, CalledProcessError
+from json import dumps as json_dumps
+
+hostname = os.uname()[1]
+whoami = sys._getframe().f_code.co_name
+script = os.path.basename(__file__).split(".")[0]
+
+for pylib in list(sys.path):
+    if '/usr/local/lib' in pylib:
+        sys.path.remove(pylib)
+        continue
+    elif '/export/home/snet/.local' in pylib:
+        sys.path.remove(pylib)
+        continue
+
+''' BASE CONFIG '''
+global_iniFile = '/opt/etc/ini/global.ini'
+config_global = ConfigParser.RawConfigParser()
+config_global.optionxform(str())
+config_global.optionxform = str
+config_global.read(global_iniFile)
+sys.path.append(config_global.get('APPLICATION', 'PYTHON-LIBRARY'))
+
+import snet.sloggly
+
+sys.path.append('/opt/auth/')
+import library.leankit as leankit
+
+try:
+    logger = snet.sloggly.setup_custom_logger(script, logging.INFO)
+except Exception as e:
+    print("\n=======\n")
+    title = "Something went wrong. Please inform SS team."
+    msg = "Error initializing the snet logger: " + str(e) + " :: " + traceback.format_exc(5)
+    print(msg)
+    whoami = sys._getframe().f_code.co_name
+    messages = [hostname, script, title, whoami, msg]
+    traceback.print_exc()
+    sys.exit(1)
+
+
+def obj_dump(obj):
+    '''
+      Object dumper
+    '''
+    for attr in dir(obj):
+        if '_' in attr:
+            continue
+        try:
+            print("obj.%s = %s" % (attr, str(getattr(obj, attr))))
+        except:  # noqa: E722
+            print("obj.%s = %s" % (attr, getattr(obj, attr)))
+
+    for name, data in inspect.getmembers(obj):
+        if inspect.isclass(data):
+            print('name:%s' % (name))
+            print(data)
+
+
+def obj_dump_r(obj, level=0, deepth=2):
+    '''
+       Recursive Object dumper
+    '''
+    for attr in dir(obj):
+        if '_' in attr:
+            continue
+        try:
+            msg = 2 * level * ' '
+            msg += ("obj.%s = %s" % (attr, str(getattr(obj, attr))))
+            print(msg)
+        except:  # noqa: E722
+            msg = 2 * level * ' '
+            msg += ("obj.%s = %s" % (attr, getattr(obj, attr)))
+            print(msg)
+
+        if level >= deepth:
+            continue
+
+        try:
+            obj_dump_r(getattr(obj, attr), level=level + 1)
+        except:  # noqa: E722
+            msg = 2 * level * ' '
+            msg = 2 * level * ' '
+            msg += "Dump is stinking... crashed."
+            print(msg)
+
+
+if 'http_proxy' in os.environ:
+    del os.environ['http_proxy']
+if 'https_proxy' in os.environ:
+    del os.environ['https_proxy']
+
+CA_bundle = '/usr/local/share/ca-certificates/snetroot/SNetRootCA_device_bundle.pem'
+CA_bundle = '/etc/ssl/certs/ca-certificates.crt'
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--leankit-board', type=str, required=False,
+                    help='The leankit board name for the card creation', dest='leankit_board')
+parser.add_argument('--leankit-board-id', type=int, required=False,
+                    help='The leankit board id for the card creation', dest='leankit_board_id')
+args = parser.parse_args()
+
+# leankit validation:
+if args.leankit_board is None and args.leankit_board_id is None:
+    logger.error("leankit_board or leankit_board_id is not provided.")
+    logger.error("This is incompatible.")
+    print(parser.format_help())
+    sys.exit(1)
+
+leankit_board_id = None
+
+if args.leankit_board_id is not None:
+    leankit_board_id = args.leankit_board_id
+
+elif args.leankit_board is not None:
+    leankit_res = leankit.get_board(args.leankit_board)
+    # print(leankit_res)
+    '''
+        {'pageMeta': {'totalRecords': 2, 'offset': 0, 'limit': 100, 'startRow': 1, 'endRow': 2}, 'boards': [{'id': '31512088856393', 'title': 'DEV', 'description': '', 'boardRoleId': 4, 'isWelcome': False, 'boardRole': 'boardAdministrator', 'level': {'id': '31512085971730', 'depth': 3, 'maxDepth': 3, 'label': 'Team', 'color': '#ff841f'}}, {'id': '31512088544453', 'title': 'DEV-NMS3-phasein', 'description': '', 'boardRoleId': 4, 'isWelcome': False, 'boardRole': 'boardAdministrator'}]}
+    '''
+    if leankit_res is None:
+        logger.error("Leankit board '%s': id is not found. Check the board name parameter." % args.leankit_board)
+        sys.exit(1)
+
+    leankit_board_id = leankit_res['id']
+
+# check lane
+leankit_res = leankit.get_board_detail(leankit_board_id)
+# print(json_dumps(leankit_res, sort_keys=True, indent=4))
+
+leankit_lanes = dict()
+for ll in leankit_res['lanes']:
+    leankit_lanes[ll['id']] = ll['name']
+
+# Get Users
+leankit_users = dict()
+for ll in leankit_res['users']:
+    leankit_users[ll['id']] = ll['fullName']
+
+# Get board contents
+leankit_cards = dict()
+# leankit_res = leankit.get_board_detail(leankit_board_id)
+# limit 500 is max.
+leankit_res = leankit.get_cards(board_id=leankit_board_id, limit=500, offset=0)
+print(json_dumps(leankit_res, sort_keys=True, indent=4))
+# print(leankit_res)
diff --git a/bin/redmine_create_repo.py b/bin/redmine_create_repo.py
new file mode 100755
index 0000000..28570c1
--- /dev/null
+++ b/bin/redmine_create_repo.py
@@ -0,0 +1,104 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from __future__ import absolute_import, print_function
+
+import os
+import sys
+
+import configparser as ConfigParser
+import pprint
+import inspect
+import traceback
+import shlex
+import re
+import requests
+import time
+from subprocess import check_output, STDOUT, CalledProcessError
+
+pp = pprint.PrettyPrinter(indent=4)
+
+PROGNAME = os.path.basename(sys.argv[0]).split(".")[0]
+script = os.path.basename(__file__).split(".")[0]
+
+global_iniFile = '/opt/etc/ini/global.ini'
+config_global = ConfigParser.RawConfigParser()
+config_global.optionxform(str())
+config_global.optionxform = str
+config_global.read(global_iniFile)
+sys.path.append(config_global.get('APPLICATION', 'PYTHON-LIBRARY'))
+
+from redminelib import Redmine
+
+if 'http_proxy' in os.environ:
+    del os.environ['http_proxy']
+if 'https_proxy' in os.environ:
+    del os.environ['https_proxy']
+
+# find /opt/SNet/scm -path '*/.hg' -prune -o -type d -path '*/.hg' | grep -v '^.hg$' | sed 's/\/\.hg$//' | xargs -n1 -P1 -I% echo % && sudo -u www-data RAILS_ENV=production bundle exec rails runner "Repository.find_by_url('%').fetch_changesets"
+
+CA_bundle = '/usr/local/share/ca-certificates/snetroot/SNetRootCA_device_bundle.pem'
+CA_bundle = '/etc/ssl/certs/ca-certificates.crt'
+
+redmine_config_global = ConfigParser.RawConfigParser()
+redmine_config_global.read(config_global.get('INI', 'Redmine'))
+
+# Parse config
+REDMINE_HOSTNAME = redmine_config_global.get('GLOBAL', 'HOST')
+REDMINE_PROTO = redmine_config_global.get('GLOBAL', 'PROTO')
+REDMINE_KEY = redmine_config_global.get('CREDENTIAL', 'APIkey')
+REDMINE_WS_KEY = redmine_config_global.get('GLOBAL', 'WS_KEY')
+
+redmine = Redmine('%s://%s' % (REDMINE_PROTO, REDMINE_HOSTNAME), key=REDMINE_KEY, requests={'verify': CA_bundle}, version='3.4.4')
+
+project_name = "bind9-bindhg-snet"
+repo_url = "/opt/SNet/scm/pkg/bind9-snet/bind9-bindhg-snet"
+
+#
+u = redmine.project.get(project_name, include='enabled_modules,repositories')
+
+print('%s:%s:%s' % (u.id, u.identifier, u.name))
+
+if 'repository' not in u.enabled_modules:
+    print("Repository is not activated for repo %s:%s (%s)" % (u.id, u.identifier, u.name))
+    sys.exit(1)
+#    continue
+
+elif len(u.repositories) > 0:
+    print("Repository is not defined for repo %s:%s (%s)" % (u.id, u.identifier, u.name))
+    sys.exit(1)
+#    continue
+
+redmine_url = "%s://%s/sys/projects/%s/repository?key=%s" % (REDMINE_PROTO, REDMINE_HOSTNAME, u.id, REDMINE_WS_KEY)
+# print('curl -s "%s"' % (redmine_url))
+# curl -v -H "Content-Type: application/json" -X POST -d '{"id": "3581", "vendor": "Mercurial", "repository": {"url": "/opt/SNet/scm/pkg/bind9-snet/bind9-bindhg-snet", "identifier":"bind9-bindhg-snet"}}' "https://redmine.snmc.cec.eu.int/sys/projects/3581/repository?key=tU0LvEthIX4cMzCI9YPI"
+
+print('curl -v -H "Content-Type: application/json" -X POST -d \'{"id": "%s", "vendor": "Mercurial", "repository": {"identifier": "%s", "url": "%s"}}\' "%s"' % (u.id, u.name, repo_url, redmine_url))
+
+'''
+    time.sleep(120)
+
+    try:
+        response = requests.get(redmine_url,
+                                allow_redirects=True,
+                                # headers=headers,
+                                verify=CA_bundle)
+    except requests.exceptions.SSLError as e:
+        print('%s: %s' % (redmine_url, str(e)))
+        time.sleep(360)
+        continue
+    except Exception as e:
+        print('Generic: %s' % (str(e)))
+        time.sleep(360)
+        continue
+
+    if response.status_code == 200:
+        print(response.content)
+    else:
+        print('ERROR')
+        print(response.status_code)
+        print(response.content)
+        time.sleep(360)
+'''
+
+sys.exit(0)
diff --git a/bin/redmine_create_sc_projects.py b/bin/redmine_create_sc_projects.py
new file mode 100755
index 0000000..e5395c4
--- /dev/null
+++ b/bin/redmine_create_sc_projects.py
@@ -0,0 +1,760 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from __future__ import absolute_import, print_function
+
+import os
+import sys
+
+import configparser as ConfigParser
+import pprint
+import inspect
+import traceback
+import shlex
+import re
+import requests
+from subprocess import check_output, STDOUT, CalledProcessError
+
+pp = pprint.PrettyPrinter(indent=4)
+
+PROGNAME = os.path.basename(sys.argv[0]).split(".")[0]
+script = os.path.basename(__file__).split(".")[0]
+
+global_iniFile = '/opt/etc/ini/global.ini'
+config_global = ConfigParser.RawConfigParser()
+config_global.optionxform(str())
+config_global.optionxform = str
+config_global.read(global_iniFile)
+sys.path.append(config_global.get('APPLICATION', 'PYTHON-LIBRARY'))
+
+from redminelib import Redmine
+
+if 'http_proxy' in os.environ:
+    del os.environ['http_proxy']
+if 'https_proxy' in os.environ:
+    del os.environ['https_proxy']
+
+CA_bundle = '/usr/local/share/ca-certificates/snetroot/SNetRootCA_device_bundle.pem'
+CA_bundle = '/etc/ssl/certs/ca-certificates.crt'
+
+basedir = '/opt/SNet/scm'
+
+wanted_membership = {}
+wanted_membership['com'] = 'Reporter'
+wanted_membership['mgt'] = 'Reporter'
+wanted_membership['officials'] = 'Reporter'
+wanted_membership['net'] = 'Developer'
+wanted_membership['pi'] = 'Developer'
+wanted_membership['sd'] = 'Developer'
+wanted_membership['sec'] = 'Developer'
+wanted_membership['sup'] = 'Developer'
+wanted_membership['tda'] = 'Developer'
+wanted_membership['pm'] = 'Manager'
+
+cmd = ("ssh vcodebox-lu find %s -path '\*/.hg' -prune -o -type d -path '\*/.hg' | grep -v '^.hg$'" % (basedir))
+
+try:
+    output = check_output((shlex.split(cmd)), stderr=STDOUT, shell=False)
+except CalledProcessError as ex:
+    output = ex.output
+# print(output)
+
+folder_projects = []
+for l in output.splitlines():
+    if not l.startswith(basedir):
+        continue
+    if not l.endswith('/.hg'):
+        continue
+    if l == basedir + '/.hg':
+        continue
+    if 'archive_' in l:
+        continue
+    pat = l.replace('/.hg', '').replace(basedir + '/', '')
+
+    # print("%s %s" % (l, pat))
+    folder_projects.append(pat)
+
+
+def obj_dump(obj):
+    '''
+      Object dumper
+    '''
+    for attr in dir(obj):
+        if '_' in attr:
+            continue
+        try:
+            print("obj.%s = %s" % (attr, str(getattr(obj, attr))))
+        except:
+            print("obj.%s = %s" % (attr, getattr(obj, attr)))
+
+    for name, data in inspect.getmembers(obj):
+        if inspect.isclass(data):
+            print('name:%s' % (name))
+            print(data)
+
+
+def obj_dump_r(obj, level=0, deepth=2):
+    '''
+       Recursive Object dumper
+    '''
+    for attr in dir(obj):
+        if '_' in attr:
+            continue
+        try:
+            msg = 2*level*' '
+            msg += ("obj.%s = %s" % (attr, str(getattr(obj, attr))))
+            print(msg)
+        except:
+            msg = 2*level*' '
+            msg += ("obj.%s = %s" % (attr, getattr(obj, attr)))
+            print(msg)
+
+        if level >= deepth:
+            continue
+
+        try:
+            obj_dump_r(getattr(obj, attr), level=level+1)
+        except:
+            msg = 2*level*' '
+            msg += "Dump is stinking... crashed."
+            print(msg)
+
+
+def redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, pj_id, pj_ident, repository_url):
+
+    '''
+       curl -v -H "Content-Type: application/json" -X POST -d '{"id": "3581", "vendor": "Mercurial", "repository": {"url": "/opt/SNet/scm/pkg/bind9-snet/bind9-bindhg-snet", "identifier":"bind9-bindhg-snet"}}' "https://redmine.snmc.cec.eu.int/sys/projects/3581/repository?key=tU0LvEthIX4cMzCI9YPI"
+    '''
+
+    redmine_url = "%s://%s/sys/projects/%s/repository?key=%s" % (REDMINE_PROTO, REDMINE_HOSTNAME, pj_id, REDMINE_WS_KEY)
+    playload = {}
+    playload['id'] = pj_id
+    playload['vendor'] = 'Mercurial'
+    playload['repository'] = {}
+    playload['repository']['identifier'] = pj_ident
+    playload['repository']['url'] = repository_url
+
+    try:
+        response = requests.post(redmine_url,
+                                 json=playload,
+                                 allow_redirects=True,
+                                 verify=CA_bundle)
+
+    except requests.exceptions.SSLError as e:
+        self.logger.error('%s: %s' % (redmine_url, str(e)))
+        return None
+    except Exception as e:
+        self.logger.error('Generic: %s' % (str(e)))
+        return None
+
+    if response.status_code == 201:
+        print('OK')
+        print(response.content)
+        return None
+    else:
+        print('ERROR')
+        print(response.status_code)
+        print(response.content)
+        return None
+
+
+redmine_config_global = ConfigParser.RawConfigParser()
+redmine_config_global.read(config_global.get('INI', 'Redmine'))
+
+# Parse config
+REDMINE_HOSTNAME = redmine_config_global.get('GLOBAL', 'HOST')
+REDMINE_PROTO = redmine_config_global.get('GLOBAL', 'PROTO')
+REDMINE_KEY = redmine_config_global.get('CREDENTIAL', 'APIkey')
+REDMINE_WS_KEY = redmine_config_global.get('GLOBAL', 'WS_KEY')
+
+redmine = Redmine('%s://%s' % (REDMINE_PROTO, REDMINE_HOSTNAME), key=REDMINE_KEY, requests={'verify': CA_bundle}, version='3.4.4')
+
+all_red_parent = {}
+all_red_pj = {}
+all_red_cross_pj = {}
+red_projects = redmine.project.all(offset=0, limit=1000, include='enabled_modules,repositories,trackers')
+
+for u in red_projects:
+    # print(u)
+    # print('%s' % (u.id))
+    # print('%s' % (u.name))
+    # print('%s' % (u.identifier))
+    all_red_pj[u.identifier] = {}
+    all_red_pj[u.identifier]['id'] = u.id
+    all_red_pj[u.identifier]['name'] = u.name
+    all_red_pj[u.identifier]['identifier'] = u.identifier
+    all_red_pj[u.identifier]['enabled_modules'] = u.enabled_modules
+    all_red_pj[u.identifier]['repositories'] = u.repositories
+    if hasattr(u, 'is_public'):
+        all_red_pj[u.identifier]['is_public'] = u.is_public
+    else:
+        all_red_pj[u.identifier]['is_public'] = False
+
+    if 'parent' in dir(u):
+        # print('parent:%s' % (u.parent))
+        all_red_pj[u.identifier]['parent'] = {}
+        all_red_pj[u.identifier]['parent']['name'] = u.parent.name
+        all_red_pj[u.identifier]['parent']['id'] = u.parent.id
+        # all_red_pj[u.identifier]['parent']['identifier'] = u.parent.identifier
+        all_red_parent[u.parent.name+'/'+u.name] = u.identifier
+
+    if u.identifier == 'refconfig':
+        pp.pprint(all_red_pj[u.identifier])
+        # obj_dump(u)
+        # obj_dump_r(u, level=0, deepth=1)
+        print(u.enabled_modules)
+        print(u.repositories)
+        print(u.is_public)
+        print(list(u))
+        # sys.exit(0)
+
+    if u.name != u.identifier:
+        all_red_cross_pj[u.name] = u.identifier
+        # pp.pprint(all_red_cross_pj[u.name])
+
+    continue
+    print('%s' % (u.id))
+    print('%s' % (u.name))
+    print('%s' % (u.identifier))
+    if 'parent' in u:
+        print('%s' % (u.parent))
+
+pp.pprint(all_red_parent)
+
+red_groups = redmine.group.all()
+all_red_grp = {}
+for g in red_groups:
+    all_red_grp[g.name] = {}
+    all_red_grp[g.name]['id'] = g.id
+    all_red_grp[g.id] = {}
+    all_red_grp[g.id]['name'] = g.name
+# print(pp.pformat(all_red_grp))
+
+red_roles = redmine.role.all()
+all_red_rl = {}
+for r in red_roles:
+    all_red_rl[r.name] = {}
+    all_red_rl[r.name]['id'] = r.id
+    all_red_rl[r.id] = {}
+    all_red_rl[r.id]['name'] = r.name
+# print(pp.pformat(all_red_rl))
+
+# sys.exit(1)
+
+limit = 3000
+cpt = 0
+for pj in sorted(folder_projects):
+    if cpt > limit:
+        break
+    cpt += 1
+
+    print("----%s" % (pj))
+    if '/' in pj:
+        (parent, pjj) = pj.rsplit('/', 1)
+        if '/' in parent:
+            cnt = parent.count('/')
+            if cnt == 1:
+                if parent in all_red_parent:
+                    parent = all_red_parent[parent]
+                else:
+                    print("Parent '%s' with 1/ but not found (%s), creating pre-parent" % (parent, pj))
+
+                    prepa, ppa = parent.split('/')
+                    prepa_ident = prepa.lower().replace('.', '-')
+                    ppa_ident = ppa.lower().replace('.', '-')
+                    ''' Pre-parent check-up. '''
+                    if prepa_ident in all_red_pj:
+                        print("Pre-Parent '%s' is found" % (prepa))
+                        prepa_id = all_red_pj[prepa_ident]['id']
+                    elif prepa in all_red_cross_pj:
+                        print("Pre-Parent '%s' is found in the bad list" % (prepa))
+                        prepa_id = all_red_pj[all_red_cross_pj[prepa]]['id']
+                    else:
+                        print("Pre-Parent '%s:%s' need to be created" % (prepa, prepa_ident))
+
+                        try:
+                            project = redmine.project.new()
+                            project.name = prepa
+                            project.identifier = prepa_ident
+                            project.description = prepa
+                            project.homepage = None
+                            project.is_public = True
+                            project.inherit_members = False
+                            project.parent_id = None
+                            project.enabled_module_names = []
+                            project.save()
+                        except Exception as e:
+                            print('The creation of the ressources project "%s" did not suceed: %s' % (parent, str(e)))
+                            print(traceback.format_exc(5))
+                            sys.exit(1)
+                        prepa_id = project.id
+
+                        all_red_pj[project.identifier] = {}
+                        all_red_pj[project.identifier]['id'] = project.id
+                        all_red_pj[project.identifier]['name'] = project.name
+                        all_red_pj[project.identifier]['identifier'] = project.identifier
+                        all_red_pj[project.identifier]['enabled_modules'] = project.enabled_modules
+                        all_red_pj[project.identifier]['repositories'] = project.repositories
+                        if hasattr(project, 'is_public'):
+                            all_red_pj[project.identifier]['is_public'] = project.is_public
+                        else:
+                            all_red_pj[project.identifier]['is_public'] = False
+
+                    # Preparent membership
+
+                    print("membership prepa_id is %s." % (prepa_id))
+
+                    pj_wanted_membership = dict(wanted_membership)
+                    pj_membership_del = []
+                    real_membership = redmine.project_membership.filter(project_id=prepa_id)
+
+                    for mb in real_membership:
+                        if hasattr(mb, 'user'):
+                            continue
+                        '''
+                        print("------------")
+                        print("membership")
+                        print("mb.project: %s %s" % (mb.project.id, mb.project.name))
+                        print("mb.group: %s %s" % (mb.group.id, mb.group.name))
+                        print("mb.roles")
+                        for rl in mb.roles:
+                            print("%s %s" % (rl.id, rl.name))
+                        '''
+                        if mb.group.name in pj_wanted_membership:
+                            for rl in mb.roles:
+                                if pj_wanted_membership[mb.group.name] == rl.name:
+                                    del(pj_wanted_membership[mb.group.name])
+                                else:
+                                    for rl in mb.roles:
+                                        pj_membership_del.append(mb.id)
+
+                        else:
+                            pj_membership_del.append(mb.id)
+
+                    pp.pprint(pj_wanted_membership)
+                    for gr in pj_wanted_membership:
+                        membership = redmine.project_membership.new()
+                        membership.project_id = prepa_id
+                        # http://www.redmine.org/issues/17904 group is user...
+                        membership.user_id = all_red_grp[gr]['id']
+                        membership.role_ids = [all_red_rl[pj_wanted_membership[gr]]['id']]
+                        membership.save()
+
+                    pp.pprint(pj_membership_del)
+                    for mb in pj_membership_del:
+                        membership = redmine.project_membership.get(prepa_id)
+                        membership.delete(mb)
+
+                    ''' Parent check-up. '''
+                    if ppa_ident in all_red_pj:
+                        print("Parent '%s' is found" % (ppa))
+                        ppa_id = all_red_pj[ppa_ident]['id']
+                    elif ppa in all_red_cross_pj:
+                        print("Parent '%s' is found in the bad list" % (ppa))
+                        ppa_id = all_red_pj[all_red_cross_pj[ppa]]['id']
+                    else:
+                        print("Parent '%s:%s' need to be created" % (ppa, ppa_ident))
+
+                        try:
+                            project = redmine.project.new()
+                            project.name = ppa
+                            project.identifier = ppa_ident
+                            project.description = ppa
+                            project.homepage = None
+                            project.is_public = True
+                            project.inherit_members = False
+                            project.parent_id = prepa_id
+                            project.enabled_module_names = []
+                            project.save()
+                        except Exception as e:
+                            print('The creation of the ressources project "%s" did not suceed: %s' % (ppa, str(e)))
+                            print(traceback.format_exc(5))
+                            sys.exit(1)
+                        ppa_id = project.id
+
+                        all_red_pj[project.identifier] = {}
+                        all_red_pj[project.identifier]['id'] = project.id
+                        all_red_pj[project.identifier]['name'] = project.name
+                        all_red_pj[project.identifier]['identifier'] = project.identifier
+                        all_red_pj[project.identifier]['enabled_modules'] = project.enabled_modules
+                        if hasattr(project, 'is_public'):
+                            all_red_pj[project.identifier]['is_public'] = project.is_public
+                        else:
+                            all_red_pj[project.identifier]['is_public'] = False
+
+                        all_red_pj[project.identifier]['parent'] = {}
+                        all_red_pj[project.identifier]['parent']['name'] = project.parent.name
+                        all_red_pj[project.identifier]['parent']['id'] = project.parent.id
+                        all_red_parent[project.parent.name+'/'+project.name] = project.identifier
+
+            else:
+                match = re.search(r'^.*/([^/]+/[^/]+)$', parent)
+                if match.group(1) in all_red_parent:
+                    parent = all_red_parent[match.group(1)]
+                else:
+                    print("Parent '%s' need to be decomposed for %s, skipping for now" % (parent, pj))
+                    continue
+    else:
+        parent = None
+        pjj = pj
+
+    print("%s:%s" % (parent, pjj))
+    if parent:
+        parent_ident = parent.lower().replace('.', '-')
+    pj_ident = pjj.lower().replace('.', '-')
+
+    '''
+        PARENT
+    '''
+
+    if parent and parent_ident in all_red_pj:
+        print("Parent '%s' is found" % (parent))
+        parent_id = all_red_pj[parent_ident]['id']
+    elif parent and parent in all_red_cross_pj:
+        print("Parent '%s' is found in the bad list" % (parent))
+        parent_id = all_red_pj[all_red_cross_pj[parent]]['id']
+    elif parent:
+        print("Parent '%s:%s' need to be created" % (parent, parent_ident))
+
+        try:
+            project = redmine.project.new()
+            project.name = parent
+            project.identifier = parent_ident
+            project.description = parent
+            project.homepage = None
+            project.is_public = True
+            project.inherit_members = False
+            project.parent_id = None
+            project.enabled_module_names = []
+            # project.enabled_modules = [] readonly attribute
+            # project.custom_fields = [{'id': 1, 'value': 'PE'}, {'id': 11, 'value': 'scm'}]
+            # list(project)
+            project.save()
+        except Exception as e:
+            print('The creation of the ressources project "%s" did not suceed: %s' % (parent, str(e)))
+            print(traceback.format_exc(5))
+            break
+
+        all_red_pj[project.identifier] = {}
+        all_red_pj[project.identifier]['id'] = project.id
+        all_red_pj[project.identifier]['name'] = project.name
+        all_red_pj[project.identifier]['identifier'] = project.identifier
+        all_red_pj[project.identifier]['is_public'] = True
+        parent_id = project.id
+
+    else:
+        parent_id = None
+
+    if parent_id is not None:
+
+        project = redmine.project.get(parent_id)
+        project.is_public = True
+        project.inherit_members = False
+        project.save()
+
+        if 'enabled_modules' not in all_red_pj[parent_ident]:
+            print("No repository module activated for parent, OK")
+
+        elif 'repository' not in all_red_pj[parent_ident]['enabled_modules']:
+            print("No repository for parent, OK")
+
+        elif len(all_red_pj[parent_ident]['repositories']) == 0:
+            print("No repository for parent, OK")
+
+        else:
+            print("repository activated for parent should not")
+
+        print("membership parent_id is %s." % (parent_id))
+
+        pj_wanted_membership = dict(wanted_membership)
+        pj_membership_del = []
+        real_membership = redmine.project_membership.filter(project_id=parent_id)
+
+        for mb in real_membership:
+            if hasattr(mb, 'user'):
+                continue
+            '''
+            print("------------")
+            print("membership")
+            print("mb.project: %s %s" % (mb.project.id, mb.project.name))
+            print("mb.group: %s %s" % (mb.group.id, mb.group.name))
+            print("mb.roles")
+            for rl in mb.roles:
+                print("%s %s" % (rl.id, rl.name))
+            '''
+            if mb.group.name in pj_wanted_membership:
+                for rl in mb.roles:
+                    if pj_wanted_membership[mb.group.name] == rl.name:
+                        del(pj_wanted_membership[mb.group.name])
+                    else:
+                        for rl in mb.roles:
+                            pj_membership_del.append(mb.id)
+
+            else:
+                pj_membership_del.append(mb.id)
+
+        pp.pprint(pj_wanted_membership)
+        for gr in pj_wanted_membership:
+            membership = redmine.project_membership.new()
+            membership.project_id = parent_id
+            # http://www.redmine.org/issues/17904 group is user...
+            membership.user_id = all_red_grp[gr]['id']
+            membership.role_ids = [all_red_rl[pj_wanted_membership[gr]]['id']]
+            membership.save()
+
+        pp.pprint(pj_membership_del)
+        for mb in pj_membership_del:
+            membership = redmine.project_membership.get(parent_id)
+            membership.delete(mb)
+
+    '''
+        ITSELF
+    '''
+
+    if pjj in all_red_pj:
+        print("The project '%s' is found in all_red_pj." % (pjj))
+        repository_url = os.path.join(basedir, pj)
+        print("hg:%s:%s" % (pj_ident, repository_url))
+        pp.pprint(all_red_pj[pjj])
+
+        if parent and 'parent' in all_red_pj[pjj]:
+            if parent != all_red_pj[pjj]['parent']['name']:
+                print("Not the same parent %s:%s" % (parent, all_red_pj[pjj]['parent']['name']))
+                project = redmine.project.get(all_red_pj[pjj]['id'])
+                project.parent_id = parent_id
+                project.is_public = True
+                project.inherit_members = False
+                project.custom_fields = [{'id': 11, 'value': repository_url}]
+                project.save()
+
+        elif parent:
+            print("Not the same parent %s:None" % (parent))
+            project = redmine.project.get(all_red_pj[pjj]['id'])
+            project.parent_id = parent_id
+            project.is_public = True
+            project.inherit_members = False
+            project.custom_fields = [{'id': 11, 'value': repository_url}]
+            project.save()
+            redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[pjj]['id'], pj_ident, repository_url)
+
+        if 'repository' not in all_red_pj[pjj]['enabled_modules']:
+            print("Repository is not activated for repo %s:%s" % (pjj, pj_ident))
+            project = redmine.project.get(all_red_pj[pjj]['id'])
+            project.is_public = True
+            project.inherit_members = False
+            project.custom_fields = [{'id': 11, 'value': repository_url}]
+            project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking',
+                                            'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt']
+            project.tracker_ids = [1, 2]
+            project.save()
+            redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[pjj]['id'], pj_ident, repository_url)
+
+        elif len(all_red_pj[pjj]['repositories']) == 0:
+            print("Repository URL is empty for repo %s:%s (%s)" % (pjj, pj_ident, os.path.join(basedir, pj)))
+            project = redmine.project.get(all_red_pj[pjj]['id'])
+            project.is_public = True
+            project.inherit_members = False
+            project.custom_fields = [{'id': 11, 'value': repository_url}]
+            project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking',
+                                            'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt']
+            project.tracker_ids = [1, 2]
+            project.save()
+            redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[pjj]['id'], pj_ident, repository_url)
+
+        elif os.path.join(basedir, pj) != all_red_pj[pjj]['repositories'][0]['url']:
+            print("Repository URL is bad for repo %s:%s (%s <> %s)"
+                  % (pjj, pj_ident, os.path.join(basedir, pj), all_red_pj[pjj]['repositories'][0]['url']))
+
+        # if all_red_pj[pjj]['is_public']:
+        # reset verything to is_public false
+        project = redmine.project.get(all_red_pj[pjj]['id'])
+        project.is_public = True
+        project.inherit_members = False
+        project.custom_fields = [{'id': 11, 'value': repository_url}]
+        project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking',
+                                        'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt']
+        project.tracker_ids = [1, 2]
+        project.save()
+
+        print("membership all_red_pj id %s." % (all_red_pj[pjj]['id']))
+
+        pj_wanted_membership = dict(wanted_membership)
+        pj_membership_del = []
+        real_membership = redmine.project_membership.filter(project_id=all_red_pj[pjj]['id'])
+        # print('%s' % (pp.pprint(pj_wanted_membership)))
+
+        for mb in real_membership:
+            if hasattr(mb, 'user'):
+                continue
+            '''
+            print("------------")
+            print("membership")
+            print(list(mb))
+            print("mb.project: %s %s" % (mb.project.id, mb.project.name))
+            print("mb.group: %s %s" % (mb.group.id, mb.group.name))
+            print("mb.roles")
+            for rl in mb.roles:
+                print("%s %s" % (rl.id, rl.name))
+            if 'inherited' in mb:
+                if mb.inherited == True:
+                    print("inherited = True")
+                else:
+                    print("inherited = False")
+            '''
+            if mb.group.name in pj_wanted_membership:
+                for rl in mb.roles:
+                    if mb.group.name in pj_wanted_membership and pj_wanted_membership[mb.group.name] == rl.name:
+                        del(pj_wanted_membership[mb.group.name])
+                    else:
+                        for rl in mb.roles:
+                            pj_membership_del.append(mb.id)
+
+            else:
+                pj_membership_del.append(mb.id)
+
+        pp.pprint(pj_wanted_membership)
+        for gr in pj_wanted_membership:
+            membership = redmine.project_membership.new()
+            membership.project_id = all_red_pj[pjj]['id']
+            # http://www.redmine.org/issues/17904 group is user...
+            membership.user_id = all_red_grp[gr]['id']
+            membership.role_ids = [all_red_rl[pj_wanted_membership[gr]]['id']]
+            membership.save()
+
+        pp.pprint(pj_membership_del)
+        for mb in pj_membership_del:
+            membership = redmine.project_membership.get(all_red_pj[pjj]['id'])
+            membership.delete(mb)
+
+    elif pjj in all_red_cross_pj:
+        print("The project '%s' is found in all_red_cross_pj." % (pjj))
+        repository_url = os.path.join(basedir, pj)
+        print("hg:%s:%s" % (pj_ident, repository_url))
+        pp.pprint(all_red_pj[all_red_cross_pj[pjj]])
+        if parent and 'parent' in all_red_pj[all_red_cross_pj[pjj]]:
+            if parent != all_red_pj[all_red_cross_pj[pjj]]['parent']['name']:
+                print("Not the same parent %s:%s" % (parent, all_red_pj[all_red_cross_pj[pjj]]['parent']['name']))
+        elif parent:
+            print("Not the same parent %s:None" % (parent))
+        elif 'parent' in all_red_pj[all_red_cross_pj[pjj]]:
+            print("Not the same parent None:%s" % (all_red_pj[all_red_cross_pj[pjj]]['parent']['name']))
+
+        if 'repository' not in all_red_pj[all_red_cross_pj[pjj]]['enabled_modules']:
+            print("Repository is not activated for repo %s:%s" % (pjj, pj_ident))
+            project = redmine.project.get(all_red_pj[all_red_cross_pj[pjj]]['id'])
+            project.is_public = True
+            project.inherit_members = False
+            project.custom_fields = [{'id': 11, 'value': os.path.join(basedir, pj)}]
+            project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking',
+                                            'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt']
+            project.tracker_ids = [1, 2]
+            project.save()
+            redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[all_red_cross_pj[pjj]]['id'], pj_ident, repository_url)
+
+        elif len(all_red_pj[all_red_cross_pj[pjj]]['repositories']) == 0:
+            print("Repository URL is empty for repo %s:%s (%s)" % (pjj, pj_ident, repository_url))
+            project = redmine.project.get(all_red_pj[all_red_cross_pj[pjj]]['id'])
+            project.is_public = True
+            project.inherit_members = False
+            project.custom_fields = [{'id': 11, 'value': os.path.join(basedir, pj)}]
+            project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking',
+                                            'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt']
+            project.tracker_ids = [1, 2]
+            project.save()
+            redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[all_red_cross_pj[pjj]]['id'], pj_ident, repository_url)
+
+        elif os.path.join(basedir, pj) != all_red_pj[all_red_cross_pj[pjj]]['repositories'][0]['url']:
+            print("Repository URL is bad for repo %s:%s (%s <> %s)"
+                  % (pjj, pj_ident, os.path.join(basedir, pj), all_red_pj[all_red_cross_pj[pjj]]['repositories'][0]['url']))
+
+        # if all_red_pj[pjj]['is_public']:
+        # reset verything to is_public false
+        project = redmine.project.get(all_red_pj[all_red_cross_pj[pjj]]['id'])
+        project.is_public = True
+        project.inherit_members = False
+        project.custom_fields = [{'id': 11, 'value': os.path.join(basedir, pj)}]
+        project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking',
+                                        'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt']
+        project.tracker_ids = [1, 2]
+        project.save()
+
+        print("membership all_red_cross_pj id %s." % (all_red_pj[all_red_cross_pj[pjj]]['id']))
+
+        pj_wanted_membership = dict(wanted_membership)
+        pj_membership_del = []
+        real_membership = redmine.project_membership.filter(project_id=all_red_pj[all_red_cross_pj[pjj]]['id'])
+
+        for mb in real_membership:
+            if hasattr(mb, 'user'):
+                continue
+            '''
+            print("------------")
+            print("membership")
+            print("mb.project: %s %s" % (mb.project.id, mb.project.name))
+            print("mb.group: %s %s" % (mb.group.id, mb.group.name))
+            print("mb.roles")
+            for rl in mb.roles:
+                print("%s %s" % (rl.id, rl.name))
+            '''
+            if mb.group.name in pj_wanted_membership:
+                for rl in mb.roles:
+                    if pj_wanted_membership[mb.group.name] == rl.name:
+                        del(pj_wanted_membership[mb.group.name])
+                    else:
+                        for rl in mb.roles:
+                            pj_membership_del.append(mb.id)
+
+            else:
+                pj_membership_del.append(mb.id)
+
+        pp.pprint(pj_wanted_membership)
+        for gr in pj_wanted_membership:
+            membership = redmine.project_membership.new()
+            membership.project_id = all_red_pj[all_red_cross_pj[pjj]]['id']
+            # http://www.redmine.org/issues/17904 group is user...
+            membership.user_id = all_red_grp[gr]['id']
+            membership.role_ids = [all_red_rl[pj_wanted_membership[gr]]['id']]
+            membership.save()
+
+        pp.pprint(pj_membership_del)
+        for mb in pj_membership_del:
+            membership = redmine.project_membership.get(all_red_pj[all_red_cross_pj[pjj]]['id'])
+            membership.delete(mb)
+
+        # break
+
+    else:
+        print("The project '%s' need to be created." % (pj))
+        print("hg:%s:%s" % (pj_ident, os.path.join(basedir, pj)))
+
+        if parent and parent in all_red_pj:
+            print("Parent '%s' is found" % (parent))
+        elif parent and parent in all_red_cross_pj:
+            print("Parent '%s' is found in the bad list" % (parent))
+
+        try:
+            print('id:%s' % (pj_ident))
+            project = redmine.project.new()
+            project.name = pjj
+            project.identifier = pj_ident
+            project.description = pjj
+            project.homepage = None
+            project.is_public = True
+            project.inherit_members = False
+            project.parent_id = parent_id
+            # project.enabled_modules = ['repository'] Readonly attribute
+            # project.custom_fields = [{'id': 1, 'value': 'PE'}, {'id': 11, 'value': 'scm'}]
+            project.custom_fields = [{'id': 11, 'value': os.path.join(basedir, pj)}]
+            # list(project)
+            project.save()
+        except Exception as e:
+            print('The creation of the ressources project "%s" did not suceed: %s' % (pjj, str(e)))
+            print(traceback.format_exc(5))
+            break
+
+    # try:
+    #     project = redmine.project.get(pjj)
+    # except ResourceNotFoundError as e:
+    #     print('The ressources is not found')
+
+sys.exit(0)
diff --git a/bin/redmine_fetch_changeset.py b/bin/redmine_fetch_changeset.py
new file mode 100755
index 0000000..b7883ea
--- /dev/null
+++ b/bin/redmine_fetch_changeset.py
@@ -0,0 +1,94 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from __future__ import absolute_import, print_function
+
+import os
+import sys
+
+import configparser as ConfigParser
+import pprint
+import inspect
+import traceback
+import shlex
+import re
+import requests
+import time
+from subprocess import check_output, STDOUT, CalledProcessError
+
+pp = pprint.PrettyPrinter(indent=4)
+
+PROGNAME = os.path.basename(sys.argv[0]).split(".")[0]
+script = os.path.basename(__file__).split(".")[0]
+
+global_iniFile = '/opt/etc/ini/global.ini'
+config_global = ConfigParser.RawConfigParser()
+config_global.optionxform(str())
+config_global.optionxform = str
+config_global.read(global_iniFile)
+sys.path.append(config_global.get('APPLICATION', 'PYTHON-LIBRARY'))
+
+from redminelib import Redmine
+
+if 'http_proxy' in os.environ:
+    del os.environ['http_proxy']
+if 'https_proxy' in os.environ:
+    del os.environ['https_proxy']
+
+# find /opt/SNet/scm -path '*/.hg' -prune -o -type d -path '*/.hg' | grep -v '^.hg$' | sed 's/\/\.hg$//' | xargs -n1 -P1 -I% echo % && sudo -u www-data RAILS_ENV=production bundle exec rails runner "Repository.find_by_url('%').fetch_changesets"
+
+CA_bundle = '/usr/local/share/ca-certificates/snetroot/SNetRootCA_device_bundle.pem'
+CA_bundle = '/etc/ssl/certs/ca-certificates.crt'
+
+redmine_config_global = ConfigParser.RawConfigParser()
+redmine_config_global.read(config_global.get('INI', 'Redmine'))
+
+# Parse config
+REDMINE_HOSTNAME = redmine_config_global.get('GLOBAL', 'HOST')
+REDMINE_PROTO = redmine_config_global.get('GLOBAL', 'PROTO')
+REDMINE_KEY = redmine_config_global.get('CREDENTIAL', 'APIkey')
+REDMINE_WS_KEY = redmine_config_global.get('GLOBAL', 'WS_KEY')
+
+redmine = Redmine('%s://%s' % (REDMINE_PROTO, REDMINE_HOSTNAME), key=REDMINE_KEY, requests={'verify': CA_bundle}, version='3.4.4')
+
+red_projects = redmine.project.all(offset=0, limit=1000, include='enabled_modules,repositories,trackers')
+
+for u in red_projects:
+    print('%s:%s:%s' % (u.id, u.identifier, u.name))
+
+    if 'repository' not in u.enabled_modules:
+        print("Repository is not activated for repo %s:%s (%s)" % (u.id, u.identifier, u.name))
+        continue
+
+    elif len(u.repositories) == 0:
+        print("Repository is not defined for repo %s:%s (%s)" % (u.id, u.identifier, u.name))
+        continue
+
+    redmine_url = "%s://%s/sys/fetch_changesets?key=%s&id=%s" % (REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, u.id)
+    # print('curl -s "%s"' % (redmine_url))
+
+    time.sleep(120)
+
+    try:
+        response = requests.get(redmine_url,
+                                allow_redirects=True,
+                                # headers=headers,
+                                verify=CA_bundle)
+    except requests.exceptions.SSLError as e:
+        print('%s: %s' % (redmine_url, str(e)))
+        time.sleep(360)
+        continue
+    except Exception as e:
+        print('Generic: %s' % (str(e)))
+        time.sleep(360)
+        continue
+
+    if response.status_code == 200:
+        print(response.content)
+    else:
+        print('ERROR')
+        print(response.status_code)
+        print(response.content)
+        time.sleep(360)
+
+sys.exit(0)
diff --git a/bin/redmine_issue b/bin/redmine_issue
new file mode 100755
index 0000000..088c67b
--- /dev/null
+++ b/bin/redmine_issue
@@ -0,0 +1,226 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from __future__ import absolute_import, print_function
+
+import os
+import sys
+
+import configparser as ConfigParser
+import argparse
+import pprint
+import inspect
+# import traceback
+import shlex
+import re
+# import requests
+from subprocess import check_output, STDOUT, CalledProcessError
+
+pp = pprint.PrettyPrinter(indent=4)
+
+PROGNAME = os.path.basename(sys.argv[0]).split(".")[0]
+script = os.path.basename(__file__).split(".")[0]
+
+global_iniFile = '/opt/etc/ini/global.ini'
+config_global = ConfigParser.RawConfigParser()
+config_global.optionxform(str())
+config_global.optionxform = str
+config_global.read(global_iniFile)
+sys.path.append(config_global.get('APPLICATION', 'PYTHON-LIBRARY'))
+
+from redminelib import Redmine
+
+if 'http_proxy' in os.environ:
+    del os.environ['http_proxy']
+if 'https_proxy' in os.environ:
+    del os.environ['https_proxy']
+
+CA_bundle = '/usr/local/share/ca-certificates/snetroot/SNetRootCA_device_bundle.pem'
+CA_bundle = '/etc/ssl/certs/ca-certificates.crt'
+
+basedir = '/opt/SNet/scm'
+
+parser = argparse.ArgumentParser()
+parser.add_argument('-p', '--project', type=str, default='local',
+                    help='The project to restrict: ALL for all',
+                    dest='project')
+args = parser.parse_args()
+
+project_filter = 'ALL'
+project_filter = args.project
+
+redmine_config_global = ConfigParser.RawConfigParser()
+redmine_config_global.read(config_global.get('INI', 'Redmine'))
+
+# Parse config
+REDMINE_HOSTNAME = redmine_config_global.get('GLOBAL', 'HOST')
+REDMINE_PROTO = redmine_config_global.get('GLOBAL', 'PROTO')
+REDMINE_KEY = redmine_config_global.get('CREDENTIAL', 'APIkey')
+REDMINE_WS_KEY = redmine_config_global.get('GLOBAL', 'WS_KEY')
+REDMINE_VERSION = redmine_config_global.get('GLOBAL', 'VERSION')
+redmine = None
+
+
+def obj_dump(obj):
+    '''
+      Object dumper
+    '''
+    for attr in dir(obj):
+        if '_' in attr:
+            continue
+        try:
+            print("obj.%s = %s" % (attr, str(getattr(obj, attr))))
+        except:
+            print("obj.%s = %s" % (attr, getattr(obj, attr)))
+
+    for name, data in inspect.getmembers(obj):
+        if inspect.isclass(data):
+            print('name:%s' % (name))
+            print(data)
+
+
+def obj_dump_r(obj, level=0, deepth=2):
+    '''
+       Recursive Object dumper
+    '''
+    for attr in dir(obj):
+        if '_' in attr:
+            continue
+        try:
+            msg = 2*level*' '
+            msg += ("obj.%s = %s" % (attr, str(getattr(obj, attr))))
+            print(msg)
+        except:
+            msg = 2*level*' '
+            msg += ("obj.%s = %s" % (attr, getattr(obj, attr)))
+            print(msg)
+
+        if level >= deepth:
+            continue
+
+        if isinstance(getattr(obj, attr), (int, str, unicode)):
+            continue
+
+        try:
+            obj_dump_r(getattr(obj, attr), level=level+1)
+        except:
+            msg = 2*level*' '
+            msg += "Dump is stinking... crashed."
+            print(msg)
+
+
+if project_filter == 'local':
+    # cmd = ("pwd")
+    # cmd = ("hg config paths.default || git config --get remote.origin.url")
+    cmds = []
+    cmds.append("hg config paths.default")
+    cmds.append("git config --get remote.origin.url")
+
+    vcs = ''
+    for cmd in cmds:
+        # print("hg-git cmd: %s" % (cmd))
+        # print("hg-git cmd: %s" % (shlex.split(cmd)))
+
+        try:
+            output = check_output((shlex.split(cmd)),
+                                  stderr=STDOUT,
+                                  shell=False)
+        except CalledProcessError as ex:
+            output = ex.output
+
+        # print("hg-git output: '%s'" % (output))
+        if output == '':
+            continue
+        if ':/' in output and '.git' in output:
+            vcs = 'git'
+            break
+        elif '//' in output:
+            vcs = 'hg'
+            break
+
+    if vcs == '':
+        print("bad repo: %s, abort." % (output))
+        sys.exit(1)
+    if vcs == 'hg':
+        match = re.search(r'^.*/(/.*)$', output)
+    elif vcs == 'git':
+        match = re.search(r'^.*:(/.*)$', output)
+    if match:
+        repo = match.group(1)
+    else:
+        print("bad repo: %s, abort." % (output))
+        sys.exit(1)
+
+    print("repo: %s" % (repo))
+
+    redmine = Redmine('%s://%s' % (REDMINE_PROTO, REDMINE_HOSTNAME),
+                      key=REDMINE_KEY, requests={'verify': CA_bundle},
+                      version='3.4.4')
+
+    red_projects = redmine.project.all(offset=0, limit=1000, include='enabled_modules,repositories')
+    for u in red_projects:
+        if 'repository' not in u.enabled_modules:
+            continue
+        if 'issue_tracking' not in u.enabled_modules:
+            continue
+
+        # if obj.trackers
+        # print(u)
+        pp.pprint(u)
+        # obj_dump(u)
+        # obj_dump_r(u, level=0, deepth=1)
+        print("'%s' '%s' '%s'" % (u.id, u.name, u.identifier))
+        print(u.enabled_modules)
+
+        try:
+            if len(u.repositories) == 0:
+                continue
+        except Exception as e:
+            print('no repository: %s' % (str(e)))
+            continue
+
+        if str(repo) == u.repositories[0]['url']:
+            print("found project %s" % (u.name))
+            project_filter = u.name
+            break
+
+if redmine is None:
+    redmine = Redmine('%s://%s' % (REDMINE_PROTO, REDMINE_HOSTNAME),
+                      key=REDMINE_KEY, requests={'verify': CA_bundle},
+                      version=REDMINE_VERSION)
+
+if project_filter == 'ALL':
+    issues = redmine.issue.filter(status_id='open', sort='project:asc,id:asc')
+else:
+    issues = redmine.issue.filter(status_id='open', project_id=project_filter, sort='project:asc,id:asc')
+
+for i in issues:
+    msg = ('#%s' % (i.id))
+    if project_filter == 'ALL':
+        msg += (' p:%s\n' % (i.project))
+        msg += ('      status_id:%s\n' % (i.status))
+        msg += ('      priority_id:%s\n' % (i.priority))
+        msg += ('      tracker_id:%s\n' % (i.tracker))
+    else:
+        msg += ('      subject:%s\n' % (i.subject))
+    try:
+        msg += ('      assigned:%s\n' % (i.assigned_to.name))
+    except Exception as e:
+        pass
+    obj_dump(i)
+    print(dir(i))
+    print(i.custom_fields)
+    obj_dump(i.custom_fields)
+    print(redmine.custom_field.all())
+    print('cs:' + str(i.custom_fields.get(41)))
+    for cs in i.custom_fields:
+        print(cs)
+    # print('cs:' + str(i.custom_fields.['leankit']))
+    print(msg)
+
+    # print('project:%s' % (i.project))
+    # print('category:%s' % (i.category))
+    # i.url
+    # print('%s' % (u.identifier))
+
+sys.exit(0)
diff --git a/bin/redmine_leankit_create_issue b/bin/redmine_leankit_create_issue
index 538224d..aa1c2b7 100755
--- a/bin/redmine_leankit_create_issue
+++ b/bin/redmine_leankit_create_issue
@@ -114,7 +114,7 @@ basedir = '/opt/SNet/scm'
 
 Tracker_List = ['Bug', 'Feature', 'Service Improvement']
 leankit_tracker_conversion = dict()
-leankit_tracker_conversion['Bug'] = 'Defect'
+leankit_tracker_conversion['Bug'] = 'Task'
 leankit_tracker_conversion['Feature'] = 'Task'
 
 parser = argparse.ArgumentParser()
@@ -139,6 +139,10 @@ parser.add_argument('--leankit-board', type=str, required=False,
                     help='The leankit board name for the card creation', dest='leankit_board')
 parser.add_argument('--leankit-board-id', type=int, required=False,
                     help='The leankit board id for the card creation', dest='leankit_board_id')
+parser.add_argument('--leankit-story-point', type=int, required=False, default=1,
+                    help='The leankit story point associated with the issue', dest='leankit_story_point')
+parser.add_argument('--leankit-header', type=str, required=False, default='',
+                    help='The leankit card header for the card creation', dest='leankit_header')
 args = parser.parse_args()
 
 # leankit validation:
@@ -214,6 +218,18 @@ if leankit_card_id is not None:
 if args.leankit_create is True and args.leankit_board_id is not None:
     leankit_board_id = args.leankit_board_id
 
+    leankit_res = leankit.get_board_detail(args.leankit_board_id)
+    # print(leankit_res)
+    '''
+        {'pageMeta': {'totalRecords': 2, 'offset': 0, 'limit': 100, 'startRow': 1, 'endRow': 2}, 'boards': [{'id': '31512088856393', 'title': 'DEV', 'description': '', 'boardRoleId': 4, 'isWelcome': False, 'boardRole': 'boardAdministrator', 'level': {'id': '31512085971730', 'depth': 3, 'maxDepth': 3, 'label': 'Team', 'color': '#ff841f'}}, {'id': '31512088544453', 'title': 'DEV-NMS3-phasein', 'description': '', 'boardRoleId': 4, 'isWelcome': False, 'boardRole': 'boardAdministrator'}]}
+    '''
+    if leankit_res is None:
+        logger.error("Leankit board '%s': id is not found. Check the board name parameter." % args.leankit_board)
+        sys.exit(1)
+
+    leankit_board_id = leankit_res['id']
+    leankit_board_name = leankit_res['title']
+
 elif args.leankit_create is True and args.leankit_board is not None:
     leankit_res = leankit.get_board(args.leankit_board)
     # print(leankit_res)
@@ -225,6 +241,7 @@ elif args.leankit_create is True and args.leankit_board is not None:
         sys.exit(1)
 
     leankit_board_id = leankit_res['id']
+    leankit_board_name = leankit_res['title']
 
 if args.leankit_create is True:
     leankit_res = leankit.get_cardtype_from_board(leankit_board_id)
@@ -472,7 +489,18 @@ if args.leankit_create is True:
     leankit_card["description"] = args.title
     leankit_card["laneId"] = leankit_board_lane_id
     leankit_card["priority"] = "normal"
-    leankit_card["size"] = 1
+    leankit_card["size"] = args.leankit_story_point
+
+    if leankit_board_name == 'DEV':
+        if args.tracker == 'Bug':
+            leankit_card["customIconId"] = "31512101365737"
+
+        # leankit_card["customId"] = dict()
+        # leankit_card["customId"]["value"] = args.leankit_header
+        # leankit_card["customId"]["prefix"] = '[' + leankit_board_name + '] '
+        # leankit_card["customId"]["url"] = None
+        leankit_card["customId"] = args.leankit_header
+
     leankit_card["customFields"] = list()
     t = dict()
     t["fieldId"] = "31512088868633"
diff --git a/bin/sid_user.py b/bin/sid_user.py
index bdf135d..0ab71ba 100755
--- a/bin/sid_user.py
+++ b/bin/sid_user.py
@@ -108,7 +108,7 @@ def snet_ldap_get():
                     attributes=uattributes)
 
     for entry in ldap_con.response:
-        print(entry)
+        # print(entry)
         if uattributes[0] in entry['attributes']:
             if isinstance(entry['attributes'][uattributes[0]], list):
                 uid = entry['attributes'][uattributes[0]][0]
@@ -388,15 +388,15 @@ def sid_create_update_user_approver_scheduler_change_management(diego, dfqdn, re
     ty2 = []
     #print(results) 666060597
     if 'has as act' in results['properties'] :
-        if (isinstance(results['properties']['has as act'], list)): 
+        if (isinstance(results['properties']['has as act'], list)):
            for act in results['properties']['has as act'] :
-               ty.append(act['name'])   
-        else : 
-            ty.append(results['properties']['has as act']['name'])      
-    
+               ty.append(act['name'])
+        else :
+            ty.append(results['properties']['has as act']['name'])
+
     if typeAdd not in  ty :
-        ty.append(typeAdd)              
-    #new relation to workaround Polymorphism 
+        ty.append(typeAdd)
+    #new relation to workaround Polymorphism
     if create :
         block_to_update = {
             'uid': uid,
@@ -406,8 +406,8 @@ def sid_create_update_user_approver_scheduler_change_management(diego, dfqdn, re
             'is a specialization of' : typeAdd,
             'type': typeAdd,
         }
-        
-        #new version "has as act" 
+
+        #new version "has as act"
         block_to_update = {
             'uid': uid,
             'name': user,
@@ -461,6 +461,8 @@ def main():
                         help="increase output verbosity", dest='verbose')
     parser.add_argument('-d', '--debug', action="store_true", default=False,
                         help="increase output verbosity a lot", dest='debug')
+    parser.add_argument('--parameter', default=False,
+                        help="the login parameter to debug", dest='param')
     parser.add_argument('-e', '--env', default=False, help="Set the wanted env", dest='env', nargs='?',
                         choices=('dev', 'acc', 'prod'))
     parser.add_argument('--dryrun', action="store_true", default=False,
@@ -470,8 +472,13 @@ def main():
     args = parser.parse_args()
 
     dryrun = args.dryrun
+    debug = args.debug
+    logindebug = args.param
     res_rw_user = args.rw_user
 
+    if debug:
+        logger.setLevel(logging.DEBUG)
+
     verify = True
     if args.env is False:
         logger.debug('Using the automatic env.')
@@ -491,8 +498,7 @@ def main():
         logger.error('should not happen')
         sys.exit(1)
 
-    print(fqdn)
-    #exit(1)
+    print('Using the SID backend: ' + fqdn)
     snet_groups = 'com,mgt,net,pm,sd,sec,sup,tda'.split(',')
     official_groups = ['officials']
 
@@ -503,25 +509,40 @@ def main():
     # They are all members of C4-TA. So do not add someone not member of C4-TA. The C4-TA is hard-coded below.
     # first_request before 10/2021
     # last reminder request: 01/2022
+    # last reminder request: 04/2022 : used to remove the relations for others users
     official_broken_leg = ['tsigref', 'wagnejl', 'hautari', 'durmeda', 'stoiama']
 
-    nis_transition = ['alcobcr', 'bellimi', 'belotbe', 'culeaso', 'cultrro', 'dobolch', 'florihe', 'hainmar', 'kollepa', 'noronnu', 'panteer', 'plesspa', 'sanzale', 'soulech']
+    departments = ['DIGIT.C.4', 'DIGIT.C.4.001', 'DIGIT.C.4.002', 'DIGIT.C.4.003', 'DIGIT.C.4.006', 'DIGIT.C.4.007', 'DIGIT.C.4.008']
 
-    departments = ['DIGIT.C.4', 'DIGIT.C.4.002', 'DIGIT.C.4.003', 'DIGIT.C.4.006', 'DIGIT.C.4.007', 'DIGIT.C.4.008']
-
-
-    # last reminder request: 04/2022 : used to remove the relations for others users
     approver_scheduler_list = ['fournla', 'chevaju', 'gondago']
+
     snet_results = dict()
     snet_results = snet_ldap_get()
-    logger.debug(pformat(snet_results))
+    if debug:
+        if logindebug:
+            logger.debug("debuging " + logindebug)
+            if 'users' in snet_results and logindebug in snet_results['users']:
+                logger.debug(pformat(snet_results['users'][logindebug]))
+            else:
+                logger.debug(logindebug + " not found in snet_results.")
+        else:
+            logger.debug(pformat(snet_results))
 
     ec_results = dict()
 
     ec_ldap_users = list(snet_results['users'].keys())
     ec_ldap_users += official_broken_leg
     ec_results = ec_ldap_get_user(ec_ldap_users)
-    logger.debug(pformat(ec_results))
+    if debug:
+        if logindebug:
+            logger.debug("debuging " + logindebug)
+            if 'users' in snet_results and logindebug in snet_results['users']:
+                logger.debug(pformat(ec_results['users'][logindebug]))
+            else:
+                logger.debug(logindebug + " not found in snet_results.")
+        else:
+            logger.debug(pformat(ec_results))
+
     '''
            'yildmes': {'building': 'B-28',
                        'c': 'BE',
@@ -602,12 +623,22 @@ def main():
     logger.info('Snet User snet_mail_index: ' + pformat(snet_mail_index))
     logger.info('Snet User snet_account_index: ' + pformat(snet_account_index))
 
+
     diego = Diego(fqdn=fqdn, verify=verify)
     params = {'name': '","'.join(departments)}
     sid_results = diego.diego_run_dieget_by_name('sid_user_check', params)
     context_uid = 666000002
 
-    logger.info('SID User: ' + pformat(sid_results[1]))
+    if debug:
+        if logindebug:
+            logger.debug("debuging " + logindebug)
+            if sid_results and logindebug in sid_results[1]:
+                logger.debug(pformat(sid_results[1][logindebug]))
+            else:
+                logger.debug(logindebug + " not found in sid_results.")
+        else:
+            logger.debug('SID User: ' + pformat(sid_results[1]))
+
     '''
           'yildmes': {'belongs to': 'SNet NET',
               'has as directorate general': 'DIGIT',
@@ -626,8 +657,7 @@ def main():
     for user in sid_results[1]:
         if user in devnull_del_user:
             continue
-        if user in nis_transition:
-            # TODO: not nice, but avoid errors for now
+        if debug and logindebug and logindebug != user:
             continue
         if user not in snet_account_index:
             logger.info('SID user ' + user + ' should be updated to resigned. User missing from the snet_account_index.')
@@ -643,6 +673,9 @@ def main():
     for user in snet_account_index:
         if user in devnull_user:
             continue
+        if debug and logindebug and logindebug != user:
+            continue
+
         need_to_create = False
         need_to_update = False
         if user in sid_results[1]:
@@ -671,12 +704,26 @@ def main():
                 block_to_update['properties']['has as role'] = list()
                 block_to_update['properties']['has as role'].append(t)
 
+            if 'has write access to' not in block_to_update['properties']:
+                block_to_update['properties']['has write access to'] = list()
+            elif 'has write access to' in block_to_update['properties'] and not isinstance(block_to_update['properties']['has write access to'], list):
+                t = block_to_update['properties']['has write access to']
+                block_to_update['properties']['has write access to'] = list()
+                block_to_update['properties']['has write access to'].append(t)
+
             if 'belongs to' not in block_to_update['properties']:
                 block_to_update['properties']['belongs to'] = list()
             elif 'belongs to' in block_to_update['properties'] and not isinstance(block_to_update['properties']['belongs to'], list):
                 t = block_to_update['properties']['belongs to']
                 block_to_update['properties']['belongs to'] = list()
                 block_to_update['properties']['belongs to'].append(t)
+        else:
+            if 'has write access to' not in block_to_update['properties']:
+                block_to_update['properties']['has write access to'] = list()
+            elif 'has write access to' in block_to_update['properties'] and not isinstance(block_to_update['properties']['has write access to'], list):
+                t = block_to_update['properties']['has write access to']
+                block_to_update['properties']['has write access to'] = list()
+                block_to_update['properties']['has write access to'].append(t)
 
         if 'has as short name' not in block_to_update['properties'] or block_to_update['properties']['has as short name'] is None or '':
             block_to_update['properties']['has as short name'] = ec_results['users'][user]['givenName'][0] + ec_results['users'][user]['sn'][:2]
@@ -703,7 +750,7 @@ def main():
         block_to_update['properties']['has as status'] = 'active'
 
         block_to_update['properties']['has e-mail address'] = ec_results['users'][user]['mail']
-        if 'ecInternationalTelephoneNumber' in ec_results['users'][user] : 
+        if 'ecInternationalTelephoneNumber' in ec_results['users'][user] :
             block_to_update['properties']['has telephone number'] = ec_results['users'][user]['ecInternationalTelephoneNumber']
 
         if 'departmentNumber' in ec_results['users'][user] :
@@ -723,7 +770,7 @@ def main():
         # "has access to easiCAPs feature" should be edited to contain "Port History" and "Profile Support".
 
         for mb in snet_results['users'][user]['membership']:
-            # 'com,mgt,net,pm,sd,sec,sup,tda'
+            # 'com,mgt,net,pm,sd,sec,sup,tda,officials'
             if mb == 'com':
                 if need_to_update is False and need_to_create is True:
                     if 'SNet COM' not in block_to_update['properties']['belongs to']:
@@ -777,6 +824,7 @@ def main():
                 if 'Visual' not in block_to_update['properties']['has access to application program']:
                     block_to_update['properties']['has access to application program'].append('Visual')
 
+
             elif mb == 'pm':
                 if need_to_update is False and need_to_create is True:
                     block_to_update['properties']['belongs to'].append('SNet PM')
@@ -786,7 +834,7 @@ def main():
 
                 if 'Visual' not in block_to_update['properties']['has access to application program']:
                     block_to_update['properties']['has access to application program'].append('Visual')
-            
+
             elif mb == 'sd':
                 if need_to_update is False and need_to_create is True:
                     block_to_update['properties']['belongs to'].append('Snet NOC/SD')
@@ -833,33 +881,65 @@ def main():
                 if 'Visual' not in block_to_update['properties']['has access to application program']:
                     block_to_update['properties']['has access to application program'].append('Visual')
 
+            elif mb == 'officials':
+                '''
+                if need_to_update is False and need_to_create is True:
+                    if 'SNet SUP' not in block_to_update['properties']['belongs to']:
+                        block_to_update['properties']['belongs to'].append('SNet SUP')
+                    if 'Developer' not in block_to_update['properties']['has as role']:
+                        block_to_update['properties']['has as role'].append('Developer')
+                if 'edit object (Visual action)' not in block_to_update['properties']['is authorized to']:
+                    block_to_update['properties']['is authorized to'].append('edit object (Visual action)')
+                if 'edit relation (SID action)' not in block_to_update['properties']['is authorized to']:
+                    block_to_update['properties']['is authorized to'].append('edit relation (SID action)')
+                if 'CRUD' not in block_to_update['properties']['has access to application program']:
+                    block_to_update['properties']['has access to application program'].append('CRUD')
+
+                '''
+                if 'SnetInventory' not in block_to_update['properties']['has access to application program']:
+                    block_to_update['properties']['has access to application program'].append('SnetInventory')
+
+                '''
+                if 'Visual' not in block_to_update['properties']['has access to application program']:
+                    block_to_update['properties']['has access to application program'].append('Visual')
+                '''
+
             if need_to_update is False and need_to_create is True and 'departmentNumber' in ec_results['users'][user]:
                 if ec_results['users'][user]['departmentNumber'] == 'DIGIT.C.4.007':
                     block_to_update['properties']['belongs to'].append('NIS')
+                    block_to_update['properties']['belongs to'].append('OIS')
+
+            if 'OIS' not in block_to_update['properties']['has as role']:
+                block_to_update['properties']['has write access to'].append('wireless access point')
 
         if 'belongs to' in block_to_update['properties'] and len(block_to_update['properties']['belongs to']) == 1:
             block_to_update['properties']['belongs to'] = block_to_update['properties']['belongs to'][0]
         if 'has as role' in block_to_update['properties'] and len(block_to_update['properties']['has as role']) == 1:
             block_to_update['properties']['has as role'] = block_to_update['properties']['has as role'][0]
+        if 'has write access to' in block_to_update['properties'] and len(block_to_update['properties']['has write access to']) == 1:
+            block_to_update['properties']['has write access to'] = block_to_update['properties']['has write access to'][0]
+
         if len(block_to_update['properties']['is authorized to']) == 1:
             block_to_update['properties']['is authorized to'] = block_to_update['properties']['is authorized to'][0]
         if len(block_to_update['properties']['has access to application program']) == 1:
             block_to_update['properties']['has access to application program'] = block_to_update['properties']['has access to application program'][0]
+        if len(block_to_update['properties']['has write access to']) == 1:
+            block_to_update['properties']['has write access to'] = block_to_update['properties']['has write access to'][0]
 
         # has as role (OQM, Product Owner, SDM)
         # print("This '%s' is a PM -> also need to add a 'is a' 'approver' + 'scheduler'" % user)
         if user in sid_results[1] and 'has as role' in sid_results[1][user] :
              if isinstance(sid_results[1][user]['has as role'], list):
                 for role in sid_results[1][user]['has as role']:
-                    if role == 'OQM' or role ==  'Product Owner' or role == 'SDM' :      
+                    if role == 'OQM' or role ==  'Product Owner' or role == 'SDM' :
                         sid_need_approver.append(user)
-                        sid_need_scheduler.append(user)         
+                        sid_need_scheduler.append(user)
              else :
-                role = sid_results[1][user]['has as role'] 
-                if role == 'OQM' or role ==  'Product Owner' or role == 'SDM' :      
+                role = sid_results[1][user]['has as role']
+                if role == 'OQM' or role ==  'Product Owner' or role == 'SDM' :
                     sid_need_approver.append(user)
-                    sid_need_scheduler.append(user)         
-       
+                    sid_need_scheduler.append(user)
+
         # check and cleanup the data before scrat
         dict_keys = list(block_to_update['properties'].keys())
         for prop in dict_keys:
@@ -888,6 +968,9 @@ def main():
             to_print = pformat(block_to_update)
             for i in list(range(0, int(round(len(to_print) / 250)) + 1)):
                 logger.info('scrat %s cmd: %s' % (str(i), to_print[250 * i:250 * (i + 1)]))
+
+    sys.exit(1)
+
     params = {}
     sid_s_results = diego.diego_run_dieget_by_name('sid_sheduler_check', params)
     for user in sid_s_results[1]:
@@ -896,14 +979,14 @@ def main():
         if user not in sid_need_scheduler or user not in approver_scheduler_list:
             logger.error('SID user ' + user + ' should not be an scheduler.')
             if not dryrun:
-                if user in sid_results[1] : 
+                if user in sid_results[1] :
                     sid_update_user_exlude_approver_scheduler_change_management(diego, fqdn, res_rw_user, user, sid_results[1][user]['uid'], 'scheduler')
                 #pass
             else:
                 logger.error('dry run, user not removed from the scheduler role.')
             continue
-    
-    print(sid_need_scheduler, "SCHESDULER-LIST")
+
+    print(sid_need_scheduler, "SCHEDULERS-LIST")
     for user in sid_need_scheduler:
         if user in devnull_user:
             continue
@@ -916,15 +999,14 @@ def main():
             need_to_create = True
             logger.debug('SID user ' + user + ' should be addded to scheduler.')
             #create the relation if not exists
-        
+
         if not dryrun :
             sid_create_update_user_approver_scheduler_change_management(diego, fqdn, res_rw_user, user, sid_results[1][user]['uid'], 'scheduler', need_to_update)
             #pass
         else:
             logger.error('dry run, user not add/update from the scheduler role in "has as act"')
         continue
-    
-    
+
     params = {}
     sid_a_results = diego.diego_run_dieget_by_name('sid_approver_check', params)
     for user in sid_a_results[1]:
@@ -935,11 +1017,10 @@ def main():
             if not dryrun :
                 if user in  sid_results[1] :
                     sid_update_user_exlude_approver_scheduler_change_management(diego, fqdn, res_rw_user, user, sid_results[1][user]['uid'], 'approver')
-                #pass
             else:
                 logger.error('dry run, user not removed from the approver role.')
             continue
-    
+
     print(sid_need_approver, "APRROVERS-LIST")
     for user in sid_need_approver:
         if user in devnull_user:
@@ -952,10 +1033,10 @@ def main():
         elif user not in sid_a_results[1]:
             need_to_create = True
             logger.debug('SID user ' + user + ' should be addded to approver.')
+
         #create the relation if not exists
         if not dryrun:
             sid_create_update_user_approver_scheduler_change_management(diego, fqdn, res_rw_user, user, sid_results[1][user]['uid'], 'approver', need_to_update)
-            #pass
         else:
             logger.error('dry run, user not add/update from the approver role in "has as act".')
         continue
@@ -971,6 +1052,13 @@ def main():
         logger.info(sid_d_results[1])
 
         if 'has as member' in sid_d_results[1][department] and sid_d_results[1][department]['has as member'] is not None:
+            if not isinstance(sid_d_results[1][department]['has as member'], list):
+                # This is not a list, so this is a single value:
+                t = sid_d_results[1][department]['has as member']
+                sid_d_results[1][department]['has as member'] = list()
+                sid_d_results[1][department]['has as member'].append(t)
+                logger.info(sid_d_results[1])
+
             for user in sid_d_results[1][department]['has as member']:
                 if user in devnull_del_user:
                     logger.debug("Skipping the user in the dev_null:" + user)
@@ -983,7 +1071,7 @@ def main():
                 continue
             if 'departmentNumber' in ec_results['users'][user] and ec_results['users'][user]['departmentNumber'] != department:
                 continue
-            if 'has as member' in sid_d_results[1][department] and sid_d_results[1][department]['has as member'] is not None:
+            if 'has as member' in sid_d_results[1][department] and sid_d_results[1][department]['has as member'] is not None and user not in sid_d_results[1][department]['has as member']:
                 logger.info('SID user ' + user + ' should be addded to department ' + department + '.')
                 if not dryrun:
                     logger.info('dryrun')
diff --git a/bin/synchronize_home_Users.pl b/bin/synchronize_home_Users.pl
new file mode 100755
index 0000000..fb90e2e
--- /dev/null
+++ b/bin/synchronize_home_Users.pl
@@ -0,0 +1,422 @@
+#!/usr/bin/perl
+
+# ------------------------------------------------------------------------------
+# $Id$
+#
+# ------------------------------------------------------------------------------
+
+use strict;
+use warnings;
+use Getopt::Long;
+use Data::Dumper;
+use Config::IniFiles;
+use Net::LDAP;
+use File::Copy;
+use File::Basename;
+use Sys::Hostname;
+use Cwd;
+#use Net::OpenSSH::Compat 'Net::SSH2';
+
+# unbuffered output:
+$| = 1;
+
+use lib ( new Config::IniFiles( -file => "/opt/etc/ini/global.ini" )->val( 'APPLICATION', 'LIBRARY' ) );
+
+BEGIN {
+    my $iniFile = new Config::IniFiles( -file => "/opt/etc/ini/global.ini" );
+    push( @INC, $iniFile->val( 'APPLICATION', 'LIBRARY' ) );
+}
+
+use SNET::common;
+use SNET::snmpd;
+use SNET::LdapNS qw(:all);
+#use SNET::SSHDeviceInterfacer::Linux;
+
+use vars qw($verbose $debug $help $force $cli_mode $dry_run );
+$verbose  = 0;
+$debug    = 0;
+$cli_mode = 1;
+
+my $PROGNAME = basename( $0 );
+$PROGNAME =~ s/\.p[lm]$//;
+
+my %options = (
+                "help"    => \$help,
+                "debug"   => \$debug,
+                "verbose" => \$verbose,
+                "force"   => \$force,
+                "dry-run" => \$dry_run,
+);
+
+my $SNMP_ENTERPRISEOID = "99";
+my $SNMP_OID           = "1.3.6.1.4.1.99999.$SNMP_ENTERPRISEOID";
+my $SNMP_GEN           = "6";
+my $SNMP_SPE           = "1";
+my $msg                = '';
+my $title              = "Cacti ImportUser";
+
+help() if !GetOptions( %options ) or $help;
+$verbose = 1 if $debug;
+
+# ldap_find_users_and_groups()
+#
+# Read users and groups from SNet LDAP.
+
+sub ldap_find_users_and_groups ($$$$$$$$$$)
+{
+    my (
+         $cfg_ldap_server,              $cfg_ldap_user,            $cfg_ldap_passwd,    $cfg_ldap_group_search, $cfg_ldap_search_scope,
+         $cfg_ldap_group_search_filter, $cfg_ldap_group_attribute, $cfg_ldap_groupname, $hostname,              $cfg_ldap_cafile
+    ) = @_;
+
+    my %users;
+
+    # Connect to the LDAP server
+    metaprint( 'verbose', "Initiating connection to LDAP server <$cfg_ldap_server>:" ) if $verbose;
+    my $ldap = Net::LDAP->new(
+        $cfg_ldap_server,
+        async   => 0,
+        onerror => (
+            ( $debug == 0 ) ? sub { return $_[0] } : sub {
+                my $message = shift;
+                my $error = defined( $message->error_desc ) ? $message->error_desc : $message->error();
+                $msg = "Ldap: Unable to process request: $error.";
+                metaprint( 'error', $title . ": " . $msg );
+                snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] );
+                return $message;
+            }
+        ),
+    );
+    if ( !$ldap ) {
+        $msg = "LDAP connection to <$cfg_ldap_server> failed.";
+        metaprint( 'error', $title . ": " . $msg ) if $verbose;
+        snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] );
+        exit 1;
+    }
+    metaprint( 'verbose', "* LDAP connection completed successfully." ) if $verbose;
+
+    my $message;
+    eval {
+        print STDERR 'Starting tls' . "\n" if ( $debug );
+        $message = $ldap->start_tls( verify => 'require',
+                                     cafile => $cfg_ldap_cafile, );
+        if ( $message->is_error() ) {
+            $msg = "Could not encrypt LDAP connection.";
+            metaprint( 'error', $title . ": " . $msg ) if $verbose;
+            snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] );
+            exit 1;
+        }
+    };
+    if ( $@ ) {
+        $msg = "Crash - Could not encrypt LDAP connection.";
+        metaprint( 'error', $title . ": " . $msg ) if $verbose;
+        snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] );
+        exit 1;
+    }
+
+    eval {
+        print STDERR 'binding' . "\n" if ( $debug );
+        $message = $ldap->bind(
+                                $cfg_ldap_user,
+                                password => $cfg_ldap_passwd,
+                                version  => 3,
+        );
+        if ( $message->is_error() ) {
+            $msg = "LDAP bind error occurred.";
+            metaprint( 'error', $title . ": " . $msg ) if $verbose;
+            snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] );
+            exit 1;
+        }
+    };
+    if ( $@ ) {
+        $msg = "Crash - LDAP bind error occurred ('" . $message->error_name . "').";
+        metaprint( 'error', $title . ": " . $msg ) if $verbose;
+        snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] );
+        exit 1;
+    }
+
+    metaprint( 'verbose', "* LDAP bind operation completed successfully." ) if $verbose;
+
+    # Search AD for objects in a particular group using LDAP
+
+    metaprint( 'info', "Getting the LDAP member with expiration." ) if $verbose;
+    my %searchargs;
+    $searchargs{base}   = 'ou=posix,' . $cfg_ldap_group_search;
+    $searchargs{scope}  = $cfg_ldap_search_scope;
+    $searchargs{filter} = $cfg_ldap_group_search_filter;
+    $searchargs{attrs}  = $cfg_ldap_group_attribute;
+
+    print Dumper( \%searchargs ) if $verbose;
+
+    my $results;
+    eval { $results = $ldap->search( %searchargs ); };
+    if ( $@ ) {
+        my $title = "Check Password";
+        my $msg   = "Crash - LDAP Users Search.";
+        metaprint( 'error', $title . ": " . $msg ) if $verbose;
+        snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] );
+        exit 1;
+    }
+
+    if ( $results->is_error() ) {
+        metaprint( 'error', 'search failed: ' . $results->error_text );
+        metaprint( 'error', 'search failed: ' . $results->code );
+        metaprint( 'error', 'search failed: ' . $results->error );
+    } elsif ( $results->count() == 0 ) {
+        metaprint( 'error', 'no result' );
+    } else {
+        metaprint( 'verbose', "* Search returned " . $results->count . " object." ) if $verbose;
+        print Dumper( $results->as_struct() ) if $verbose;
+        my $ldap_hash = $results->as_struct();
+
+        my $attribute = $searchargs{attrs}[0];
+        if ( defined( $ldap_hash->{ "cn=$cfg_ldap_groupname," . $searchargs{base} }{$attribute} ) ) {
+            foreach my $url ( @{ $ldap_hash->{ "cn=$cfg_ldap_groupname," . $searchargs{base} }{$attribute} } ) {
+
+                print "$url\n" if $verbose;
+                push( @{ $users{$url}{'groups'} }, $cfg_ldap_groupname );
+
+                # fetch the user gecos
+                my %usersearch;
+                $usersearch{base} = $cfg_ldap_group_search;
+                $usersearch{base} =~ s/groups/people/;
+                $usersearch{attrs}  = [ 'gecos', 'uid' ];
+                $usersearch{scope}  = 'sub';
+                $usersearch{filter} = '(&(objectClass=posixAccount)(uid=' . $url . '))';
+                print Dumper( \%usersearch ) if $verbose;
+
+                my $userresults;
+                eval { $userresults = $ldap->search( %usersearch ); };
+                if ( $@ ) {
+                    my $title = "Check Password";
+                    my $msg   = "Crash - LDAP Mail Users Search.";
+                    metaprint( 'error', $title . ": " . $msg ) if $verbose;
+                    snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] );
+                    exit 1;
+                }
+                if ( $userresults->is_error() ) {
+                    metaprint( 'error', 'search failed: ' . $userresults->error_text );
+                    metaprint( 'error', 'search failed: ' . $userresults->code );
+                    metaprint( 'error', 'search failed: ' . $userresults->error );
+                } elsif ( $userresults->count() == 0 ) {
+                    metaprint( 'error', 'no result' );
+                } else {
+                    metaprint( 'info', "* Search returned " . $userresults->count . " url for '$url'." ) if $verbose;
+                    print Dumper ( $userresults ) if $verbose;
+
+                    foreach my $uid ( $userresults->entries ) {
+                        print "'" . $uid->get_value( 'uid' ) . "'\n" if $verbose;
+                        if ( !defined( $uid->get_value( 'gecos' ) ) ) {
+                            $users{ $uid->get_value( 'uid' ) } = '';
+                        } else {
+                            $users{ $uid->get_value( 'uid' ) }{'gecos'} = $uid->get_value( 'gecos' );
+                        }
+                    }
+                }
+
+            }
+        } else {
+            metaprint( 'error', "Could not parse the hash result: {" . "cn=$cfg_ldap_groupname," . $searchargs{base} . "} { " . $attribute . " }" );
+        }
+    }
+
+    print "\nClosing LDAP connection.\n" if $verbose;
+    $ldap->unbind;
+    return %users;
+}
+
+#
+# Global Declarations
+#
+# load the INI
+metaprint( "info", "Loading INI file Parameters" );
+my $global_iniFile = new Config::IniFiles( -file => "/opt/etc/ini/global.ini" );
+
+my $CiniFile = new Config::IniFiles( -file => $global_iniFile->val( 'INI', 'RME' ) );
+metaprint( "error", "error value of CiniFile is undefined" ) if ( !defined( $CiniFile ) );
+
+my $outpath = $CiniFile->val( 'GLOBAL', 'OUTPATH' );
+metaprint( "error", "The defined outpath is not valid, please correct-it" ) if ( !defined( $outpath ) );
+
+my $AiniFile = new Config::IniFiles( -file => $global_iniFile->val( 'INI', 'LDAP' ) );
+metaprint( "error", "error value of AiniFile is undefined" ) if ( !defined( $AiniFile ) );
+
+my $cfg_ldap_server = $AiniFile->val( 'LDAP_SNET_NG', 'SERVER' );
+metaprint( "error", "error value of cfg_ldap_server is undefined" ) if ( !defined( $cfg_ldap_server ) );
+my $cfg_ldap_user = $AiniFile->val( 'LDAP_SNET_NG', 'USER' );
+metaprint( "error", "error value of cfg_ldap_user is undefined" ) if ( !defined( $cfg_ldap_user ) );
+my $cfg_ldap_passwd = $AiniFile->val( 'LDAP_SNET_NG', 'PASSWORD' );
+metaprint( "error", "error value of cfg_ldap_passwd is undefined" ) if ( !defined( $cfg_ldap_passwd ) );
+my $cfg_ldap_group_search = $AiniFile->val( 'LDAP_SNET_NG', 'GRP_SEARCH' );
+metaprint( "error", "error value of cfg_ldap_group_search is undefined" ) if ( !defined( $cfg_ldap_group_search ) );
+my $cfg_ldap_group_search_filter = $AiniFile->val( 'LDAP_SNET_NG', 'FILTER' );
+metaprint( "error", "error value of cfg_ldap_group_search_filter is undefined" ) if ( !defined( $cfg_ldap_group_search_filter ) );
+$cfg_ldap_group_search_filter = "(&(objectclass=posixGroup)(cn=REPLACE))";
+my $cfg_ldap_group_attribute = $AiniFile->val( 'LDAP_SNET_NG', 'GRP_ATTRIBUTE' );
+metaprint( "error", "error value of cfg_ldap_group_attribute is undefined" ) if ( !defined( $cfg_ldap_group_attribute ) );
+$cfg_ldap_group_attribute = ["memberuid"];
+my $cfg_ldap_search_scope = $AiniFile->val( 'LDAP_SNET_NG', 'SEARCH_SCOPE' );
+metaprint( "error", "error value of cfg_ldap_search_scope is undefined" ) if ( !defined( $cfg_ldap_search_scope ) );
+my $cfg_ldap_cafile = $AiniFile->val( 'LDAP_SNET_NG', 'CA' );
+metaprint( "error", "error value of cfg_ldap_cafile is undefined" ) if ( !defined( $cfg_ldap_cafile ) );
+
+# vSHARE credentails configuration
+my $LiniFile = new Config::IniFiles( -file => $global_iniFile->val( 'INI', 'RME' ) );
+metaprint( "error", "error value of LiniFile is undefined" ) if ( !defined( $LiniFile ) );
+my $vshare_servers = $LiniFile->val( 'vshare', 'SERVERS' );
+metaprint( "error", "error value of vshare_servers is undefined" ) if ( !defined( $vshare_servers ) );
+my $vshare_user = $LiniFile->val( 'vshare', 'USER' );
+metaprint( "error", "error value of vshare_user is undefined" ) if ( !defined( $vshare_user ) );
+my $vshare_passwd = $LiniFile->val( 'vshare', 'PASSWD' );
+metaprint( "error", "error value of vshare_passwd is undefined" ) if ( !defined( $vshare_passwd ) );
+
+my @filters;
+push( @filters, 'com' );
+push( @filters, 'mgt' );
+push( @filters, 'net' );
+push( @filters, 'pi' );
+push( @filters, 'pm' );
+push( @filters, 'sd' );
+push( @filters, 'sec' );
+push( @filters, 'sup' );
+push( @filters, 'tda' );
+push( @filters, 'officials' );
+
+my $hostname = hostname();
+
+# Main Application
+metaprint( "info", "Starting users synchro" );
+
+my $errors = 0;
+
+my $already_defined_users = {};
+my $ssh;
+my $out;
+
+metaprint( 'info', "processing vshare servers..." );
+foreach my $server ( split( /,/, $vshare_servers ) ) {
+
+    # SSH to server.
+    metaprint 'info', 'Working on ' . $server . '...';
+    $ssh = new SNET::SSHDeviceInterfacer::Linux( $debug, $server, $vshare_user, $vshare_passwd );
+    if ( !$cli_mode ) {
+        $ssh->set_webmode( 1 );
+    }
+
+    if ( $ssh->openSSHConnection() ) {
+        metaprint 'info', "-> ok connected";
+    } else {
+        metaprint 'error', "-> connection failed";
+        $errors++;
+        next;
+    }
+
+    my $cln = ();
+    $cln->{'uid'}  = 3;
+    $cln->{'gid'}  = 4;
+    $cln->{'name'} = 9;
+
+    $out = $ssh->sendCMD( "/bin/ls -aildn /opt/home/*" );
+    if ( $out =~ m/\s\/opt\/home\/\w+/i ) {
+        foreach my $line ( split( /\n/, $out ) ) {
+            chomp $line;
+            next if ( $line =~ /ls -aildn/ );
+            next if ( $line =~ /\/export\/home\/snet/ );
+            next if ( $line =~ /lost\+found/ );
+            $line =~ s/^\s*//;
+            print Dumper ( $line ) if $debug;
+
+            my $tmp = ();
+            @$tmp = split( /\s+/, $line );
+            $tmp->[ $cln->{'name'} ] =~ s/\/*$//g;
+            $tmp->[ $cln->{'name'} ] =~ s/^\/.*\///;
+            print Dumper ( $tmp ) if $debug;
+
+            # 3 : uid
+            # 4 : gid
+            # 9 : name
+            foreach my $pos ( keys %$cln ) {
+                $already_defined_users->{ $tmp->[ $cln->{'name'} ] }{$pos} = $tmp->[ $cln->{$pos} ];
+            }
+        }
+        last;
+    } else {
+        $errors++;
+        next;
+    }
+
+}
+
+if ( $errors ) {
+    metaprint( 'error', "Some errors have been found, please contact SS Team!" . nl() . "Please copy/paste the output to the email!" );
+    exit 1;
+}
+
+#Print Users from Cacti
+print Dumper ( $already_defined_users ) if $verbose;
+
+# -- Create the import file
+my $cpt     = 0;
+my $cpt_del = 0;
+
+foreach my $filter ( @filters ) {
+
+    metaprint "info", "Checking groups '$filter'.";
+    my $cfg_ldap_group_search_f = $cfg_ldap_group_search_filter;
+    $cfg_ldap_group_search_f =~ s/REPLACE/$filter/;
+    print "$cfg_ldap_group_search_f\n" if $verbose;
+    my %ldap_users = ldap_find_users_and_groups( $cfg_ldap_server,         $cfg_ldap_user,            $cfg_ldap_passwd, $cfg_ldap_group_search, $cfg_ldap_search_scope,
+                                                 $cfg_ldap_group_search_f, $cfg_ldap_group_attribute, $filter,          $hostname,              $cfg_ldap_cafile );
+
+    print Dumper ( \%ldap_users ) if $verbose;
+
+    foreach my $u ( keys %ldap_users ) {
+        if ( defined( $already_defined_users->{$u} ) && ( $already_defined_users->{$u} ) ) {
+            metaprint( "info", "Skipping user $u import, user is already defined, but user need to be checked." ) if $verbose;
+
+            # TODO check uid:gid
+            $already_defined_users->{$u}{'found'} = 1;
+            next;
+        }
+
+        next if ( $ldap_users{$u} =~ /^$/ );
+        my $cmd = "sudo mkdir /mnt/home/$u && sudo chown $u:snmc /mnt/home/$u";
+        metaprint( "info", "$u need to be created: '$cmd'." );
+        if ( !$dry_run ) {
+            eval { $out = $ssh->sendCMD( $cmd ); };
+            if ( $out =~ m/password/i ) {
+                $out = $ssh->sendCMD( $vshare_passwd );
+            }
+            print $out;
+        }
+        $cpt++;
+    }
+}
+
+my $local_user_no_del = ();
+$local_user_no_del->{'snet'}       = 1;
+$local_user_no_del->{'quotas'}     = 1;
+$local_user_no_del->{'casuser'}    = 1;
+$local_user_no_del->{'ns-vernada'} = 1;
+
+metaprint "info", "Checking all others vshare home directory users defined.";
+foreach my $u ( keys %$already_defined_users ) {
+    if (    defined( $already_defined_users->{$u} )
+         && ( $already_defined_users->{$u} )
+         && defined( $already_defined_users->{$u}{'found'} )
+         && ( $already_defined_users->{$u}{'found'} ) ) {
+        next;
+    } elsif ( defined( $local_user_no_del->{$u} ) ) {
+        next;
+    } else {
+        metaprint( "error", "User $u need to be deleted manually." );
+        metaprint( "error", "MANUAL: sudo tar -jcf /mnt/home/_OLD/$u.tbz /mnt/home/$u ; sudo rm -rf /mnt/home/$u" );
+        $cpt_del++;
+    }
+}
+eval { $out = $ssh->sendCMD( "exit" ); };
+
+metaprint( "info", "$cpt user(s) created." );
+metaprint( "info", "$cpt_del user(s) need to be deleted." );
+metaprint( "info", "--- Process Done ---" );
+exit( 0 );
diff --git a/bin/synchronize_redmine_projects.py b/bin/synchronize_redmine_projects.py
new file mode 100755
index 0000000..e5395c4
--- /dev/null
+++ b/bin/synchronize_redmine_projects.py
@@ -0,0 +1,760 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from __future__ import absolute_import, print_function
+
+import os
+import sys
+
+import configparser as ConfigParser
+import pprint
+import inspect
+import traceback
+import shlex
+import re
+import requests
+from subprocess import check_output, STDOUT, CalledProcessError
+
+pp = pprint.PrettyPrinter(indent=4)
+
+PROGNAME = os.path.basename(sys.argv[0]).split(".")[0]
+script = os.path.basename(__file__).split(".")[0]
+
+global_iniFile = '/opt/etc/ini/global.ini'
+config_global = ConfigParser.RawConfigParser()
+config_global.optionxform(str())
+config_global.optionxform = str
+config_global.read(global_iniFile)
+sys.path.append(config_global.get('APPLICATION', 'PYTHON-LIBRARY'))
+
+from redminelib import Redmine
+
+if 'http_proxy' in os.environ:
+    del os.environ['http_proxy']
+if 'https_proxy' in os.environ:
+    del os.environ['https_proxy']
+
+CA_bundle = '/usr/local/share/ca-certificates/snetroot/SNetRootCA_device_bundle.pem'
+CA_bundle = '/etc/ssl/certs/ca-certificates.crt'
+
+basedir = '/opt/SNet/scm'
+
+wanted_membership = {}
+wanted_membership['com'] = 'Reporter'
+wanted_membership['mgt'] = 'Reporter'
+wanted_membership['officials'] = 'Reporter'
+wanted_membership['net'] = 'Developer'
+wanted_membership['pi'] = 'Developer'
+wanted_membership['sd'] = 'Developer'
+wanted_membership['sec'] = 'Developer'
+wanted_membership['sup'] = 'Developer'
+wanted_membership['tda'] = 'Developer'
+wanted_membership['pm'] = 'Manager'
+
+cmd = ("ssh vcodebox-lu find %s -path '\*/.hg' -prune -o -type d -path '\*/.hg' | grep -v '^.hg$'" % (basedir))
+
+try:
+    output = check_output((shlex.split(cmd)), stderr=STDOUT, shell=False)
+except CalledProcessError as ex:
+    output = ex.output
+# print(output)
+
+folder_projects = []
+for l in output.splitlines():
+    if not l.startswith(basedir):
+        continue
+    if not l.endswith('/.hg'):
+        continue
+    if l == basedir + '/.hg':
+        continue
+    if 'archive_' in l:
+        continue
+    pat = l.replace('/.hg', '').replace(basedir + '/', '')
+
+    # print("%s %s" % (l, pat))
+    folder_projects.append(pat)
+
+
+def obj_dump(obj):
+    '''
+      Object dumper
+    '''
+    for attr in dir(obj):
+        if '_' in attr:
+            continue
+        try:
+            print("obj.%s = %s" % (attr, str(getattr(obj, attr))))
+        except:
+            print("obj.%s = %s" % (attr, getattr(obj, attr)))
+
+    for name, data in inspect.getmembers(obj):
+        if inspect.isclass(data):
+            print('name:%s' % (name))
+            print(data)
+
+
+def obj_dump_r(obj, level=0, deepth=2):
+    '''
+       Recursive Object dumper
+    '''
+    for attr in dir(obj):
+        if '_' in attr:
+            continue
+        try:
+            msg = 2*level*' '
+            msg += ("obj.%s = %s" % (attr, str(getattr(obj, attr))))
+            print(msg)
+        except:
+            msg = 2*level*' '
+            msg += ("obj.%s = %s" % (attr, getattr(obj, attr)))
+            print(msg)
+
+        if level >= deepth:
+            continue
+
+        try:
+            obj_dump_r(getattr(obj, attr), level=level+1)
+        except:
+            msg = 2*level*' '
+            msg += "Dump is stinking... crashed."
+            print(msg)
+
+
+def redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, pj_id, pj_ident, repository_url):
+
+    '''
+       curl -v -H "Content-Type: application/json" -X POST -d '{"id": "3581", "vendor": "Mercurial", "repository": {"url": "/opt/SNet/scm/pkg/bind9-snet/bind9-bindhg-snet", "identifier":"bind9-bindhg-snet"}}' "https://redmine.snmc.cec.eu.int/sys/projects/3581/repository?key=tU0LvEthIX4cMzCI9YPI"
+    '''
+
+    redmine_url = "%s://%s/sys/projects/%s/repository?key=%s" % (REDMINE_PROTO, REDMINE_HOSTNAME, pj_id, REDMINE_WS_KEY)
+    playload = {}
+    playload['id'] = pj_id
+    playload['vendor'] = 'Mercurial'
+    playload['repository'] = {}
+    playload['repository']['identifier'] = pj_ident
+    playload['repository']['url'] = repository_url
+
+    try:
+        response = requests.post(redmine_url,
+                                 json=playload,
+                                 allow_redirects=True,
+                                 verify=CA_bundle)
+
+    except requests.exceptions.SSLError as e:
+        self.logger.error('%s: %s' % (redmine_url, str(e)))
+        return None
+    except Exception as e:
+        self.logger.error('Generic: %s' % (str(e)))
+        return None
+
+    if response.status_code == 201:
+        print('OK')
+        print(response.content)
+        return None
+    else:
+        print('ERROR')
+        print(response.status_code)
+        print(response.content)
+        return None
+
+
+redmine_config_global = ConfigParser.RawConfigParser()
+redmine_config_global.read(config_global.get('INI', 'Redmine'))
+
+# Parse config
+REDMINE_HOSTNAME = redmine_config_global.get('GLOBAL', 'HOST')
+REDMINE_PROTO = redmine_config_global.get('GLOBAL', 'PROTO')
+REDMINE_KEY = redmine_config_global.get('CREDENTIAL', 'APIkey')
+REDMINE_WS_KEY = redmine_config_global.get('GLOBAL', 'WS_KEY')
+
+redmine = Redmine('%s://%s' % (REDMINE_PROTO, REDMINE_HOSTNAME), key=REDMINE_KEY, requests={'verify': CA_bundle}, version='3.4.4')
+
+all_red_parent = {}
+all_red_pj = {}
+all_red_cross_pj = {}
+red_projects = redmine.project.all(offset=0, limit=1000, include='enabled_modules,repositories,trackers')
+
+for u in red_projects:
+    # print(u)
+    # print('%s' % (u.id))
+    # print('%s' % (u.name))
+    # print('%s' % (u.identifier))
+    all_red_pj[u.identifier] = {}
+    all_red_pj[u.identifier]['id'] = u.id
+    all_red_pj[u.identifier]['name'] = u.name
+    all_red_pj[u.identifier]['identifier'] = u.identifier
+    all_red_pj[u.identifier]['enabled_modules'] = u.enabled_modules
+    all_red_pj[u.identifier]['repositories'] = u.repositories
+    if hasattr(u, 'is_public'):
+        all_red_pj[u.identifier]['is_public'] = u.is_public
+    else:
+        all_red_pj[u.identifier]['is_public'] = False
+
+    if 'parent' in dir(u):
+        # print('parent:%s' % (u.parent))
+        all_red_pj[u.identifier]['parent'] = {}
+        all_red_pj[u.identifier]['parent']['name'] = u.parent.name
+        all_red_pj[u.identifier]['parent']['id'] = u.parent.id
+        # all_red_pj[u.identifier]['parent']['identifier'] = u.parent.identifier
+        all_red_parent[u.parent.name+'/'+u.name] = u.identifier
+
+    if u.identifier == 'refconfig':
+        pp.pprint(all_red_pj[u.identifier])
+        # obj_dump(u)
+        # obj_dump_r(u, level=0, deepth=1)
+        print(u.enabled_modules)
+        print(u.repositories)
+        print(u.is_public)
+        print(list(u))
+        # sys.exit(0)
+
+    if u.name != u.identifier:
+        all_red_cross_pj[u.name] = u.identifier
+        # pp.pprint(all_red_cross_pj[u.name])
+
+    continue
+    print('%s' % (u.id))
+    print('%s' % (u.name))
+    print('%s' % (u.identifier))
+    if 'parent' in u:
+        print('%s' % (u.parent))
+
+pp.pprint(all_red_parent)
+
+red_groups = redmine.group.all()
+all_red_grp = {}
+for g in red_groups:
+    all_red_grp[g.name] = {}
+    all_red_grp[g.name]['id'] = g.id
+    all_red_grp[g.id] = {}
+    all_red_grp[g.id]['name'] = g.name
+# print(pp.pformat(all_red_grp))
+
+red_roles = redmine.role.all()
+all_red_rl = {}
+for r in red_roles:
+    all_red_rl[r.name] = {}
+    all_red_rl[r.name]['id'] = r.id
+    all_red_rl[r.id] = {}
+    all_red_rl[r.id]['name'] = r.name
+# print(pp.pformat(all_red_rl))
+
+# sys.exit(1)
+
+limit = 3000
+cpt = 0
+for pj in sorted(folder_projects):
+    if cpt > limit:
+        break
+    cpt += 1
+
+    print("----%s" % (pj))
+    if '/' in pj:
+        (parent, pjj) = pj.rsplit('/', 1)
+        if '/' in parent:
+            cnt = parent.count('/')
+            if cnt == 1:
+                if parent in all_red_parent:
+                    parent = all_red_parent[parent]
+                else:
+                    print("Parent '%s' with 1/ but not found (%s), creating pre-parent" % (parent, pj))
+
+                    prepa, ppa = parent.split('/')
+                    prepa_ident = prepa.lower().replace('.', '-')
+                    ppa_ident = ppa.lower().replace('.', '-')
+                    ''' Pre-parent check-up. '''
+                    if prepa_ident in all_red_pj:
+                        print("Pre-Parent '%s' is found" % (prepa))
+                        prepa_id = all_red_pj[prepa_ident]['id']
+                    elif prepa in all_red_cross_pj:
+                        print("Pre-Parent '%s' is found in the bad list" % (prepa))
+                        prepa_id = all_red_pj[all_red_cross_pj[prepa]]['id']
+                    else:
+                        print("Pre-Parent '%s:%s' need to be created" % (prepa, prepa_ident))
+
+                        try:
+                            project = redmine.project.new()
+                            project.name = prepa
+                            project.identifier = prepa_ident
+                            project.description = prepa
+                            project.homepage = None
+                            project.is_public = True
+                            project.inherit_members = False
+                            project.parent_id = None
+                            project.enabled_module_names = []
+                            project.save()
+                        except Exception as e:
+                            print('The creation of the ressources project "%s" did not suceed: %s' % (parent, str(e)))
+                            print(traceback.format_exc(5))
+                            sys.exit(1)
+                        prepa_id = project.id
+
+                        all_red_pj[project.identifier] = {}
+                        all_red_pj[project.identifier]['id'] = project.id
+                        all_red_pj[project.identifier]['name'] = project.name
+                        all_red_pj[project.identifier]['identifier'] = project.identifier
+                        all_red_pj[project.identifier]['enabled_modules'] = project.enabled_modules
+                        all_red_pj[project.identifier]['repositories'] = project.repositories
+                        if hasattr(project, 'is_public'):
+                            all_red_pj[project.identifier]['is_public'] = project.is_public
+                        else:
+                            all_red_pj[project.identifier]['is_public'] = False
+
+                    # Preparent membership
+
+                    print("membership prepa_id is %s." % (prepa_id))
+
+                    pj_wanted_membership = dict(wanted_membership)
+                    pj_membership_del = []
+                    real_membership = redmine.project_membership.filter(project_id=prepa_id)
+
+                    for mb in real_membership:
+                        if hasattr(mb, 'user'):
+                            continue
+                        '''
+                        print("------------")
+                        print("membership")
+                        print("mb.project: %s %s" % (mb.project.id, mb.project.name))
+                        print("mb.group: %s %s" % (mb.group.id, mb.group.name))
+                        print("mb.roles")
+                        for rl in mb.roles:
+                            print("%s %s" % (rl.id, rl.name))
+                        '''
+                        if mb.group.name in pj_wanted_membership:
+                            for rl in mb.roles:
+                                if pj_wanted_membership[mb.group.name] == rl.name:
+                                    del(pj_wanted_membership[mb.group.name])
+                                else:
+                                    for rl in mb.roles:
+                                        pj_membership_del.append(mb.id)
+
+                        else:
+                            pj_membership_del.append(mb.id)
+
+                    pp.pprint(pj_wanted_membership)
+                    for gr in pj_wanted_membership:
+                        membership = redmine.project_membership.new()
+                        membership.project_id = prepa_id
+                        # http://www.redmine.org/issues/17904 group is user...
+                        membership.user_id = all_red_grp[gr]['id']
+                        membership.role_ids = [all_red_rl[pj_wanted_membership[gr]]['id']]
+                        membership.save()
+
+                    pp.pprint(pj_membership_del)
+                    for mb in pj_membership_del:
+                        membership = redmine.project_membership.get(prepa_id)
+                        membership.delete(mb)
+
+                    ''' Parent check-up. '''
+                    if ppa_ident in all_red_pj:
+                        print("Parent '%s' is found" % (ppa))
+                        ppa_id = all_red_pj[ppa_ident]['id']
+                    elif ppa in all_red_cross_pj:
+                        print("Parent '%s' is found in the bad list" % (ppa))
+                        ppa_id = all_red_pj[all_red_cross_pj[ppa]]['id']
+                    else:
+                        print("Parent '%s:%s' need to be created" % (ppa, ppa_ident))
+
+                        try:
+                            project = redmine.project.new()
+                            project.name = ppa
+                            project.identifier = ppa_ident
+                            project.description = ppa
+                            project.homepage = None
+                            project.is_public = True
+                            project.inherit_members = False
+                            project.parent_id = prepa_id
+                            project.enabled_module_names = []
+                            project.save()
+                        except Exception as e:
+                            print('The creation of the ressources project "%s" did not suceed: %s' % (ppa, str(e)))
+                            print(traceback.format_exc(5))
+                            sys.exit(1)
+                        ppa_id = project.id
+
+                        all_red_pj[project.identifier] = {}
+                        all_red_pj[project.identifier]['id'] = project.id
+                        all_red_pj[project.identifier]['name'] = project.name
+                        all_red_pj[project.identifier]['identifier'] = project.identifier
+                        all_red_pj[project.identifier]['enabled_modules'] = project.enabled_modules
+                        if hasattr(project, 'is_public'):
+                            all_red_pj[project.identifier]['is_public'] = project.is_public
+                        else:
+                            all_red_pj[project.identifier]['is_public'] = False
+
+                        all_red_pj[project.identifier]['parent'] = {}
+                        all_red_pj[project.identifier]['parent']['name'] = project.parent.name
+                        all_red_pj[project.identifier]['parent']['id'] = project.parent.id
+                        all_red_parent[project.parent.name+'/'+project.name] = project.identifier
+
+            else:
+                match = re.search(r'^.*/([^/]+/[^/]+)$', parent)
+                if match.group(1) in all_red_parent:
+                    parent = all_red_parent[match.group(1)]
+                else:
+                    print("Parent '%s' need to be decomposed for %s, skipping for now" % (parent, pj))
+                    continue
+    else:
+        parent = None
+        pjj = pj
+
+    print("%s:%s" % (parent, pjj))
+    if parent:
+        parent_ident = parent.lower().replace('.', '-')
+    pj_ident = pjj.lower().replace('.', '-')
+
+    '''
+        PARENT
+    '''
+
+    if parent and parent_ident in all_red_pj:
+        print("Parent '%s' is found" % (parent))
+        parent_id = all_red_pj[parent_ident]['id']
+    elif parent and parent in all_red_cross_pj:
+        print("Parent '%s' is found in the bad list" % (parent))
+        parent_id = all_red_pj[all_red_cross_pj[parent]]['id']
+    elif parent:
+        print("Parent '%s:%s' need to be created" % (parent, parent_ident))
+
+        try:
+            project = redmine.project.new()
+            project.name = parent
+            project.identifier = parent_ident
+            project.description = parent
+            project.homepage = None
+            project.is_public = True
+            project.inherit_members = False
+            project.parent_id = None
+            project.enabled_module_names = []
+            # project.enabled_modules = [] readonly attribute
+            # project.custom_fields = [{'id': 1, 'value': 'PE'}, {'id': 11, 'value': 'scm'}]
+            # list(project)
+            project.save()
+        except Exception as e:
+            print('The creation of the ressources project "%s" did not suceed: %s' % (parent, str(e)))
+            print(traceback.format_exc(5))
+            break
+
+        all_red_pj[project.identifier] = {}
+        all_red_pj[project.identifier]['id'] = project.id
+        all_red_pj[project.identifier]['name'] = project.name
+        all_red_pj[project.identifier]['identifier'] = project.identifier
+        all_red_pj[project.identifier]['is_public'] = True
+        parent_id = project.id
+
+    else:
+        parent_id = None
+
+    if parent_id is not None:
+
+        project = redmine.project.get(parent_id)
+        project.is_public = True
+        project.inherit_members = False
+        project.save()
+
+        if 'enabled_modules' not in all_red_pj[parent_ident]:
+            print("No repository module activated for parent, OK")
+
+        elif 'repository' not in all_red_pj[parent_ident]['enabled_modules']:
+            print("No repository for parent, OK")
+
+        elif len(all_red_pj[parent_ident]['repositories']) == 0:
+            print("No repository for parent, OK")
+
+        else:
+            print("repository activated for parent should not")
+
+        print("membership parent_id is %s." % (parent_id))
+
+        pj_wanted_membership = dict(wanted_membership)
+        pj_membership_del = []
+        real_membership = redmine.project_membership.filter(project_id=parent_id)
+
+        for mb in real_membership:
+            if hasattr(mb, 'user'):
+                continue
+            '''
+            print("------------")
+            print("membership")
+            print("mb.project: %s %s" % (mb.project.id, mb.project.name))
+            print("mb.group: %s %s" % (mb.group.id, mb.group.name))
+            print("mb.roles")
+            for rl in mb.roles:
+                print("%s %s" % (rl.id, rl.name))
+            '''
+            if mb.group.name in pj_wanted_membership:
+                for rl in mb.roles:
+                    if pj_wanted_membership[mb.group.name] == rl.name:
+                        del(pj_wanted_membership[mb.group.name])
+                    else:
+                        for rl in mb.roles:
+                            pj_membership_del.append(mb.id)
+
+            else:
+                pj_membership_del.append(mb.id)
+
+        pp.pprint(pj_wanted_membership)
+        for gr in pj_wanted_membership:
+            membership = redmine.project_membership.new()
+            membership.project_id = parent_id
+            # http://www.redmine.org/issues/17904 group is user...
+            membership.user_id = all_red_grp[gr]['id']
+            membership.role_ids = [all_red_rl[pj_wanted_membership[gr]]['id']]
+            membership.save()
+
+        pp.pprint(pj_membership_del)
+        for mb in pj_membership_del:
+            membership = redmine.project_membership.get(parent_id)
+            membership.delete(mb)
+
+    '''
+        ITSELF
+    '''
+
+    if pjj in all_red_pj:
+        print("The project '%s' is found in all_red_pj." % (pjj))
+        repository_url = os.path.join(basedir, pj)
+        print("hg:%s:%s" % (pj_ident, repository_url))
+        pp.pprint(all_red_pj[pjj])
+
+        if parent and 'parent' in all_red_pj[pjj]:
+            if parent != all_red_pj[pjj]['parent']['name']:
+                print("Not the same parent %s:%s" % (parent, all_red_pj[pjj]['parent']['name']))
+                project = redmine.project.get(all_red_pj[pjj]['id'])
+                project.parent_id = parent_id
+                project.is_public = True
+                project.inherit_members = False
+                project.custom_fields = [{'id': 11, 'value': repository_url}]
+                project.save()
+
+        elif parent:
+            print("Not the same parent %s:None" % (parent))
+            project = redmine.project.get(all_red_pj[pjj]['id'])
+            project.parent_id = parent_id
+            project.is_public = True
+            project.inherit_members = False
+            project.custom_fields = [{'id': 11, 'value': repository_url}]
+            project.save()
+            redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[pjj]['id'], pj_ident, repository_url)
+
+        if 'repository' not in all_red_pj[pjj]['enabled_modules']:
+            print("Repository is not activated for repo %s:%s" % (pjj, pj_ident))
+            project = redmine.project.get(all_red_pj[pjj]['id'])
+            project.is_public = True
+            project.inherit_members = False
+            project.custom_fields = [{'id': 11, 'value': repository_url}]
+            project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking',
+                                            'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt']
+            project.tracker_ids = [1, 2]
+            project.save()
+            redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[pjj]['id'], pj_ident, repository_url)
+
+        elif len(all_red_pj[pjj]['repositories']) == 0:
+            print("Repository URL is empty for repo %s:%s (%s)" % (pjj, pj_ident, os.path.join(basedir, pj)))
+            project = redmine.project.get(all_red_pj[pjj]['id'])
+            project.is_public = True
+            project.inherit_members = False
+            project.custom_fields = [{'id': 11, 'value': repository_url}]
+            project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking',
+                                            'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt']
+            project.tracker_ids = [1, 2]
+            project.save()
+            redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[pjj]['id'], pj_ident, repository_url)
+
+        elif os.path.join(basedir, pj) != all_red_pj[pjj]['repositories'][0]['url']:
+            print("Repository URL is bad for repo %s:%s (%s <> %s)"
+                  % (pjj, pj_ident, os.path.join(basedir, pj), all_red_pj[pjj]['repositories'][0]['url']))
+
+        # if all_red_pj[pjj]['is_public']:
+        # reset verything to is_public false
+        project = redmine.project.get(all_red_pj[pjj]['id'])
+        project.is_public = True
+        project.inherit_members = False
+        project.custom_fields = [{'id': 11, 'value': repository_url}]
+        project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking',
+                                        'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt']
+        project.tracker_ids = [1, 2]
+        project.save()
+
+        print("membership all_red_pj id %s." % (all_red_pj[pjj]['id']))
+
+        pj_wanted_membership = dict(wanted_membership)
+        pj_membership_del = []
+        real_membership = redmine.project_membership.filter(project_id=all_red_pj[pjj]['id'])
+        # print('%s' % (pp.pprint(pj_wanted_membership)))
+
+        for mb in real_membership:
+            if hasattr(mb, 'user'):
+                continue
+            '''
+            print("------------")
+            print("membership")
+            print(list(mb))
+            print("mb.project: %s %s" % (mb.project.id, mb.project.name))
+            print("mb.group: %s %s" % (mb.group.id, mb.group.name))
+            print("mb.roles")
+            for rl in mb.roles:
+                print("%s %s" % (rl.id, rl.name))
+            if 'inherited' in mb:
+                if mb.inherited == True:
+                    print("inherited = True")
+                else:
+                    print("inherited = False")
+            '''
+            if mb.group.name in pj_wanted_membership:
+                for rl in mb.roles:
+                    if mb.group.name in pj_wanted_membership and pj_wanted_membership[mb.group.name] == rl.name:
+                        del(pj_wanted_membership[mb.group.name])
+                    else:
+                        for rl in mb.roles:
+                            pj_membership_del.append(mb.id)
+
+            else:
+                pj_membership_del.append(mb.id)
+
+        pp.pprint(pj_wanted_membership)
+        for gr in pj_wanted_membership:
+            membership = redmine.project_membership.new()
+            membership.project_id = all_red_pj[pjj]['id']
+            # http://www.redmine.org/issues/17904 group is user...
+            membership.user_id = all_red_grp[gr]['id']
+            membership.role_ids = [all_red_rl[pj_wanted_membership[gr]]['id']]
+            membership.save()
+
+        pp.pprint(pj_membership_del)
+        for mb in pj_membership_del:
+            membership = redmine.project_membership.get(all_red_pj[pjj]['id'])
+            membership.delete(mb)
+
+    elif pjj in all_red_cross_pj:
+        print("The project '%s' is found in all_red_cross_pj." % (pjj))
+        repository_url = os.path.join(basedir, pj)
+        print("hg:%s:%s" % (pj_ident, repository_url))
+        pp.pprint(all_red_pj[all_red_cross_pj[pjj]])
+        if parent and 'parent' in all_red_pj[all_red_cross_pj[pjj]]:
+            if parent != all_red_pj[all_red_cross_pj[pjj]]['parent']['name']:
+                print("Not the same parent %s:%s" % (parent, all_red_pj[all_red_cross_pj[pjj]]['parent']['name']))
+        elif parent:
+            print("Not the same parent %s:None" % (parent))
+        elif 'parent' in all_red_pj[all_red_cross_pj[pjj]]:
+            print("Not the same parent None:%s" % (all_red_pj[all_red_cross_pj[pjj]]['parent']['name']))
+
+        if 'repository' not in all_red_pj[all_red_cross_pj[pjj]]['enabled_modules']:
+            print("Repository is not activated for repo %s:%s" % (pjj, pj_ident))
+            project = redmine.project.get(all_red_pj[all_red_cross_pj[pjj]]['id'])
+            project.is_public = True
+            project.inherit_members = False
+            project.custom_fields = [{'id': 11, 'value': os.path.join(basedir, pj)}]
+            project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking',
+                                            'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt']
+            project.tracker_ids = [1, 2]
+            project.save()
+            redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[all_red_cross_pj[pjj]]['id'], pj_ident, repository_url)
+
+        elif len(all_red_pj[all_red_cross_pj[pjj]]['repositories']) == 0:
+            print("Repository URL is empty for repo %s:%s (%s)" % (pjj, pj_ident, repository_url))
+            project = redmine.project.get(all_red_pj[all_red_cross_pj[pjj]]['id'])
+            project.is_public = True
+            project.inherit_members = False
+            project.custom_fields = [{'id': 11, 'value': os.path.join(basedir, pj)}]
+            project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking',
+                                            'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt']
+            project.tracker_ids = [1, 2]
+            project.save()
+            redmine_create_repository(REDMINE_PROTO, REDMINE_HOSTNAME, REDMINE_WS_KEY, all_red_pj[all_red_cross_pj[pjj]]['id'], pj_ident, repository_url)
+
+        elif os.path.join(basedir, pj) != all_red_pj[all_red_cross_pj[pjj]]['repositories'][0]['url']:
+            print("Repository URL is bad for repo %s:%s (%s <> %s)"
+                  % (pjj, pj_ident, os.path.join(basedir, pj), all_red_pj[all_red_cross_pj[pjj]]['repositories'][0]['url']))
+
+        # if all_red_pj[pjj]['is_public']:
+        # reset verything to is_public false
+        project = redmine.project.get(all_red_pj[all_red_cross_pj[pjj]]['id'])
+        project.is_public = True
+        project.inherit_members = False
+        project.custom_fields = [{'id': 11, 'value': os.path.join(basedir, pj)}]
+        project.enabled_module_names = ['repository', 'issue_tracking', 'time_tracking',
+                                        'calendar', 'gantt', 'agile', 'scrum', 'easy_gantt']
+        project.tracker_ids = [1, 2]
+        project.save()
+
+        print("membership all_red_cross_pj id %s." % (all_red_pj[all_red_cross_pj[pjj]]['id']))
+
+        pj_wanted_membership = dict(wanted_membership)
+        pj_membership_del = []
+        real_membership = redmine.project_membership.filter(project_id=all_red_pj[all_red_cross_pj[pjj]]['id'])
+
+        for mb in real_membership:
+            if hasattr(mb, 'user'):
+                continue
+            '''
+            print("------------")
+            print("membership")
+            print("mb.project: %s %s" % (mb.project.id, mb.project.name))
+            print("mb.group: %s %s" % (mb.group.id, mb.group.name))
+            print("mb.roles")
+            for rl in mb.roles:
+                print("%s %s" % (rl.id, rl.name))
+            '''
+            if mb.group.name in pj_wanted_membership:
+                for rl in mb.roles:
+                    if pj_wanted_membership[mb.group.name] == rl.name:
+                        del(pj_wanted_membership[mb.group.name])
+                    else:
+                        for rl in mb.roles:
+                            pj_membership_del.append(mb.id)
+
+            else:
+                pj_membership_del.append(mb.id)
+
+        pp.pprint(pj_wanted_membership)
+        for gr in pj_wanted_membership:
+            membership = redmine.project_membership.new()
+            membership.project_id = all_red_pj[all_red_cross_pj[pjj]]['id']
+            # http://www.redmine.org/issues/17904 group is user...
+            membership.user_id = all_red_grp[gr]['id']
+            membership.role_ids = [all_red_rl[pj_wanted_membership[gr]]['id']]
+            membership.save()
+
+        pp.pprint(pj_membership_del)
+        for mb in pj_membership_del:
+            membership = redmine.project_membership.get(all_red_pj[all_red_cross_pj[pjj]]['id'])
+            membership.delete(mb)
+
+        # break
+
+    else:
+        print("The project '%s' need to be created." % (pj))
+        print("hg:%s:%s" % (pj_ident, os.path.join(basedir, pj)))
+
+        if parent and parent in all_red_pj:
+            print("Parent '%s' is found" % (parent))
+        elif parent and parent in all_red_cross_pj:
+            print("Parent '%s' is found in the bad list" % (parent))
+
+        try:
+            print('id:%s' % (pj_ident))
+            project = redmine.project.new()
+            project.name = pjj
+            project.identifier = pj_ident
+            project.description = pjj
+            project.homepage = None
+            project.is_public = True
+            project.inherit_members = False
+            project.parent_id = parent_id
+            # project.enabled_modules = ['repository'] Readonly attribute
+            # project.custom_fields = [{'id': 1, 'value': 'PE'}, {'id': 11, 'value': 'scm'}]
+            project.custom_fields = [{'id': 11, 'value': os.path.join(basedir, pj)}]
+            # list(project)
+            project.save()
+        except Exception as e:
+            print('The creation of the ressources project "%s" did not suceed: %s' % (pjj, str(e)))
+            print(traceback.format_exc(5))
+            break
+
+    # try:
+    #     project = redmine.project.get(pjj)
+    # except ResourceNotFoundError as e:
+    #     print('The ressources is not found')
+
+sys.exit(0)
diff --git a/bin/synchronize_redmine_users.py b/bin/synchronize_redmine_users.py
new file mode 100755
index 0000000..e7e9d6c
--- /dev/null
+++ b/bin/synchronize_redmine_users.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from __future__ import absolute_import, print_function
+
+import os
+import sys
+
+import configparser as ConfigParser
+import pprint
+import inspect
+
+pp = pprint.PrettyPrinter(indent=4)
+
+PROGNAME = os.path.basename(sys.argv[0]).split(".")[0]
+script = os.path.basename(__file__).split(".")[0]
+
+global_iniFile = '/opt/etc/ini/global.ini'
+config_global = ConfigParser.RawConfigParser()
+config_global.optionxform(str())
+config_global.optionxform = str
+config_global.read(global_iniFile)
+sys.path.append(config_global.get('APPLICATION', 'PYTHON-LIBRARY'))
+
+from redminelib import Redmine
+
+if 'http_proxy' in os.environ:
+    del os.environ['http_proxy']
+if 'https_proxy' in os.environ:
+    del os.environ['https_proxy']
+
+
+CA_bundle = '/usr/local/share/ca-certificates/snetroot/SNetRootCA_device_bundle.pem'
+CA_bundle = '/etc/ssl/certs/ca-certificates.crt'
+
+def obj_dump(obj):
+    '''
+      Object dumper
+    '''
+    for attr in dir(obj):
+        if '_' in attr:
+            continue
+        try:
+            print("obj.%s = %s" % (attr, str(getattr(obj, attr))))
+        except:
+            print("obj.%s = %s" % (attr, getattr(obj, attr)))
+
+    for name, data in inspect.getmembers(obj):
+        if inspect.isclass(data):
+            print('name:%s' % (name))
+            print(data)
+
+redmine_config_global = ConfigParser.RawConfigParser()
+redmine_config_global.read(config_global.get('INI', 'Redmine'))
+
+# Parse config
+REDMINE_HOSTNAME = redmine_config_global.get('GLOBAL', 'HOST')
+REDMINE_PROTO = redmine_config_global.get('GLOBAL', 'PROTO')
+REDMINE_KEY = redmine_config_global.get('CREDENTIAL', 'APIkey')
+
+redmine = Redmine('%s://%s' % (REDMINE_PROTO, REDMINE_HOSTNAME), key=REDMINE_KEY, requests={'verify': CA_bundle})
+
+users = redmine.user.all(offset=0, limit=100)
+for u in users:
+    # print(u)
+    # print '%s' % (u.id)
+    # print '%s' % (u.login)
+    # print '%s' % (u.firstname)
+    # print '%s' % (u.lastname)
+    # print '%s' % (u.mail)
+    # print '%s' % (u.auth_source_id)
+    # print '%s' % (u.mail_notification)
+
+    print('%s %s %s <%s> (%s)' % (u.login, u.firstname, u.lastname, u.mail, u.id))
+    obj_dump(u)
+    # obj_dump(u.contacts)
+    # obj_dump(u.deals)
+    obj_dump(u.groups)
+    obj_dump(u.memberships)
+    break
-- 
GitLab