Initial commit
This commit is contained in:
commit
03e1952419
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
lib
|
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
[submodule "mod/operator"]
|
||||
path = mod/operator
|
||||
url = https://github.com/canonical/operator
|
||||
[submodule "mod/interface-ceph-client"]
|
||||
path = mod/interface-ceph-client
|
||||
url = https://github.com/gnuoy/oper-interface-ceph-client.git
|
18
README.md
Normal file
18
README.md
Normal file
@ -0,0 +1,18 @@
|
||||
Ceph iSCSI Gateway charm
|
||||
========================
|
||||
|
||||
To use, first pull in dependencies:
|
||||
|
||||
```bash
|
||||
./charm-prep.sh
|
||||
```
|
||||
|
||||
To deploy with an example and test:
|
||||
|
||||
```bash
|
||||
cd test
|
||||
./deploy.sh
|
||||
./01-setup-client-apt.sh
|
||||
./02-setup-gw.sh
|
||||
./03-setup-client-iscsi.sh
|
||||
```
|
10
charm-prep.sh
Executable file
10
charm-prep.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
rm -rf lib/*
|
||||
|
||||
pip install -t lib/ git+https://github.com/juju/charm-helpers.git
|
||||
|
||||
git submodule init
|
||||
git submodule update
|
||||
(cd lib; ln -s ../mod/operator/ops;)
|
||||
(cd lib; ln -s ../mod/interface-ceph-client/interface_ceph_client.py;)
|
49
config.yaml
Normal file
49
config.yaml
Normal file
@ -0,0 +1,49 @@
|
||||
options:
|
||||
loglevel:
|
||||
default: 1
|
||||
type: int
|
||||
description: Mon and OSD debug level. Max is 20.
|
||||
source:
|
||||
type: string
|
||||
default:
|
||||
description: |
|
||||
Optional configuration to support use of additional sources such as:
|
||||
- ppa:myteam/ppa
|
||||
- cloud:trusty-proposed/kilo
|
||||
- http://my.archive.com/ubuntu main
|
||||
The last option should be used in conjunction with the key configuration
|
||||
option.
|
||||
Note that a minimum ceph version of 0.48.2 is required for use with this
|
||||
charm which is NOT provided by the packages in the main Ubuntu archive
|
||||
for precise but is provided in the Ubuntu cloud archive.
|
||||
key:
|
||||
type: string
|
||||
default:
|
||||
description: |
|
||||
Key ID to import to the apt keyring to support use with arbitary source
|
||||
configuration from outside of Launchpad archives or PPA's.
|
||||
use-syslog:
|
||||
type: boolean
|
||||
default: False
|
||||
description: |
|
||||
If set to True, supporting services will log to syslog.
|
||||
ceph-public-network:
|
||||
type: string
|
||||
default:
|
||||
description: |
|
||||
The IP address and netmask of the public (front-side) network (e.g.,
|
||||
192.168.0.0/24).
|
||||
If multiple networks are to be used, a space-delimited list of a.b.c.d/x
|
||||
can be provided.
|
||||
prefer-ipv6:
|
||||
type: boolean
|
||||
default: False
|
||||
description: |
|
||||
If True enables IPv6 support. The charm will expect network interfaces
|
||||
to be configured with an IPv6 address. If set to False (default) IPv4
|
||||
is expected.
|
||||
|
||||
NOTE: these charms do not currently support IPv6 privacy extension. In
|
||||
order for this charm to function correctly, the privacy extension must be
|
||||
disabled and a non-temporary address must be configured/available on
|
||||
your network interface.
|
1
hooks/install
Symbolic link
1
hooks/install
Symbolic link
@ -0,0 +1 @@
|
||||
../src/charm.py
|
19
metadata.yaml
Normal file
19
metadata.yaml
Normal file
@ -0,0 +1,19 @@
|
||||
name: ceph-iscsi
|
||||
summary: Gateway for provisioning iscsi devices backed by ceph.
|
||||
maintainer: OpenStack Charmers <openstack-charmers@lists.ubuntu.com>
|
||||
description: |
|
||||
The iSCSI gateway is integrating Ceph Storage with the iSCSI standard to
|
||||
provide a Highly Available (HA) iSCSI target that exports RADOS Block Device
|
||||
(RBD) images as SCSI disks.
|
||||
tags:
|
||||
- openstack
|
||||
- storage
|
||||
- misc
|
||||
series:
|
||||
- focal
|
||||
subordinate: false
|
||||
requires:
|
||||
ceph-client:
|
||||
interface: ceph-client
|
||||
extra-bindings:
|
||||
public:
|
1
mod/interface-ceph-client
Submodule
1
mod/interface-ceph-client
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 93b4661be184753038da626d3a04d3855f948430
|
1
mod/operator
Submodule
1
mod/operator
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 3a73427dee96f49acfe25880924528a3e57834cc
|
83
src/charm.py
Executable file
83
src/charm.py
Executable file
@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
sys.path.append('lib')
|
||||
|
||||
from ops.charm import CharmBase
|
||||
from ops.framework import (
|
||||
StoredState,
|
||||
)
|
||||
from ops.main import main
|
||||
from charmhelpers.fetch import (
|
||||
apt_install,
|
||||
apt_update,
|
||||
)
|
||||
import charmhelpers.core.host as ch_host
|
||||
import charmhelpers.core.templating as ch_templating
|
||||
import interface_ceph_client
|
||||
|
||||
|
||||
class CephISCSIGatewayCharm(CharmBase):
|
||||
state = StoredState()
|
||||
|
||||
PACKAGES = ['ceph-iscsi', 'tcmu-runner', 'ceph-common']
|
||||
CEPH_CAPABILITIES = [
|
||||
"osd", "allow *",
|
||||
"mon", "allow *",
|
||||
"mgr", "allow r"]
|
||||
|
||||
def __init__(self, framework, key):
|
||||
super().__init__(framework, key)
|
||||
self.framework.observe(self.on.install, self)
|
||||
self.framework.observe(self.on.ceph_client_relation_joined, self)
|
||||
self.ceph_client = interface_ceph_client.CephClientRequires(
|
||||
self,
|
||||
'ceph-client')
|
||||
self.framework.observe(self.ceph_client.on.pools_available, self)
|
||||
|
||||
def on_install(self, event):
|
||||
apt_update(fatal=True)
|
||||
apt_install(self.PACKAGES, fatal=True)
|
||||
|
||||
def on_ceph_client_relation_joined(self, event):
|
||||
self.ceph_client.create_replicated_pool('rbd')
|
||||
self.ceph_client.request_ceph_permissions(
|
||||
'ceph-iscsi',
|
||||
self.CEPH_CAPABILITIES)
|
||||
|
||||
def on_pools_available(self, event):
|
||||
ceph_context = {
|
||||
'use_syslog':
|
||||
str(self.framework.model.config['use-syslog']).lower(),
|
||||
'loglevel': self.framework.model.config['loglevel']
|
||||
}
|
||||
ceph_context.update(self.ceph_client.get_pool_data())
|
||||
ceph_context['mon_hosts'] = ' '.join(ceph_context['mon_hosts'])
|
||||
|
||||
restart_map = {
|
||||
'/etc/ceph/ceph.conf': ['rbd-target-api'],
|
||||
'/etc/ceph/iscsi-gateway.cfg': ['rbd-target-api'],
|
||||
'/etc/ceph/ceph.client.ceph-iscsi.keyring': ['rbd-target-api']}
|
||||
|
||||
def daemon_reload_and_restart(service_name):
|
||||
subprocess.check_call(['systemctl', 'daemon-reload'])
|
||||
subprocess.check_call(['systemctl', 'restart', service_name])
|
||||
|
||||
rfuncs = {
|
||||
'rbd-target-api': daemon_reload_and_restart}
|
||||
|
||||
@ch_host.restart_on_change(restart_map, restart_functions=rfuncs)
|
||||
def render_configs():
|
||||
for config_file in restart_map.keys():
|
||||
ch_templating.render(
|
||||
os.path.basename(config_file),
|
||||
config_file,
|
||||
ceph_context)
|
||||
render_configs()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(CephISCSIGatewayCharm)
|
3
templates/ceph.client.ceph-iscsi.keyring
Normal file
3
templates/ceph.client.ceph-iscsi.keyring
Normal file
@ -0,0 +1,3 @@
|
||||
[client.ceph-iscsi]
|
||||
key = {{ key }}
|
||||
|
15
templates/ceph.conf
Normal file
15
templates/ceph.conf
Normal file
@ -0,0 +1,15 @@
|
||||
###############################################################################
|
||||
# [ WARNING ]
|
||||
# configuration file maintained by Juju
|
||||
# local changes will be overwritten.
|
||||
###############################################################################
|
||||
[global]
|
||||
auth_supported = {{ auth_supported }}
|
||||
mon host = {{ mon_hosts }}
|
||||
keyring = /etc/ceph/$cluster.$name.keyring
|
||||
|
||||
[client.ceph-iscsi]
|
||||
client mount uid = 0
|
||||
client mount gid = 0
|
||||
log file = /var/log/ceph/ceph-client.iscsi.log
|
||||
|
27
templates/iscsi-gateway.cfg
Normal file
27
templates/iscsi-gateway.cfg
Normal file
@ -0,0 +1,27 @@
|
||||
[config]
|
||||
# Name of the Ceph storage cluster. A suitable Ceph configuration file allowing
|
||||
# # access to the Ceph storage cluster from the gateway node is required, if not
|
||||
# # colocated on an OSD node.
|
||||
logger_level = DEBUG
|
||||
cluster_name = ceph
|
||||
cluster_client_name = client.ceph-iscsi
|
||||
#
|
||||
# # Place a copy of the ceph cluster's admin keyring in the gateway's /etc/ceph
|
||||
# # drectory and reference the filename here
|
||||
#gateway_keyring = ceph.client.admin.keyring
|
||||
gateway_keyring = ceph.client.ceph-iscsi.keyring
|
||||
#
|
||||
#
|
||||
# # API settings.
|
||||
# # The API supports a number of options that allow you to tailor it to your
|
||||
# # local environment. If you want to run the API under https, you will need to
|
||||
# # create cert/key files that are compatible for each iSCSI gateway node, that is
|
||||
# # not locked to a specific node. SSL cert and key files *must* be called
|
||||
# # 'iscsi-gateway.crt' and 'iscsi-gateway.key' and placed in the '/etc/ceph/' directory
|
||||
# # on *each* gateway node. With the SSL files in place, you can use 'api_secure = true'
|
||||
# # to switch to https mode.
|
||||
#
|
||||
# # To support the API, the bear minimum settings are:
|
||||
api_secure = false
|
||||
#
|
||||
#
|
13
test-requirements.txt
Normal file
13
test-requirements.txt
Normal file
@ -0,0 +1,13 @@
|
||||
# This file is managed centrally. If you find the need to modify this as a
|
||||
# one-off, please don't. Intead, consult #openstack-charms and ask about
|
||||
# requirements management in charms via bot-control. Thank you.
|
||||
#
|
||||
# Lint and unit test requirements
|
||||
flake8>=2.2.4,<=2.4.1
|
||||
stestr>=2.2.0
|
||||
requests>=2.18.4
|
||||
charms.reactive
|
||||
mock>=1.2
|
||||
nose>=1.3.7
|
||||
coverage>=3.6
|
||||
git+https://github.com/openstack/charms.openstack.git#egg=charms.openstack
|
7
tests/01-setup-client-apt.sh
Executable file
7
tests/01-setup-client-apt.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
client="ubuntu/0"
|
||||
|
||||
juju run --unit $client "apt install --yes open-iscsi multipath-tools"
|
||||
juju run --unit $client "systemctl start iscsi"
|
||||
juju run --unit $client "systemctl start iscsid"
|
26
tests/02-setup-gw.sh
Executable file
26
tests/02-setup-gw.sh
Executable file
@ -0,0 +1,26 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
gw1="ceph-iscsi/0"
|
||||
gw2="ceph-iscsi/1"
|
||||
|
||||
gw1_hostname=$(juju run --unit $gw1 "hostname -f")
|
||||
gw2_hostname=$(juju run --unit $gw2 "hostname -f")
|
||||
gw1_ip=$(juju status $gw1 --format=oneline | awk '{print $3}' | tr -d \\n )
|
||||
gw2_ip=$(juju status $gw2 --format=oneline | awk '{print $3}' | tr -d \\n )
|
||||
client_initiatorname=$(juju run --unit ubuntu/0 "grep -E '^InitiatorName' /etc/iscsi/initiatorname.iscsi")
|
||||
client_initiatorname=$(echo $client_initiatorname | awk 'BEGIN {FS="="} {print $2}')
|
||||
echo "!$gw1_hostname!"
|
||||
echo "!$gw2_hostname!"
|
||||
echo "!$gw1_ip!"
|
||||
echo "!$gw2_ip!"
|
||||
echo "!$client_initiatorname!"
|
||||
|
||||
gw_iqn="iqn.2003-01.com.canonical.iscsi-gw:iscsi-igw"
|
||||
|
||||
juju run --unit $gw1 "gwcli /iscsi-targets/ create $gw_iqn"
|
||||
juju run --unit $gw1 "gwcli /iscsi-targets/${gw_iqn}/gateways create $gw1_hostname $gw1_ip skipchecks=true"
|
||||
juju run --unit $gw1 "gwcli /iscsi-targets/${gw_iqn}/gateways create $gw2_hostname $gw2_ip skipchecks=true"
|
||||
juju run --unit $gw1 "gwcli /disks create pool=rbd image=disk_1 size=1G"
|
||||
juju run --unit $gw1 "gwcli /iscsi-targets/${gw_iqn}/hosts create ${client_initiatorname}"
|
||||
juju run --unit $gw1 "gwcli /iscsi-targets/${gw_iqn}/hosts/${client_initiatorname} auth username=myiscsiusername password=myiscsipassword"
|
||||
juju run --unit $gw1 "gwcli /iscsi-targets/${gw_iqn}/hosts/${client_initiatorname} disk add rbd/disk_1"
|
18
tests/03-setup-client-iscsi.sh
Executable file
18
tests/03-setup-client-iscsi.sh
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
client="ubuntu/0"
|
||||
|
||||
gw1="ceph-iscsi/0"
|
||||
|
||||
gw1_ip=$(juju status $gw1 --format=oneline | awk '{print $3}' | tr -d \\n )
|
||||
|
||||
juju run --unit $client "iscsiadm -m discovery -t st -p $gw1_ip"
|
||||
|
||||
target_name="iqn.2003-01.com.canonical.iscsi-gw:iscsi-igw"
|
||||
|
||||
juju run --unit $client "iscsiadm --mode node --targetname ${target_name} --op=update --name node.session.auth.authmethod --value=CHAP"
|
||||
juju run --unit $client "iscsiadm --mode node --targetname ${target_name} --op=update --name node.session.auth.username --value=myiscsiusername"
|
||||
juju run --unit $client "iscsiadm --mode node --targetname ${target_name} --op=update --name node.session.auth.password --value=myiscsipassword"
|
||||
juju run --unit $client "iscsiadm --mode node --targetname ${target_name} --login"
|
||||
sleep 5
|
||||
juju ssh ubuntu/0 "ls -l /dev/dm-0"
|
1
tests/deploy.sh
Executable file
1
tests/deploy.sh
Executable file
@ -0,0 +1 @@
|
||||
juju deploy --force ./focal.yaml
|
28
tests/focal.yaml
Normal file
28
tests/focal.yaml
Normal file
@ -0,0 +1,28 @@
|
||||
series: bionic
|
||||
applications:
|
||||
ubuntu:
|
||||
charm: cs:ubuntu
|
||||
num_units: 1
|
||||
ceph-iscsi:
|
||||
charm: ../
|
||||
series: focal
|
||||
num_units: 2
|
||||
ceph-osd:
|
||||
charm: cs:~openstack-charmers-next/ceph-osd
|
||||
num_units: 3
|
||||
storage:
|
||||
osd-devices: 'cinder,10G'
|
||||
options:
|
||||
osd-devices: '/dev/test-non-existent'
|
||||
source: cloud:bionic-train
|
||||
ceph-mon:
|
||||
charm: cs:~openstack-charmers-next/ceph-mon
|
||||
num_units: 3
|
||||
options:
|
||||
monitor-count: '3'
|
||||
source: cloud:bionic-train
|
||||
relations:
|
||||
- - ceph-mon:client
|
||||
- ceph-iscsi:ceph-client
|
||||
- - ceph-osd:mon
|
||||
- ceph-mon:osd
|
92
tox.ini
Normal file
92
tox.ini
Normal file
@ -0,0 +1,92 @@
|
||||
# Source charm: ./tox.ini
|
||||
# This file is managed centrally by release-tools and should not be modified
|
||||
# within individual charm repos. See the 'global' dir contents for available
|
||||
# choices of tox.ini for OpenStack Charms:
|
||||
# https://github.com/openstack-charmers/release-tools
|
||||
|
||||
[tox]
|
||||
skipsdist = True
|
||||
envlist = pep8,py3
|
||||
# NOTE: Avoid build/test env pollution by not enabling sitepackages.
|
||||
sitepackages = False
|
||||
# NOTE: Avoid false positives by not skipping missing interpreters.
|
||||
skip_missing_interpreters = False
|
||||
|
||||
[testenv]
|
||||
setenv = VIRTUAL_ENV={envdir}
|
||||
PYTHONHASHSEED=0
|
||||
TERM=linux
|
||||
LAYER_PATH={toxinidir}/layers
|
||||
INTERFACE_PATH={toxinidir}/interfaces
|
||||
JUJU_REPOSITORY={toxinidir}/build
|
||||
passenv = http_proxy https_proxy INTERFACE_PATH LAYER_PATH JUJU_REPOSITORY
|
||||
install_command =
|
||||
pip install {opts} {packages}
|
||||
deps =
|
||||
-r{toxinidir}/requirements.txt
|
||||
|
||||
[testenv:build]
|
||||
basepython = python3
|
||||
commands =
|
||||
charm-build --log-level DEBUG -o {toxinidir}/build src {posargs}
|
||||
|
||||
[testenv:py3]
|
||||
basepython = python3
|
||||
deps = -r{toxinidir}/test-requirements.txt
|
||||
commands = stestr run --slowest {posargs}
|
||||
|
||||
[testenv:py35]
|
||||
basepython = python3.5
|
||||
deps = -r{toxinidir}/test-requirements.txt
|
||||
commands = stestr run --slowest {posargs}
|
||||
|
||||
[testenv:py36]
|
||||
basepython = python3.6
|
||||
deps = -r{toxinidir}/test-requirements.txt
|
||||
commands = stestr run --slowest {posargs}
|
||||
|
||||
[testenv:py37]
|
||||
basepython = python3.7
|
||||
deps = -r{toxinidir}/test-requirements.txt
|
||||
commands = stestr run --slowest {posargs}
|
||||
|
||||
[testenv:pep8]
|
||||
basepython = python3
|
||||
deps = -r{toxinidir}/test-requirements.txt
|
||||
commands = flake8 {posargs} src unit_tests
|
||||
|
||||
[testenv:cover]
|
||||
# Technique based heavily upon
|
||||
# https://github.com/openstack/nova/blob/master/tox.ini
|
||||
basepython = python3
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
setenv =
|
||||
{[testenv]setenv}
|
||||
PYTHON=coverage run
|
||||
commands =
|
||||
coverage erase
|
||||
stestr run --slowest {posargs}
|
||||
coverage combine
|
||||
coverage html -d cover
|
||||
coverage xml -o cover/coverage.xml
|
||||
coverage report
|
||||
|
||||
[coverage:run]
|
||||
branch = True
|
||||
concurrency = multiprocessing
|
||||
parallel = True
|
||||
source =
|
||||
.
|
||||
omit =
|
||||
.tox/*
|
||||
*/charmhelpers/*
|
||||
unit_tests/*
|
||||
|
||||
[testenv:venv]
|
||||
basepython = python3
|
||||
commands = {posargs}
|
||||
|
||||
[flake8]
|
||||
# E402 ignore necessary for path append before sys module import in actions
|
||||
ignore = E402,W504
|
Loading…
x
Reference in New Issue
Block a user