diff --git a/README.md b/README.md
index 8e976b0dd21147049d9dac313890e9812a17402f..7d4c12dc8ab03f389619d84b6a0173d8eff5d3a8 100644
--- a/README.md
+++ b/README.md
@@ -1,93 +1 @@
-# Script-Sammlung
-
-
-
-## Getting started
-
-To make it easy for you to get started with GitLab, here's a list of recommended next steps.
-
-Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
-
-## Add your files
-
-- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
-- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
-
-```
-cd existing_repo
-git remote add origin https://gitlab.hrz.tu-chemnitz.de/kuki797d--tu-dresden.de/script-sammlung.git
-git branch -M main
-git push -uf origin main
-```
-
-## Integrate with your tools
-
-- [ ] [Set up project integrations](https://gitlab.hrz.tu-chemnitz.de/kuki797d--tu-dresden.de/script-sammlung/-/settings/integrations)
-
-## Collaborate with your team
-
-- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
-- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
-- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
-- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
-- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
-
-## Test and Deploy
-
-Use the built-in continuous integration in GitLab.
-
-- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
-- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
-- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
-- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
-- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
-
-***
-
-# Editing this README
-
-When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
-
-## Suggestions for a good README
-
-Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
-
-## Name
-Choose a self-explaining name for your project.
-
-## Description
-Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
-
-## Badges
-On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
-
-## Visuals
-Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
-
-## Installation
-Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
-
-## Usage
-Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
-
-## Support
-Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
-
-## Roadmap
-If you have ideas for releases in the future, it is a good idea to list them in the README.
-
-## Contributing
-State if you are open to contributions and what your requirements are for accepting them.
-
-For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
-
-You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
-
-## Authors and acknowledgment
-Show your appreciation to those who have contributed to the project.
-
-## License
-For open source projects, say how it is licensed.
-
-## Project status
-If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
+# Script-Sammlung
\ No newline at end of file
diff --git a/clustershell/README.md b/clustershell/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..dc8e5089a9863a98c442a2fb9894357387509423
--- /dev/null
+++ b/clustershell/README.md
@@ -0,0 +1,14 @@
+# Clustershell Auto-Update Script
+
+- **Setup**
+    - ```clustershell_add_cfg``` to ```/home/jmp```
+    - ```nagios/check_update_clustershell_ips``` to ```/usr/lib/nagios/plugins``` 
+    - ```systemd/*``` to ```/etc/systemd/system``` and start/enable
+
+    - */etc/nagios/nrpe.cfg*
+        - ```command[clsh_update]=sudo -u jmp /usr/lib/nagios/plugins/check_update_clustershell_ips```
+
+- **clustershell_add_cfg/clsh_get_cfg.py**
+    - This script checks all VMs with the custom field "SERVICE_CLASS"=="PaaS" and tries to read out the guest-os from the vm-object as well as the custom field "PRIMARY_IP_ADDRESS". If everything is available the script will check the guest-os-string for any "identifiers" under  any "os_configuration" as given in the config. The ip-addresses for each "os_configuration" for each "vcenter_configuration" are temporarily written to a file under /tmp. After everything is done, the temporary files of each "os_configuration" are combined, sorted and written to the "outputfile" given in the config. (so that the same "os_configuration" from different "vcenter_configuration" are combined as well)
+    - *Required Parameters*: --config
+    - *Config*: See ```clustershell_add_cfg``` for examples
\ No newline at end of file
diff --git a/clustershell/clustershell_add_cfg/clsh_get_cfg.py b/clustershell/clustershell_add_cfg/clsh_get_cfg.py
new file mode 100644
index 0000000000000000000000000000000000000000..df39bb31506ab73a12dd99576fd74dfdbad6a522
--- /dev/null
+++ b/clustershell/clustershell_add_cfg/clsh_get_cfg.py
@@ -0,0 +1,203 @@
+#!/usr/bin/python3
+
+import json
+import argparse
+import warnings
+from os import remove
+from os.path import isfile, exists, basename
+from atexit import register
+from sys import exit, stdout
+import datetime
+from socket import inet_aton
+import struct
+from pyVim.connect import *
+from pyVmomi import vmodl, vim
+
+# This script checks all VMs with the custom field "SERVICE_CLASS"=="PaaS" and tries to read out the guest-os from the vm-object as well as the custom field "PRIMARY_IP_ADDRESS".
+# If everything is available the script will check the guest-os-string for any "identifiers" under  any "os_configuration" as given in the config.
+# The ip-addresses for each "os_configuration" for each "vcenter_configuration" are temporarily written to a file under /tmp.
+# After everything is done, the temporary files of each "os_configuration" are combined, sorted and written to the "outputfile" given in the config.
+# (so that the same "os_configuration" from different "vcenter_configuration" are combined as well)
+
+
+def arg_parser():
+    # Just the arguments parser
+    my_parser = argparse.ArgumentParser(description="Metric script")
+
+    my_parser.add_argument(
+        "--config",
+        action="store",
+        type=str,
+        help="Path to a config file.",
+    )
+
+    args = my_parser.parse_args()
+
+    if args.config is not None:
+        if not isfile(args.config):
+            print("The path specified from -C / --config does not exist")
+            exit()
+    else:
+        print("config file is required. -C / --config")
+        exit()
+
+    return args
+
+
+def sort_ips(ips):
+    return sorted(ips, key=lambda ip: struct.unpack("!L", inet_aton(ip))[0])
+
+
+def main():
+    # argparser
+    warnings.filterwarnings("ignore", category=DeprecationWarning)
+    s = ssl.SSLContext()
+    s.verify_mode = ssl.CERT_NONE
+    args = arg_parser()
+
+    with open(args.config) as json_file:
+        loaded = json.load(json_file)
+        vcenters = loaded["vcenter_configuration"]
+        WARNINGS = loaded["warnings"]
+
+    for vcenter in vcenters:
+        # connect
+        print("Starting with VCenter {}".format(vcenter["hostname"]))
+
+        si = SmartConnect(
+            host=vcenter["hostname"],
+            user=vcenter["username"],
+            pwd=vcenter["password"],
+            sslContext=s,
+            port=443,
+        )
+        register(Disconnect, si)
+        content = si.RetrieveContent()
+
+        # the custom attributes are mapped to a key (a unique number)
+        # we first have to get this id trough customFieldsmanager
+        SERVICE_CLASS_ID = None
+        PRIMARY_IP_ADDRESS_ID = None
+
+        cfm = content.customFieldsManager
+        for some_field in cfm.field:
+            if some_field.name == "SERVICE_CLASS":
+                SERVICE_CLASS_ID = some_field.key
+
+            elif some_field.name == "PRIMARY_IP_ADDRESS":
+                PRIMARY_IP_ADDRESS_ID = some_field.key
+
+        if not SERVICE_CLASS_ID or not PRIMARY_IP_ADDRESS_ID:
+            print(
+                "Couldn't find the key to SERVICE_CLASS or PRIMARY_IP_ADDRESS custom field."
+            )
+            exit(1)
+
+        # get all avaialble vm objects
+        container = content.rootFolder
+        viewType = [vim.VirtualMachine]
+        recursive = True
+        containerView = content.viewManager.CreateContainerView(
+            container, viewType, recursive
+        )
+        vms = containerView.view
+
+        # those are the configurations for the operating systems
+        os_check_map = vcenter["os_configuration"]
+        # create some empty array, in which the ips are stored
+        for os in os_check_map:
+            os["ips"] = []
+
+        for vm in vms:
+            if vm.guest and vm.config and vm.config.extraConfig:
+
+                # check if PaaS is set
+                if any(
+                    cfg_opt.key == SERVICE_CLASS_ID and cfg_opt.value == "PaaS"
+                    for cfg_opt in vm.customValue
+                ):
+                    # check if vm.guest is accessible
+                    if not vm.guest:
+                        vm_guest_os = vm.config.guestFullName
+                    else:
+                        vm_guest_os = vm.guest.guestFullName
+
+                    vm_ip_address = next(
+                        (x for x in vm.customValue if x.key == PRIMARY_IP_ADDRESS_ID),
+                        None,
+                    )
+                    vm_ip_address = (
+                        vm_ip_address.value if vm_ip_address is not None else None
+                    )
+
+                    # check if guest os & ip address are accessible
+                    if vm_guest_os is None or vm_ip_address is None:
+                        if WARNINGS:
+                            print(
+                                "VM {} - can't read IP Address or GuestOS Name. Skipping.".format(
+                                    vm.name
+                                )
+                            )
+                        continue
+
+                    # go over all os-configurations given under the os_configuration key in the config file
+                    for os in os_check_map:
+                        # check if any of the identifiers given in the config file match anything in the guestFullName
+                        if (
+                            any(
+                                identifier in vm_guest_os
+                                for identifier in os["identifiers"]
+                            )
+                            and vm_ip_address not in os["ips"]
+                        ):
+                            os["ips"].append(vm_ip_address)
+
+        # write temporary files to /tmp for this vcenter
+        for os in os_check_map:
+            if exists("/tmp"):
+                name = basename(os["outputfile"])
+                os["temporary_outputfile"] = (
+                    "/tmp/" + name + vcenter["hostname"] + ".tmp"
+                )
+            else:
+                name = basename(os["outputfile"])
+                os["temporary_outputfile"] = name + vcenter["hostname"] + ".tmp"
+
+            # write the collected ip addresses of this vcenter to a temporary output file in /tmp
+            with open(os["temporary_outputfile"], "w") as f:
+                f.write("\n".join(os["ips"]) + "\n")
+
+        print("Done with VCenter {}".format(vcenter["hostname"]))
+
+    # map the temporary files to the output-file-path of the os
+    # (key = outputpath, value= array of temporary files that will be written to the outputpath)
+    file_map = {}
+    for vcenter in vcenters:
+        os_check_map = vcenter["os_configuration"]
+        for os in os_check_map:
+            if os["outputfile"] in file_map:
+                file_map[os["outputfile"]].append(os["temporary_outputfile"])
+            else:
+                file_map[os["outputfile"]] = [os["temporary_outputfile"]]
+
+    # write all temp files to their actual files
+    for output_file in file_map:
+        with open(output_file, "w") as write_file:
+            all_ips = []
+            # go over all temporary files belonging to the output_file of the current os
+            # and add any ip address in those files to all_ips
+            for read_file in file_map[output_file]:
+                with open(read_file, "r") as infile:
+                    temp_ips = infile.read().split()
+                    for temp_ip in temp_ips:
+                        all_ips.append(temp_ip)
+                remove(read_file)
+
+            # sort all_ips by ip address
+            all_ips = sort_ips(all_ips)
+
+            write_file.write("\n".join(all_ips) + "\n")
+
+
+if __name__ == "__main__":
+    main()
diff --git a/clustershell/clustershell_add_cfg/config_enterprise.json b/clustershell/clustershell_add_cfg/config_enterprise.json
new file mode 100644
index 0000000000000000000000000000000000000000..01c3e208268fa014c681b88e5d9f452ba4f64cc8
--- /dev/null
+++ b/clustershell/clustershell_add_cfg/config_enterprise.json
@@ -0,0 +1,71 @@
+{
+    "_comment": "Warnings include: VMware tools not installed, no matching identifier in guest os string",
+    "warnings": false,
+    "_comment2": "Each vcenter has its own configuration, containing authentication & operating systems to be checked.",
+    "vcenter_configuration": [
+        {
+            "hostname": "vc-enterprise-lzr.zih.tu-dresden.de",
+            "username": "jmp@vsphere.local",
+            "password": "REDACTED",
+            "os_configuration": [
+                {
+                    "identifiers": [
+                        "CentOS"
+                    ],
+                    "outputfile": "/etc/clustershell/groups.conf.d/vms/red"
+                },
+                {
+                    "identifiers": [
+                        "Debian"
+                    ],
+                    "outputfile": "/etc/clustershell/groups.conf.d/vms/debian"
+                },
+                {
+                    "identifiers": [
+                        "Ubuntu"
+                    ],
+                    "outputfile": "/etc/clustershell/groups.conf.d/vms/ubuntu"
+                },
+                {
+                    "identifiers": [
+                        "SUSE",
+                        "SLES"
+                    ],
+                    "outputfile": "/etc/clustershell/groups.conf.d/vms/suse"
+                }
+            ]
+        },
+        {
+            "hostname": "vc-enterprise-tre.zih.tu-dresden.de",
+            "username": "jmp@vsphere.local",
+            "password": "REDACTED",
+            "os_configuration": [
+                {
+                    "identifiers": [
+                        "CentOS"
+                    ],
+                    "outputfile": "/etc/clustershell/groups.conf.d/vms/red"
+                },
+                {
+                    "identifiers": [
+                        "Debian"
+                    ],
+                    "outputfile": "/etc/clustershell/groups.conf.d/vms/debian"
+                },
+                {
+                    "identifiers": [
+                        "Ubuntu"
+                    ],
+                    "outputfile": "/etc/clustershell/groups.conf.d/vms/ubuntu"
+                },
+                {
+                    "identifiers": [
+                        "SUSE",
+                        "SLES"
+                    ],
+                    "outputfile": "/etc/clustershell/groups.conf.d/vms/suse"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/clustershell/clustershell_add_cfg/config_infrastructure.json b/clustershell/clustershell_add_cfg/config_infrastructure.json
new file mode 100644
index 0000000000000000000000000000000000000000..38b0c0f2fb946b02603b57a4d28744a6278e17d0
--- /dev/null
+++ b/clustershell/clustershell_add_cfg/config_infrastructure.json
@@ -0,0 +1,71 @@
+{
+    "_comment": "Warnings include: VMware tools not installed, no matching identifier in guest os string",
+    "warnings": false,
+    "_comment2": "Each vcenter has its own configuration, containing authentication & operating systems to be checked.",
+    "vcenter_configuration": [
+        {
+            "hostname": "vc-infrastructure-lzr.zih.tu-dresden.de",
+            "username": "jmp@vsphere.local",
+            "password": "REDACTED",
+            "os_configuration": [
+                {
+                    "identifiers": [
+                        "CentOS"
+                    ],
+                    "outputfile": "/etc/clustershell/groups.conf.d/vms/red"
+                },
+                {
+                    "identifiers": [
+                        "Debian"
+                    ],
+                    "outputfile": "/etc/clustershell/groups.conf.d/vms/debian"
+                },
+                {
+                    "identifiers": [
+                        "Ubuntu"
+                    ],
+                    "outputfile": "/etc/clustershell/groups.conf.d/vms/ubuntu"
+                },
+                {
+                    "identifiers": [
+                        "SUSE",
+                        "SLES"
+                    ],
+                    "outputfile": "/etc/clustershell/groups.conf.d/vms/suse"
+                }
+            ]
+        },
+        {
+            "hostname": "vc-infrastructure-tre.zih.tu-dresden.de",
+            "username": "jmp@vsphere.local",
+            "password": "REDACTED",
+            "os_configuration": [
+                {
+                    "identifiers": [
+                        "CentOS"
+                    ],
+                    "outputfile": "/etc/clustershell/groups.conf.d/vms/red"
+                },
+                {
+                    "identifiers": [
+                        "Debian"
+                    ],
+                    "outputfile": "/etc/clustershell/groups.conf.d/vms/debian"
+                },
+                {
+                    "identifiers": [
+                        "Ubuntu"
+                    ],
+                    "outputfile": "/etc/clustershell/groups.conf.d/vms/ubuntu"
+                },
+                {
+                    "identifiers": [
+                        "SUSE",
+                        "SLES"
+                    ],
+                    "outputfile": "/etc/clustershell/groups.conf.d/vms/suse"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/clustershell/nagios/check_update_clustershell_ips b/clustershell/nagios/check_update_clustershell_ips
new file mode 100644
index 0000000000000000000000000000000000000000..1e842e5160acffd5a730dfd3e4af384a3cadd35c
--- /dev/null
+++ b/clustershell/nagios/check_update_clustershell_ips
@@ -0,0 +1,24 @@
+#!/bin/bash
+STATE_OK=0
+STATE_WARNING=1
+STATE_CRITICAL=2
+
+time=$(systemctl status update_clustershell_ips | awk -F ' ' '{print $3'} | tail -1 | tr -d "\n")
+status=$(systemctl status update_clustershell_ips | grep -o -P '(?<=status=).*(?=/)' | tail -1)
+exitok() {
+        echo -n OK : Last run at $time
+        echo $*
+        exit $STATE_OK
+}
+
+exitwarning(){
+        echo -n WARNING : Last run at $time didnt complete successfully
+        echo $*
+        exit $STATE_WARNING
+}
+
+if [ $status = "0" ]; then
+        exitok
+else
+        exitwarning
+fi
diff --git a/clustershell/systemd/update_clustershell_ips.service b/clustershell/systemd/update_clustershell_ips.service
new file mode 100644
index 0000000000000000000000000000000000000000..d390a462f6cda59695f662d9e518d91ab31b3194
--- /dev/null
+++ b/clustershell/systemd/update_clustershell_ips.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Update ips in /etc/clustershell/groups.conf.d/vms
+
+[Service] 
+Type=simple
+User=jmp
+ExecStart=/home/jmp/clustershell_add_cfg/.venv/bin/python3 /home/jmp/clustershell_add_cfg/clsh_get_cfg.py --config /home/jmp/clustershell_add_cfg/config.json
+Type=oneshot
\ No newline at end of file
diff --git a/clustershell/systemd/update_clustershell_ips.timer b/clustershell/systemd/update_clustershell_ips.timer
new file mode 100644
index 0000000000000000000000000000000000000000..faa2e089aa6c5f3cd542eef3d8e94a818c486cae
--- /dev/null
+++ b/clustershell/systemd/update_clustershell_ips.timer
@@ -0,0 +1,15 @@
+[Unit]
+Description=Run update clustershell ips script daily
+
+[Timer]
+#Execute job if it missed a run due to machine being off
+Persistent=true
+#Run 120 seconds after boot for the first time
+OnBootSec=120
+#Run every 1 hour thereafter
+OnCalendar=*-*-* 20:00:00
+#File describing job to execute
+Unit=update_clustershell_ips.service 
+
+[Install]
+WantedBy=timers.target
\ No newline at end of file
diff --git a/cmdbscript/README.md b/cmdbscript/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..9cb6fc9c207753b3ff36c938c0152511368cfe02
--- /dev/null
+++ b/cmdbscript/README.md
@@ -0,0 +1,3 @@
+keine ahnung was das ist
+
+baut glaube ich die berechtigungen von diensten der cmdb im vcenter nach
diff --git a/cmdbscript/auth_example b/cmdbscript/auth_example
new file mode 100644
index 0000000000000000000000000000000000000000..a0edea94379fddef18697becc91d67b78d70940c
--- /dev/null
+++ b/cmdbscript/auth_example
@@ -0,0 +1,5 @@
+vcenter-username=kuki797d@vsphere.local
+vcenter-password=
+cmdb-username=kuki797d
+cmdb-password=
+cmdb-api=https://cmdb.zih.tu-dresden.de:31342
diff --git a/cmdbscript/cmdbscript.py b/cmdbscript/cmdbscript.py
new file mode 100644
index 0000000000000000000000000000000000000000..af2f232738024ca55d320b9caf7fb51bad0c5465
--- /dev/null
+++ b/cmdbscript/cmdbscript.py
@@ -0,0 +1,640 @@
+#!/usr/bin/python3
+
+import requests
+import json
+import argparse
+import warnings
+import datetime
+import time
+from os.path import isfile
+from atexit import register
+from sys import exit, stdout
+import re
+
+# if used on windows its pyvim
+# pip install pyvim pyvmomi
+from pyVim.connect import *
+from pyVmomi import vmodl, vim
+
+
+# ########################## CMDB FUNCTIONS ###############################################
+REQUEST_HEADER = {"content-type": "application/json"}
+
+
+def establish_session(login, password, CMDB_API):
+    """Authenticate with ZIH credentials.
+    Resulting session will be used for any further requests.
+    """
+
+    login_header = {
+        **REQUEST_HEADER,
+        "X-RPC-Auth-Username": login,
+        "X-RPC-Auth-Password": password,
+    }
+    request = {"version": "2.0", "method": "idoit.login", "params": {}, "id": 1}
+
+    raw_response = requests.post(
+        CMDB_API, data=json.dumps(request), headers=login_header
+    )
+    response = raw_response.json()
+
+    if "result" in response and response["result"] != {}:
+        REQUEST_HEADER["X-RPC-Auth-Session"] = response["result"]["session-id"]
+    else:
+        print(response)
+        raise Exception("No session could be established")
+
+
+def api_request(CMDB_API, method, params={}):
+    """Very simple handler for cmdb requests."""
+
+    call = {"version": "2.0", "method": method, "params": params, "id": 1}
+
+    response = requests.post(CMDB_API, data=json.dumps(call), headers=REQUEST_HEADER)
+    return response.json()
+
+
+def parse_category(obj_id, category, CMDB_API):
+    """Execute 'cmdb.category.read' for given object and category.
+    Return False if no result was received.
+    """
+
+    raw_response = api_request(
+        CMDB_API,
+        "cmdb.category.read",
+        {
+            "category": category,
+            "objID": obj_id,
+            "status": 2,  # Show normal entries, ignore archived and deleted
+        },
+    )
+    if "result" not in raw_response:
+        return False
+    return raw_response["result"]
+
+
+def parse_object(obj_id, CMDB_API):
+    """Execute 'cmdb.category.read' for given object and category.
+    Return False if no result was received.
+    """
+
+    raw_response = api_request(
+        CMDB_API,
+        "cmdb.objects.read",
+        {"filter": [{"type": obj_id}]},
+    )
+    if "result" not in raw_response:
+        return False
+    return raw_response["result"]
+
+
+# an array which contains vms that already have been sorted to a service
+# some vms have multiple services
+HANDLED_VMS = []
+
+
+# [{
+#     "name": "Servicename",
+#     "id": 1,
+#     "contacts": [
+#         {
+#             "login": "kuki797d",
+#             "primary": true
+#         },
+#         {
+#             "login": "test999",
+#             "primary": false
+#         }
+#     ],
+#     "vms": [
+#         {
+#             "id": 82823,
+#             "vcenter_id": 1
+#         },
+#         {
+#             "id": 232332,
+#             "vcenter_id": 2
+#         }
+#     ]
+# },]
+
+# fetch_cmdb_data returns a list as described above
+def fetch_cmdb_data(login, password, CMDB_API, debug):
+    """Fetch all required Data from the CMDB. Returns a list of dictionaries, that contain the data."""
+    establish_session(login, password, CMDB_API)
+    SERVICES = []
+    # parse data from https://cmdb.zih.tu-dresden.de/?viewMode=1001&objTypeID=108
+    raw_services = parse_object(108, CMDB_API)
+    i = 0
+    service_len = len(raw_services)
+    print("Fetching CMDB Data...")
+    for service in raw_services:
+
+        service_map = {}
+        service_map["name"] = service["title"]
+        service_map["id"] = service["id"]
+        service_id = service["id"]
+        # parse data from contacts
+        service_contacts = parse_category(int(service_id), "C__CATG__CONTACT", CMDB_API)
+
+        service_map["contacts"] = []
+        primary_key_set = False
+        has_contacts = False
+        for contact in service_contacts:
+            # check of contact is really a person, can also be a group
+            if contact["contact"]["type"] == "C__OBJTYPE__PERSON":
+                if contact["contact"]["login"] != "":
+                    contact_map = {}
+                    contact_map["login"] = contact["contact"]["login"]
+                    if int(contact["primary"]["value"]) == 1:
+                        primary_key_set = True
+                        contact_map["primary"] = True
+                    else:
+                        contact_map["primary"] = False
+                    service_map["contacts"].append(contact_map)
+                    has_contacts = True
+
+        if not has_contacts:
+            if debug:
+                print(
+                    f"Warning: Service {service['title']} has no or no valid contacts."
+                )
+
+        if not primary_key_set:
+            try:
+                # set the first contact as primary, as there should always be at least one contact that has the primary flag
+                service_map["contacts"][0]["primary"] = True
+                if debug:
+                    print(
+                        f"Warning: Service {service['title']} has no primary key set. This would result in no VM-Admin Role being given. Giving this Role to the first available contact."
+                    )
+            except IndexError:
+                pass
+
+        service_map["vms"] = []
+
+        # parse data from service components
+        service_components = parse_category(
+            int(service_id), "C__CATG__IT_SERVICE_COMPONENTS", CMDB_API
+        )
+
+        has_vms = False
+        for component in service_components:
+            if component["connected_object"]["type"] == "C__OBJTYPE__VIRTUAL_SERVER":
+                raw_name = component["connected_object"]["title"]
+                # vms should always be only mapped to one service
+                # some vms are in multiple services, this would result in inconsistent behaviour
+                # the vm would be moved around in multiple serivce-folders
+                if raw_name not in HANDLED_VMS:
+                    HANDLED_VMS.append(raw_name)
+                    vmname = raw_name.replace("(", "").replace(")", "")
+                    vm_id = vmname.split("-")[-2]
+                    vm_vcenter_id = vmname.split("-")[-1]
+                    vm_map = {"id": vm_id, "vcenter_id": vm_vcenter_id}
+                    service_map["vms"].append(vm_map)
+                    has_vms = True
+
+        if not has_vms:
+            if debug:
+                print(
+                    f"Warning: Service {service['title']} has no VMs registered to it."
+                )
+
+        SERVICES.append(service_map)
+
+        i += 1
+        stdout.write(f"Service {i} / {service_len}")
+        stdout.write("\r")
+
+    api_request(CMDB_API, "idoit.logout")
+    return SERVICES
+
+
+# ###################################################################################
+
+
+def arg_parser():
+    # Just the arguments parser
+    my_parser = argparse.ArgumentParser(description="Metric script")
+    my_parser.add_argument(
+        "--vcenter_hostname",
+        action="store",
+        type=str,
+        help="The VCenter hostname. Required if not given in authfile. Required if not given in authfile.",
+    )
+    my_parser.add_argument(
+        "--vcenter_username",
+        action="store",
+        type=str,
+        help="The username to log into the VCenter. Required if not given in authfile.",
+    )
+    my_parser.add_argument(
+        "--vcenter_password",
+        action="store",
+        type=str,
+        help="The password for your VCenter username. Required if not given in authfile.",
+    )
+    my_parser.add_argument(
+        "--cmdb_api",
+        action="store",
+        type=str,
+        help="CMDB Api including port. Example: https://cmdb.zih.tu-dresden.de:31342",
+    )
+    my_parser.add_argument(
+        "--cmdb_username",
+        action="store",
+        type=str,
+        help="The username to log into the CMDB. Required if not given in authfile.",
+    )
+    my_parser.add_argument(
+        "--cmdb_password",
+        action="store",
+        type=str,
+        help="The CMDB password for your username. Required if not given in authfile.",
+    )
+    my_parser.add_argument(
+        "--authfile",
+        "-A",
+        action="store",
+        type=str,
+        help="Authfile that may contain hostname, username and/or password. Authfile values will always override CMD args.",
+    )
+    my_parser.add_argument(
+        "--config",
+        action="store",
+        type=str,
+        help="Path to a config file.",
+    )
+    my_parser.add_argument(
+        "--debug",
+        "-D",
+        action=argparse.BooleanOptionalAction,
+        help="Enable debug mode",
+    )
+
+    my_parser.add_argument(
+        "--test",
+        action=argparse.BooleanOptionalAction,
+        help="Test Mode, doesn't apply anything. Temporarily creates folders but deletes them after.",
+    )
+    args = my_parser.parse_args()
+
+    # check if any authentication method is supplied
+    if (
+        args.vcenter_username is None
+        or args.vcenter_password is None
+        or args.cmdb_username is None
+        or args.cmdb_password is None
+        or args.cmdb_api is None
+    ):
+        if args.authfile is None:
+            print("No / Not Enough Authentification Methods or CMDB Api supplied.")
+            exit()
+        else:
+            if not isfile(args.authfile):
+                print("The path specified from -A / --authfile does not exist")
+                exit()
+            else:
+                authfile = open(args.authfile, "r")
+                try:
+                    for line in authfile:
+                        if "vcenter-username" in line:
+                            args.vcenter_username = line.split("=")[1].strip()
+                        elif "vcenter-password" in line:
+                            args.vcenter_password = line.split("=")[1].strip()
+                        elif "cmdb-username" in line:
+                            args.cmdb_username = line.split("=")[1].strip()
+                        elif "cmdb-password" in line:
+                            args.cmdb_password = line.split("=")[1].strip()
+                        elif "cmdb-api" in line:
+                            args.cmdb_api = line.split("=")[1].strip()
+                except Exception as E:
+                    print(f"Error parsing authfile.\n{E}")
+                    authfile.close()
+                authfile.close()
+    if args.test is None:
+        args.test = False
+
+    if args.config is not None:
+        if not isfile(args.config):
+            print("The path specified from -C / --config does not exist")
+            exit()
+    else:
+        print("config file is required. -C / --config")
+        exit()
+
+    return args
+
+
+def find_root_folder(root_folder_id, content):
+    """Find the working folder by ID. Returns the folder Object."""
+    container = content.rootFolder
+    container_view = content.viewManager.CreateContainerView(
+        container, [vim.Folder], True
+    )
+    # iterate over all folders
+    for folder in container_view.view:
+        # get the root Folder
+        folderid = str(folder).split("-")[-1]
+        folderid = re.sub("[^0-9]", "", folderid)
+        folderid = int(folderid)
+        if folderid == root_folder_id:
+            return folder
+
+
+def check_if_vm_in_folder(vm, folder, content):
+    """Check if vm is in folder. Returns a Boolean."""
+    vm_in_folder = False
+    container_view = content.viewManager.CreateContainerView(
+        folder, [vim.VirtualMachine], True
+    )
+    for n_vm in container_view.view:
+        if n_vm == vm:
+            vm_in_folder = True
+            break
+    return vm_in_folder
+
+
+def check_if_folder_exist(folder_tsid, root_folder, content):
+    """Check if a folder exists in the root_folder thats contains the folder_tsid"""
+    container_view = content.viewManager.CreateContainerView(
+        root_folder, [vim.Folder], True
+    )
+
+    for folderobj in container_view.view:
+        tsid = folderobj.name
+        if "TSID:" in folderobj.name:
+            tsid = tsid.split("TSID:")[1]
+            tsid = re.sub("[^0-9]", "", tsid)
+            tsid = int(tsid)
+            if tsid == folder_tsid:
+                return folderobj
+
+    return None
+
+
+def wait_for_task(task):
+    while task.info.state not in [vim.TaskInfo.State.success, vim.TaskInfo.State.error]:
+        time.sleep(0.1)
+        print("Waiting for task to finish.")
+    if task.info.state == vim.TaskInfo.State.error:
+        return 1
+    return 0
+
+
+def main():
+    # argparser
+
+    args = arg_parser()
+
+    if not args.debug:
+        print(
+            "Started the Script without --debug. Highly recommended to see changes made."
+        )
+
+    if args.test:
+        print(
+            "Started in Test-Mode. No changes will be made. Folders will be temporarily created and ALL empty folders under the root folder will be deleted in the end."
+        )
+    else:
+        print(
+            "Attention! This script will delete ALL empty folders under the given root folder. (Not Recursive)"
+        )
+
+    with open(args.config) as json_file:
+        VCENTERS = json.load(json_file)
+
+    SERVICES = fetch_cmdb_data(
+        args.cmdb_username, args.cmdb_password, args.cmdb_api, args.debug
+    )
+    print("Sucessfully fetched CMDB Data.")
+
+    for service in SERVICES:
+        for vcenter in VCENTERS:
+            # check if any vm from this service is located in this vcenter
+            # if not go to the next vcenter
+            found = False
+            for vm in service["vms"]:
+                if int(vm["vcenter_id"]) == int(vcenter["id"]):
+                    found = True
+            if not found:
+                continue
+
+            if args.debug:
+                print(
+                    f"Service: {service['name']} has VMs in VCenter {vcenter['hostname']}."
+                )
+
+            # Connect to the vcenter
+            warnings.filterwarnings("ignore", category=DeprecationWarning)
+            s = ssl.SSLContext()
+            s.verify_mode = ssl.CERT_NONE
+            si = SmartConnect(
+                host=vcenter["hostname"],
+                user=args.vcenter_username,
+                pwd=args.vcenter_password,
+                sslContext=s,
+                port=443,
+            )
+            register(Disconnect, si)
+            content = si.RetrieveContent()
+            container = content.rootFolder
+
+            auth_manager = content.authorizationManager
+            # get all roles from the system and map the name to the roleId
+            role_id_map = {}
+            for role in auth_manager.roleList:
+                role_id_map[role.name] = role.roleId
+
+            # finding the 'root' folder by id
+
+            ROOT_FOLDER = find_root_folder(int(vcenter["root_folder_id"]), content)
+            if ROOT_FOLDER is None:
+                print(f"Root Folder doesnt exist in {vcenter['hostname']}, Exiting")
+                exit(1)
+
+            # folder name like DHCP [TSID:236148]
+            name_length = len(service["name"]) + 9 + len(str(service["id"]))
+            if name_length > 79:
+                re = name_length - 79
+                foldername = f"{service['name'][:-re]} [TSID:{service['id']}]"
+            else:
+                foldername = f"{service['name']} [TSID:{service['id']}]"
+
+            # try to find a folder with this name else return None
+            get_folder = check_if_folder_exist(service["id"], ROOT_FOLDER, content)
+
+            # if return None create the Folder
+            if get_folder is None:
+                if args.debug:
+                    print(
+                        f"Creating Folder in VCenter {vcenter['hostname']}: {foldername} for Service {service['name']}"
+                    )
+                working_folder = ROOT_FOLDER.CreateFolder(foldername)
+            else:
+                working_folder = get_folder
+
+            # retrieve existing permissions from folder
+            existing_permissions = auth_manager.RetrieveEntityPermissions(
+                working_folder, False
+            )
+
+            vm_admin_permission = []
+            vm_ko_admin_permission = []
+
+            # If a user exists with the role VM-Admin and VM-Ko-Admin,
+            # that is in the existing permissions but doesnt exist in the CMDB, remove this users permissions
+            unknown_users = []
+
+            # go over all existing permissions
+            for permission in existing_permissions:
+                # only interesting roles = VM-Admin and VM-Ko-Admin
+                if permission.roleId == role_id_map["VM-Admin"]:
+                    vm_admin_permission.append(permission.principal)
+                    unknown_users.append(str(permission.principal))
+                elif permission.roleId == role_id_map["VM-Ko-Admin"]:
+                    vm_ko_admin_permission.append(permission.principal)
+                    unknown_users.append(str(permission.principal))
+
+            # go over all contacts from this service
+            for contact in service["contacts"]:
+
+                # vcenter principal name like DOM\name
+                vcenter_principal_name = f"DOM\\{contact['login']}"
+
+                # if primary flag -> VM-Admin
+                if contact["primary"] == True:
+                    # check if user already has this permission
+                    if vcenter_principal_name in vm_admin_permission:
+                        # remove this user from unknown users
+                        unknown_users.remove(vcenter_principal_name)
+
+                    # if not create it
+                    else:
+                        vcenter_set_permission_name = (
+                            f"{contact['login']}@dom.tu-dresden.de"
+                        )
+                        perm = vim.AuthorizationManager.Permission()
+                        perm.group = False
+                        perm.principal = vcenter_set_permission_name
+                        perm.propagate = True
+                        perm.roleId = role_id_map["VM-Admin"]
+                        if not args.test:
+                            auth_manager.SetEntityPermissions(working_folder, [perm])
+                        if args.debug:
+                            print(
+                                f"Adding permission VM-Admin for user {vcenter_set_permission_name} on folder {foldername}"
+                            )
+                # if not primary flag -> VM-Ko-Admin
+                else:
+                    # check if user already has those permissions
+                    if vcenter_principal_name in vm_ko_admin_permission:
+                        # remove this user from unknown users
+                        unknown_users.remove(vcenter_principal_name)
+                    else:
+                        vcenter_set_permission_name = (
+                            f"{contact['login']}@dom.tu-dresden.de"
+                        )
+                        perm = vim.AuthorizationManager.Permission()
+                        perm.group = False
+                        perm.principal = vcenter_set_permission_name
+                        perm.propagate = True
+                        perm.roleId = role_id_map["VM-Ko-Admin"]
+                        if not args.test:
+                            auth_manager.SetEntityPermissions(working_folder, [perm])
+                        if args.debug:
+                            print(
+                                f"Adding permission VM-Ko-Admin for user {vcenter_set_permission_name} on folder {foldername}"
+                            )
+
+            for user in unknown_users:
+                if args.debug:
+                    print(
+                        f"Removing permissions for {user} on Folder {foldername} as Users permissions were removed in the CMDB."
+                    )
+                if not args.test:
+                    auth_manager.RemoveEntityPermission(working_folder, user, False)
+
+            vms_to_move = []
+
+            vms = content.viewManager.CreateContainerView(
+                container, [vim.VirtualMachine], True
+            )
+
+            # iterate over all VMs in the VCenter and try to find the specified VMs by the ID
+            for vm_obj in vms.view:
+                for vm in service["vms"]:
+                    # check if the vm is in the current vcenter
+                    if int(vm["vcenter_id"]) != vcenter["id"]:
+                        continue
+
+                    vmid = str(vm_obj).replace("'", "").split("-")[1]
+                    if vm["id"] == vmid:
+                        if not check_if_vm_in_folder(vm_obj, working_folder, content):
+                            vms_to_move.append(vm_obj)
+                            if args.debug:
+                                print(
+                                    f"VM {vm_obj.summary.config.name} will be moved to folder {foldername}."
+                                )
+
+            # finally move the vms to the service folder
+            if len(vms_to_move) > 0:
+                if not args.test:
+                    task = working_folder.MoveInto(vms_to_move)
+                    ret_val = wait_for_task(task)
+                    if ret_val == 1:
+                        print(f"Error while moving vms: {str(vms_to_move)}")
+
+    # delete all empty folders across all vcenters after everything is done
+    for vcenter in VCENTERS:
+        # Connect to the vcenter
+        warnings.filterwarnings("ignore", category=DeprecationWarning)
+        s = ssl.SSLContext()
+        s.verify_mode = ssl.CERT_NONE
+        si = SmartConnect(
+            host=vcenter["hostname"],
+            user=args.vcenter_username,
+            pwd=args.vcenter_password,
+            sslContext=s,
+            port=443,
+        )
+        register(Disconnect, si)
+        content = si.RetrieveContent()
+        container = content.rootFolder
+        ROOT_FOLDER = find_root_folder(int(vcenter["root_folder_id"]), content)
+        if ROOT_FOLDER is None:
+            print(f"Root Folder doesnt exist in {vcenter['hostname']}, Exiting")
+            exit(1)
+
+        subfolders = content.viewManager.CreateContainerView(
+            ROOT_FOLDER, [vim.Folder], False
+        )
+
+        # delete all empty folders
+        for folder in subfolders.view:
+            # THIS WILL DELETE _ALL_ CHILDREN OF THIS FOLDER AS WELL WITHOUT ANY WARNING
+            # SO USE A DOUBLE CHECK TO REALLY MAKE SURE THE FOLDER IS EMPTY
+            check_content = folder.childEntity
+            if len(check_content) == 0:
+                check2 = content.viewManager.CreateContainerView(
+                    folder, [vim.VirtualMachine, vim.Folder], True
+                )
+                if len(check2.view) == 0:
+                    # shouldnt throw exceptions but a folder was created where i have no deletion rights
+                    try:
+                        if args.debug:
+                            print(
+                                f"Destroying Folder {str(folder.name)}, as it has no contents."
+                            )
+                        if not args.test:
+                            folder.Destroy_Task()
+                            ret_val = wait_for_task(task)
+                            if ret_val == 1:
+                                print(f"Error removing folder {folder.name}")
+
+                    except:
+                        pass
+
+
+if __name__ == "__main__":
+    main()
diff --git a/cmdbscript/config.json b/cmdbscript/config.json
new file mode 100644
index 0000000000000000000000000000000000000000..4190128cac5fa1c8ad941fb5c49d8680bfd2a7ab
--- /dev/null
+++ b/cmdbscript/config.json
@@ -0,0 +1,7 @@
+[
+    {
+        "hostname": "vc-enterprise-tre.zih.tu-dresden.de", 
+        "id": 1, 
+        "root_folder_id": 369807
+    }
+]
\ No newline at end of file
diff --git a/cmdbscript/servicemap.json b/cmdbscript/servicemap.json
new file mode 100644
index 0000000000000000000000000000000000000000..0419d827f2694eda882b2ebd01b513be4a523c11
--- /dev/null
+++ b/cmdbscript/servicemap.json
@@ -0,0 +1,52 @@
+
+[
+    {
+        "name": "Servicename",
+        "id": 1,
+        "contacts": [
+            {
+                "login": "kuki797d",
+                "primary": true
+            },
+            {
+                "login": "test999",
+                "primary": false
+            }
+        ],
+        "vms": [
+            {
+                "id": 82823,
+                "vcenter_id": 1
+            },
+            {
+                "id": 232332,
+                "vcenter_id": 2
+            }
+        ]
+    },
+
+    {
+        "name": "Servicename2",
+        "id": 1,
+        "contacts": [
+            {
+                "login": "kuki797d",
+                "primary": true
+            },
+            {
+                "login": "test999",
+                "primary": false
+            }
+        ],
+        "vms": [
+            {
+                "id": 82823,
+                "vcenter_id": 1
+            },
+            {
+                "id": 232332,
+                "vcenter_id": 2
+            }
+        ]
+    }
+]