├── roles ├── ceph-osd │ ├── templates │ │ ├── osd.conf.j2 │ │ ├── ceph-osd.service.j2 │ │ └── ceph-osd-run.sh.j2 │ ├── tasks │ │ ├── docker │ │ │ ├── dirs_permissions.yml │ │ │ ├── selinux.yml │ │ │ ├── checks.yml │ │ │ ├── fetch_configs.yml │ │ │ ├── main.yml │ │ │ └── start_docker_osd.yml │ │ ├── scenarios │ │ │ ├── raw_multi_journal.yml │ │ │ ├── dmcrypt-dedicated-journal.yml │ │ │ ├── osd_directory.yml │ │ │ ├── bluestore.yml │ │ │ ├── dmcrypt-journal-collocation.yml │ │ │ └── journal_collocation.yml │ │ ├── pre_requisite.yml │ │ ├── check_devices_static.yml │ │ ├── check_devices_auto.yml │ │ ├── main.yml │ │ ├── osd_fragment.yml │ │ ├── check_devices.yml │ │ ├── check_mandatory_vars.yml │ │ └── activate_osds.yml │ ├── meta │ │ └── main.yml │ ├── README.md │ ├── defaults │ │ └── main.yml │ └── LICENSE ├── ceph-mon │ ├── files │ │ └── precise │ │ │ └── 92-ceph │ ├── tasks │ │ ├── calamari.yml │ │ ├── start_monitor.yml │ │ ├── docker │ │ │ ├── copy_configs.yml │ │ │ ├── dirs_permissions.yml │ │ │ ├── selinux.yml │ │ │ ├── checks.yml │ │ │ ├── fetch_configs.yml │ │ │ ├── create_configs.yml │ │ │ ├── start_docker_monitor.yml │ │ │ └── main.yml │ │ ├── secure_cluster.yml │ │ ├── check_mandatory_vars.yml │ │ ├── rbd_pool.yml │ │ ├── rbd_pool_pgs.yml │ │ ├── openstack_config.yml │ │ ├── rbd_pool_size.yml │ │ ├── main.yml │ │ ├── create_mds_filesystems.yml │ │ ├── deploy_monitors.yml │ │ └── ceph_keys.yml │ ├── meta │ │ └── main.yml │ ├── README.md │ ├── templates │ │ └── ceph-mon.service.j2 │ ├── defaults │ │ └── main.yml │ └── LICENSE ├── ceph-common │ ├── tasks │ │ ├── installs │ │ │ ├── install_on_clear.yml │ │ │ ├── redhat_ceph_repository.yml │ │ │ ├── install_on_debian.yml │ │ │ ├── install_rh_storage_on_redhat.yml │ │ │ ├── debian_ceph_repository.yml │ │ │ ├── install_rh_storage_on_debian.yml │ │ │ └── install_on_redhat.yml │ │ ├── checks │ │ │ ├── check_ntp_atomic.yml │ │ │ ├── check_ntp_debian.yml │ │ │ ├── check_ntp_redhat.yml │ │ │ ├── check_socket.yml │ │ │ ├── check_mandatory_vars.yml │ │ │ ├── check_system.yml │ │ │ └── check_firewall.yml │ │ ├── misc │ │ │ ├── ntp_atomic.yml │ │ │ ├── ntp_debian.yml │ │ │ ├── ntp_redhat.yml │ │ │ └── system_tuning.yml │ │ ├── release.yml │ │ ├── create_rbd_client_dir.yml │ │ ├── create_ceph_initial_dirs.yml │ │ ├── generate_ceph_conf.yml │ │ ├── generate_cluster_fsid.yml │ │ ├── pre_requisites │ │ │ ├── prerequisite_rhcs_iso_install.yml │ │ │ └── prerequisite_rhcs_cdn_install.yml │ │ ├── docker │ │ │ └── fetch_image.yml │ │ ├── configure_cluster_name.yml │ │ ├── facts_mon_fsid.yml │ │ ├── facts.yml │ │ └── main.yml │ ├── templates │ │ ├── client_restapi_interface.j2 │ │ ├── client_restapi_address.j2 │ │ ├── rhcs.pref.j2 │ │ ├── redhat_storage_repo.j2 │ │ ├── ganesha.conf.j2 │ │ └── ceph.conf.j2 │ ├── meta │ │ └── main.yml │ ├── handlers │ │ ├── restart-mds.yml │ │ ├── restart-rgw.yml │ │ ├── main.yml │ │ ├── restart-mon.yml │ │ ├── restart-osd.yml │ │ ├── validate-osd.yml │ │ └── validate-mon.yml │ ├── plugins │ │ └── actions │ │ │ └── config_template.py │ ├── files │ │ ├── cephstable.asc │ │ ├── cephstablerhcs.asc │ │ └── cephdev.asc │ ├── README.md │ └── LICENSE └── ceph-mds │ ├── tasks │ ├── main.yml │ ├── docker │ │ ├── dirs_permissions.yml │ │ ├── selinux.yml │ │ ├── start_docker_mds.yml │ │ ├── checks.yml │ │ ├── fetch_configs.yml │ │ └── main.yml │ └── pre_requisite.yml │ ├── meta │ └── main.yml │ ├── README.md │ ├── defaults │ └── main.yml │ ├── templates │ └── ceph-mds.service.j2 │ └── LICENSE ├── examples └── ceph │ ├── hosts │ ├── group_vars │ ├── all │ └── osds │ ├── ansible.cfg │ └── ceph_deploy.yml ├── Makefile ├── README.md ├── .gitignore └── LICENSE /roles/ceph-osd/templates/osd.conf.j2: -------------------------------------------------------------------------------- 1 | [osd.{{ item.stdout }}] 2 | osd crush location = {{ osd_crush_location }} 3 | -------------------------------------------------------------------------------- /roles/ceph-mon/files/precise/92-ceph: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo -n "Ceph state is: " 4 | /usr/bin/ceph health 5 | echo "" 6 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/installs/install_on_clear.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install ceph bundle 3 | package: name=storage-cluster state=present 4 | -------------------------------------------------------------------------------- /examples/ceph/hosts: -------------------------------------------------------------------------------- 1 | [mons] 2 | 172.28.128.6 3 | 4 | [osds] 5 | 172.28.128.7 6 | 172.28.128.8 7 | 172.28.128.9 8 | 9 | [mdss] 10 | 172.28.128.10 11 | -------------------------------------------------------------------------------- /examples/ceph/group_vars/all: -------------------------------------------------------------------------------- 1 | --- 2 | journal_size: 5120 3 | monitor_interface: eno1 4 | public_network: 172.28.128.0/24 5 | cluster_network: "{{ public_network }}" 6 | -------------------------------------------------------------------------------- /examples/ceph/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | # Enable to print how much time takes each task 3 | # callback_whitelist = profile_tasks 4 | 5 | [ssh_connection] 6 | pipelining = True 7 | -------------------------------------------------------------------------------- /roles/ceph-common/templates/client_restapi_interface.j2: -------------------------------------------------------------------------------- 1 | public addr = {{ hostvars[inventory_hostname]['ansible_' + restapi_interface]['ipv4']['address'] }}:{{ restapi_port }} 2 | 3 | -------------------------------------------------------------------------------- /roles/ceph-mds/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: pre_requisite.yml 3 | when: not mds_containerized_deployment 4 | 5 | - include: ./docker/main.yml 6 | when: mds_containerized_deployment 7 | -------------------------------------------------------------------------------- /examples/ceph/ceph_deploy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: mons 3 | roles: 4 | - ceph-mon 5 | 6 | - hosts: osds 7 | roles: 8 | - ceph-osd 9 | 10 | - hosts: mdss 11 | roles: 12 | - ceph-mds 13 | -------------------------------------------------------------------------------- /roles/ceph-common/templates/client_restapi_address.j2: -------------------------------------------------------------------------------- 1 | public addr = {{ hostvars[inventory_hostname]['restapi_address'] if hostvars[inventory_hostname]['restapi_address'] is defined else restapi_address }}:{{ restapi_port }} 2 | 3 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/checks/check_ntp_atomic.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check ntp installation on atomic 3 | command: rpm -q chrony 4 | register: ntp_pkg_query 5 | ignore_errors: true 6 | always_run: true 7 | changed_when: false 8 | -------------------------------------------------------------------------------- /roles/ceph-common/templates/rhcs.pref.j2: -------------------------------------------------------------------------------- 1 | #jinja2: trim_blocks: "true", lstrip_blocks: "true" 2 | # {{ ansible_managed }} 3 | 4 | Explanation: Prefer Red Hat packages 5 | Package: * 6 | Pin: release o=/Red Hat/ 7 | Pin-Priority: 999 8 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/checks/check_ntp_debian.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check ntp installation on debian 3 | command: dpkg -s ntp 4 | register: ntp_pkg_query 5 | ignore_errors: true 6 | always_run: true 7 | changed_when: false 8 | when: ansible_os_family == 'Debian' 9 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/checks/check_ntp_redhat.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check ntp installation on redhat 3 | command: rpm -q ntp 4 | register: ntp_pkg_query 5 | ignore_errors: true 6 | always_run: true 7 | changed_when: false 8 | when: ansible_os_family == 'RedHat' 9 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/calamari.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install calamari server 3 | package: 4 | name: calamari-server 5 | state: present 6 | tags: 7 | - package-install 8 | 9 | - name: initialize the calamari server api 10 | command: calamari-ctl initialize 11 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/misc/ntp_atomic.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: ../checks/check_ntp_atomic.yml 3 | when: is_atomic 4 | 5 | - name: start the ntp service 6 | service: 7 | name: chronyd 8 | enabled: yes 9 | state: started 10 | when: 11 | - ntp_pkg_query.rc == 0 12 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/misc/ntp_debian.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: ../checks/check_ntp_debian.yml 3 | when: ansible_os_family == 'Debian' 4 | 5 | - name: start the ntp service 6 | service: 7 | name: ntp 8 | enabled: yes 9 | state: started 10 | when: 11 | - ntp_pkg_query.rc == 0 12 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/misc/ntp_redhat.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: ../checks/check_ntp_redhat.yml 3 | when: ansible_os_family == 'RedHat' 4 | 5 | - name: start the ntp service 6 | service: 7 | name: ntpd 8 | enabled: yes 9 | state: started 10 | when: 11 | - ntp_pkg_query.rc == 0 12 | -------------------------------------------------------------------------------- /roles/ceph-mds/tasks/docker/dirs_permissions.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: create bootstrap directories 3 | file: 4 | path: "{{ item }}" 5 | state: directory 6 | owner: "64045" 7 | group: "64045" 8 | mode: "0755" 9 | with_items: 10 | - /etc/ceph/ 11 | - /var/lib/ceph/bootstrap-mds 12 | -------------------------------------------------------------------------------- /roles/ceph-osd/tasks/docker/dirs_permissions.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: create bootstrap directories 3 | file: 4 | path: "{{ item }}" 5 | state: directory 6 | owner: "64045" 7 | group: "64045" 8 | mode: "0755" 9 | with_items: 10 | - /etc/ceph/ 11 | - /var/lib/ceph/bootstrap-osd 12 | -------------------------------------------------------------------------------- /roles/ceph-common/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: Sébastien Han 4 | description: Installs Ceph 5 | license: Apache 6 | min_ansible_version: 1.7 7 | platforms: 8 | - name: Ubuntu 9 | versions: 10 | - trusty 11 | categories: 12 | - system 13 | dependencies: [] 14 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/start_monitor.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: start the monitor service 3 | service: 4 | name: ceph-mon@{{ monitor_name }} 5 | state: started 6 | enabled: yes 7 | changed_when: false 8 | 9 | - name: Enable ceph-mon.target 10 | service: name=ceph-mon.target enabled=yes 11 | when: ansible_os_family == 'ClearLinux' 12 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/docker/copy_configs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: push ceph files to the ansible server 3 | fetch: 4 | src: "{{ item.0 }}" 5 | dest: "{{ fetch_directory }}/docker_mon_files/{{ item.0 }}" 6 | flat: yes 7 | with_together: 8 | - "{{ ceph_config_keys }}" 9 | - "{{ statconfig.results }}" 10 | when: item.1.stat.exists == false 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DESTDIR=%{buildroot} 2 | ansibledir = /usr/share/ansible 3 | 4 | all: 5 | 6 | install: 7 | install -m755 -d $(DESTDIR)$(ansibledir) 8 | cp -r roles $(DESTDIR)$(ansibledir) 9 | cp -r examples $(DESTDIR)$(ansibledir) 10 | install -m755 -d $(DESTDIR)$(ansibledir)/plugins/action 11 | mv roles/ceph-common/plugins/actions/*.py $(DESTDIR)$(ansibledir)/plugins/action 12 | -------------------------------------------------------------------------------- /roles/ceph-mds/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: Sébastien Han 4 | description: Installs Ceph Metadata 5 | license: Apache 6 | min_ansible_version: 1.7 7 | platforms: 8 | - name: Ubuntu 9 | versions: 10 | - trusty 11 | categories: 12 | - system 13 | dependencies: 14 | - { role: ceph-common, when: not mds_containerized_deployment } 15 | -------------------------------------------------------------------------------- /roles/ceph-mon/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: Sébastien Han 4 | description: Installs Ceph Monitor 5 | license: Apache 6 | min_ansible_version: 1.7 7 | platforms: 8 | - name: Ubuntu 9 | versions: 10 | - trusty 11 | categories: 12 | - system 13 | dependencies: 14 | - { role: ceph-common, when: not mon_containerized_deployment } 15 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/docker/dirs_permissions.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: create bootstrap directories 3 | file: 4 | path: "{{ item }}" 5 | state: directory 6 | owner: "64045" 7 | group: "64045" 8 | mode: "0755" 9 | with_items: 10 | - /etc/ceph/ 11 | - /var/lib/ceph/bootstrap-osd 12 | - /var/lib/ceph/bootstrap-mds 13 | - /var/lib/ceph/bootstrap-rgw 14 | -------------------------------------------------------------------------------- /roles/ceph-osd/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: Sébastien Han 4 | description: Installs Ceph Object Storage Daemon 5 | license: Apache 6 | min_ansible_version: 1.7 7 | platforms: 8 | - name: Ubuntu 9 | versions: 10 | - trusty 11 | categories: 12 | - system 13 | dependencies: 14 | - { role: ceph-common, when: not osd_containerized_deployment } 15 | -------------------------------------------------------------------------------- /roles/ceph-mds/tasks/docker/selinux.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check if selinux is enabled 3 | command: getenforce 4 | register: sestatus 5 | changed_when: false 6 | always_run: true 7 | 8 | - name: set selinux permissions 9 | shell: chcon -Rt svirt_sandbox_file_t {{ item }} 10 | with_items: 11 | - /etc/ceph 12 | - /var/lib/ceph 13 | changed_when: false 14 | when: sestatus.stdout != 'Disabled' 15 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/docker/selinux.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check if selinux is enabled 3 | command: getenforce 4 | register: sestatus 5 | changed_when: false 6 | always_run: true 7 | 8 | - name: set selinux permissions 9 | shell: chcon -Rt svirt_sandbox_file_t {{ item }} 10 | with_items: 11 | - /etc/ceph 12 | - /var/lib/ceph 13 | changed_when: false 14 | when: sestatus.stdout != 'Disabled' 15 | -------------------------------------------------------------------------------- /roles/ceph-osd/tasks/docker/selinux.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check if selinux is enabled 3 | command: getenforce 4 | register: sestatus 5 | changed_when: false 6 | always_run: true 7 | 8 | - name: set selinux permissions 9 | shell: chcon -Rt svirt_sandbox_file_t {{ item }} 10 | with_items: 11 | - /etc/ceph 12 | - /var/lib/ceph 13 | changed_when: false 14 | when: sestatus.stdout != 'Disabled' 15 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/secure_cluster.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: collect all the pools 3 | command: rados --cluster {{ cluster }} lspools 4 | register: ceph_pools 5 | always_run: true 6 | 7 | - name: secure the cluster 8 | command: ceph --cluster {{ cluster }} osd pool set {{ item[0] }} {{ item[1] }} true 9 | with_nested: 10 | - "{{ ceph_pools.stdout_lines|default([]) }}" 11 | - "{{ secure_cluster_flags }}" 12 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Set ceph_release to ceph_stable by default 3 | - set_fact: 4 | ceph_release: "{{ ceph_stable_release }}" 5 | 6 | # Set ceph_release to latest known release (Which should match ceph_dev) 7 | - set_fact: 8 | ceph_release: "{{ item.key }}" 9 | when: 10 | - ceph_dev 11 | - ({{ item.value }} > ceph_release_num.{{ ceph_release }}) 12 | with_dict: "{{ ceph_release_num }}" 13 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/create_rbd_client_dir.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: create rbd client directory 3 | file: 4 | path: "{{ item }}" 5 | state: directory 6 | owner: "{{ rbd_client_directory_owner }}" 7 | group: "{{ rbd_client_directory_group }}" 8 | mode: "{{ rbd_client_directory_mode }}" 9 | with_items: 10 | - "{{ rbd_client_admin_socket_path }}" 11 | - "{{ rbd_client_log_path }}" 12 | when: rbd_client_directories 13 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/check_mandatory_vars.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: make sure monitor_interface or monitor_address or monitor_address_block is configured 3 | fail: 4 | msg: "Either monitor_interface, monitor_address, or monitor_address_block must be configured. Interface for the monitor to listen on or IP address of that interface" 5 | when: 6 | - monitor_interface == 'interface' 7 | - monitor_address == '0.0.0.0' 8 | - not monitor_address_block 9 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/checks/check_socket.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check for a ceph socket 3 | shell: "stat /var/run/ceph/*.asok > /dev/null 2>&1" 4 | changed_when: false 5 | failed_when: false 6 | always_run: true 7 | register: socket 8 | 9 | - name: check for a rados gateway socket 10 | shell: "stat {{ rbd_client_admin_socket_path }}*.asok > /dev/null 2>&1" 11 | changed_when: false 12 | failed_when: false 13 | always_run: true 14 | register: socketrgw 15 | -------------------------------------------------------------------------------- /roles/ceph-common/handlers/restart-mds.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart ceph mdss 3 | service: 4 | name: ceph-mds@{{ mds_name }} 5 | state: restarted 6 | # serial: 1 would be the proper solution here, but that can only be set on play level 7 | # upstream issue: https://github.com/ansible/ansible/issues/12170 8 | run_once: true 9 | with_items: "{{ groups[mds_group_name] }}" 10 | delegate_to: "{{ item }}" 11 | when: 12 | - socket.rc == 0 13 | - mds_group_name in group_names 14 | -------------------------------------------------------------------------------- /roles/ceph-common/handlers/restart-rgw.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart ceph rgws 3 | service: 4 | name: ceph-rgw@{{ ansible_hostname }} 5 | state: restarted 6 | # serial: 1 would be the proper solution here, but that can only be set on play level 7 | # upstream issue: https://github.com/ansible/ansible/issues/12170 8 | run_once: true 9 | with_items: "{{ groups[rgw_group_name] }}" 10 | delegate_to: "{{ item }}" 11 | when: 12 | - socketrgw.rc == 0 13 | - rgw_group_name in group_names 14 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/rbd_pool.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check rbd pool usage 3 | shell: | 4 | ceph --connect-timeout 5 --cluster {{ cluster }} df | awk '/rbd/ {print $3}' 5 | changed_when: false 6 | failed_when: false 7 | always_run: true 8 | register: rbd_pool_df 9 | 10 | - name: check pg num for rbd pool 11 | shell: | 12 | ceph --connect-timeout 5 --cluster {{ cluster }} osd pool get rbd pg_num | awk '{print $2}' 13 | changed_when: false 14 | failed_when: false 15 | always_run: true 16 | register: rbd_pool_pgs 17 | 18 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/create_ceph_initial_dirs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: create ceph initial directories 3 | file: 4 | path: "{{ item }}" 5 | state: directory 6 | owner: ceph 7 | group: ceph 8 | mode: 0755 9 | with_items: 10 | - /etc/ceph 11 | - /var/lib/ceph/ 12 | - /var/lib/ceph/mon 13 | - /var/lib/ceph/osd 14 | - /var/lib/ceph/mds 15 | - /var/lib/ceph/tmp 16 | - /var/lib/ceph/radosgw 17 | - /var/lib/ceph/bootstrap-rgw 18 | - /var/lib/ceph/bootstrap-mds 19 | - /var/lib/ceph/bootstrap-osd 20 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/rbd_pool_pgs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: destroy and recreate rbd pool if osd_pool_default_pg_num is not honoured 3 | shell: | 4 | ceph --connect-timeout 5 --cluster {{ cluster }} osd pool rm rbd rbd --yes-i-really-really-mean-it 5 | ceph --connect-timeout 5 --cluster {{ cluster }} osd pool create rbd {{ ceph_conf_overrides.global.osd_pool_default_pg_num }} 6 | changed_when: false 7 | failed_when: false 8 | when: 9 | - rbd_pool_df.stdout == "0" 10 | - rbd_pool_pgs.stdout != "{{ ceph_conf_overrides.global.osd_pool_default_pg_num }}" 11 | -------------------------------------------------------------------------------- /roles/ceph-common/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: update apt cache 3 | apt: 4 | update-cache: yes 5 | when: ansible_os_family == 'Debian' 6 | 7 | - name: restart ceph mons 8 | include: "./restart-mon.yml" 9 | 10 | - name: restart ceph osds 11 | include: "./restart-osd.yml" 12 | 13 | - name: restart ceph mdss 14 | include: "./restart-mds.yml" 15 | 16 | - name: restart ceph rgws 17 | include: "./restart-rgw.yml" 18 | 19 | - name: restart ceph nfss 20 | service: 21 | name: nfs-ganesha 22 | state: restarted 23 | when: 24 | - nfs_group_name in group_names 25 | -------------------------------------------------------------------------------- /roles/ceph-osd/templates/ceph-osd.service.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | [Unit] 3 | Description=Ceph OSD 4 | After=docker.service 5 | 6 | [Service] 7 | EnvironmentFile=-/etc/environment 8 | ExecStartPre=-/usr/bin/docker stop {{ ansible_hostname }}-osd-dev%i 9 | ExecStartPre=-/usr/bin/docker rm -f {{ ansible_hostname }}-osd-dev%i 10 | ExecStart={{ ceph_osd_docker_run_script_path }}/ceph-osd-run.sh %i 11 | ExecStop=-/usr/bin/docker stop {{ ansible_hostname }}-osd-dev%i 12 | Restart=always 13 | RestartSec=10s 14 | TimeoutStartSec=120 15 | TimeoutStopSec=15 16 | 17 | [Install] 18 | WantedBy=multi-user.target 19 | -------------------------------------------------------------------------------- /roles/ceph-common/handlers/restart-mon.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart ceph mons 3 | service: 4 | name: ceph-mon@{{ monitor_name }} 5 | state: restarted 6 | # serial: 1 would be the proper solution here, but that can only be set on play level 7 | # upstream issue: https://github.com/ansible/ansible/issues/12170 8 | run_once: true 9 | with_items: "{{ groups[mon_group_name] }}" 10 | delegate_to: "{{ item }}" 11 | when: 12 | - socket.rc == 0 13 | - mon_group_name in group_names 14 | 15 | - name: validate monitors 16 | include: validate-mon.yml 17 | when: mon_group_name in group_names 18 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/openstack_config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: create openstack pool 3 | command: ceph --cluster {{ cluster }} osd pool create {{ item.name }} {{ item.pg_num }} 4 | with_items: "{{ openstack_pools | unique }}" 5 | changed_when: false 6 | failed_when: false 7 | 8 | - name: create openstack keys 9 | command: ceph --cluster {{ cluster }} auth get-or-create {{ item.name }} {{ item.value }} -o /etc/ceph/{{ cluster }}.{{ item.name }}.keyring 10 | args: 11 | creates: /etc/ceph/{{ cluster }}.{{ item.name }}.keyring 12 | with_items: "{{ openstack_keys }}" 13 | changed_when: false 14 | when: cephx 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Clear Config Management 2 | This repository contains application roles to be used with Ansible 3 | as Configuration Management Engine running on Clear Linux*. 4 | 5 | ## Components supported 6 | At the moment, this installer is able to deploy the following components 7 | - [Ceph](https://github.com/clearlinux/clear-config-management/tree/master/examples/ceph) 8 | 9 | ## How to use it in Clear Linux* 10 | - https://clearlinux.org/documentation/ceph-deploy.html 11 | 12 | ## BUGS & Features 13 | Please use the [issue tracker](http://github.com/clearlinux/clear-config-management/issues) 14 | to report bugs or ask for features. 15 | -------------------------------------------------------------------------------- /roles/ceph-common/templates/redhat_storage_repo.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | [rh_storage_mon] 3 | name=Red Hat Ceph Storage - local packages for Ceph monitor 4 | baseurl=file://{{ ceph_rhcs_repository_path }}/MON 5 | enabled=1 6 | gpgcheck=1 7 | priority=1 8 | 9 | [rh_storage_osd] 10 | name=Red Hat Ceph Storage - local packages for Ceph OSD 11 | baseurl=file://{{ ceph_rhcs_repository_path }}/OSD 12 | enabled=1 13 | gpgcheck=1 14 | priority=1 15 | 16 | [rh_storage_tools] 17 | name=Red Hat Ceph Storage - local packages for Ceph client, MDS, and RGW 18 | baseurl=file://{{ ceph_rhcs_repository_path }}/Tools 19 | enabled=1 20 | gpgcheck=1 21 | priority=1 22 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/generate_ceph_conf.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: create ceph conf directory 3 | file: 4 | path: /etc/ceph 5 | state: directory 6 | owner: "ceph" 7 | group: "ceph" 8 | mode: "0755" 9 | 10 | - name: "generate ceph configuration file: {{ cluster }}.conf" 11 | action: config_template 12 | args: 13 | src: ceph.conf.j2 14 | dest: /etc/ceph/{{ cluster }}.conf 15 | owner: "ceph" 16 | group: "ceph" 17 | mode: "0644" 18 | config_overrides: "{{ ceph_conf_overrides }}" 19 | config_type: ini 20 | notify: 21 | - restart ceph mons 22 | - restart ceph osds 23 | - restart ceph mdss 24 | - restart ceph rgws 25 | - restart ceph nfss 26 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/rbd_pool_size.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check size for rbd pool 3 | shell: | 4 | ceph --connect-timeout 5 --cluster {{ cluster }} osd pool get rbd size | awk '{print $2}' 5 | changed_when: false 6 | failed_when: false 7 | always_run: true 8 | register: rbd_pool_size 9 | 10 | - name: change rbd pool size if osd_pool_default_size is not honoured 11 | command: ceph --connect-timeout 5 --cluster {{ cluster }} osd pool set rbd size {{ ceph_conf_overrides.global.osd_pool_default_size }} 12 | changed_when: false 13 | failed_when: false 14 | when: 15 | - rbd_pool_df.stdout == "0" 16 | - rbd_pool_size.stdout != "{{ ceph_conf_overrides.global.osd_pool_default_size }}" 17 | -------------------------------------------------------------------------------- /roles/ceph-mds/tasks/docker/start_docker_mds.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: generate systemd unit file 3 | become: true 4 | template: 5 | src: "{{ role_path }}/templates/ceph-mds.service.j2" 6 | dest: /etc/systemd/system/ceph-mds@.service 7 | owner: "root" 8 | group: "root" 9 | mode: "0644" 10 | 11 | - name: enable systemd unit file for mds instance 12 | shell: systemctl enable ceph-mds@{{ ansible_hostname }}.service 13 | failed_when: false 14 | changed_when: false 15 | 16 | - name: reload systemd unit files 17 | shell: systemctl daemon-reload 18 | changed_when: false 19 | failed_when: false 20 | 21 | - name: systemd start mds container 22 | service: 23 | name: ceph-mds@{{ ansible_hostname }} 24 | state: started 25 | enabled: yes 26 | changed_when: false 27 | -------------------------------------------------------------------------------- /roles/ceph-osd/tasks/scenarios/raw_multi_journal.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ## SCENARIO 3: N JOURNAL DEVICES FOR N OSDS 3 | 4 | - include: ../check_devices.yml 5 | 6 | # NOTE (leseb): the prepare process must be parallelized somehow... 7 | # if you have 64 disks with 4TB each, this will take a while 8 | # since Ansible will sequential process the loop 9 | 10 | - name: prepare filestore osd disk(s) with a dedicated journal device 11 | command: "ceph-disk prepare --cluster {{ cluster }} {{ item.1 }} {{ item.2 }}" 12 | with_together: 13 | - "{{ parted_results.results }}" 14 | - "{{ devices }}" 15 | - "{{ raw_journal_devices }}" 16 | changed_when: false 17 | when: 18 | - item.0.get("skipped") or item.0.get("rc", 0) != 0 19 | - raw_multi_journal 20 | - not osd_auto_discovery 21 | 22 | - include: ../activate_osds.yml 23 | -------------------------------------------------------------------------------- /roles/ceph-common/handlers/restart-osd.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # This does not just restart OSDs but everything else too. Unfortunately 3 | # at this time the ansible role does not have an OSD id list to use 4 | # for restarting them specifically. 5 | - name: restart ceph osds 6 | shell: | 7 | for id in $(ls /var/lib/ceph/osd/ |grep -oP '\d+$'); do 8 | systemctl restart ceph-osd@$id 9 | sleep 5 10 | done 11 | # serial: 1 would be the proper solution here, but that can only be set on play level 12 | # upstream issue: https://github.com/ansible/ansible/issues/12170 13 | run_once: true 14 | with_items: "{{ groups[osd_group_name] }}" 15 | delegate_to: "{{ item }}" 16 | when: 17 | - socket.rc == 0 18 | - osd_group_name in group_names 19 | 20 | - name: validate osds 21 | include: validate-osd.yml 22 | when: osd_group_name in group_names 23 | -------------------------------------------------------------------------------- /roles/ceph-common/handlers/validate-osd.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: collect osds 3 | shell: | 4 | ls /var/lib/ceph/osd/ |grep -oP '\d+$' 5 | register: osd_ids 6 | 7 | - name: wait for ceph osd socket(s) 8 | wait_for: 9 | path: "/var/run/ceph/{{ cluster }}-osd.{{ item }}.asok" 10 | with_items: "{{ osd_ids.stdout_lines }}" 11 | 12 | - name: waiting for clean pgs... 13 | shell: | 14 | test "$(ceph --cluster {{ cluster }} pg stat | sed 's/^.*pgs://;s/active+clean.*//;s/ //')" -eq "$(ceph --cluster {{ cluster }} pg stat | sed 's/pgs.*//;s/^.*://;s/ //')" && ceph --cluster {{ cluster }} health | egrep -sq "HEALTH_OK|HEALTH_WARN" 15 | register: result 16 | until: result.rc == 0 17 | retries: "{{ handler_health_osd_check_retries }}" 18 | delay: "{{ handler_health_osd_check_delay }}" 19 | delegate_to: "{{ groups[mon_group_name][0] }}" 20 | when: handler_health_osd_check 21 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: deploy_monitors.yml 3 | when: not mon_containerized_deployment 4 | 5 | - include: start_monitor.yml 6 | when: not mon_containerized_deployment 7 | 8 | - include: ceph_keys.yml 9 | when: not mon_containerized_deployment 10 | # this avoids the bug mentioned here: https://github.com/ansible/ansible/issues/18206 11 | static: no 12 | 13 | - include: create_mds_filesystems.yml 14 | when: 15 | - not mon_containerized_deployment 16 | - groups[mds_group_name] is defined 17 | - "{{ groups[mds_group_name]|length > 0 }}" 18 | - inventory_hostname == groups.mons|last 19 | 20 | - include: secure_cluster.yml 21 | when: 22 | - secure_cluster 23 | - not mon_containerized_deployment 24 | 25 | - include: ./docker/main.yml 26 | when: mon_containerized_deployment 27 | 28 | - include: calamari.yml 29 | when: calamari 30 | -------------------------------------------------------------------------------- /roles/ceph-mds/README.md: -------------------------------------------------------------------------------- 1 | # Ansible role: Ceph Metadata 2 | 3 | This role bootstraps Ceph metadata(s). 4 | It can bootstrap dockerized Ceph metadata(s). 5 | 6 | # Requirements 7 | 8 | Nothing, it runs out of the box. 9 | 10 | # Role variables 11 | 12 | Have a look at: `defaults/main.yml`. 13 | 14 | ## Mandatory variables 15 | 16 | None. 17 | 18 | # Dependencies 19 | 20 | The role `leseb.ceph-common` must be installed. 21 | 22 | # Example Playbook 23 | 24 | ``` 25 | - hosts: servers 26 | remote_user: ubuntu 27 | roles: 28 | - { role: leseb.ceph-mds } 29 | ``` 30 | 31 | # Contribution 32 | 33 | **THIS REPOSITORY DOES NOT ACCEPT PULL REQUESTS** 34 | **PULL REQUESTS MUST GO THROUGH [CEPH-ANSIBLE](https://github.com/ceph/ceph-ansible)** 35 | 36 | # License 37 | 38 | Apache 39 | 40 | # Author Information 41 | 42 | This role was created by [Sébastien Han](http://sebastien-han.fr/). 43 | -------------------------------------------------------------------------------- /roles/ceph-mds/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # You can override vars by using host or group vars 3 | 4 | ########### 5 | # GENERAL # 6 | ########### 7 | 8 | fetch_directory: fetch/ 9 | 10 | # Even though MDS nodes should not have the admin key 11 | # at their disposal, some people might want to have it 12 | # distributed on MDS nodes. Setting 'copy_admin_key' to 'true' 13 | # will copy the admin key to the /etc/ceph/ directory 14 | copy_admin_key: false 15 | 16 | cephx: true 17 | 18 | 19 | ########## 20 | # DOCKER # 21 | ########## 22 | 23 | mds_containerized_deployment: false 24 | mds_containerized_deployment_with_kv: false 25 | kv_type: etcd 26 | kv_endpoint: 127.0.0.1 27 | ceph_docker_image: "ceph/daemon" 28 | ceph_docker_image_tag: latest 29 | ceph_mds_docker_extra_env: -e CLUSTER={{ cluster }} -e MDS_NAME={{ ansible_hostname }} 30 | ceph_docker_on_openstack: false 31 | ceph_config_keys: [] # DON'T TOUCH ME 32 | -------------------------------------------------------------------------------- /examples/ceph/group_vars/osds: -------------------------------------------------------------------------------- 1 | --- 2 | # Enable only one scenario 3 | 4 | # First Scenario: Journal and osd_data on the same device 5 | # This will collocate both journal and data on the same disk 6 | # creating a partition at the beginning of the device 7 | # journal_collocation: true 8 | # devices: 9 | # - /dev/sdb 10 | # - /dev/sdc 11 | # - /dev/sdd 12 | 13 | # Second Scenario: N journal devices for N OSDs 14 | # In this example: sdb will be used for journaling of sdc and sdd 15 | # sdf will be used for journaling of sde 16 | # raw_multi_journal: true 17 | # devices: 18 | # - /dev/sdc 19 | # - /dev/sdd 20 | # - /dev/sde 21 | # raw_journal_devices: 22 | # - /dev/sdb 23 | # - /dev/sdb 24 | # - /dev/sdf 25 | 26 | # Third Scenario: Use a directory instead of a disk for OSDs 27 | # osd_directory: true 28 | # osd_directories: 29 | # - /var/lib/ceph/osd/mydir1 30 | # - /var/lib/ceph/osd/mydir2 31 | # - /var/lib/ceph/osd/mydir3 32 | 33 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/generate_cluster_fsid.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: generate cluster fsid 3 | local_action: shell python -c 'import uuid; print(str(uuid.uuid4()))' | tee {{ fetch_directory }}/ceph_cluster_uuid.conf 4 | creates="{{ fetch_directory }}/ceph_cluster_uuid.conf" 5 | register: cluster_uuid 6 | become: false 7 | when: 8 | - generate_fsid 9 | - ceph_current_fsid.rc != 0 10 | 11 | - name: reuse cluster fsid when cluster is already running 12 | local_action: shell echo {{ fsid }} | tee {{ fetch_directory }}/ceph_cluster_uuid.conf 13 | creates="{{ fetch_directory }}/ceph_cluster_uuid.conf" 14 | become: false 15 | when: ceph_current_fsid.rc == 0 16 | 17 | - name: read cluster fsid if it already exists 18 | local_action: command cat {{ fetch_directory }}/ceph_cluster_uuid.conf 19 | removes="{{ fetch_directory }}/ceph_cluster_uuid.conf" 20 | changed_when: false 21 | register: cluster_uuid 22 | become: false 23 | always_run: true 24 | when: generate_fsid 25 | -------------------------------------------------------------------------------- /roles/ceph-mds/tasks/docker/checks.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: set config and keys paths 3 | set_fact: 4 | ceph_config_keys: 5 | - /etc/ceph/{{ cluster }}.client.admin.keyring 6 | - /etc/ceph/{{ cluster }}.conf 7 | - /etc/ceph/monmap-{{ cluster }} 8 | - /etc/ceph/{{ cluster }}.mon.keyring 9 | - /var/lib/ceph/bootstrap-osd/{{ cluster }}.keyring 10 | - /var/lib/ceph/bootstrap-rgw/{{ cluster }}.keyring 11 | - /var/lib/ceph/bootstrap-mds/{{ cluster }}.keyring 12 | 13 | - name: stat for ceph config and keys 14 | stat: 15 | path: "{{ item }}" 16 | with_items: "{{ ceph_config_keys }}" 17 | changed_when: false 18 | failed_when: false 19 | always_run: true 20 | register: statleftover 21 | 22 | - name: fail if we find existing cluster files 23 | fail: 24 | msg: "looks like no cluster is running but ceph files are present, please remove them" 25 | with_together: 26 | - "{{ ceph_config_keys }}" 27 | - "{{ statleftover.results }}" 28 | when: item.1.stat.exists == true 29 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/docker/checks.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: set config and keys paths 3 | set_fact: 4 | ceph_config_keys: 5 | - /etc/ceph/{{ cluster }}.client.admin.keyring 6 | - /etc/ceph/{{ cluster }}.conf 7 | - /etc/ceph/monmap-{{ cluster }} 8 | - /etc/ceph/{{ cluster }}.mon.keyring 9 | - /var/lib/ceph/bootstrap-osd/{{ cluster }}.keyring 10 | - /var/lib/ceph/bootstrap-rgw/{{ cluster }}.keyring 11 | - /var/lib/ceph/bootstrap-mds/{{ cluster }}.keyring 12 | 13 | - name: stat for ceph config and keys 14 | stat: 15 | path: "{{ item }}" 16 | with_items: "{{ ceph_config_keys }}" 17 | changed_when: false 18 | failed_when: false 19 | register: statleftover 20 | always_run: true 21 | 22 | - name: fail if we find existing cluster files 23 | fail: 24 | msg: "looks like no cluster is running but ceph files are present, please remove them" 25 | with_together: 26 | - "{{ ceph_config_keys }}" 27 | - "{{ statleftover.results }}" 28 | when: item.1.stat.exists == true 29 | -------------------------------------------------------------------------------- /roles/ceph-osd/tasks/docker/checks.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: set config and keys paths 3 | set_fact: 4 | ceph_config_keys: 5 | - /etc/ceph/{{ cluster }}.client.admin.keyring 6 | - /etc/ceph/{{ cluster }}.conf 7 | - /etc/ceph/monmap-{{ cluster }} 8 | - /etc/ceph/{{ cluster }}.mon.keyring 9 | - /var/lib/ceph/bootstrap-osd/{{ cluster }}.keyring 10 | - /var/lib/ceph/bootstrap-rgw/{{ cluster }}.keyring 11 | - /var/lib/ceph/bootstrap-mds/{{ cluster }}.keyring 12 | 13 | - name: stat for ceph config and keys 14 | stat: 15 | path: "{{ item }}" 16 | with_items: "{{ ceph_config_keys }}" 17 | changed_when: false 18 | failed_when: false 19 | always_run: true 20 | register: statleftover 21 | 22 | - name: fail if we find existing cluster files 23 | fail: 24 | msg: "looks like no cluster is running but ceph files are present, please remove them" 25 | with_together: 26 | - "{{ ceph_config_keys }}" 27 | - "{{ statleftover.results }}" 28 | when: item.1.stat.exists == true 29 | -------------------------------------------------------------------------------- /roles/ceph-osd/tasks/docker/fetch_configs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: set config and keys paths 3 | set_fact: 4 | ceph_config_keys: 5 | - /etc/ceph/{{ cluster }}.conf 6 | - /var/lib/ceph/bootstrap-osd/{{ cluster }}.keyring 7 | 8 | - name: wait for ceph.conf and keys 9 | local_action: > 10 | wait_for 11 | path="{{ fetch_directory }}/docker_mon_files/{{ item.0 }}" 12 | become: false 13 | with_items: "{{ ceph_config_keys }}" 14 | 15 | - name: stat for ceph config and keys 16 | local_action: stat path={{ fetch_directory }}/docker_mon_files/{{ item }} 17 | with_items: "{{ ceph_config_keys }}" 18 | changed_when: false 19 | become: false 20 | failed_when: false 21 | always_run: true 22 | register: statconfig 23 | 24 | - name: try to copy ceph config and keys 25 | copy: 26 | src: "{{ fetch_directory }}/docker_mon_files/{{ item.0 }}" 27 | dest: "{{ item.0 }}" 28 | owner: root 29 | group: root 30 | mode: 0644 31 | changed_when: false 32 | with_items: "{{ ceph_config_keys }}" 33 | -------------------------------------------------------------------------------- /roles/ceph-mds/templates/ceph-mds.service.j2: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Ceph MDS 3 | After=docker.service 4 | 5 | [Service] 6 | EnvironmentFile=-/etc/environment 7 | ExecStartPre=-/usr/bin/docker stop {{ ansible_hostname }} 8 | ExecStartPre=-/usr/bin/docker rm {{ ansible_hostname }} 9 | ExecStart=/usr/bin/docker run --rm --net=host \ 10 | {% if not mds_containerized_deployment_with_kv -%} 11 | -v /var/lib/ceph:/var/lib/ceph \ 12 | -v /etc/ceph:/etc/ceph \ 13 | {% else -%} 14 | -e KV_TYPE={{kv_type}} \ 15 | -e KV_IP={{kv_endpoint}} \ 16 | {% endif -%} 17 | -v /etc/localtime:/etc/localtime:ro \ 18 | --privileged \ 19 | -e CEPH_DAEMON=MDS \ 20 | -e CEPHFS_CREATE=1 \ 21 | {{ ceph_mds_docker_extra_env }} \ 22 | --name={{ ansible_hostname }} \ 23 | {{ ceph_docker_registry }}/{{ ceph_docker_image }}:{{ ceph_docker_image_tag }} 24 | ExecStopPost=-/usr/bin/docker stop {{ ansible_hostname }} 25 | Restart=always 26 | RestartSec=10s 27 | TimeoutStartSec=120 28 | TimeoutStopSec=15 29 | 30 | [Install] 31 | WantedBy=multi-user.target 32 | -------------------------------------------------------------------------------- /roles/ceph-common/handlers/validate-mon.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: wait for ceph monitor socket 3 | wait_for: 4 | path: "/var/run/ceph/{{ cluster }}-mon.{{ monitor_name }}.asok" 5 | 6 | - name: set mon_host_count 7 | set_fact: mon_host_count={{ groups[mon_group_name] | length }} 8 | 9 | - name: select a running monitor 10 | set_fact: mon_host={{ item }} 11 | with_items: "{{ groups[mon_group_name] }}" 12 | when: 13 | - item != inventory_hostname 14 | - mon_host_count | int > 1 15 | 16 | - name: select first monitor if only one monitor 17 | set_fact: mon_host={{ item }} 18 | with_items: "{{ groups[mon_group_name][0] }}" 19 | when: mon_host_count | int == 1 20 | 21 | - name: waiting for the monitor to join the quorum... 22 | shell: | 23 | ceph -s --cluster {{ cluster }} | grep monmap | sed 's/.*quorum//' | egrep -sq {{ ansible_hostname }} 24 | register: result 25 | until: result.rc == 0 26 | retries: "{{ handler_health_mon_check_retries }}" 27 | delay: "{{ handler_health_mon_check_delay }}" 28 | delegate_to: "{{ mon_host }}" 29 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/checks/check_mandatory_vars.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: make sure an installation origin was chosen 3 | fail: 4 | msg: "choose an installation origin" 5 | when: 6 | - ceph_origin != 'upstream' 7 | - ceph_origin != 'distro' 8 | - ceph_origin != 'local' 9 | tags: 10 | - package-install 11 | 12 | - name: make sure an installation source was chosen 13 | fail: 14 | msg: "choose an upstream installation source or read https://github.com/ceph/ceph-ansible/wiki" 15 | when: 16 | - ceph_origin == 'upstream' 17 | - not ceph_stable 18 | - not ceph_dev 19 | - not ceph_rhcs 20 | - not ceph_stable_uca 21 | - not ceph_custom 22 | tags: 23 | - package-install 24 | 25 | - name: verify that a method was chosen for red hat storage 26 | fail: 27 | msg: "choose between ceph_rhcs_cdn_install and ceph_rhcs_iso_install" 28 | when: 29 | - ceph_rhcs 30 | - not ceph_rhcs_cdn_install 31 | - not ceph_rhcs_iso_install 32 | - ceph_origin == "upstream" 33 | tags: 34 | - package-install 35 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/misc/system_tuning.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: disable osd directory parsing by updatedb 3 | command: updatedb -e /var/lib/ceph 4 | changed_when: false 5 | failed_when: false 6 | 7 | - name: disable transparent hugepage 8 | shell: | 9 | echo never > /sys/kernel/mm/transparent_hugepage/enabled 10 | changed_when: false 11 | failed_when: false 12 | when: disable_transparent_hugepage 13 | 14 | - name: get default vm.min_free_kbytes 15 | command: sysctl -b vm.min_free_kbytes 16 | changed_when: false 17 | failed_when: false 18 | always_run: yes 19 | register: default_vm_min_free_kbytes 20 | 21 | - name: define vm.min_free_kbytes 22 | set_fact: 23 | vm_min_free_kbytes: "{{ 4194303 if ansible_memtotal_mb >= 49152 else default_vm_min_free_kbytes.stdout }}" 24 | 25 | - name: apply operating system tuning 26 | sysctl: 27 | name: "{{ item.name }}" 28 | value: "{{ item.value }}" 29 | state: present 30 | sysctl_file: /etc/sysctl.conf 31 | ignoreerrors: yes 32 | with_items: "{{ os_tuning_params }}" 33 | -------------------------------------------------------------------------------- /roles/ceph-mds/tasks/docker/fetch_configs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # NOTE (leseb): the mds container needs the admin key 3 | # so it can create the mds pools for cephfs 4 | - name: set config and keys paths 5 | set_fact: 6 | ceph_config_keys: 7 | - /etc/ceph/{{ cluster }}.conf 8 | - /etc/ceph/{{ cluster }}.client.admin.keyring 9 | - /var/lib/ceph/bootstrap-mds/{{ cluster }}.keyring 10 | 11 | - name: stat for ceph config and keys 12 | local_action: stat path={{ fetch_directory }}/docker_mon_files/{{ item }} 13 | with_items: "{{ ceph_config_keys }}" 14 | changed_when: false 15 | become: false 16 | failed_when: false 17 | always_run: true 18 | register: statconfig 19 | 20 | - name: try to fetch ceph config and keys 21 | copy: 22 | src: "{{ fetch_directory }}/docker_mon_files/{{ item.0 }}" 23 | dest: "{{ item.0 }}" 24 | owner: root 25 | group: root 26 | mode: 0644 27 | changed_when: false 28 | with_together: 29 | - "{{ ceph_config_keys }}" 30 | - "{{ statconfig.results }}" 31 | when: item.1.stat.exists == true 32 | -------------------------------------------------------------------------------- /roles/ceph-mon/README.md: -------------------------------------------------------------------------------- 1 | # Ansible role: Ceph Monitor 2 | 3 | This role mainly bootstraps Ceph monitor(s) but also has several capabilities: 4 | 5 | * Deploys Ceph monitor(s) 6 | * Manages Ceph keys 7 | * Can create OpenStack pools, users and keys 8 | * Secures a cluster (protect pools) 9 | * Bootstraps dockerized Ceph monitors 10 | 11 | # Requirements 12 | 13 | Nothing, it runs out of the box. 14 | 15 | # Role variables 16 | 17 | Have a look at: `defaults/main.yml`. 18 | 19 | ## Mandatory variables 20 | 21 | None. 22 | 23 | # Dependencies 24 | 25 | The role `leseb.ceph-common` must be installed. 26 | 27 | # Example Playbook 28 | 29 | ``` 30 | - hosts: servers 31 | remote_user: ubuntu 32 | roles: 33 | - { role: leseb.ceph-mon } 34 | ``` 35 | 36 | # Contribution 37 | 38 | **THIS REPOSITORY DOES NOT ACCEPT PULL REQUESTS** 39 | **PULL REQUESTS MUST GO THROUGH [CEPH-ANSIBLE](https://github.com/ceph/ceph-ansible)** 40 | 41 | # License 42 | 43 | Apache 44 | 45 | # Author Information 46 | 47 | This role was created by [Sébastien Han](http://sebastien-han.fr/). 48 | -------------------------------------------------------------------------------- /roles/ceph-osd/tasks/scenarios/dmcrypt-dedicated-journal.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ## SCENARIO 6: DMCRYPT N JOURNAL DEVICES FOR N OSDS 3 | 4 | - include: ../check_devices.yml 5 | 6 | # NOTE (leseb): the prepare process must be parallelized somehow... 7 | # if you have 64 disks with 4TB each, this will take a while 8 | # since Ansible will sequential process the loop 9 | 10 | # NOTE (alahouze): if the device is a partition, the parted command below has 11 | # failed, this is why we check if the device is a partition too. 12 | - name: prepare dmcrypt osd disk(s) with a dedicated journal device 13 | command: "ceph-disk prepare --dmcrypt --cluster {{ cluster }} {{ item.2 }} {{ item.3 }}" 14 | with_together: 15 | - "{{ parted_results.results }}" 16 | - "{{ ispartition_results.results }}" 17 | - "{{ devices }}" 18 | - "{{ raw_journal_devices }}" 19 | changed_when: false 20 | when: 21 | - not item.0.get("skipped") 22 | - not item.1.get("skipped") 23 | - item.0.get("rc", 0) != 0 24 | - item.1.get("rc", 0) != 0 25 | - not osd_auto_discovery 26 | - dmcrypt_dedicated_journal 27 | 28 | - include: ../activate_osds.yml 29 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/docker/fetch_configs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: set config and keys paths 3 | set_fact: 4 | ceph_config_keys: 5 | - /etc/ceph/{{ cluster }}.conf 6 | - /etc/ceph/{{ cluster }}.client.admin.keyring 7 | - /etc/ceph/monmap-{{ cluster }} 8 | - /etc/ceph/{{ cluster }}.mon.keyring 9 | - /var/lib/ceph/bootstrap-osd/{{ cluster }}.keyring 10 | - /var/lib/ceph/bootstrap-rgw/{{ cluster }}.keyring 11 | - /var/lib/ceph/bootstrap-mds/{{ cluster }}.keyring 12 | 13 | - name: stat for ceph config and keys 14 | local_action: stat path={{ fetch_directory }}/docker_mon_files/{{ item }} 15 | with_items: "{{ ceph_config_keys }}" 16 | changed_when: false 17 | become: false 18 | failed_when: false 19 | register: statconfig 20 | always_run: true 21 | 22 | - name: try to fetch ceph config and keys 23 | copy: 24 | src: "{{ fetch_directory }}/docker_mon_files/{{ item.0 }}" 25 | dest: "{{ item.0 }}" 26 | owner: root 27 | group: root 28 | mode: 0644 29 | changed_when: false 30 | with_together: 31 | - "{{ ceph_config_keys }}" 32 | - "{{ statconfig.results }}" 33 | when: item.1.stat.exists == true 34 | -------------------------------------------------------------------------------- /roles/ceph-osd/README.md: -------------------------------------------------------------------------------- 1 | # Ansible role: Ceph OSD 2 | 3 | This role bootstraps Ceph OSD(s). 4 | It can bootstrap dockerized Ceph OSD(s). 5 | 6 | # Requirements 7 | 8 | Nothing, it runs out of the box. 9 | 10 | # Role variables 11 | 12 | Have a look at: `defaults/main.yml`. 13 | 14 | ## Mandatory variables 15 | 16 | Choose between the following scenario to configure your OSDs, **choose only one**: 17 | 18 | * `journal_collocation` 19 | * `raw_multi_journal` 20 | * `osd_directory` 21 | 22 | Then: 23 | 24 | * `devices` 25 | * `raw_journal_devices` (**only if** you activated `raw_multi_journal`) 26 | * `osd_directories` (**only if** you activated `osd_directory`) 27 | 28 | # Dependencies 29 | 30 | The role `leseb.ceph-common` must be installed. 31 | 32 | # Example Playbook 33 | 34 | ``` 35 | - hosts: servers 36 | remote_user: ubuntu 37 | roles: 38 | - { role: leseb.ceph-osd } 39 | ``` 40 | 41 | # Contribution 42 | 43 | **THIS REPOSITORY DOES NOT ACCEPT PULL REQUESTS** 44 | **PULL REQUESTS MUST GO THROUGH [CEPH-ANSIBLE](https://github.com/ceph/ceph-ansible)** 45 | 46 | # License 47 | 48 | Apache 49 | 50 | # Author Information 51 | 52 | This role was created by [Sébastien Han](http://sebastien-han.fr/). 53 | -------------------------------------------------------------------------------- /roles/ceph-osd/tasks/scenarios/osd_directory.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ## SCENARIO 4: USE A DIRECTORY INSTEAD OF A DISK FOR OSD 3 | 4 | # NOTE (leseb): we do not check the filesystem underneath the directory 5 | # so it is really up to you to configure this properly. 6 | # Declaring more than one directory on the same filesystem will confuse Ceph. 7 | - name: create osd directories 8 | file: 9 | path: "{{ item }}" 10 | state: directory 11 | owner: "ceph" 12 | group: "ceph" 13 | with_items: "{{ osd_directories }}" 14 | 15 | # NOTE (leseb): the prepare process must be parallelized somehow... 16 | # if you have 64 disks with 4TB each, this will take a while 17 | # since Ansible will sequential process the loop 18 | - name: prepare osd directory disk(s) 19 | command: "ceph-disk prepare --cluster {{ cluster }} {{ item }}" 20 | with_items: "{{ osd_directories }}" 21 | changed_when: false 22 | when: osd_directory 23 | 24 | - name: activate osd(s) 25 | command: "ceph-disk activate {{ item }}" 26 | with_items: "{{ osd_directories }}" 27 | changed_when: false 28 | 29 | - name: start and add osd target(s) to the systemd sequence 30 | service: 31 | name: ceph.target 32 | state: started 33 | enabled: yes 34 | -------------------------------------------------------------------------------- /roles/ceph-common/plugins/actions/config_template.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015, Rackspace US, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import sys 17 | 18 | from distutils.version import LooseVersion 19 | from ansible import __version__ as __ansible_version__ 20 | 21 | # This appends the sys path with the file path which is used for the 22 | # import of the specific verion of the config_template action plugin 23 | # needed based on the ansible version calling the plugin. 24 | sys.path.append(os.path.dirname(__file__)) 25 | 26 | if LooseVersion(__ansible_version__) < LooseVersion("2.0"): 27 | from _v1_config_template import * 28 | else: 29 | from _v2_config_template import * 30 | -------------------------------------------------------------------------------- /roles/ceph-mds/tasks/docker/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check if a cluster is already running 3 | command: "docker ps -q -a --filter='ancestor={{ ceph_docker_image }}:{{ ceph_docker_image_tag }}'" 4 | register: ceph_health 5 | changed_when: false 6 | failed_when: false 7 | always_run: true 8 | 9 | - include: checks.yml 10 | when: 11 | - ceph_health.rc != 0 12 | - not "{{ rolling_update | default(false) }}" 13 | 14 | - include: "{{ playbook_dir }}/roles/ceph-common/tasks/misc/ntp_atomic.yml" 15 | when: 16 | - is_atomic 17 | - ansible_os_family == 'RedHat' 18 | - ntp_service_enabled 19 | 20 | - include: "{{ playbook_dir }}/roles/ceph-common/tasks/misc/ntp_redhat.yml" 21 | when: 22 | - not is_atomic 23 | - ansible_os_family == 'RedHat' 24 | - ntp_service_enabled 25 | 26 | - include: "{{ playbook_dir }}/roles/ceph-common/tasks/misc/ntp_debian.yml" 27 | when: 28 | - ansible_os_family == 'Debian' 29 | - ntp_service_enabled 30 | 31 | - include: "{{ playbook_dir }}/roles/ceph-common/tasks/docker/fetch_image.yml" 32 | - include: dirs_permissions.yml 33 | - include: fetch_configs.yml 34 | 35 | - include: selinux.yml 36 | when: ansible_os_family == 'RedHat' 37 | 38 | - include: start_docker_mds.yml 39 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/docker/create_configs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: create a local fetch directory if it does not exist 3 | local_action: file path={{ fetch_directory }} state=directory 4 | changed_when: false 5 | become: false 6 | run_once: true 7 | when: cephx or generate_fsid 8 | 9 | - name: generate cluster uuid 10 | local_action: shell python -c 'import uuid; print(str(uuid.uuid4()))' | tee {{ fetch_directory }}/ceph_cluster_uuid.conf 11 | creates="{{ fetch_directory }}/ceph_cluster_uuid.conf" 12 | register: cluster_uuid 13 | become: false 14 | when: generate_fsid 15 | 16 | - name: read cluster uuid if it already exists 17 | local_action: command cat {{ fetch_directory }}/ceph_cluster_uuid.conf 18 | removes="{{ fetch_directory }}/ceph_cluster_uuid.conf" 19 | changed_when: false 20 | register: cluster_uuid 21 | always_run: true 22 | become: false 23 | when: generate_fsid 24 | 25 | - name: "generate {{ cluster }}.conf configuration file" 26 | action: config_template 27 | args: 28 | src: "{{ playbook_dir }}/roles/ceph-common/templates/ceph.conf.j2" 29 | dest: "/etc/ceph/{{ cluster }}.conf" 30 | owner: "root" 31 | group: "root" 32 | mode: "0644" 33 | config_overrides: "{{ ceph_conf_overrides }}" 34 | config_type: ini 35 | -------------------------------------------------------------------------------- /roles/ceph-mon/templates/ceph-mon.service.j2: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Ceph Monitor 3 | After=docker.service 4 | 5 | [Service] 6 | EnvironmentFile=-/etc/environment 7 | ExecStartPre=-/usr/bin/docker rm %i 8 | ExecStartPre=$(command -v mkdir) -p /etc/ceph /var/lib/ceph/mon 9 | ExecStart=/usr/bin/docker run --rm --name %i --net=host \ 10 | {% if not mon_containerized_deployment_with_kv -%} 11 | -v /var/lib/ceph:/var/lib/ceph \ 12 | -v /etc/ceph:/etc/ceph \ 13 | {% else -%} 14 | -e KV_TYPE={{kv_type}} \ 15 | -e KV_IP={{kv_endpoint}}\ 16 | -e KV_PORT={{kv_port}} \ 17 | {% endif -%} 18 | -v /etc/localtime:/etc/localtime:ro \ 19 | {% if mon_docker_privileged -%} 20 | --privileged \ 21 | {% endif -%} 22 | {% if mon_docker_net_host -%} 23 | --net=host \ 24 | {% endif -%} 25 | -e CEPH_DAEMON=MON \ 26 | -e MON_IP={{ hostvars[inventory_hostname]['ansible_' + ceph_mon_docker_interface]['ipv4']['address'] }} \ 27 | -e CEPH_PUBLIC_NETWORK={{ ceph_mon_docker_subnet }} \ 28 | {{ ceph_mon_docker_extra_env }} \ 29 | {{ceph_docker_registry }}/{{ ceph_docker_image }}:{{ ceph_docker_image_tag }} 30 | ExecStopPost=-/usr/bin/docker stop %i 31 | Restart=always 32 | RestartSec=10s 33 | TimeoutStartSec=120 34 | TimeoutStopSec=15 35 | 36 | [Install] 37 | WantedBy=multi-user.target 38 | -------------------------------------------------------------------------------- /roles/ceph-common/templates/ganesha.conf.j2: -------------------------------------------------------------------------------- 1 | #jinja2: trim_blocks: "true", lstrip_blocks: "true" 2 | # {{ ansible_managed }} 3 | 4 | {% if nfs_file_gw %} 5 | EXPORT 6 | { 7 | Export_ID={{ ceph_nfs_ceph_export_id }}; 8 | 9 | Path = "/"; 10 | 11 | Pseudo = {{ ceph_nfs_ceph_pseudo_path }}; 12 | 13 | Access_Type = {{ ceph_nfs_ceph_access_type }}; 14 | 15 | NFS_Protocols = {{ ceph_nfs_ceph_protocols }}; 16 | 17 | Transport_Protocols = TCP; 18 | 19 | Sectype = sys,krb5,krb5i,krb5p; 20 | 21 | FSAL { 22 | Name = CEPH; 23 | } 24 | } 25 | {% endif %} 26 | {% if nfs_obj_gw %} 27 | EXPORT 28 | { 29 | Export_ID={{ ceph_nfs_rgw_export_id }}; 30 | 31 | Path = "/"; 32 | 33 | Pseudo = {{ ceph_nfs_rgw_pseudo_path }}; 34 | 35 | Access_Type = {{ ceph_nfs_rgw_access_type }}; 36 | 37 | NFS_Protocols = {{ ceph_nfs_rgw_protocols }}; 38 | 39 | Transport_Protocols = TCP; 40 | 41 | Sectype = sys,krb5,krb5i,krb5p; 42 | 43 | FSAL { 44 | Name = RGW; 45 | User_Id = "{{ ceph_nfs_rgw_user }}"; 46 | Access_Key_Id ="{{ ceph_nfs_rgw_access_key }}"; 47 | Secret_Access_Key = "{{ ceph_nfs_rgw_secret_key }}"; 48 | } 49 | } 50 | {% endif %} 51 | 52 | LOG { 53 | Facility { 54 | name = FILE; 55 | destination = "{{ ceph_nfs_log_file }}"; 56 | enable = active; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /roles/ceph-osd/tasks/pre_requisite.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: enable extras repo for centos 3 | ini_file: 4 | dest: /etc/yum.repos.d/CentOS-Base.repo 5 | section: extras 6 | option: enabled 7 | value: 1 8 | when: ansible_distribution == 'CentOS' 9 | 10 | - name: install rependencies 11 | package: 12 | name: parted 13 | state: present 14 | when: ansible_os_family != 'ClearLinux' 15 | 16 | - name: create bootstrap-osd and osd directories 17 | file: 18 | path: "{{ item }}" 19 | state: directory 20 | owner: "ceph" 21 | group: "ceph" 22 | mode: "0755" 23 | when: 24 | cephx 25 | with_items: 26 | - /var/lib/ceph/bootstrap-osd/ 27 | - /var/lib/ceph/osd/ 28 | 29 | - name: copy ceph admin key when using dmcrypt 30 | set_fact: 31 | copy_admin_key: true 32 | when: 33 | - dmcrypt_journal_collocation or dmcrypt_dedicated_journal 34 | 35 | - name: copy osd bootstrap key 36 | copy: 37 | src: "{{ fetch_directory }}/{{ fsid }}{{ item.name }}" 38 | dest: "{{ item.name }}" 39 | owner: "ceph" 40 | group: "ceph" 41 | mode: "0600" 42 | with_items: 43 | - { name: "/var/lib/ceph/bootstrap-osd/{{ cluster }}.keyring", copy_key: true } 44 | - { name: "/etc/ceph/{{ cluster }}.client.admin.keyring", copy_key: "{{ copy_admin_key }}" } 45 | when: 46 | - cephx 47 | - item.copy_key|bool 48 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/pre_requisites/prerequisite_rhcs_iso_install.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: create red hat storage package directories 3 | file: 4 | path: "{{ item }}" 5 | state: directory 6 | with_items: 7 | - "{{ ceph_rhcs_mount_path }}" 8 | - "{{ ceph_rhcs_repository_path }}" 9 | 10 | - name: ensure destination iso directory exists 11 | file: 12 | path: "{{ ceph_rhcs_iso_path | dirname }}" 13 | state: directory 14 | recurse: yes 15 | when: "'{{ ceph_rhcs_iso_path | dirname }}' != '/'" 16 | 17 | - name: fetch the red hat storage iso from the ansible server 18 | copy: 19 | src: "{{ ceph_rhcs_iso_path }}" 20 | dest: "{{ ceph_rhcs_iso_path }}" 21 | 22 | # assumption: ceph_rhcs_mount_path does not specify directory 23 | 24 | - name: mount red hat storage iso file 25 | mount: 26 | name: "{{ ceph_rhcs_mount_path }}" 27 | src: "{{ ceph_rhcs_iso_path }}" 28 | fstype: iso9660 29 | opts: ro,loop,noauto 30 | passno: 2 31 | state: mounted 32 | 33 | - name: copy red hat storage iso content 34 | shell: cp -r {{ ceph_rhcs_mount_path }}/* {{ ceph_rhcs_repository_path }} 35 | args: 36 | creates: "{{ ceph_rhcs_repository_path }}/README" 37 | 38 | - name: unmount red hat storage iso file 39 | mount: 40 | name: "{{ ceph_rhcs_mount_path }}" 41 | src: "{{ ceph_rhcs_iso_path }}" 42 | fstype: iso9660 43 | state: unmounted 44 | -------------------------------------------------------------------------------- /roles/ceph-osd/tasks/scenarios/bluestore.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ## SCENARIO 4: BLUESTORE 3 | 4 | - include: ../check_devices.yml 5 | 6 | # NOTE (leseb): the prepare process must be parallelized somehow... 7 | # if you have 64 disks with 4TB each, this will take a while 8 | # since Ansible will sequential process the loop 9 | 10 | # NOTE (alahouze): if the device is a partition, the parted command below has 11 | # failed, this is why we check if the device is a partition too. 12 | - name: automatic prepare bluestore osd disk(s) without partitions 13 | command: ceph-disk prepare --bluestore --cluster "{{ cluster }}" "/dev/{{ item.key }}" 14 | register: prepared_osds 15 | with_dict: "{{ ansible_devices }}" 16 | when: 17 | - ansible_devices is defined 18 | - item.value.removable == "0" 19 | - item.value.partitions|count == 0 20 | - bluestore 21 | - osd_auto_discovery 22 | 23 | - name: manually prepare bluestore osd disk(s) 24 | command: ceph-disk prepare --bluestore --cluster "{{ cluster }}" "{{ item.2 }}" 25 | with_together: 26 | - "{{ parted_results.results }}" 27 | - "{{ ispartition_results.results }}" 28 | - "{{ devices }}" 29 | when: 30 | - not item.0.get("skipped") 31 | - not item.1.get("skipped") 32 | - item.0.get("rc", 0) != 0 33 | - item.1.get("rc", 0) != 0 34 | - bluestore 35 | - not osd_auto_discovery 36 | 37 | - include: ../activate_osds.yml 38 | -------------------------------------------------------------------------------- /roles/ceph-osd/tasks/scenarios/dmcrypt-journal-collocation.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ## SCENARIO 5: DMCRYPT 3 | 4 | - include: ../check_devices.yml 5 | 6 | # NOTE (leseb): the prepare process must be parallelized somehow... 7 | # if you have 64 disks with 4TB each, this will take a while 8 | # since Ansible will sequential process the loop 9 | 10 | # NOTE (alahouze): if the device is a partition, the parted command below has 11 | # failed, this is why we check if the device is a partition too. 12 | - name: automatic prepare dmcrypt osd disk(s) without partitions with collocated osd data and journal 13 | command: ceph-disk prepare --dmcrypt --cluster "{{ cluster }}" "/dev/{{ item.key }}" 14 | with_dict: "{{ ansible_devices }}" 15 | when: 16 | - ansible_devices is defined 17 | - item.value.removable == "0" 18 | - item.value.partitions|count == 0 19 | - dmcrypt_journal_collocation 20 | - osd_auto_discovery 21 | 22 | - name: manually prepare dmcrypt osd disk(s) with collocated osd data and journal 23 | command: ceph-disk prepare --dmcrypt --cluster "{{ cluster }}" "{{ item.2 }}" 24 | with_together: 25 | - "{{ parted_results.results }}" 26 | - "{{ ispartition_results.results }}" 27 | - "{{ devices }}" 28 | when: 29 | - not item.0.get("skipped") 30 | - not item.1.get("skipped") 31 | - item.0.get("rc", 0) != 0 32 | - item.1.get("rc", 0) != 0 33 | - dmcrypt_journal_collocation 34 | - not osd_auto_discovery 35 | 36 | - include: ../activate_osds.yml 37 | -------------------------------------------------------------------------------- /roles/ceph-osd/tasks/docker/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check if a cluster is already running 3 | command: "docker ps -q -a --filter='ancestor={{ ceph_docker_image }}:{{ ceph_docker_image_tag }}'" 4 | register: ceph_health 5 | changed_when: false 6 | failed_when: false 7 | always_run: true 8 | 9 | - include: checks.yml 10 | when: 11 | - ceph_health.rc != 0 12 | - not osd_containerized_deployment_with_kv 13 | - not "{{ rolling_update | default(false) }}" 14 | 15 | - include: "{{ playbook_dir }}/roles/ceph-common/tasks/misc/ntp_atomic.yml" 16 | when: 17 | - is_atomic 18 | - ansible_os_family == 'RedHat' 19 | - ntp_service_enabled 20 | 21 | - include: "{{ playbook_dir }}/roles/ceph-common/tasks/misc/ntp_redhat.yml" 22 | when: 23 | - not is_atomic 24 | - ansible_os_family == 'RedHat' 25 | - ntp_service_enabled 26 | 27 | - include: "{{ playbook_dir }}/roles/ceph-common/tasks/misc/ntp_debian.yml" 28 | when: 29 | - ansible_os_family == 'Debian' 30 | - ntp_service_enabled 31 | 32 | - include: "{{ playbook_dir }}/roles/ceph-common/tasks/docker/fetch_image.yml" 33 | 34 | # NOTE (jimcurtis): dirs_permissions.yml must precede fetch_configs.yml 35 | # because it creates the directories needed by the latter. 36 | - include: dirs_permissions.yml 37 | 38 | - include: fetch_configs.yml 39 | when: not osd_containerized_deployment_with_kv 40 | 41 | - include: selinux.yml 42 | when: ansible_os_family == 'RedHat' 43 | 44 | - include: start_docker_osd.yml 45 | -------------------------------------------------------------------------------- /roles/ceph-osd/tasks/scenarios/journal_collocation.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ## SCENARIO 1: JOURNAL AND OSD_DATA ON THE SAME DEVICE 3 | 4 | - include: ../check_devices.yml 5 | 6 | # NOTE (leseb): the prepare process must be parallelized somehow... 7 | # if you have 64 disks with 4TB each, this will take a while 8 | # since Ansible will sequential process the loop 9 | 10 | # NOTE (alahouze): if the device is a partition, the parted command below has 11 | # failed, this is why we check if the device is a partition too. 12 | - name: automatic prepare filestore osd disk(s) without partitions with collocated osd data and journal 13 | command: ceph-disk prepare --cluster "{{ cluster }}" "/dev/{{ item.key }}" 14 | register: prepared_osds 15 | with_dict: "{{ ansible_devices }}" 16 | when: 17 | - ansible_devices is defined 18 | - item.value.removable == "0" 19 | - item.value.partitions|count == 0 20 | - journal_collocation 21 | - osd_auto_discovery 22 | 23 | - name: manually prepare filestore osd disk(s) with collocated osd data and journal 24 | command: "ceph-disk prepare --cluster {{ cluster }} {{ item.2 }}" 25 | with_together: 26 | - "{{ parted_results.results }}" 27 | - "{{ ispartition_results.results }}" 28 | - "{{ devices }}" 29 | when: 30 | - not item.0.get("skipped") 31 | - not item.1.get("skipped") 32 | - item.0.get("rc", 0) != 0 33 | - item.1.get("rc", 0) != 0 34 | - journal_collocation 35 | - not osd_auto_discovery 36 | 37 | - include: ../activate_osds.yml 38 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/docker/fetch_image.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Normal case - pull image from registry 3 | - name: "pull {{ ceph_docker_image }} image" 4 | command: "docker pull {{ ceph_docker_registry}}/{{ ceph_docker_image }}:{{ ceph_docker_image_tag }}" 5 | changed_when: false 6 | when: ceph_docker_dev_image is undefined or not ceph_docker_dev_image 7 | 8 | # Dev case - export local dev image and send it across 9 | - name: export local ceph dev image 10 | local_action: command docker save -o "/tmp/{{ ceph_docker_username }}-{{ ceph_docker_imagename }}-{{ ceph_docker_image_tag }}.tar" "{{ ceph_docker_username }}/{{ ceph_docker_imagename }}:{{ ceph_docker_image_tag }}" 11 | when: ceph_docker_dev_image is defined and ceph_docker_dev_image 12 | run_once: true 13 | 14 | - name: copy ceph dev image file 15 | copy: 16 | src: "/tmp/{{ ceph_docker_username }}-{{ ceph_docker_imagename }}-{{ ceph_docker_image_tag }}.tar" 17 | dest: "/tmp/{{ ceph_docker_username }}-{{ ceph_docker_imagename }}-{{ ceph_docker_image_tag }}.tar" 18 | when: ceph_docker_dev_image is defined and ceph_docker_dev_image 19 | 20 | - name: load ceph dev image 21 | command: "docker load -i /tmp/{{ ceph_docker_username }}-{{ ceph_docker_imagename }}-{{ ceph_docker_image_tag }}.tar" 22 | when: ceph_docker_dev_image is defined and ceph_docker_dev_image 23 | 24 | - name: remove tmp ceph dev image file 25 | command: "rm /tmp/{{ ceph_docker_username }}-{{ ceph_docker_imagename }}-{{ ceph_docker_image_tag }}.tar" 26 | when: ceph_docker_dev_image is defined and ceph_docker_dev_image 27 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/create_mds_filesystems.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # NOTE (leseb): in the present playbook the conditional is done on the task 3 | # We don't do this in main.yml because of the 'docker' variable, when set to true 4 | # the role 'ceph-common' doesn't get inherited so the condition can not be evaluate 5 | # since those check are performed by the ceph-common role 6 | - name: create filesystem pools 7 | command: ceph --cluster {{ cluster }} osd pool create {{ item }} {{ osd_pool_default_pg_num }} 8 | with_items: 9 | - cephfs_data 10 | - cephfs_metadata 11 | changed_when: false 12 | 13 | - name: check if ceph filesystem already exists 14 | command: ceph --cluster {{ cluster }} fs get {{ cephfs }} 15 | register: check_existing_cephfs 16 | changed_when: false 17 | failed_when: false 18 | 19 | - name: create ceph filesystem 20 | command: ceph --cluster {{ cluster }} fs new {{ cephfs }} {{ cephfs_metadata }} {{ cephfs_data }} 21 | changed_when: false 22 | when: check_existing_cephfs.rc != 0 23 | 24 | - name: allow multimds 25 | command: ceph --cluster {{ cluster }} fs set {{ cephfs }} allow_multimds true --yes-i-really-mean-it 26 | changed_when: false 27 | when: 28 | - ceph_release_num.{{ ceph_release }} >= ceph_release_num.jewel 29 | - mds_allow_multimds 30 | 31 | - name: set max_mds 32 | command: ceph --cluster {{ cluster }} fs set {{ cephfs }} max_mds {{ mds_max_mds }} 33 | changed_when: false 34 | when: 35 | - ceph_release_num.{{ ceph_release }} >= ceph_release_num.jewel 36 | - mds_allow_multimds 37 | - mds_max_mds > 1 38 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/checks/check_system.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: fail on unsupported system 3 | fail: 4 | msg: "System not supported {{ ansible_system }}" 5 | when: "'{{ ansible_system }}' not in ['Linux']" 6 | 7 | - name: fail on unsupported architecture 8 | fail: 9 | msg: "Architecture not supported {{ ansible_architecture }}" 10 | when: "'{{ ansible_architecture }}' not in ['x86_64', 'ppc64le', 'armv7l']" 11 | 12 | - name: fail on unsupported distribution 13 | fail: 14 | msg: "Distribution not supported {{ ansible_os_family }}" 15 | when: "'{{ ansible_os_family }}' not in ['Debian', 'RedHat', 'ClearLinux']" 16 | 17 | - name: fail on unsupported distribution for red hat ceph storage 18 | fail: 19 | msg: "Distribution not supported {{ ansible_distribution_version }} by Red Hat Ceph Storage, only RHEL 7" 20 | when: 21 | - ceph_rhcs 22 | - ansible_distribution_version | version_compare('7.3', '<') 23 | 24 | - name: fail on unsupported distribution for ubuntu cloud archive 25 | fail: 26 | msg: "Distribution not supported by Ubuntu Cloud Archive: {{ ansible_distribution }}" 27 | when: 28 | ceph_stable_uca and 29 | '{{ ansible_distribution }}' not in ['Ubuntu'] 30 | 31 | - name: fail on unsupported ansible version 32 | fail: 33 | msg: "Ansible version must be >= 1.9, please update!" 34 | when: 35 | - ansible_version.major|int == 1 36 | - ansible_version.minor|int < 9 37 | 38 | - name: fail if systemd is not present 39 | fail: 40 | msg: "Systemd must be present" 41 | when: ansible_service_mgr != 'systemd' 42 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/configure_cluster_name.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: configure cluster name 3 | lineinfile: 4 | dest: /etc/sysconfig/ceph 5 | insertafter: EOF 6 | create: yes 7 | line: "CLUSTER={{ cluster }}" 8 | when: ansible_os_family == "RedHat" 9 | 10 | # NOTE(leseb): we are performing the following check 11 | # to ensure any Jewel installation will not fail. 12 | # The following commit https://github.com/ceph/ceph/commit/791eba81a5467dd5de4f1680ed0deb647eb3fb8b 13 | # fixed a package issue where the path was the wrong. 14 | # This bug is not yet on all the distros package so we are working around it 15 | # Impacted versions: 16 | # - Jewel from UCA: https://bugs.launchpad.net/ubuntu/+source/ceph/+bug/1582773 17 | # - Jewel from latest Canonical 16.04 distro 18 | # - All previous versions from Canonical 19 | # - Infernalis from ceph.com 20 | - name: check /etc/default/ceph exist 21 | stat: 22 | path: /etc/default/ceph 23 | register: etc_default_ceph 24 | always_run: true 25 | when: ansible_os_family == "Debian" 26 | 27 | - name: configure cluster name 28 | lineinfile: 29 | dest: /etc/default/ceph 30 | insertafter: EOF 31 | create: yes 32 | line: "CLUSTER={{ cluster }}" 33 | when: 34 | - ansible_os_family == "Debian" 35 | - etc_default_ceph.stat.exists 36 | - not etc_default_ceph.stat.isdir 37 | 38 | - name: configure cluster name 39 | lineinfile: 40 | dest: /etc/default/ceph/ceph 41 | insertafter: EOF 42 | create: yes 43 | line: "CLUSTER={{ cluster }}" 44 | when: 45 | - ansible_os_family == "Debian" 46 | - etc_default_ceph.stat.exists 47 | - etc_default_ceph.stat.isdir 48 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/installs/redhat_ceph_repository.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install the ceph stable repository key 3 | rpm_key: 4 | key: "{{ ceph_stable_key }}" 5 | state: present 6 | when: ceph_stable 7 | 8 | - name: add ceph stable repository 9 | yum_repository: 10 | name: ceph_stable 11 | description: Ceph Stable repo 12 | gpgcheck: yes 13 | state: present 14 | gpgkey: "{{ ceph_stable_key }}" 15 | baseurl: "{{ ceph_mirror }}/rpm-{{ ceph_stable_release }}/{{ ceph_stable_redhat_distro }}/$basearch" 16 | when: ceph_stable 17 | 18 | # we must use curl instead of ansible's uri module because SNI support in 19 | # Python is only available in 2.7.9 and later, and most supported distributions 20 | # don't have that version, so a request to https fails. 21 | - name: fetch ceph development repo file 22 | command: 'curl -L https://shaman.ceph.com/api/repos/ceph/{{ ceph_dev_branch }}/{{ ceph_dev_sha1 }}/{{ ansible_distribution | lower }}/{{ ansible_distribution_major_version }}/repo' 23 | register: ceph_dev_yum_repo 24 | when: ceph_dev 25 | 26 | - name: add ceph development repository 27 | copy: 28 | content: "{{ ceph_dev_yum_repo.stdout }}" 29 | dest: /etc/yum.repos.d/ceph-dev.repo 30 | owner: root 31 | group: root 32 | backup: yes 33 | when: ceph_dev 34 | 35 | - name: add custom repo 36 | get_url: 37 | url: "{{ ceph_custom_repo }}" 38 | dest: /etc/yum.repos.d 39 | owner: root 40 | group: root 41 | when: ceph_custom 42 | 43 | # Remove yum caches so yum doesn't get confused if we are reinstalling a different ceph version 44 | - name: purge yum cache 45 | command: yum clean all 46 | when: 47 | ansible_pkg_mgr == 'yum' 48 | -------------------------------------------------------------------------------- /roles/ceph-mds/tasks/pre_requisite.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: create bootstrap-mds directory 3 | file: 4 | path: /var/lib/ceph/bootstrap-mds/ 5 | state: directory 6 | owner: "ceph" 7 | group: "ceph" 8 | mode: "0755" 9 | 10 | - name: copy mds bootstrap key 11 | copy: 12 | src: "{{ fetch_directory }}/{{ fsid }}{{ item.name }}" 13 | dest: "{{ item.name }}" 14 | owner: "ceph" 15 | group: "ceph" 16 | mode: "0600" 17 | with_items: 18 | - { name: "/var/lib/ceph/bootstrap-mds/{{ cluster }}.keyring", copy_key: true } 19 | - { name: "/etc/ceph/{{ cluster }}.client.admin.keyring", copy_key: "{{ copy_admin_key }}" } 20 | when: 21 | - cephx 22 | - item.copy_key|bool 23 | 24 | - name: create mds directory 25 | file: 26 | path: /var/lib/ceph/mds/{{ cluster }}-{{ mds_name }} 27 | state: directory 28 | owner: "ceph" 29 | group: "ceph" 30 | mode: "0755" 31 | 32 | - name: create mds keyring 33 | command: ceph --cluster {{ cluster }} --name client.bootstrap-mds --keyring /var/lib/ceph/bootstrap-mds/{{ cluster }}.keyring auth get-or-create mds.{{ mds_name }} osd 'allow rwx' mds 'allow' mon 'allow profile mds' -o /var/lib/ceph/mds/{{ cluster }}-{{ mds_name }}/keyring 34 | args: 35 | creates: /var/lib/ceph/mds/{{ cluster }}-{{ mds_name }}/keyring 36 | changed_when: false 37 | when: cephx 38 | 39 | - name: set mds key permissions 40 | file: 41 | path: /var/lib/ceph/mds/{{ cluster }}-{{ mds_name }}/keyring 42 | owner: "ceph" 43 | group: "ceph" 44 | mode: "0600" 45 | when: cephx 46 | 47 | - name: start and add that the metadata service to the init sequence 48 | service: 49 | name: ceph-mds@{{ mds_name }} 50 | state: started 51 | enabled: yes 52 | changed_when: false 53 | -------------------------------------------------------------------------------- /roles/ceph-common/files/cephstable.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | Version: GnuPG v1 3 | 4 | mQINBFX4hgkBEADLqn6O+UFp+ZuwccNldwvh5PzEwKUPlXKPLjQfXlQRig1flpCH 5 | E0HJ5wgGlCtYd3Ol9f9+qU24kDNzfbs5bud58BeE7zFaZ4s0JMOMuVm7p8JhsvkU 6 | C/Lo/7NFh25e4kgJpjvnwua7c2YrA44ggRb1QT19ueOZLK5wCQ1mR+0GdrcHRCLr 7 | 7Sdw1d7aLxMT+5nvqfzsmbDullsWOD6RnMdcqhOxZZvpay8OeuK+yb8FVQ4sOIzB 8 | FiNi5cNOFFHg+8dZQoDrK3BpwNxYdGHsYIwU9u6DWWqXybBnB9jd2pve9PlzQUbO 9 | eHEa4Z+jPqxY829f4ldaql7ig8e6BaInTfs2wPnHJ+606g2UH86QUmrVAjVzlLCm 10 | nqoGymoAPGA4ObHu9X3kO8viMBId9FzooVqR8a9En7ZE0Dm9O7puzXR7A1f5sHoz 11 | JdYHnr32I+B8iOixhDUtxIY4GA8biGATNaPd8XR2Ca1hPuZRVuIiGG9HDqUEtXhV 12 | fY5qjTjaThIVKtYgEkWMT+Wet3DPPiWT3ftNOE907e6EWEBCHgsEuuZnAbku1GgD 13 | LBH4/a/yo9bNvGZKRaTUM/1TXhM5XgVKjd07B4cChgKypAVHvef3HKfCG2U/DkyA 14 | LjteHt/V807MtSlQyYaXUTGtDCrQPSlMK5TjmqUnDwy6Qdq8dtWN3DtBWQARAQAB 15 | tCpDZXBoLmNvbSAocmVsZWFzZSBrZXkpIDxzZWN1cml0eUBjZXBoLmNvbT6JAjgE 16 | EwECACIFAlX4hgkCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEOhKwsBG 17 | DzmUXdIQAI8YPcZMBWdv489q8CzxlfRIRZ3Gv/G/8CH+EOExcmkVZ89mVHngCdAP 18 | DOYCl8twWXC1lwJuLDBtkUOHXNuR5+Jcl5zFOUyldq1Hv8u03vjnGT7lLJkJoqpG 19 | l9QD8nBqRvBU7EM+CU7kP8+09b+088pULil+8x46PwgXkvOQwfVKSOr740Q4J4nm 20 | /nUOyTNtToYntmt2fAVWDTIuyPpAqA6jcqSOC7Xoz9cYxkVWnYMLBUySXmSS0uxl 21 | 3p+wK0lMG0my/gb+alke5PAQjcE5dtXYzCn+8Lj0uSfCk8Gy0ZOK2oiUjaCGYN6D 22 | u72qDRFBnR3jaoFqi03bGBIMnglGuAPyBZiI7LJgzuT9xumjKTJW3kN4YJxMNYu1 23 | FzmIyFZpyvZ7930vB2UpCOiIaRdZiX4Z6ZN2frD3a/vBxBNqiNh/BO+Dex+PDfI4 24 | TqwF8zlcjt4XZ2teQ8nNMR/D8oiYTUW8hwR4laEmDy7ASxe0p5aijmUApWq5UTsF 25 | +s/QbwugccU0iR5orksM5u9MZH4J/mFGKzOltfGXNLYI6D5Mtwrnyi0BsF5eY0u6 26 | vkdivtdqrq2DXY+ftuqLOQ7b+t1RctbcMHGPptlxFuN9ufP5TiTWSpfqDwmHCLsT 27 | k2vFiMwcHdLpQ1IH8ORVRgPPsiBnBOJ/kIiXG2SxPUTjjEGOVgeA 28 | =/Tod 29 | -----END PGP PUBLIC KEY BLOCK----- 30 | -------------------------------------------------------------------------------- /roles/ceph-osd/tasks/check_devices_static.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check if the device is a partition 3 | shell: "readlink -f {{ item }} | egrep '/dev/([hsv]d[a-z]{1,2}|cciss/c[0-9]d[0-9]p|nvme[0-9]n[0-9]p)[0-9]{1,2}$'" 4 | with_items: "{{ devices }}" 5 | changed_when: false 6 | failed_when: false 7 | always_run: true 8 | register: ispartition_results 9 | 10 | - name: check the partition status of the osd disks 11 | shell: "parted --script {{ item.1 }} print > /dev/null 2>&1" 12 | with_together: 13 | - "{{ ispartition_results.results }}" 14 | - "{{ devices }}" 15 | changed_when: false 16 | failed_when: false 17 | always_run: true 18 | register: osd_partition_status_results 19 | when: item.0.rc != 0 20 | 21 | # NOTE: The following calls to sgdisk are retried because sgdisk is known to 22 | # fully wipe a device the first time around. There is no need to halt execution 23 | # of zapping the whole device so these try again. It is easier to use `||` to 24 | # keep the current flow of the task. 25 | # See: https://github.com/ceph/ceph-ansible/issues/759 26 | - name: fix partitions gpt header or labels of the osd disks 27 | shell: "sgdisk --zap-all --clear --mbrtogpt -- {{ item.1 }} || sgdisk --zap-all --clear --mbrtogpt -- {{ item.1 }}" 28 | with_together: 29 | - "{{ osd_partition_status_results.results }}" 30 | - "{{ devices }}" 31 | changed_when: false 32 | when: 33 | - not item.0.get("skipped") 34 | - item.0.get("rc", 0) != 0 35 | 36 | - name: check if a partition named 'ceph' exists 37 | shell: "parted --script {{ item.1 }} print | egrep -sq '^ 1.*ceph'" 38 | with_together: 39 | - "{{ ispartition_results.results }}" 40 | - "{{ devices }}" 41 | changed_when: false 42 | failed_when: false 43 | always_run: true 44 | register: parted_results 45 | when: item.0.rc != 0 46 | -------------------------------------------------------------------------------- /roles/ceph-common/README.md: -------------------------------------------------------------------------------- 1 | # Ansible role: Ceph Common 2 | 3 | This role does several things prior to bootstrapping your Ceph cluster: 4 | 5 | * Checks the system and validates that Ceph can be installed 6 | * Tunes the operating system if the node is an OSD server 7 | * Installs Ceph 8 | * Generates `ceph.conf` 9 | 10 | # Requirements 11 | 12 | Move the `plugins/actions/config_template.py` file to your top level playbook directory. 13 | Edit your `ansible.cfg` like so: 14 | 15 | action_plugins = plugins/actions 16 | 17 | Depending on how you are managing your playbook, the path might be different so edit the file accordingly if necessary. 18 | 19 | # Role variables 20 | 21 | Have a look at `defaults/main.yml`. 22 | 23 | ## Mandatory variables 24 | 25 | * Install source, choose one of these: 26 | * `ceph_stable` 27 | * `ceph_dev` 28 | * `ceph_rhcs` 29 | * `ceph_custom` 30 | * `journal_size` 31 | * `monitor_interface` 32 | * `public_network` 33 | * `cluster_network` 34 | 35 | ## Handlers 36 | 37 | * update apt cache 38 | * restart ceph-mon 39 | * restart ceph-osd 40 | * restart ceph-mds 41 | * restart ceph-rgw 42 | * restart ceph-restapi 43 | 44 | # Dependencies 45 | 46 | None 47 | 48 | # Example Playbook 49 | 50 | ``` 51 | - hosts: servers 52 | remote_user: ubuntu 53 | roles: 54 | - { role: leseb.ceph-common } 55 | ``` 56 | 57 | # Misc 58 | 59 | This role is a **mandatory** dependency for the following roles: 60 | 61 | * ceph-mon 62 | * ceph-osd 63 | * ceph-mds 64 | * ceph-rgw 65 | * ceph-restapi 66 | 67 | # Contribution 68 | 69 | **THIS REPOSITORY DOES NOT ACCEPT PULL REQUESTS**. 70 | **PULL REQUESTS MUST GO THROUGH [CEPH-ANSIBLE](https://github.com/ceph/ceph-ansible)**. 71 | 72 | # License 73 | 74 | Apache 75 | 76 | # Author Information 77 | 78 | This role was created by [Sébastien Han](http://sebastien-han.fr/). 79 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/facts_mon_fsid.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check if /var/lib/ceph/mon/{{ cluster }}-{{ monitor_name }}/keyring already exists 3 | stat: 4 | path: /var/lib/ceph/mon/{{ cluster }}-{{ monitor_name }}/keyring 5 | register: initial_mon_keyring 6 | 7 | - name: fail if /var/lib/ceph/mon/{{ cluster }}-{{ monitor_name }}/keyring doesn't exist 8 | fail: 9 | msg: "/var/lib/ceph/mon/{{ cluster }}-{{ monitor_name }}/keyring not found" 10 | when: 11 | - not initial_mon_keyring.stat.exists 12 | - ceph_current_fsid.rc == 0 13 | 14 | - name: get existing initial mon keyring if it already exists but not monitor_keyring.conf in {{ fetch_directory }} 15 | shell: | 16 | grep key /var/lib/ceph/mon/{{ cluster }}-{{ monitor_name }}/keyring | sed 's/^.*= //' 17 | register: monitor_keyring 18 | when: 19 | - not monitor_keyring_conf.stat.exists 20 | - ceph_current_fsid.rc == 0 21 | 22 | - name: test existing initial mon keyring 23 | command: ceph --connect-timeout 3 --cluster {{ cluster }} --keyring /var/lib/ceph/mon/{{ cluster }}-{{ monitor_name }}/keyring -n mon. fsid 24 | register: test_initial_monitor_keyring 25 | ignore_errors: true 26 | 27 | - name: fail if initial mon keyring found doesn't work 28 | fail: 29 | msg: "Initial mon keyring found doesn't work." 30 | when: test_initial_monitor_keyring.rc != 0 31 | 32 | - name: write initial mon keyring in {{ fetch_directory }}/monitor_keyring.conf if it doesn't exist 33 | local_action: shell echo {{ monitor_keyring.stdout }} | tee {{ fetch_directory }}/monitor_keyring.conf 34 | become: false 35 | when: 36 | - test_initial_monitor_keyring.rc == 0 37 | 38 | - name: put initial mon keyring in mon kv store 39 | command: ceph --cluster {{ cluster }} config-key put initial_mon_keyring {{ monitor_keyring.stdout }} 40 | when: test_initial_monitor_keyring.rc == 0 41 | -------------------------------------------------------------------------------- /roles/ceph-osd/tasks/check_devices_auto.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check if the device is a partition (autodiscover disks) 3 | shell: "readlink -f /dev/{{ item.key }} | egrep '/dev/([hsv]d[a-z]{1,2}|cciss/c[0-9]d[0-9]p|nvme[0-9]n[0-9]p)[0-9]{1,2}$'" 4 | with_dict: "{{ ansible_devices }}" 5 | changed_when: false 6 | failed_when: false 7 | always_run: true 8 | register: ispartition_results 9 | when: 10 | - ansible_devices is defined 11 | - item.value.removable == "0" 12 | 13 | - name: check the partition status of the osd disks (autodiscover disks) 14 | shell: "parted --script /dev/{{ item.key }} print > /dev/null 2>&1" 15 | with_dict: "{{ ansible_devices }}" 16 | changed_when: false 17 | failed_when: false 18 | always_run: true 19 | register: osd_partition_status_results 20 | when: 21 | - ansible_devices is defined 22 | - item.value.removable == "0" 23 | - item.value.partitions|count == 0 24 | 25 | - name: fix partitions gpt header or labels of the osd disks (autodiscover disks) 26 | shell: "sgdisk --zap-all --clear --mbrtogpt -- '/dev/{{ item.0.item.key }}' || sgdisk --zap-all --clear --mbrtogpt -- '/dev/{{ item.0.item.key }}'" 27 | with_together: 28 | - "{{ osd_partition_status_results.results }}" 29 | - "{{ ansible_devices }}" 30 | changed_when: false 31 | when: 32 | - ansible_devices is defined 33 | - item.0.item.value.removable == "0" 34 | - item.0.item.value.partitions|count == 0 35 | - item.0.rc != 0 36 | 37 | - name: check if a partition named 'ceph' exists (autodiscover disks) 38 | shell: "parted --script /dev/{{ item.key }} print | egrep -sq '^ 1.*ceph'" 39 | with_dict: "{{ ansible_devices }}" 40 | changed_when: false 41 | failed_when: false 42 | always_run: true 43 | register: parted_results 44 | when: 45 | - ansible_devices is defined 46 | - item.value.removable == "0" 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/python,emacs,vim 3 | 4 | ### Python ### 5 | # Byte-compiled / optimized / DLL files 6 | __pycache__/ 7 | *.py[cod] 8 | *$py.class 9 | 10 | # C extensions 11 | *.so 12 | 13 | # Distribution / packaging 14 | .Python 15 | env/ 16 | build/ 17 | develop-eggs/ 18 | dist/ 19 | downloads/ 20 | eggs/ 21 | .eggs/ 22 | lib/ 23 | lib64/ 24 | parts/ 25 | sdist/ 26 | var/ 27 | *.egg-info/ 28 | .installed.cfg 29 | *.egg 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *,cover 50 | .hypothesis/ 51 | 52 | # Translations 53 | *.mo 54 | *.pot 55 | 56 | # Django stuff: 57 | *.log 58 | 59 | # Sphinx documentation 60 | docs/_build/ 61 | 62 | # PyBuilder 63 | target/ 64 | 65 | #Ipython Notebook 66 | .ipynb_checkpoints 67 | 68 | 69 | ### Emacs ### 70 | # -*- mode: gitignore; -*- 71 | *~ 72 | \#*\# 73 | /.emacs.desktop 74 | /.emacs.desktop.lock 75 | *.elc 76 | auto-save-list 77 | tramp 78 | .\#* 79 | 80 | # Org-mode 81 | .org-id-locations 82 | *_archive 83 | 84 | # flymake-mode 85 | *_flymake.* 86 | 87 | # eshell files 88 | /eshell/history 89 | /eshell/lastdir 90 | 91 | # elpa packages 92 | /elpa/ 93 | 94 | # reftex files 95 | *.rel 96 | 97 | # AUCTeX auto folder 98 | /auto/ 99 | 100 | # cask packages 101 | .cask/ 102 | 103 | # server auth directory 104 | /server/ 105 | 106 | 107 | ### Vim ### 108 | [._]*.s[a-w][a-z] 109 | [._]s[a-w][a-z] 110 | *.un~ 111 | Session.vim 112 | .netrwhist 113 | *~ 114 | -------------------------------------------------------------------------------- /roles/ceph-common/files/cephstablerhcs.asc: -------------------------------------------------------------------------------- 1 | pub 4096R/FD431D51 2009-10-22 2 | Key fingerprint = 567E 347A D004 4ADE 55BA 8A5F 199E 2F91 FD43 1D51 3 | uid Red Hat, Inc. (release key 2) 4 | 5 | -----BEGIN PGP PUBLIC KEY BLOCK----- 6 | Version: GnuPG v1.4.5 (GNU/Linux) 7 | 8 | mQINBErgSTsBEACh2A4b0O9t+vzC9VrVtL1AKvUWi9OPCjkvR7Xd8DtJxeeMZ5eF 9 | 0HtzIG58qDRybwUe89FZprB1ffuUKzdE+HcL3FbNWSSOXVjZIersdXyH3NvnLLLF 10 | 0DNRB2ix3bXG9Rh/RXpFsNxDp2CEMdUvbYCzE79K1EnUTVh1L0Of023FtPSZXX0c 11 | u7Pb5DI5lX5YeoXO6RoodrIGYJsVBQWnrWw4xNTconUfNPk0EGZtEnzvH2zyPoJh 12 | XGF+Ncu9XwbalnYde10OCvSWAZ5zTCpoLMTvQjWpbCdWXJzCm6G+/hx9upke546H 13 | 5IjtYm4dTIVTnc3wvDiODgBKRzOl9rEOCIgOuGtDxRxcQkjrC+xvg5Vkqn7vBUyW 14 | 9pHedOU+PoF3DGOM+dqv+eNKBvh9YF9ugFAQBkcG7viZgvGEMGGUpzNgN7XnS1gj 15 | /DPo9mZESOYnKceve2tIC87p2hqjrxOHuI7fkZYeNIcAoa83rBltFXaBDYhWAKS1 16 | PcXS1/7JzP0ky7d0L6Xbu/If5kqWQpKwUInXtySRkuraVfuK3Bpa+X1XecWi24JY 17 | HVtlNX025xx1ewVzGNCTlWn1skQN2OOoQTV4C8/qFpTW6DTWYurd4+fE0OJFJZQF 18 | buhfXYwmRlVOgN5i77NTIJZJQfYFj38c/Iv5vZBPokO6mffrOTv3MHWVgQARAQAB 19 | tDNSZWQgSGF0LCBJbmMuIChyZWxlYXNlIGtleSAyKSA8c2VjdXJpdHlAcmVkaGF0 20 | LmNvbT6JAjYEEwECACAFAkrgSTsCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAK 21 | CRAZni+R/UMdUWzpD/9s5SFR/ZF3yjY5VLUFLMXIKUztNN3oc45fyLdTI3+UClKC 22 | 2tEruzYjqNHhqAEXa2sN1fMrsuKec61Ll2NfvJjkLKDvgVIh7kM7aslNYVOP6BTf 23 | C/JJ7/ufz3UZmyViH/WDl+AYdgk3JqCIO5w5ryrC9IyBzYv2m0HqYbWfphY3uHw5 24 | un3ndLJcu8+BGP5F+ONQEGl+DRH58Il9Jp3HwbRa7dvkPgEhfFR+1hI+Btta2C7E 25 | 0/2NKzCxZw7Lx3PBRcU92YKyaEihfy/aQKZCAuyfKiMvsmzs+4poIX7I9NQCJpyE 26 | IGfINoZ7VxqHwRn/d5mw2MZTJjbzSf+Um9YJyA0iEEyD6qjriWQRbuxpQXmlAJbh 27 | 8okZ4gbVFv1F8MzK+4R8VvWJ0XxgtikSo72fHjwha7MAjqFnOq6eo6fEC/75g3NL 28 | Ght5VdpGuHk0vbdENHMC8wS99e5qXGNDued3hlTavDMlEAHl34q2H9nakTGRF5Ki 29 | JUfNh3DVRGhg8cMIti21njiRh7gyFI2OccATY7bBSr79JhuNwelHuxLrCFpY7V25 30 | OFktl15jZJaMxuQBqYdBgSay2G0U6D1+7VsWufpzd/Abx1/c3oi9ZaJvW22kAggq 31 | dzdA27UUYjWvx42w9menJwh/0jeQcTecIUd0d0rFcw/c1pvgMMl/Q73yzKgKYw== 32 | =zbHE 33 | -----END PGP PUBLIC KEY BLOCK----- 34 | 35 | -------------------------------------------------------------------------------- /roles/ceph-osd/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: check_mandatory_vars.yml 3 | 4 | - include: pre_requisite.yml 5 | when: not osd_containerized_deployment 6 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 7 | static: False 8 | 9 | - include: ./scenarios/journal_collocation.yml 10 | when: 11 | - journal_collocation 12 | - not osd_containerized_deployment 13 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 14 | static: False 15 | 16 | - include: ./scenarios/raw_multi_journal.yml 17 | when: 18 | - raw_multi_journal 19 | - not osd_containerized_deployment 20 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 21 | static: False 22 | 23 | - include: ./scenarios/osd_directory.yml 24 | when: 25 | - osd_directory 26 | - not osd_containerized_deployment 27 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 28 | static: False 29 | 30 | - include: ./scenarios/bluestore.yml 31 | when: 32 | - osd_objectstore == 'bluestore' 33 | - not osd_containerized_deployment 34 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 35 | static: False 36 | 37 | - include: ./scenarios/dmcrypt-journal-collocation.yml 38 | when: 39 | - dmcrypt_journal_collocation 40 | - not osd_containerized_deployment 41 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 42 | static: False 43 | 44 | - include: ./scenarios/dmcrypt-dedicated-journal.yml 45 | when: 46 | - dmcrypt_dedicated_journal 47 | - not osd_containerized_deployment 48 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 49 | static: False 50 | 51 | - include: ./docker/main.yml 52 | when: osd_containerized_deployment 53 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 54 | static: False 55 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/deploy_monitors.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: generate monitor initial keyring 3 | local_action: shell python2 -c "import os ; import struct ; import time; import base64 ; key = os.urandom(16) ; header = struct.pack(' 9 disks 11 | # for SSD journals. 12 | 13 | - include: ./check_devices_static.yml 14 | when: 15 | - not osd_auto_discovery 16 | - not osd_directory 17 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 18 | static: False 19 | 20 | - include: ./check_devices_auto.yml 21 | when: 22 | - osd_auto_discovery 23 | - not osd_directory 24 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 25 | static: False 26 | 27 | - name: check the journal device is partition 28 | shell: "readlink -f {{ item }} | egrep '/dev/([hsv]d[a-z]{1,2}|cciss/c[0-9]d[0-9]p|nvme[0-9]n[0-9]p)[0-9]{1,2}$'" 29 | with_items: "{{ raw_journal_devices }}" 30 | changed_when: false 31 | failed_when: false 32 | always_run: true 33 | register: journal_ispartition_results 34 | 35 | - name: check the partition status of the journal devices 36 | shell: "parted --script {{ item.1 }} print > /dev/null 2>&1" 37 | with_together: 38 | - "{{ journal_ispartition_results.results }}" 39 | - "{{ raw_journal_devices|unique }}" 40 | changed_when: false 41 | failed_when: false 42 | always_run: true 43 | register: journal_partition_status 44 | when: 45 | - (raw_multi_journal or dmcrypt_dedicated_journal) 46 | - item.0.rc != 0 47 | 48 | - name: fix partitions gpt header or labels of the journal devices 49 | shell: "sgdisk --zap-all --clear --mbrtogpt -- {{ item.1 }} || sgdisk --zap-all --clear --mbrtogpt -- {{ item.1 }}" 50 | with_together: 51 | - "{{ journal_partition_status.results }}" 52 | - "{{ raw_journal_devices|unique }}" 53 | changed_when: false 54 | when: 55 | - (raw_multi_journal or dmcrypt_dedicated_journal) 56 | - not item.0.get("skipped") 57 | - item.0.get("rc", 0) != 0 58 | -------------------------------------------------------------------------------- /roles/ceph-common/files/cephdev.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | Version: GnuPG v1.4.10 (GNU/Linux) 3 | 4 | mQGiBE1Rr28RBADCxdpLV3ea9ocpS/1+UCvHqD5xjmlw/9dmji4qrUX0+IhPMNuA 5 | GBBt2CRaR7ygMF5S0NFXooegph0/+NT0KisLIuhUI3gde4SWb5jsb8hpGUse9MC5 6 | DN39P46zZSpepIMlQuQUkge8W/H2qBu10RcwQhs7o2fZ1zK9F3MmRCkBqwCggpap 7 | GsOgE2IlWjcztmE6xcPO0wED/R4BxTaQM+jxIjylnHgn9PYy6795yIc/ZoYjNnIh 8 | QyjqbLWnyzeTmjPBwcXNljKqzEoA/Cjb2gClxHXrYAw7bGu7wKbnqhzdghSx7ab+ 9 | HwIoy/v6IQqv+EXZgYHonqQwqtgfAHp5ON2gWu03cHoGkXfmA4qZIoowqMolZhGo 10 | cF30A/9GotDdnMlqh8bFBOCMuxfRow7H8RpfL0fX7VHA0knAZEDk2rNFeebL5QKH 11 | GNJm9Wa6JSVj1NUIaz4LHyravqXi4MXzlUqauhLHw1iG+qwZlPM04z+1Dj6A+2Hr 12 | b5UxI/I+EzmO5OYa38YWOqybNVBH0wO+sMCpdBq0LABa8X29LbRPQ2VwaCBhdXRv 13 | bWF0ZWQgcGFja2FnZSBidWlsZCAoQ2VwaCBhdXRvbWF0ZWQgcGFja2FnZSBidWls 14 | ZCkgPHNhZ2VAbmV3ZHJlYW0ubmV0PohgBBMRAgAgAhsDBgsJCAcDAgQVAggDBBYC 15 | AwECHgECF4AFAlEUm1YACgkQbq6uIgPDlRqTUACeMqJ+vwatwb+y/KWeNfmgtQ8+ 16 | kDwAn0MHwY42Wmb7FA891j88enooCdxRuQQNBE1Rr28QEACKG04kxGY1cwGoInHV 17 | P6z1+8oqGiaiYWFflYRtSiwoUVtl30T1sMOSzoEvmauc+rmBBfsyaBb8DLDUIgGK 18 | v1FCOY/tfqnOyQXotPjgaLeCtK5A5Z5D212wbskf5fRHAxiychwKURiEeesRa7EW 19 | rF6ohFxOTy9NOlFi7ctusShw6Q2kUtN7bQCX9hJdYs7PYQXvCXvW8DNt7IitF7Mp 20 | gMHNcj0wik6p38I4s7pqK6mqP4AXVVSWbJKr/LSz8bI8KhWRAT7erVAZf6FElR2x 21 | ZVr3c4zsE2HFpnZTsM5y/nj8fUkgKGl8OfBuUoh+MCVfnPmE6sgWfDTKkwWtUcmL 22 | 6V9UQ1INUJ3sk+XBY9SMNbOn04su9FjQyNEMI/3VK7yuyKBRAN7IIVgP2ch499m6 23 | +YFV9ZkG3JSTovNiqSpQouW7YPkS+8mxlPo03LQcU5bHeacBl0T8Xjlvqu6q279E 24 | liHul4huKL0+myPN4DtmOTh/kwgSy3BGCBdS+wfAJSZcuKI7pk7pHGCdUjNMHQZm 25 | PFbwzp33bVLd16gnAx0OW5DOn6l0VfgIQNSJ2rn7WZ5jdyg/Flp2VlWVtAHFLzkC 26 | a+LvQ5twSuzrV/VipSr3xz3pTDLY+ZxDztvrgA6AST8+sdq6uQTYjwUQV0wzanvp 27 | 9hkC5eqRY6YlzcgMkWFv8DCIEwADBQ//ZQaeVmG6T5vyfXf2JrCipmI4MAdO+ezE 28 | tWE82wgixlCvvm26UmUejCYgtD6DmwY/7/bIjvJDhUwP0+hAHHOpR62gncoMtbMr 29 | yHpm3FvYH58JNk5gx8ZA322WEc2GCRCQzrMQoMKBcpZY/703GpQ4l3RZ7/25gq7A 30 | NohV5zeddFQftc05PMBBJLU3U+lrnahJS1WaOXNQzS6oVj9jNda1jkgcQni6QssS 31 | IMT6rAPsVbGJhe9mxr2VWdQ90QlubpszIeSJuqqJxLwqH8XHXZmQOYxmyVP9a3pF 32 | qWDmsNxDA8ttYnMIc+nUAgCDJ84ScwQ1GvoCUD1b1cFNzvvhEHsNb4D/XbdrFcFG 33 | wEkeyivUsojdq2YnGjYSgauqyNWbeEgBrWzUe5USYysmziL/KAubcUjIbeRGxyPS 34 | 6iQ2kbvfEJJPgocWTfLs5j61FObO+MVlj+PEmxWbcsIRv/pnG2V2FPJ8evhzgvp7 35 | cG9imZPM6dWHzc/ZFdi3Bcs51RtStsvPqXv4icKIi+01h1MLHNBqwuUkIiiK7ooM 36 | lvnp+DiEsVSuYYKBdGTi+4+nduuYL2g8CTNJKZuC46dY7EcE3lRYZlxl7dwN3jfL 37 | PRlnNscs34dwhZa+b70Flia0U1DNF4jrIFFBSHD3TqMg0Z6kxp1TfxpeGOLOqnBW 38 | rr0GKehu9CGISQQYEQIACQIbDAUCURSbegAKCRBurq4iA8OVGv9TAJ9EeXVrRS3p 39 | PZkT1R21FszUc9LvmgCeMduh5IPGFWSx9MjUc7/j1QKYm7g= 40 | =per8 41 | -----END PGP PUBLIC KEY BLOCK----- 42 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/facts.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: get ceph version 3 | command: ceph --version 4 | changed_when: false 5 | always_run: yes 6 | register: ceph_version 7 | 8 | # this task shouldn't run in a rolling_update situation 9 | # because it blindly picks a mon, which may be down because 10 | # of the rolling update 11 | - name: is ceph running already? 12 | command: ceph --connect-timeout 3 --cluster {{ cluster }} fsid 13 | changed_when: false 14 | failed_when: false 15 | always_run: yes 16 | register: ceph_current_fsid 17 | delegate_to: "{{ groups[mon_group_name][0] }}" 18 | when: not rolling_update 19 | 20 | # set this as a default when performing a rolling_update 21 | # so the rest of the tasks here will succeed 22 | - set_fact: 23 | ceph_current_fsid: 24 | rc: 1 25 | when: rolling_update 26 | 27 | - name: create a local fetch directory if it does not exist 28 | local_action: file path={{ fetch_directory }} state=directory 29 | changed_when: false 30 | become: false 31 | run_once: true 32 | when: cephx or generate_fsid 33 | 34 | - set_fact: 35 | fsid: "{{ ceph_current_fsid.stdout }}" 36 | when: 37 | - ceph_current_fsid.rc == 0 38 | 39 | - set_fact: 40 | monitor_name: "{{ ansible_hostname }}" 41 | when: not mon_use_fqdn 42 | 43 | - set_fact: 44 | monitor_name: "{{ ansible_fqdn }}" 45 | when: mon_use_fqdn 46 | 47 | # We want this check to be run only on one mon 48 | - name: check if {{ fetch_directory }} directory exists 49 | local_action: stat path="{{ fetch_directory }}/monitor_keyring.conf" 50 | become: false 51 | register: monitor_keyring_conf 52 | run_once: true 53 | 54 | - include: facts_mon_fsid.yml 55 | run_once: true 56 | when: 57 | - cephx 58 | - not monitor_keyring_conf.stat.exists 59 | - ceph_current_fsid.rc == 0 60 | - mon_group_name in group_names 61 | 62 | - set_fact: 63 | ceph_version: "{{ ceph_version.stdout.split(' ')[2] }}" 64 | 65 | - set_fact: 66 | mds_name: "{{ ansible_hostname }}" 67 | when: not mds_use_fqdn 68 | 69 | - set_fact: 70 | mds_name: "{{ ansible_fqdn }}" 71 | when: mds_use_fqdn 72 | 73 | - set_fact: 74 | rbd_client_directory_owner: ceph 75 | when: 76 | - rbd_client_directory_owner is not defined 77 | or not rbd_client_directory_owner 78 | 79 | - set_fact: 80 | rbd_client_directory_group: ceph 81 | when: 82 | - rbd_client_directory_group is not defined 83 | or not rbd_client_directory_group 84 | 85 | - set_fact: 86 | rbd_client_directory_mode: "0770" 87 | when: 88 | - rbd_client_directory_mode is not defined 89 | or not rbd_client_directory_mode 90 | 91 | -------------------------------------------------------------------------------- /roles/ceph-osd/templates/ceph-osd-run.sh.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # {{ ansible_managed }} 3 | 4 | if [[ "$(blkid -t TYPE=crypto_LUKS -o value -s PARTUUID /dev/${1}* | wc -l)" -gt 0 ]] ; then 5 | for part in /dev/${1}*; do 6 | if [[ "$(blkid -t TYPE=crypto_LUKS -o value -s PARTUUID ${part} | wc -l)" -gt 0 ]]; then 7 | DEVICES="${DEVICES} --device=/dev/disk/by-partuuid/$(blkid -t TYPE=crypto_LUKS -o value -s PARTUUID ${part}) " 8 | fi 9 | done 10 | # we test if the dm exist, if it does we add it to --device list 11 | # if not we don't add it, the first activation will fail 12 | # however the dm will be created, on the second run it'll added to the device list 13 | # the second run will succeed 14 | blkid -t TYPE=crypto_LUKS -o value -s PARTUUID /dev/${1}1 15 | # make sure blkid returns 0 otherwise we will test /dev/mapper/ which always exists 16 | if [[ -e /dev/mapper/$(blkid -t TYPE=crypto_LUKS -o value -s PARTUUID /dev/${1}1) && "$?" -eq 0 ]]; then 17 | DEVICES="${DEVICES} --device=/dev/disk/by-partuuid/$(blkid -t PARTLABEL="ceph lockbox" -o value -s PARTUUID /dev/${1}3) --device=/dev/${1}3 --device=/dev/mapper/control --device=/dev/mapper/$(blkid -t TYPE=crypto_LUKS -o value -s PARTUUID /dev/${1}2) --device=/dev/mapper/$(blkid -t TYPE=crypto_LUKS -o value -s PARTUUID /dev/${1}1)" 18 | else 19 | DEVICES="${DEVICES} --device=/dev/disk/by-partuuid/$(blkid -t PARTLABEL="ceph lockbox" -o value -s PARTUUID /dev/${1}3) --device=/dev/${1}3 --device=/dev/mapper/control --device=/dev/mapper/$(blkid -t TYPE=crypto_LUKS -o value -s PARTUUID /dev/${1}2)" 20 | fi 21 | fi 22 | 23 | /usr/bin/docker run \ 24 | --rm \ 25 | --net=host \ 26 | --cap-add SYS_ADMIN \ 27 | --pid=host \ 28 | {% if not osd_containerized_deployment_with_kv -%} 29 | -v /var/lib/ceph:/var/lib/ceph \ 30 | -v /etc/ceph:/etc/ceph \ 31 | {% else -%} 32 | -e KV_TYPE={{kv_type}} \ 33 | -e KV_IP={{kv_endpoint}} \ 34 | -e KV_PORT={{kv_port}} \ 35 | {% endif -%} 36 | -v /etc/localtime:/etc/localtime:ro \ 37 | --device=/dev/${1} \ 38 | --device=/dev/${1}1 \ 39 | {% if raw_journal_devices|length > 0 -%} 40 | -e OSD_JOURNAL={{ raw_journal_devices[0] }} \ 41 | --device={{ raw_journal_devices[0] }} \ 42 | {% else -%} 43 | --device=/dev/${1}2 \ 44 | {% endif -%} 45 | --device=/dev/disk/by-partuuid/$(python -c "import uuid; f = open('/etc/machine-id', 'r').read(); print uuid.uuid5(uuid.NAMESPACE_DNS, f.strip() + '/dev/$1')") ${DEVICES} \ 46 | -e CEPH_DAEMON=OSD_CEPH_DISK_ACTIVATE \ 47 | -e OSD_DEVICE=/dev/${1} \ 48 | {{ ceph_osd_docker_extra_env }} \ 49 | --name={{ ansible_hostname }}-osd-dev${1} \ 50 | {{ ceph_docker_registry }}/{{ ceph_docker_image }}:{{ ceph_docker_image_tag }} 51 | -------------------------------------------------------------------------------- /roles/ceph-mon/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # You can override vars by using host or group vars 3 | 4 | ########### 5 | # GENERAL # 6 | ########### 7 | 8 | fetch_directory: fetch/ 9 | 10 | mon_group_name: mons 11 | 12 | # ACTIVATE BOTH FSID AND MONITOR_SECRET VARIABLES FOR NON-VAGRANT DEPLOYMENT 13 | fsid: "{{ cluster_uuid.stdout }}" 14 | monitor_secret: "{{ monitor_keyring.stdout }}" 15 | cephx: true 16 | 17 | # CephFS 18 | cephfs_data: cephfs_data 19 | cephfs_metadata: cephfs_metadata 20 | cephfs: cephfs 21 | 22 | # Secure your cluster 23 | # This will set the following flags on all the pools: 24 | # * nosizechange 25 | # * nopgchange 26 | # * nodelete 27 | 28 | secure_cluster: false 29 | secure_cluster_flags: 30 | - nopgchange 31 | - nodelete 32 | - nosizechange 33 | 34 | # Enable the Calamari-backed REST API on a Monitor 35 | calamari: false 36 | 37 | ############# 38 | # OPENSTACK # 39 | ############# 40 | 41 | openstack_config: false 42 | openstack_glance_pool: 43 | name: images 44 | pg_num: "{{ osd_pool_default_pg_num }}" 45 | openstack_cinder_pool: 46 | name: volumes 47 | pg_num: "{{ osd_pool_default_pg_num }}" 48 | openstack_nova_pool: 49 | name: vms 50 | pg_num: "{{ osd_pool_default_pg_num }}" 51 | openstack_cinder_backup_pool: 52 | name: backups 53 | pg_num: "{{ osd_pool_default_pg_num }}" 54 | 55 | openstack_pools: 56 | - "{{ openstack_glance_pool }}" 57 | - "{{ openstack_cinder_pool }}" 58 | - "{{ openstack_nova_pool }}" 59 | - "{{ openstack_cinder_backup_pool }}" 60 | 61 | openstack_keys: 62 | - { name: client.glance, value: "mon 'allow r' osd 'allow class-read object_prefix rbd_children, allow rwx pool={{ openstack_glance_pool.name }}'" } 63 | - { name: client.cinder, value: "mon 'allow r' osd 'allow class-read object_prefix rbd_children, allow rwx pool={{ openstack_cinder_pool.name }}, allow rwx pool={{ openstack_nova_pool.name }}, allow rx pool={{ openstack_glance_pool.name }}'" } 64 | - { name: client.cinder-backup, value: "mon 'allow r' osd 'allow class-read object_prefix rbd_children, allow rwx pool={{ openstack_cinder_backup_pool.name }}'" } 65 | 66 | ########## 67 | # DOCKER # 68 | ########## 69 | 70 | mon_containerized_deployment: false 71 | mon_containerized_deployment_with_kv: false 72 | # This is currently in ceph-common defaults because it is shared with ceph-nfs 73 | #mon_containerized_default_ceph_conf_with_kv: false 74 | ceph_mon_docker_interface: "{{ monitor_interface }}" 75 | ceph_mon_docker_subnet: "{{ public_network }}"# subnet of the ceph_mon_docker_interface 76 | ceph_docker_image: "ceph/daemon" 77 | ceph_docker_image_tag: latest 78 | ceph_mon_docker_extra_env: -e CLUSTER={{ cluster }} -e FSID={{ fsid }} -e MON_NAME={{ ansible_hostname }} 79 | ceph_docker_on_openstack: false 80 | mon_docker_privileged: false 81 | mon_docker_net_host: true 82 | ceph_config_keys: [] # DON'T TOUCH ME 83 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/docker/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check if a cluster is already running 3 | command: "docker ps -q -a --filter='ancestor={{ ceph_docker_image }}:{{ ceph_docker_image_tag }}'" 4 | register: ceph_health 5 | changed_when: false 6 | failed_when: false 7 | always_run: true 8 | 9 | - include: checks.yml 10 | when: 11 | - ceph_health.rc != 0 12 | - not mon_containerized_deployment_with_kv 13 | - not "{{ rolling_update | default(false) }}" 14 | 15 | - include: "{{ playbook_dir }}/roles/ceph-common/tasks/misc/ntp_atomic.yml" 16 | when: 17 | - is_atomic 18 | - ansible_os_family == 'RedHat' 19 | - ntp_service_enabled 20 | 21 | - include: "{{ playbook_dir }}/roles/ceph-common/tasks/misc/ntp_redhat.yml" 22 | when: 23 | - not is_atomic 24 | - ansible_os_family == 'RedHat' 25 | - ntp_service_enabled 26 | 27 | - include: "{{ playbook_dir }}/roles/ceph-common/tasks/misc/ntp_debian.yml" 28 | when: 29 | - ansible_os_family == 'Debian' 30 | - ntp_service_enabled 31 | 32 | - include: "{{ playbook_dir }}/roles/ceph-common/tasks/docker/fetch_image.yml" 33 | 34 | - include: dirs_permissions.yml 35 | 36 | # let the first mon create configs and keyrings 37 | - include: create_configs.yml 38 | when: 39 | - not mon_containerized_default_ceph_conf_with_kv 40 | 41 | - include: fetch_configs.yml 42 | when: not mon_containerized_deployment_with_kv 43 | 44 | - include: selinux.yml 45 | when: ansible_os_family == 'RedHat' 46 | 47 | - include: start_docker_monitor.yml 48 | 49 | - name: wait for monitor socket to exist 50 | command: docker exec {{ ansible_hostname }} stat /var/run/ceph/{{ cluster }}-mon.{{ ansible_hostname }}.asok 51 | register: monitor_socket 52 | retries: 5 53 | delay: 10 54 | until: monitor_socket.rc == 0 55 | 56 | - name: force peer addition as potential bootstrap peer for cluster bringup 57 | command: docker exec {{ ansible_hostname }} ceph --admin-daemon /var/run/ceph/{{ cluster }}-mon.{{ ansible_hostname }}.asok add_bootstrap_peer_hint {{ hostvars[item]['ansible_' + ceph_mon_docker_interface].ipv4.address }} 58 | with_items: "{{ groups.mons }}" 59 | changed_when: false 60 | failed_when: false 61 | when: 62 | - inventory_hostname == groups.mons[0] 63 | - not mon_containerized_deployment_with_kv 64 | 65 | - include: copy_configs.yml 66 | when: not mon_containerized_deployment_with_kv 67 | 68 | - name: create ceph rest api keyring when mon is containerized 69 | command: docker exec {{ ansible_hostname }} ceph --cluster {{ cluster }} auth get-or-create client.restapi osd 'allow *' mon 'allow *' -o /etc/ceph/{{ cluster }}.client.restapi.keyring 70 | args: 71 | creates: /etc/ceph/{{ cluster }}.client.restapi.keyring 72 | changed_when: false 73 | when: 74 | - cephx 75 | - mon_containerized_deployment 76 | - groups[restapi_group_name] is defined 77 | - inventory_hostname == groups.mons|last 78 | - not mon_containerized_deployment_with_kv 79 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/installs/install_rh_storage_on_debian.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # NOTE: this assumes that the ISO will always have a MON directory. Current 3 | # ISOs have MON, OSD, Tools, and Agent. If ISOs change the layout or provide 4 | # certain repos depending on the type of node this task will require a more 5 | # intelligent way to determine the location of the key. 6 | - name: install the red hat ceph storage repository key 7 | apt_key: 8 | file: "{{ ceph_rhcs_repository_path }}/MON/release.asc" 9 | state: present 10 | when: ceph_rhcs_iso_install 11 | 12 | - name: add red hat ceph storage repositories 13 | apt_repository: 14 | repo: "deb file://{{ ceph_rhcs_repository_path }}/{{ item }}/ {{ ansible_lsb.codename }} main" 15 | state: present 16 | changed_when: false 17 | with_items: 18 | - "MON" 19 | - "OSD" 20 | - "Tools" 21 | - "Agent" 22 | when: ceph_rhcs_iso_install 23 | 24 | - name: set apt pinning for red hat ceph storage 25 | template: 26 | src: "{{ role_path }}/templates/rhcs.pref.j2" 27 | dest: /etc/apt/preferences.d/rhcs.pref 28 | owner: root 29 | group: root 30 | mode: 0644 31 | 32 | - name: add red hat storage apt-key 33 | apt_key: 34 | data: "{{ lookup('file', role_path+'/files/cephstablerhcs.asc') }}" 35 | state: present 36 | when: not ceph_rhcs_iso_install 37 | 38 | - name: install dependencies 39 | apt: 40 | pkg: "{{ item }}" 41 | state: present 42 | update_cache: yes 43 | cache_valid_time: 3600 44 | with_items: "{{ debian_package_dependencies }}" 45 | 46 | - name: install red hat storage ceph mon 47 | apt: 48 | name: ceph-mon 49 | state: "{{ (upgrade_ceph_packages|bool) | ternary('latest','present') }}" 50 | when: mon_group_name in group_names 51 | 52 | - name: install red hat storage ceph osd 53 | apt: 54 | name: ceph-osd 55 | state: "{{ (upgrade_ceph_packages|bool) | ternary('latest','present') }}" 56 | when: osd_group_name in group_names 57 | 58 | - name: install ceph-test 59 | apt: 60 | name: ceph-test 61 | state: "{{ (upgrade_ceph_packages|bool) | ternary('latest','present') }}" 62 | when: ceph_test 63 | 64 | - name: install red hat storage radosgw 65 | apt: 66 | name: radosgw 67 | state: "{{ (upgrade_ceph_packages|bool) | ternary('latest','present') }}" 68 | when: rgw_group_name in group_names 69 | 70 | - name: install red hat storage ceph mds 71 | apt: 72 | pkg: ceph-mds 73 | state: "{{ (upgrade_ceph_packages|bool) | ternary('latest','present') }}" 74 | when: mds_group_name in group_names 75 | 76 | - name: install red hat storage ceph-fuse client 77 | apt: 78 | pkg: ceph-fuse 79 | state: "{{ (upgrade_ceph_packages|bool) | ternary('latest','present') }}" 80 | when: client_group_name in group_names 81 | 82 | - name: install red hat storage ceph-common 83 | apt: 84 | pkg: ceph-common 85 | state: "{{ (upgrade_ceph_packages|bool) | ternary('latest','present') }}" 86 | when: client_group_name in group_names 87 | 88 | - name: install red hat storage nfs gateway 89 | apt: 90 | name: nfs-ganesha 91 | state: "{{ (upgrade_ceph_packages|bool) | ternary('latest','present') }}" 92 | when: nfs_group_name in group_names 93 | -------------------------------------------------------------------------------- /roles/ceph-osd/tasks/check_mandatory_vars.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: make sure public_network configured 3 | fail: 4 | msg: "public_network must be configured. Ceph public network" 5 | when: public_network == '0.0.0.0/0' 6 | 7 | - name: make sure cluster_network configured 8 | fail: 9 | msg: "cluster_network must be configured. Ceph replication network" 10 | when: 11 | - cluster_network == '0.0.0.0/0' 12 | - not osd_containerized_deployment 13 | 14 | - name: make sure journal_size configured 15 | debug: 16 | msg: "WARNING: journal_size is configured to less than 5GB. This is not recommended and can lead to severe issues." 17 | when: 18 | - journal_size|int < 5120 19 | - osd_objectstore != 'bluestore' 20 | - osd_group_name in group_names 21 | 22 | - name: make sure an osd scenario was chosen 23 | fail: 24 | msg: "please choose an osd scenario" 25 | when: 26 | - osd_group_name is defined 27 | - osd_group_name in group_names 28 | - not osd_containerized_deployment 29 | - not journal_collocation 30 | - not raw_multi_journal 31 | - not osd_directory 32 | - not bluestore 33 | - not dmcrypt_journal_collocation 34 | - not dmcrypt_dedicated_journal 35 | 36 | - name: verify only one osd scenario was chosen 37 | fail: 38 | msg: "please select only one osd scenario" 39 | when: 40 | - osd_group_name is defined 41 | - osd_group_name in group_names 42 | - not osd_containerized_deployment 43 | - (journal_collocation and raw_multi_journal) 44 | or (journal_collocation and osd_directory) 45 | or (journal_collocation and bluestore) 46 | or (raw_multi_journal and osd_directory) 47 | or (raw_multi_journal and bluestore) 48 | or (osd_directory and bluestore) 49 | or (dmcrypt_journal_collocation and journal_collocation) 50 | or (dmcrypt_journal_collocation and raw_multi_journal) 51 | or (dmcrypt_journal_collocation and osd_directory) 52 | or (dmcrypt_journal_collocation and bluestore) 53 | or (dmcrypt_dedicated_journal and journal_collocation) 54 | or (dmcrypt_dedicated_journal and raw_multi_journal) 55 | or (dmcrypt_dedicated_journal and osd_directory) 56 | or (dmcrypt_dedicated_journal and bluestore) 57 | or (dmcrypt_dedicated_journal and dmcrypt_journal_collocation) 58 | 59 | - name: verify devices have been provided 60 | fail: 61 | msg: "please provide devices to your osd scenario" 62 | when: 63 | - osd_group_name is defined 64 | - osd_group_name in group_names 65 | - (journal_collocation or osd_containerized_deployment) 66 | - not osd_auto_discovery 67 | - devices|length == 0 68 | 69 | - name: verify journal devices have been provided 70 | fail: 71 | msg: "please provide devices and raw journal devices to your osd scenario" 72 | when: 73 | - osd_group_name is defined 74 | - osd_group_name in group_names 75 | - not osd_containerized_deployment 76 | - raw_multi_journal 77 | - raw_journal_devices|length == 0 78 | or devices|length == 0 79 | 80 | - name: verify directories have been provided 81 | fail: 82 | msg: "please provide directories to your osd scenario" 83 | when: 84 | - osd_group_name is defined 85 | - osd_group_name in group_names 86 | - not osd_containerized_deployment 87 | - osd_directory 88 | - osd_directories is not defined 89 | -------------------------------------------------------------------------------- /roles/ceph-osd/tasks/activate_osds.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # NOTE (leseb) : this task is for disk devices only because of the explicit use of the first 3 | # partition. 4 | 5 | - name: automatically activate osd disk(s) without partitions 6 | command: ceph-disk activate "/dev/{{ item.key | regex_replace('^(\/dev\/cciss\/c[0-9]{1}d[0-9]{1})$', '\\1p') }}1" 7 | ignore_errors: true 8 | with_dict: "{{ ansible_devices }}" 9 | when: 10 | - ansible_devices is defined 11 | - item.value.removable == "0" 12 | - item.value.partitions|count == 0 13 | - journal_collocation 14 | - osd_auto_discovery 15 | 16 | - name: activate osd(s) when device is a disk 17 | command: ceph-disk activate {{ item.1 | regex_replace('^(\/dev\/cciss\/c[0-9]{1}d[0-9]{1})$', '\\1p') }}1 18 | with_together: 19 | - "{{ ispartition_results.results }}" 20 | - "{{ devices|unique }}" 21 | changed_when: false 22 | failed_when: false 23 | register: activate_osd_disk 24 | when: 25 | - not item.0.get("skipped") 26 | - item.0.get("rc", 0) != 0 27 | - not osd_auto_discovery 28 | - raw_multi_journal 29 | 30 | - name: automatically activate osd disk(s) without partitions (dmcrypt) 31 | command: ceph-disk activate --dmcrypt "/dev/{{ item.key }}" 32 | ignore_errors: true 33 | with_dict: "{{ ansible_devices }}" 34 | when: 35 | - ansible_devices is defined 36 | - item.value.removable == "0" 37 | - item.value.partitions|count == 0 38 | - osd_auto_discovery 39 | - dmcrypt_journal_collocation 40 | 41 | - name: activate osd(s) when device is a disk (dmcrypt) 42 | command: ceph-disk activate --dmcrypt {{ item.1 | regex_replace('^(\/dev\/cciss\/c[0-9]{1}d[0-9]{1})$', '\\1p') }}1 43 | with_together: 44 | - "{{ ispartition_results.results }}" 45 | - "{{ devices|unique }}" 46 | changed_when: false 47 | failed_when: false 48 | register: activate_osd_disk_dmcrypt 49 | when: 50 | - not item.0.get("skipped") 51 | - item.0.get("rc", 0) != 0 52 | - not osd_auto_discovery 53 | - dmcrypt_dedicated_journal 54 | 55 | # NOTE (leseb): we must do this because of 56 | # https://github.com/ansible/ansible/issues/4297 57 | - name: combine ispartition results 58 | set_fact: 59 | combined_activate_osd_disk_results: "{{ activate_osd_disk if not dmcrypt_journal_collocation else activate_osd_disk_dmcrypt }}" 60 | 61 | - name: fail if ceph-disk cannot create an OSD 62 | fail: 63 | msg: "ceph-disk failed to create an OSD" 64 | when: 65 | " 'ceph-disk: Error: ceph osd create failed' in item.get('stderr', '') " 66 | with_items: "{{ (combined_activate_osd_disk_results|default({})).results|default([]) }}" 67 | 68 | # NOTE (leseb): this task is for partitions because we don't explicitly use a partition. 69 | - name: activate osd(s) when device is a partition 70 | command: "ceph-disk activate {{ item.1 }}" 71 | with_together: 72 | - "{{ ispartition_results.results }}" 73 | - "{{ devices|unique }}" 74 | changed_when: false 75 | failed_when: false 76 | when: 77 | - not item.0.get("skipped") 78 | - item.0.get("rc", 0) == 0 79 | - not osd_auto_discovery 80 | 81 | - include: osd_fragment.yml 82 | when: crush_location 83 | 84 | - name: get osd id 85 | shell: 'ls /var/lib/ceph/osd/ | grep -oP "\d+$"' 86 | changed_when: false 87 | failed_when: false 88 | always_run: true 89 | register: osd_id 90 | 91 | - name: start and add that the osd service(s) to the init sequence 92 | service: 93 | name: ceph-osd@{{ item }} 94 | state: started 95 | enabled: yes 96 | with_items: "{{ (osd_id|default({})).stdout_lines|default([]) }}" 97 | changed_when: false 98 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: ./checks/check_system.yml 3 | - include: ./checks/check_mandatory_vars.yml 4 | 5 | # Set ceph_release 6 | - include: ./release.yml 7 | tags: 8 | - always 9 | 10 | - include: ./checks/check_firewall.yml 11 | when: check_firewall 12 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 13 | static: False 14 | 15 | - include: ./misc/system_tuning.yml 16 | when: osd_group_name in group_names 17 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 18 | static: False 19 | 20 | - include: ./pre_requisites/prerequisite_rhcs_iso_install.yml 21 | when: 22 | - ceph_rhcs 23 | - ceph_rhcs_iso_install 24 | tags: 25 | - package-install 26 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 27 | static: False 28 | 29 | - include: ./pre_requisites/prerequisite_rhcs_cdn_install.yml 30 | when: 31 | - ceph_rhcs 32 | - ceph_rhcs_cdn_install 33 | - ansible_os_family == "RedHat" 34 | tags: 35 | - package-install 36 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 37 | static: False 38 | 39 | - include: ./installs/install_on_redhat.yml 40 | when: 41 | ansible_os_family == 'RedHat' and 42 | not ceph_rhcs_iso_install 43 | tags: 44 | - package-install 45 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 46 | static: False 47 | 48 | - include: ./installs/install_rh_storage_on_redhat.yml 49 | when: 50 | - ansible_distribution == "RedHat" 51 | - ceph_rhcs 52 | tags: 53 | - package-install 54 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 55 | static: False 56 | 57 | - include: ./installs/install_on_debian.yml 58 | when: 59 | - ansible_os_family == 'Debian' 60 | - not ceph_rhcs 61 | tags: 62 | - package-install 63 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 64 | static: False 65 | 66 | - include: ./installs/install_rh_storage_on_debian.yml 67 | when: 68 | - ansible_os_family == 'Debian' 69 | - ceph_rhcs 70 | tags: 71 | - package-install 72 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 73 | static: False 74 | 75 | - include: ./installs/install_on_clear.yml 76 | when: ansible_os_family == 'ClearLinux' 77 | tags: 78 | - package-install 79 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 80 | static: False 81 | 82 | - include: ./misc/ntp_redhat.yml 83 | when: 84 | - ansible_os_family == 'RedHat' 85 | - ntp_service_enabled 86 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 87 | static: False 88 | 89 | - include: ./misc/ntp_debian.yml 90 | when: 91 | - ansible_os_family == 'Debian' 92 | - ntp_service_enabled 93 | # Hard code this so we will skip the entire file instead of individual tasks (Default isn't Consistent) 94 | static: False 95 | 96 | - include: facts.yml 97 | - include: ./checks/check_socket.yml 98 | - include: create_ceph_initial_dirs.yml 99 | - include: generate_cluster_fsid.yml 100 | - include: generate_ceph_conf.yml 101 | - include: create_rbd_client_dir.yml 102 | - include: configure_cluster_name.yml 103 | -------------------------------------------------------------------------------- /roles/ceph-osd/tasks/docker/start_docker_osd.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # For openstack VMs modify the mount point below depending on if the Openstack 3 | # VM deploy tool defaults to mounting ephemeral disks 4 | - name: umount ceph disk (if on openstack) 5 | mount: 6 | name: /mnt 7 | src: /dev/vdb 8 | fstype: ext3 9 | state: unmounted 10 | when: ceph_docker_on_openstack 11 | 12 | - name: verify if the disk was already prepared 13 | shell: "lsblk -o PARTLABEL {{ item }} | grep -sq 'ceph'" 14 | failed_when: false 15 | always_run: true 16 | with_items: "{{ ceph_osd_docker_devices }}" 17 | register: osd_prepared 18 | 19 | # use shell rather than docker module 20 | # to ensure osd disk prepare finishes before 21 | # starting the next task 22 | - name: prepare ceph osd disk 23 | shell: | 24 | docker run --net=host \ 25 | --pid=host \ 26 | --privileged=true \ 27 | --name="{{ ansible_hostname }}-osd-prepare-{{ item.0 | regex_replace('/', '') }}" \ 28 | -v /etc/ceph:/etc/ceph \ 29 | -v /var/lib/ceph/:/var/lib/ceph/ \ 30 | -v /dev:/dev \ 31 | -v /etc/localtime:/etc/localtime:ro \ 32 | -e "OSD_DEVICE={{ item.0 }}" \ 33 | -e "OSD_JOURNAL_UUID=$(python -c "import uuid; print uuid.uuid5(uuid.NAMESPACE_DNS, '{{ ansible_machine_id }}{{ item.0 }}')")" \ 34 | -e CEPH_DAEMON=OSD_CEPH_DISK_PREPARE \ 35 | {{ ceph_osd_docker_prepare_env }} \ 36 | "{{ ceph_docker_registry }}/{{ ceph_docker_image }}:{{ ceph_docker_image_tag }}" 37 | with_together: 38 | - "{{ ceph_osd_docker_devices }}" 39 | - "{{ osd_prepared.results }}" 40 | when: 41 | - item.1.get("rc", 0) != 0 42 | - ceph_osd_docker_prepare_env is defined 43 | - not osd_containerized_deployment_with_kv 44 | 45 | - name: prepare ceph osd disk with kv_store 46 | shell: | 47 | docker run --net=host \ 48 | --pid=host \ 49 | --privileged=true \ 50 | --name="{{ ansible_hostname }}-osd-prepare-{{ item.0 | regex_replace('/', '') }}" \ 51 | -v /dev:/dev \ 52 | -v /etc/localtime:/etc/localtime:ro \ 53 | -e "OSD_DEVICE={{ item.0 }}" \ 54 | -e "OSD_JOURNAL_UUID=$(python -c "import uuid; print uuid.uuid5(uuid.NAMESPACE_DNS, '{{ ansible_machine_id }}{{ item.0 }}')")" \ 55 | -e "{{ ceph_osd_docker_prepare_env }}" \ 56 | -e CEPH_DAEMON=OSD_CEPH_DISK_PREPARE \ 57 | -e KV_TYPE={{kv_type}} \ 58 | -e KV_IP={{kv_endpoint}} \ 59 | -e KV_PORT={{kv_port}} \ 60 | {{ ceph_osd_docker_prepare_env }} \ 61 | "{{ ceph_docker_registry }}/{{ ceph_docker_image }}:{{ ceph_docker_image_tag }}" \ 62 | with_together: 63 | - "{{ ceph_osd_docker_devices }}" 64 | - "{{ osd_prepared.results }}" 65 | when: 66 | - item.1.get("rc", 0) != 0 67 | - ceph_osd_docker_prepare_env is defined 68 | - osd_containerized_deployment_with_kv 69 | 70 | - name: generate ceph osd docker run script 71 | become: true 72 | template: 73 | src: "{{ role_path }}/templates/ceph-osd-run.sh.j2" 74 | dest: "{{ ceph_osd_docker_run_script_path }}/ceph-osd-run.sh" 75 | owner: "root" 76 | group: "root" 77 | mode: "0744" 78 | 79 | - name: generate systemd unit file 80 | become: true 81 | template: 82 | src: "{{ role_path }}/templates/ceph-osd.service.j2" 83 | dest: /etc/systemd/system/ceph-osd@.service 84 | owner: "root" 85 | group: "root" 86 | mode: "0644" 87 | 88 | - name: enable systemd unit file for osd instance 89 | shell: systemctl enable ceph-osd@{{ item | basename }}.service 90 | changed_when: false 91 | with_items: "{{ ceph_osd_docker_devices }}" 92 | 93 | - name: reload systemd unit files 94 | shell: systemctl daemon-reload 95 | changed_when: false 96 | 97 | - name: systemd start osd container 98 | service: 99 | name: ceph-osd@{{ item | basename }} 100 | state: started 101 | enabled: yes 102 | changed_when: false 103 | with_items: "{{ ceph_osd_docker_devices }}" 104 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/checks/check_firewall.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check if nmap is installed 3 | local_action: shell command -v nmap 4 | changed_when: false 5 | failed_when: false 6 | register: nmapexist 7 | run_once: true 8 | always_run: true 9 | 10 | - name: inform that nmap is not present 11 | debug: 12 | msg: "nmap is not installed, can not test if ceph ports are allowed :(" 13 | run_once: true 14 | when: 15 | - nmapexist.rc != 0 16 | 17 | - name: check if monitor port is not filtered 18 | local_action: shell set -o pipefail && nmap -p 6789 {{ hostvars[inventory_hostname]['ansible_' + monitor_interface]['ipv4']['address'] if hostvars[inventory_hostname]['ansible_' + monitor_interface] is defined else hostvars[inventory_hostname]['monitor_address'] }} | grep -sqo -e filtered -e '0 hosts up' 19 | changed_when: false 20 | failed_when: false 21 | register: monportstate 22 | always_run: true 23 | when: 24 | - mon_group_name in group_names 25 | - nmapexist.rc == 0 26 | 27 | - name: fail if monitor port is filtered 28 | fail: 29 | msg: "Please allow port 6789 on your firewall" 30 | when: 31 | - mon_group_name in group_names 32 | - nmapexist.rc == 0 33 | - monportstate.rc == 0 34 | 35 | - name: check if osd and mds range is not filtered (osd hosts) 36 | local_action: shell set -o pipefail && nmap -p 6800-7300 {{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }} | grep -sqo -e filtered -e '0 hosts up' 37 | changed_when: false 38 | failed_when: false 39 | register: osdrangestate 40 | always_run: true 41 | when: 42 | - osd_group_name in group_names 43 | - nmapexist.rc == 0 44 | 45 | - name: fail if osd and mds range is filtered (osd hosts) 46 | fail: 47 | msg: "Please allow range from 6800 to 7300 on your firewall" 48 | when: 49 | - osd_group_name in group_names 50 | - nmapexist.rc == 0 51 | - osdrangestate.rc == 0 52 | 53 | - name: check if osd and mds range is not filtered (mds hosts) 54 | local_action: shell set -o pipefail && nmap -p 6800-7300 {{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }} | grep -sqo -e filtered -e '0 hosts up' 55 | changed_when: false 56 | failed_when: false 57 | register: mdsrangestate 58 | always_run: true 59 | when: 60 | - mds_group_name in group_names 61 | - nmapexist.rc == 0 62 | 63 | - name: fail if osd and mds range is filtered (mds hosts) 64 | fail: 65 | msg: "Please allow range from 6800 to 7300 on your firewall" 66 | when: 67 | - mds_group_name in group_names 68 | - nmapexist.rc == 0 69 | - mdsrangestate.rc == 0 70 | 71 | - name: check if rados gateway port is not filtered 72 | local_action: shell set -o pipefail && nmap -p {{ radosgw_civetweb_port }} {{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }} | grep -sqo -e filtered -e '0 hosts up' 73 | changed_when: false 74 | failed_when: false 75 | register: rgwportstate 76 | always_run: true 77 | when: 78 | - rgw_group_name in group_names 79 | - nmapexist.rc == 0 80 | 81 | - name: fail if rados gateway port is filtered 82 | fail: 83 | msg: "Please allow port {{ radosgw_civetweb_port }} on your firewall" 84 | when: 85 | - rgw_group_name in group_names 86 | - nmapexist.rc == 0 87 | - rgwportstate.rc == 0 88 | 89 | - name: check if NFS ports are not filtered 90 | local_action: shell set -o pipefail && nmap -p 111,2049 {{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }} | grep -sqo -e filtered -e '0 hosts up' 91 | changed_when: false 92 | failed_when: false 93 | register: nfsportstate 94 | always_run: true 95 | when: 96 | - nfs_group_name in group_names 97 | - nmapexist.rc == 0 98 | 99 | - name: fail if NFS ports are filtered 100 | fail: 101 | msg: "Please allow ports 111 and 2049 on your firewall" 102 | when: 103 | - nfs_group_name in group_names 104 | - nmapexist.rc == 0 105 | - nfsportstate.rc == 0 106 | -------------------------------------------------------------------------------- /roles/ceph-common/tasks/installs/install_on_redhat.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: install redhat dependencies 3 | package: 4 | name: "{{ item }}" 5 | state: present 6 | with_items: "{{ redhat_package_dependencies }}" 7 | when: ansible_distribution == "RedHat" 8 | 9 | - name: install centos dependencies 10 | package: 11 | name: "{{ item }}" 12 | state: present 13 | with_items: "{{ centos_package_dependencies }}" 14 | when: ansible_distribution == "CentOS" 15 | 16 | - name: configure ceph yum repository 17 | include: redhat_ceph_repository.yml 18 | when: ceph_origin == 'upstream' 19 | 20 | - name: make sure /tmp exists 21 | file: 22 | path: /tmp 23 | state: directory 24 | when: 25 | - ceph_origin == 'local' 26 | - use_installer 27 | 28 | - name: use mktemp to create name for rundep 29 | command: "mktemp /tmp/rundep.XXXXXXXX" 30 | register: rundep_location 31 | when: 32 | - ceph_origin == 'local' 33 | - use_installer 34 | 35 | - name: copy rundep 36 | copy: 37 | src: "{{ansible_dir}}/rundep" 38 | dest: "{{ item }}" 39 | with_items: "{{ (rundep_location|default({})).stdout_lines|default([]) }}" 40 | when: 41 | - ceph_origin == 'local' 42 | - use_installer 43 | 44 | - name: install ceph dependencies 45 | script: "{{ ansible_dir }}/rundep_installer.sh {{ item }}" 46 | become: true 47 | with_items: "{{ (rundep_location|default({})).stdout_lines|default([]) }}" 48 | when: 49 | - ceph_origin == 'local' 50 | - use_installer 51 | 52 | - name: synchronize ceph install 53 | synchronize: 54 | src: "{{ceph_installation_dir}}/" 55 | dest: "/" 56 | when: 57 | - ceph_origin == 'local' 58 | 59 | - name: create user group ceph 60 | group: 61 | name: 'ceph' 62 | when: 63 | - ceph_origin == 'local' 64 | 65 | - name: create user ceph 66 | user: 67 | name: 'ceph' 68 | when: 69 | - ceph_origin == 'local' 70 | 71 | - name: install distro or red hat storage ceph mon 72 | package: 73 | name: "ceph-mon" 74 | state: "{{ (upgrade_ceph_packages|bool) | ternary('latest','present') }}" 75 | when: 76 | - mon_group_name in group_names 77 | or ceph_origin == "distro" 78 | or ceph_custom 79 | 80 | - name: install distro or red hat storage ceph osd 81 | package: 82 | name: "ceph-osd" 83 | state: "{{ (upgrade_ceph_packages|bool) | ternary('latest','present') }}" 84 | when: 85 | - osd_group_name in group_names 86 | or ceph_origin == "distro" 87 | or ceph_custom 88 | 89 | - name: install distro or red hat storage ceph mds 90 | package: 91 | name: "ceph-mds" 92 | state: "{{ (upgrade_ceph_packages|bool) | ternary('latest','present') }}" 93 | when: 94 | - mds_group_name in group_names 95 | or ceph_origin == "distro" 96 | or ceph_custom 97 | 98 | - name: install distro or red hat storage ceph-fuse 99 | package: 100 | name: "ceph-fuse" 101 | state: "{{ (upgrade_ceph_packages|bool) | ternary('latest','present') }}" 102 | when: 103 | - client_group_name in group_names 104 | or ceph_origin == "distro" 105 | or ceph_dev 106 | or ceph_custom 107 | 108 | - name: install distro or red hat storage ceph base 109 | package: 110 | name: "ceph-base" 111 | state: "{{ (upgrade_ceph_packages|bool) | ternary('latest','present') }}" 112 | when: 113 | - client_group_name in group_names 114 | or ceph_origin == "distro" 115 | or ceph_custom 116 | 117 | - name: install ceph-test 118 | package: 119 | name: ceph-test 120 | state: "{{ (upgrade_ceph_packages|bool) | ternary('latest','present') }}" 121 | when: ceph_test 122 | 123 | - name: install rados gateway 124 | package: 125 | name: ceph-radosgw 126 | state: "{{ (upgrade_ceph_packages|bool) | ternary('latest','present') }}" 127 | when: rgw_group_name in group_names 128 | 129 | - name: install nfs ceph gateway 130 | package: 131 | name: nfs-ganesha-ceph 132 | when: 133 | - nfs_group_name in group_names 134 | - nfs_file_gw 135 | 136 | - name: install nfs rgw gateway 137 | package: 138 | name: "{{ item }}" 139 | with_items: 140 | - nfs-ganesha-rgw 141 | - ceph-radosgw 142 | when: 143 | - nfs_group_name in group_names 144 | - nfs_obj_gw 145 | -------------------------------------------------------------------------------- /roles/ceph-mon/tasks/ceph_keys.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: collect admin and bootstrap keys (for or after kraken release) 3 | command: ceph-create-keys --cluster {{ cluster }} -i {{ monitor_name }} 4 | args: 5 | creates: /etc/ceph/{{ cluster }}.client.admin.keyring 6 | failed_when: false 7 | changed_when: false 8 | always_run: true 9 | when: 10 | - cephx 11 | - ceph_release_num.{{ ceph_release }} > ceph_release_num.jewel 12 | 13 | # NOTE (leseb): wait for mon discovery and quorum resolution 14 | # the admin key is not instantaneously created so we have to wait a bit 15 | - name: "wait for {{ cluster }}.client.admin.keyring exists" 16 | wait_for: 17 | path: /etc/ceph/{{ cluster }}.client.admin.keyring 18 | when: cephx 19 | 20 | - name: test if initial mon keyring is in mon kv store 21 | command: ceph --cluster {{ cluster }} config-key get initial_mon_keyring 22 | changed_when: false 23 | ignore_errors: true 24 | always_run: true 25 | run_once: true 26 | register: is_initial_mon_keyring_in_kv 27 | 28 | - name: put initial mon keyring in mon kv store 29 | command: ceph --cluster {{ cluster }} config-key put initial_mon_keyring {{ monitor_keyring.stdout }} 30 | changed_when: false 31 | always_run: true 32 | run_once: true 33 | when: 34 | - is_initial_mon_keyring_in_kv.rc != 0 35 | - cephx 36 | 37 | - name: create ceph rest api keyring when mon is not containerized 38 | command: ceph --cluster {{ cluster }} auth get-or-create client.restapi osd 'allow *' mon 'allow *' -o /etc/ceph/{{ cluster }}.client.restapi.keyring 39 | args: 40 | creates: /etc/ceph/{{ cluster }}.client.restapi.keyring 41 | changed_when: false 42 | when: 43 | - cephx 44 | - groups[restapi_group_name] is defined 45 | 46 | # NOTE(leseb): we add a conditional for backward compatibility 47 | # so people that had 'pool_default_pg_num' declared will get 48 | # the same behaviour 49 | # 50 | - name: check if does global key exist in ceph_conf_overrides 51 | set_fact: 52 | global_in_ceph_conf_overrides: "{{ 'global' in ceph_conf_overrides }}" 53 | 54 | - name: check if ceph_conf_overrides.global.osd_pool_default_pg_num is set 55 | set_fact: 56 | osd_pool_default_pg_num_in_overrides: "{{ 'osd_pool_default_pg_num' in ceph_conf_overrides.global }}" 57 | when: global_in_ceph_conf_overrides 58 | 59 | - name: get default value for osd_pool_default_pg_num 60 | shell: | 61 | ceph --cluster {{ cluster }} daemon mon.{{ monitor_name }} config get osd_pool_default_pg_num | grep -Po '(?<="osd_pool_default_pg_num": ")[^"]*' 62 | failed_when: false 63 | changed_when: false 64 | run_once: true 65 | register: default_pool_default_pg_num 66 | when: (pool_default_pg_num is not defined or not global_in_ceph_conf_overrides) 67 | 68 | - set_fact: 69 | osd_pool_default_pg_num: "{{ pool_default_pg_num }}" 70 | when: pool_default_pg_num is defined 71 | 72 | - set_fact: 73 | osd_pool_default_pg_num: "{{ default_pool_default_pg_num.stdout }}" 74 | when: 75 | - pool_default_pg_num is not defined 76 | - default_pool_default_pg_num.rc == 0 77 | - (osd_pool_default_pg_num_in_overrides is not defined or not osd_pool_default_pg_num_in_overrides) 78 | 79 | - set_fact: 80 | osd_pool_default_pg_num: "{{ ceph_conf_overrides.global.osd_pool_default_pg_num }}" 81 | when: 82 | - global_in_ceph_conf_overrides 83 | - ceph_conf_overrides.global.osd_pool_default_pg_num is defined 84 | 85 | - name: test if rbd exists 86 | command: ceph --cluster {{ cluster }} osd pool stats rbd 87 | changed_when: false 88 | failed_when: false 89 | register: rbd_pool_exist 90 | 91 | - include: rbd_pool.yml 92 | when: rbd_pool_exist.rc == 0 93 | 94 | - include: rbd_pool_pgs.yml 95 | when: 96 | - rbd_pool_exist.rc == 0 97 | - global_in_ceph_conf_overrides 98 | - ceph_conf_overrides.global.osd_pool_default_pg_num is defined 99 | 100 | - include: rbd_pool_size.yml 101 | when: 102 | - rbd_pool_exist.rc == 0 103 | - global_in_ceph_conf_overrides 104 | - ceph_conf_overrides.global.osd_pool_default_size is defined 105 | 106 | - include: openstack_config.yml 107 | when: openstack_config 108 | 109 | - name: find ceph keys 110 | shell: ls -1 /etc/ceph/*.keyring 111 | changed_when: false 112 | register: ceph_keys 113 | always_run: true 114 | when: cephx 115 | 116 | - name: set keys permissions 117 | file: 118 | path: "{{ item }}" 119 | owner: "ceph" 120 | group: "ceph" 121 | mode: "0600" 122 | with_items: 123 | - "{{ ceph_keys.get('stdout_lines') | default([]) }}" 124 | when: cephx 125 | 126 | - name: copy keys to the ansible server 127 | fetch: 128 | src: "{{ item }}" 129 | dest: "{{ fetch_directory }}/{{ fsid }}/{{ item }}" 130 | flat: yes 131 | run_once: true 132 | with_items: 133 | - "{{ ceph_keys.get('stdout_lines') | default([]) }}" 134 | - /var/lib/ceph/bootstrap-osd/{{ cluster }}.keyring 135 | - /var/lib/ceph/bootstrap-rgw/{{ cluster }}.keyring 136 | - /var/lib/ceph/bootstrap-mds/{{ cluster }}.keyring 137 | when: cephx 138 | 139 | - name: drop in a motd script to report status when logging in 140 | copy: 141 | src: precise/92-ceph 142 | dest: /etc/update-motd.d/92-ceph 143 | owner: root 144 | group: root 145 | mode: 0755 146 | when: ansible_distribution_release == 'precise' 147 | -------------------------------------------------------------------------------- /roles/ceph-common/templates/ceph.conf.j2: -------------------------------------------------------------------------------- 1 | #jinja2: trim_blocks: "true", lstrip_blocks: "true" 2 | # {{ ansible_managed }} 3 | 4 | [global] 5 | {% if not cephx %} 6 | auth cluster required = none 7 | auth service required = none 8 | auth client required = none 9 | auth supported = none 10 | {% endif %} 11 | {% if ip_version == 'ipv6' %} 12 | ms bind ipv6 = true 13 | {% endif %} 14 | {% if not mon_containerized_deployment_with_kv and not mon_containerized_deployment %} 15 | fsid = {{ fsid }} 16 | {% endif %} 17 | max open files = {{ max_open_files }} 18 | {% if common_single_host_mode is defined and common_single_host_mode %} 19 | osd crush chooseleaf type = 0 20 | {% endif %} 21 | {# NOTE (leseb): the blank lines in-between are needed otherwise we won't get any line break #} 22 | {% if groups[mon_group_name] is defined %} 23 | mon initial members = {% for host in groups[mon_group_name] %} 24 | {% if hostvars[host]['ansible_fqdn'] is defined and mon_use_fqdn -%} 25 | {{ hostvars[host]['ansible_fqdn'] }} 26 | {%- elif hostvars[host]['ansible_hostname'] is defined -%} 27 | {{ hostvars[host]['ansible_hostname'] }} 28 | {%- endif %} 29 | {%- if not loop.last %},{% endif %} 30 | {% endfor %} 31 | {% endif %} 32 | 33 | {% if not mon_containerized_deployment and not mon_containerized_deployment_with_kv %} 34 | {% if monitor_address_block %} 35 | mon host = {% for host in groups[mon_group_name] %}{{ hostvars[host]['ansible_all_ipv4_addresses'] | ipaddr(monitor_address_block) | first }}{% if not loop.last %},{% endif %}{% endfor %} 36 | {% elif groups[mon_group_name] is defined %} 37 | mon host = {% for host in groups[mon_group_name] %} 38 | {% set address = hostvars[host]['monitor_address'] if hostvars[host]['monitor_address'] is defined else monitor_address %} 39 | {% set interface = hostvars[host]['monitor_interface'] if hostvars[host]['monitor_interface'] is defined else monitor_interface %} 40 | {% if interface != "interface" %} 41 | {% for key in hostvars[host].keys() %} 42 | {% if hostvars[host][key]['macaddress'] is defined and hostvars[host][key]['device'] is defined and hostvars[host][key]['device'] == interface -%} 43 | {{ hostvars[host][key][ip_version]['address'] }} 44 | {%- endif %} 45 | {% endfor %} 46 | {% elif address != "0.0.0.0" -%} 47 | {{ address }} 48 | {%- endif %} 49 | {%- if not loop.last %},{% endif %} 50 | {% endfor %} 51 | {% endif %} 52 | {% endif %} 53 | {% if mon_containerized_deployment %} 54 | fsid = {{ fsid }} 55 | {% if groups[mon_group_name] is defined %} 56 | mon host = {% for host in groups[mon_group_name] %} 57 | {% set interface = ["ansible_",ceph_mon_docker_interface]|join %} 58 | {% if mon_containerized_deployment -%} 59 | {{ hostvars[host][interface]['ipv4']['address'] }} 60 | {%- elif hostvars[host]['monitor_address'] is defined -%} 61 | {{ hostvars[host]['monitor_address'] }} 62 | {%- elif monitor_address != "0.0.0.0" -%} 63 | {{ monitor_address }} 64 | {%- endif %} 65 | {%- if not loop.last %},{% endif %} 66 | {% endfor %} 67 | {% endif %} 68 | {% endif %} 69 | 70 | {% if public_network is defined %} 71 | public network = {{ public_network }} 72 | {% endif %} 73 | {% if cluster_network is defined %} 74 | cluster network = {{ cluster_network }} 75 | {% endif %} 76 | 77 | [client.libvirt] 78 | admin socket = {{ rbd_client_admin_socket_path }}/$cluster-$type.$id.$pid.$cctid.asok # must be writable by QEMU and allowed by SELinux or AppArmor 79 | log file = {{ rbd_client_log_file }} # must be writable by QEMU and allowed by SELinux or AppArmor 80 | 81 | [osd] 82 | osd mkfs type = {{ osd_mkfs_type }} 83 | osd mkfs options xfs = {{ osd_mkfs_options_xfs }} 84 | osd mount options xfs = {{ osd_mount_options_xfs }} 85 | osd journal size = {{ journal_size }} 86 | {% if filestore_xattr_use_omap != None %} 87 | filestore xattr use omap = {{ filestore_xattr_use_omap }} 88 | {% elif osd_mkfs_type == "ext4" %} 89 | filestore xattr use omap = true 90 | {# else, default is false #} 91 | {% endif %} 92 | 93 | {% if groups[mds_group_name] is defined %} 94 | {% for host in groups[mds_group_name] %} 95 | {% if hostvars[host]['ansible_fqdn'] is defined and mds_use_fqdn %} 96 | [mds.{{ hostvars[host]['ansible_fqdn'] }}] 97 | host = {{ hostvars[host]['ansible_fqdn'] }} 98 | {% elif hostvars[host]['ansible_hostname'] is defined %} 99 | [mds.{{ hostvars[host]['ansible_hostname'] }}] 100 | host = {{ hostvars[host]['ansible_hostname'] }} 101 | {% endif %} 102 | {% endfor %} 103 | {% endif %} 104 | 105 | {% if groups[rgw_group_name] is defined %} 106 | {% for host in groups[rgw_group_name] %} 107 | {% if hostvars[host]['ansible_hostname'] is defined %} 108 | [client.rgw.{{ hostvars[host]['ansible_hostname'] }}] 109 | {% if radosgw_dns_name is defined %} 110 | rgw dns name = {{ radosgw_dns_name }} 111 | {% endif %} 112 | host = {{ hostvars[host]['ansible_hostname'] }} 113 | keyring = /var/lib/ceph/radosgw/{{ cluster }}-rgw.{{ hostvars[host]['ansible_hostname'] }}/keyring 114 | rgw socket path = /tmp/radosgw-{{ hostvars[host]['ansible_hostname'] }}.sock 115 | log file = /var/log/ceph/{{ cluster }}-rgw-{{ hostvars[host]['ansible_hostname'] }}.log 116 | rgw data = /var/lib/ceph/radosgw/{{ cluster }}-rgw.{{ hostvars[host]['ansible_hostname'] }} 117 | rgw frontends = civetweb {{ radosgw_civetweb_options }} 118 | rgw resolve cname = {{ radosgw_resolve_cname | bool }} 119 | {% if radosgw_keystone %} 120 | rgw keystone url = {{ radosgw_keystone_url }} 121 | rgw keystone api version = {{ radosgw_keystone_api_version }} 122 | {% if radosgw_keystone_auth_method == 'admin_token' %} 123 | rgw keystone admin token = {{ radosgw_keystone_admin_token }} 124 | {% elif radosgw_keystone_auth_method == 'auth_token' %} 125 | rgw keystone admin user = {{ radosgw_keystone_admin_user }} 126 | rgw keystone admin password = {{ radosgw_keystone_admin_password }} 127 | rgw keystone admin tenant = {{ radosgw_keystone_admin_tenant }} 128 | rgw keystone admin domain = {{ radosgw_keystone_admin_domain }} 129 | {% endif %} 130 | rgw keystone accepted roles = {{ radosgw_keystone_accepted_roles }} 131 | rgw keystone token cache size = {{ radosgw_keystone_token_cache_size }} 132 | rgw keystone revocation interval = {{ radosgw_keystone_revocation_internal }} 133 | rgw s3 auth use keystone = {{ radosgw_s3_auth_use_keystone }} 134 | {% if radosgw_keystone_ssl | bool %} 135 | nss db path = {{ radosgw_nss_db_path }} 136 | {% endif %} 137 | {% endif %} 138 | {% if radosgw_usage_log | bool %} 139 | rgw enable usage log = true 140 | rgw usage log tick interval = {{ radosgw_usage_log_tick_interval }} 141 | rgw usage log flush threshold = {{ radosgw_usage_log_flush_threshold }} 142 | rgw usage max shards = {{ radosgw_usage_max_shards }} 143 | rgw usage max user shards = {{ radosgw_usage_max_user_shards }} 144 | {% endif %} 145 | {% if radosgw_static_website | bool %} 146 | rgw enable static website = {{ radosgw_static_website }} 147 | rgw dns s3website name = {{ radosgw_dns_s3website_name }} 148 | {% endif %} 149 | {% endif %} 150 | {% endfor %} 151 | {% endif %} 152 | 153 | {% if groups[restapi_group_name] is defined %} 154 | [client.restapi] 155 | {% if restapi_interface != "interface" %} 156 | {% include 'client_restapi_interface.j2' %} 157 | {% else %} 158 | {% include 'client_restapi_address.j2' %} 159 | {% endif %} 160 | keyring = /var/lib/ceph/restapi/ceph-restapi/keyring 161 | log file = /var/log/ceph/ceph-restapi.log 162 | {% endif %} 163 | -------------------------------------------------------------------------------- /roles/ceph-osd/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Variables here are applicable to all host groups NOT roles 3 | 4 | # This sample file generated by generate_group_vars_sample.sh 5 | 6 | # Dummy variable to avoid error because ansible does not recognize the 7 | # file as a good configuration file when no variable in it. 8 | dummy: 9 | 10 | # You can override default vars defined in defaults/main.yml here, 11 | # but I would advice to use host or group vars instead 12 | 13 | 14 | ########### 15 | # GENERAL # 16 | ########### 17 | 18 | fetch_directory: fetch/ 19 | 20 | # Even though OSD nodes should not have the admin key 21 | # at their disposal, some people might want to have it 22 | # distributed on OSD nodes. Setting 'copy_admin_key' to 'true' 23 | # will copy the admin key to the /etc/ceph/ directory 24 | copy_admin_key: false 25 | 26 | 27 | #################### 28 | # OSD CRUSH LOCATION 29 | #################### 30 | 31 | # /!\ 32 | # 33 | # BE EXTREMELY CAREFUL WITH THIS OPTION 34 | # DO NOT USE IT UNLESS YOU KNOW WHAT YOU ARE DOING 35 | # 36 | # /!\ 37 | # 38 | # It is probably best to keep this option to 'false' as the default 39 | # suggests it. This option should only be used while doing some complex 40 | # CRUSH map. It allows you to force a specific location for a set of OSDs. 41 | # 42 | # The following options will build a ceph.conf with OSD sections 43 | # Example: 44 | # [osd.X] 45 | # osd crush location = "root=location" 46 | # 47 | # This works with your inventory file 48 | # To match the following 'osd_crush_location' option the inventory must look like: 49 | # 50 | # [osds] 51 | # osd0 ceph_crush_root=foo ceph_crush_rack=bar 52 | 53 | crush_location: false 54 | osd_crush_location: "'root={{ ceph_crush_root }} rack={{ ceph_crush_rack }} host={{ ansible_hostname }}'" 55 | 56 | 57 | ############## 58 | # CEPH OPTIONS 59 | ############## 60 | 61 | # ACTIVATE THE FSID VARIABLE FOR NON-VAGRANT DEPLOYMENT 62 | fsid: "{{ cluster_uuid.stdout }}" 63 | cephx: true 64 | 65 | # Devices to be used as OSDs 66 | # You can pre-provision disks that are not present yet. 67 | # Ansible will just skip them. Newly added disk will be 68 | # automatically configured during the next run. 69 | # 70 | 71 | 72 | # Declare devices to be used as OSDs 73 | # All scenario(except 3rd) inherit from the following device declaration 74 | 75 | #devices: 76 | # - /dev/sdb 77 | # - /dev/sdc 78 | # - /dev/sdd 79 | # - /dev/sde 80 | 81 | devices: [] 82 | 83 | 84 | #'osd_auto_discovery' mode prevents you from filling out the 'devices' variable above. 85 | # You can use this option with First and Forth and Fifth OSDS scenario. 86 | # Device discovery is based on the Ansible fact 'ansible_devices' 87 | # which reports all the devices on a system. If chosen all the disks 88 | # found will be passed to ceph-disk. You should not be worried on using 89 | # this option since ceph-disk has a built-in check which looks for empty devices. 90 | # Thus devices with existing partition tables will not be used. 91 | # 92 | osd_auto_discovery: false 93 | 94 | 95 | # !! WARNING !! 96 | # # 97 | # # /!\ ENABLE ONLY ONE SCENARIO AT A TIME /!\ 98 | # # 99 | # # !! WARNING !! 100 | # 101 | 102 | # I. First scenario: journal and osd_data on the same device 103 | # Use 'true' to enable this scenario 104 | # This will collocate both journal and data on the same disk 105 | # creating a partition at the beginning of the device 106 | # List devices under 'devices' variable above or choose 'osd_auto_discovery' 107 | 108 | 109 | journal_collocation: false 110 | 111 | 112 | # II. Second scenario: N journal devices for N OSDs 113 | # Use 'true' for 'raw_multi_journal' to enable this scenario 114 | # List devices under 'devices' variable above and 115 | # write journal devices for those under 'raw_journal_devices' 116 | # In the following example: 117 | # * sdb and sdc will get sdf as a journal 118 | # * sdd and sde will get sdg as a journal 119 | 120 | # While starting you have 2 options: 121 | # 1. Pre-allocate all the devices 122 | # 2. Progressively add new devices 123 | raw_multi_journal: false 124 | #raw_journal_devices: 125 | # - /dev/sdf 126 | # - /dev/sdf 127 | # - /dev/sdg 128 | # - /dev/sdg 129 | # 130 | # NOTE(leseb): 131 | # On a containerized scenario we only support A SINGLE journal 132 | # for all the OSDs on a given machine. If you don't, bad things will happen 133 | # This is a limitation we plan to fix at some point. 134 | raw_journal_devices: [] 135 | 136 | 137 | # III. Use directory instead of disk for OSDs 138 | # Use 'true' to enable this scenario 139 | 140 | osd_directory: false 141 | #osd_directories: 142 | # - /var/lib/ceph/osd/mydir1 143 | # - /var/lib/ceph/osd/mydir2 144 | osd_directories: [] 145 | 146 | 147 | # IV. This will partition disks for BlueStore 148 | # Use 'true' to enable this scenario 149 | bluestore: false 150 | 151 | 152 | # V. Encrypt osd data and/or journal devices with dm-crypt. 153 | # Keys are stored into the monitors k/v store 154 | # Use 'true' to enable this scenario 155 | # Both journal and data are stored on the same dm-crypt encrypted device 156 | dmcrypt_journal_collocation: false 157 | 158 | 159 | # VI. Encrypt osd data and/or journal devices with dm-crypt. 160 | # Keys are stored into the monitors k/v store 161 | # Use 'true' to enable this scenario 162 | # Journal and osd data are separated, each with their own dm-crypt device 163 | # You must use raw_journal_devices and set your journal devices 164 | dmcrypt_dedicated_journal: false 165 | 166 | 167 | ########## 168 | # DOCKER # 169 | ########## 170 | 171 | osd_containerized_deployment: false 172 | osd_containerized_deployment_with_kv: false 173 | kv_type: etcd 174 | kv_endpoint: 127.0.0.1 175 | kv_port: 4001 176 | ceph_docker_image: "ceph/daemon" 177 | ceph_docker_image_tag: latest 178 | ceph_config_keys: [] # DON'T TOUCH ME 179 | ceph_docker_on_openstack: false 180 | 181 | # PREPARE DEVICE 182 | # Make sure you only pass a single device to raw_journal_devices, otherwise this will fail horribly. 183 | # This is why we use [0] in the example. 184 | # 185 | # WARNING /!\ DMCRYPT scenario ONLY works with Docker version 1.12.5 and above 186 | # 187 | # Examples: 188 | # Journal collocated: ceph_osd_docker_prepare_env: -e CLUSTER={{ cluster }} -e OSD_JOURNAL_SIZE={{ journal_size }} -e OSD_FORCE_ZAP=1 189 | # Dedicated journal: ceph_osd_docker_prepare_env: -e CLUSTER={{ cluster }} -e OSD_JOURNAL_SIZE={{ journal_size }} -e OSD_FORCE_ZAP=1 -e OSD_JOURNAL={{ raw_journal_devices[0] }} 190 | # Encrypted OSD: ceph_osd_docker_prepare_env: -e CLUSTER={{ cluster }} -e OSD_JOURNAL_SIZE={{ journal_size }} -e OSD_FORCE_ZAP=1 -e OSD_DMCRYPT=1 191 | # Encrypted OSD with dedicated journal: ceph_osd_docker_prepare_env: -e CLUSTER={{ cluster }} -e OSD_JOURNAL_SIZE={{ journal_size }} -e OSD_FORCE_ZAP=1 -e OSD_DMCRYPT=1 -e OSD_JOURNAL={{ raw_journal_devices[0] }} 192 | # 193 | ceph_osd_docker_devices: "{{ devices }}" 194 | ceph_osd_docker_prepare_env: -e CLUSTER={{ cluster }} -e OSD_JOURNAL_SIZE={{ journal_size }} -e OSD_FORCE_ZAP=1 195 | 196 | # ACTIVATE DEVICE 197 | # Examples: 198 | # Journal collocated or Dedicated journal: ceph_osd_docker_extra_env: -e CLUSTER={{ cluster }} -e CEPH_DAEMON=OSD_CEPH_DISK_ACTIVATE -e OSD_JOURNAL_SIZE={{ journal_size }} 199 | # Encrypted OSD or Encrypted OSD with dedicated journal: ceph_osd_docker_extra_env: -e CLUSTER={{ cluster }} -e CEPH_DAEMON=OSD_CEPH_DISK_ACTIVATE -e OSD_JOURNAL_SIZE={{ journal_size }} -e OSD_DMCRYPT=1 200 | # 201 | ceph_osd_docker_extra_env: -e CLUSTER={{ cluster }} -e CEPH_DAEMON=OSD_CEPH_DISK_ACTIVATE -e OSD_JOURNAL_SIZE={{ journal_size }} 202 | ceph_osd_docker_run_script_path: "/usr/share" # script called by systemd to run the docker command 203 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | -------------------------------------------------------------------------------- /roles/ceph-mds/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [2014] [Sébastien Han] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /roles/ceph-mon/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [2014] [Sébastien Han] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /roles/ceph-osd/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [2014] [Sébastien Han] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /roles/ceph-common/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [2014] [Sébastien Han] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------