Minor tweak to copyright
This commit is contained in:
commit
b183a9d41f
2
.bzrignore
Normal file
2
.bzrignore
Normal file
@ -0,0 +1,2 @@
|
||||
.project
|
||||
.pydevproject
|
58
README
Normal file
58
README
Normal file
@ -0,0 +1,58 @@
|
||||
Overview
|
||||
========
|
||||
|
||||
Ceph is a distributed storage and network file system designed to provide
|
||||
excellent performance, reliability, and scalability.
|
||||
|
||||
This charm deploys the RADOS Gateway, a S3 and Swift compatible HTTP gateway
|
||||
for online object storage on-top of a ceph cluster.
|
||||
|
||||
This charm only supports the S3 gateway at this point in time.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
In order to use this charm, it assumed that you have already deployed a ceph
|
||||
storage cluster using the 'ceph' charm with something like this::
|
||||
|
||||
juju deploy -n 3 --config ceph.yaml ceph
|
||||
|
||||
To deploy the RADOS gateway simple do::
|
||||
|
||||
juju deploy ceph-radosgw
|
||||
juju add-relation ceph-radosgw ceph
|
||||
|
||||
You can then directly access the RADOS gateway by exposing the service::
|
||||
|
||||
juju expose ceph-radosgw
|
||||
|
||||
The gateway can be accessed over port 80 (as show in juju status exposed
|
||||
ports).
|
||||
|
||||
Note that you will need to login to one of the service units supporting the
|
||||
ceph-radosgw charm to generate some access credentials::
|
||||
|
||||
radosgw-admin user create --uid="ubuntu" --display-name="Ubuntu Ceph"
|
||||
|
||||
Scale-out
|
||||
=========
|
||||
|
||||
Its possible to scale-out the RADOS Gateway itself::
|
||||
|
||||
juju add-unit -n 2 ceph-radosgw
|
||||
|
||||
and then stick a HA loadbalancer on the front::
|
||||
|
||||
juju deploy haproxy
|
||||
juju add-relation haproxy ceph-radosgw
|
||||
|
||||
Should give you a bit more bang on the front end if you really need it.
|
||||
|
||||
Bootnotes
|
||||
=========
|
||||
|
||||
The Ceph RADOS Gateway makes use of a multiverse package,
|
||||
libapache2-mod-fastcgi. As such it will try to automatically enable the
|
||||
multiverse pocket in /etc/apt/sources.list. Note that there is noting
|
||||
'wrong' with multiverse components - they typically have less liberal
|
||||
licensing policies or suchlike.
|
5
TODO
Normal file
5
TODO
Normal file
@ -0,0 +1,5 @@
|
||||
RADOS Gateway Charm
|
||||
-------------------
|
||||
|
||||
* cephx support
|
||||
* Improved process control of radosgw daemon (to many restarts)
|
22
config.yaml
Normal file
22
config.yaml
Normal file
@ -0,0 +1,22 @@
|
||||
options:
|
||||
source:
|
||||
type: string
|
||||
default: ppa:ceph-ubuntu/dev
|
||||
description: |
|
||||
Optional configuration to support use of additional sources such as:
|
||||
.
|
||||
- ppa:myteam/ppa
|
||||
- cloud:folsom-proposed
|
||||
- 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.
|
||||
key:
|
||||
type: string
|
||||
description: |
|
||||
Key ID to import to the apt keyring to support use with arbitary source
|
||||
configuration from outside of Launchpad archives or PPA's.
|
9
copyright
Normal file
9
copyright
Normal file
@ -0,0 +1,9 @@
|
||||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0
|
||||
|
||||
Files: *
|
||||
Copyright: 2012, Canonical Ltd.
|
||||
License: LGPL-2.1
|
||||
|
||||
License: LGPL-2.1
|
||||
On Debian GNU/Linux system you can find the complete text of the
|
||||
LGPL-2.1 license in '/usr/share/common-licenses/LGPL-2.1'
|
2
files/www/s3gw.fcgi
Executable file
2
files/www/s3gw.fcgi
Executable file
@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
exec /usr/bin/radosgw -c /etc/ceph/ceph.conf -n client.rados.gateway
|
1
hooks/config-changed
Symbolic link
1
hooks/config-changed
Symbolic link
@ -0,0 +1 @@
|
||||
hooks.py
|
1
hooks/gateway-relation-joined
Symbolic link
1
hooks/gateway-relation-joined
Symbolic link
@ -0,0 +1 @@
|
||||
hooks.py
|
139
hooks/hooks.py
Executable file
139
hooks/hooks.py
Executable file
@ -0,0 +1,139 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
#
|
||||
# Copyright 2012 Canonical Ltd.
|
||||
#
|
||||
# Authors:
|
||||
# James Page <james.page@ubuntu.com>
|
||||
#
|
||||
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import glob
|
||||
import os
|
||||
|
||||
import utils
|
||||
|
||||
|
||||
def install_www_scripts():
|
||||
for x in glob.glob('files/www/*'):
|
||||
shutil.copy(x, '/var/www/')
|
||||
|
||||
|
||||
def install():
|
||||
utils.juju_log('INFO', 'Begin install hook.')
|
||||
utils.enable_pocket('multiverse')
|
||||
utils.configure_source()
|
||||
utils.install('radosgw',
|
||||
'libapache2-mod-fastcgi',
|
||||
'apache2')
|
||||
utils.juju_log('INFO', 'End install hook.')
|
||||
|
||||
|
||||
def emit_cephconf():
|
||||
# Ensure ceph directory actually exists
|
||||
if not os.path.exists('/etc/ceph'):
|
||||
os.makedirs('/etc/ceph')
|
||||
|
||||
cephcontext = {
|
||||
'mon_hosts': ' '.join(get_mon_hosts()),
|
||||
'hostname': utils.get_unit_hostname()
|
||||
}
|
||||
|
||||
with open('/etc/ceph/ceph.conf', 'w') as cephconf:
|
||||
cephconf.write(utils.render_template('ceph.conf', cephcontext))
|
||||
|
||||
|
||||
def emit_apacheconf():
|
||||
apachecontext = {
|
||||
"hostname": utils.unit_get('private-address')
|
||||
}
|
||||
with open('/etc/apache2/sites-available/rgw', 'w') as apacheconf:
|
||||
apacheconf.write(utils.render_template('rgw', apachecontext))
|
||||
|
||||
|
||||
def apache_sites():
|
||||
utils.juju_log('INFO', 'Begin apache_sites.')
|
||||
subprocess.check_call(['a2dissite', 'default'])
|
||||
subprocess.check_call(['a2ensite', 'rgw'])
|
||||
utils.juju_log('INFO', 'End apache_sites.')
|
||||
|
||||
|
||||
def apache_modules():
|
||||
utils.juju_log('INFO', 'Begin apache_sites.')
|
||||
subprocess.check_call(['a2enmod', 'fastcgi'])
|
||||
subprocess.check_call(['a2enmod', 'rewrite'])
|
||||
utils.juju_log('INFO', 'End apache_sites.')
|
||||
|
||||
|
||||
def apache_reload():
|
||||
subprocess.call(['service', 'apache2', 'reload'])
|
||||
|
||||
|
||||
def config_changed():
|
||||
utils.juju_log('INFO', 'Begin config-changed hook.')
|
||||
emit_cephconf()
|
||||
emit_apacheconf()
|
||||
install_www_scripts()
|
||||
apache_sites()
|
||||
apache_modules()
|
||||
apache_reload()
|
||||
utils.juju_log('INFO', 'End config-changed hook.')
|
||||
|
||||
|
||||
def get_mon_hosts():
|
||||
hosts = []
|
||||
for relid in utils.relation_ids('mon'):
|
||||
for unit in utils.relation_list(relid):
|
||||
hosts.append(
|
||||
'{}:6789'.format(utils.get_host_ip(
|
||||
utils.relation_get('private-address',
|
||||
unit, relid)))
|
||||
)
|
||||
|
||||
hosts.sort()
|
||||
return hosts
|
||||
|
||||
|
||||
def mon_relation():
|
||||
utils.juju_log('INFO', 'Begin mon-relation hook.')
|
||||
emit_cephconf()
|
||||
restart()
|
||||
utils.juju_log('INFO', 'End mon-relation hook.')
|
||||
|
||||
|
||||
def gateway_relation():
|
||||
utils.juju_log('INFO', 'Begin gateway-relation hook.')
|
||||
utils.relation_set(hostname=utils.unit_get('private-address'),
|
||||
port=80)
|
||||
utils.juju_log('INFO', 'Begin gateway-relation hook.')
|
||||
|
||||
|
||||
def upgrade_charm():
|
||||
utils.juju_log('INFO', 'Begin upgrade-charm hook.')
|
||||
utils.juju_log('INFO', 'End upgrade-charm hook.')
|
||||
|
||||
|
||||
def start():
|
||||
# In case we're being redeployed to the same machines, try
|
||||
# to make sure everything is running as soon as possible.
|
||||
subprocess.call(['service', 'radosgw', 'start'])
|
||||
utils.expose(port=80)
|
||||
|
||||
|
||||
def restart():
|
||||
subprocess.call(['service', 'radosgw', 'restart'])
|
||||
|
||||
|
||||
utils.do_hooks({
|
||||
'install': install,
|
||||
'config-changed': config_changed,
|
||||
'mon-relation-departed': mon_relation,
|
||||
'mon-relation-changed': mon_relation,
|
||||
'gateway-relation-joined': gateway_relation,
|
||||
'start': start,
|
||||
'upgrade-charm': config_changed, # same function ATM
|
||||
})
|
||||
|
||||
sys.exit(0)
|
1
hooks/install
Symbolic link
1
hooks/install
Symbolic link
@ -0,0 +1 @@
|
||||
hooks.py
|
1
hooks/mon-relation-changed
Symbolic link
1
hooks/mon-relation-changed
Symbolic link
@ -0,0 +1 @@
|
||||
hooks.py
|
1
hooks/mon-relation-departed
Symbolic link
1
hooks/mon-relation-departed
Symbolic link
@ -0,0 +1 @@
|
||||
hooks.py
|
1
hooks/start
Symbolic link
1
hooks/start
Symbolic link
@ -0,0 +1 @@
|
||||
hooks.py
|
1
hooks/stop
Symbolic link
1
hooks/stop
Symbolic link
@ -0,0 +1 @@
|
||||
hooks.py
|
1
hooks/upgrade-charm
Symbolic link
1
hooks/upgrade-charm
Symbolic link
@ -0,0 +1 @@
|
||||
hooks.py
|
177
hooks/utils.py
Normal file
177
hooks/utils.py
Normal file
@ -0,0 +1,177 @@
|
||||
|
||||
#
|
||||
# Copyright 2012 Canonical Ltd.
|
||||
#
|
||||
# Authors:
|
||||
# James Page <james.page@ubuntu.com>
|
||||
# Paul Collins <paul.collins@canonical.com>
|
||||
#
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import socket
|
||||
import sys
|
||||
import re
|
||||
|
||||
|
||||
def do_hooks(hooks):
|
||||
hook = os.path.basename(sys.argv[0])
|
||||
|
||||
try:
|
||||
hooks[hook]()
|
||||
except KeyError:
|
||||
juju_log('INFO',
|
||||
"This charm doesn't know how to handle '{}'.".format(hook))
|
||||
|
||||
|
||||
def install(*pkgs):
|
||||
cmd = [
|
||||
'apt-get',
|
||||
'-y',
|
||||
'install'
|
||||
]
|
||||
for pkg in pkgs:
|
||||
cmd.append(pkg)
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
TEMPLATES_DIR = 'templates'
|
||||
|
||||
try:
|
||||
import jinja2
|
||||
except ImportError:
|
||||
install('python-jinja2')
|
||||
import jinja2
|
||||
|
||||
|
||||
def render_template(template_name, context, template_dir=TEMPLATES_DIR):
|
||||
templates = jinja2.Environment(
|
||||
loader=jinja2.FileSystemLoader(template_dir)
|
||||
)
|
||||
template = templates.get_template(template_name)
|
||||
return template.render(context)
|
||||
|
||||
|
||||
def configure_source():
|
||||
source = config_get('source')
|
||||
if (source.startswith('ppa:') or
|
||||
source.startswith('cloud:') or
|
||||
source.startswith('http:')):
|
||||
cmd = [
|
||||
'add-apt-repository',
|
||||
source
|
||||
]
|
||||
subprocess.check_call(cmd)
|
||||
if source.startswith('http:'):
|
||||
key = config_get('key')
|
||||
cmd = [
|
||||
'apt-key',
|
||||
'import',
|
||||
key
|
||||
]
|
||||
subprocess.check_call(cmd)
|
||||
cmd = [
|
||||
'apt-get',
|
||||
'update'
|
||||
]
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
|
||||
def enable_pocket(pocket):
|
||||
apt_sources = "/etc/apt/sources.list"
|
||||
with open(apt_sources, "r") as sources:
|
||||
lines = sources.readlines()
|
||||
with open(apt_sources, "w") as sources:
|
||||
for line in lines:
|
||||
if pocket in line:
|
||||
sources.write(re.sub('^# deb', 'deb', line))
|
||||
else:
|
||||
sources.write(line)
|
||||
|
||||
|
||||
# Protocols
|
||||
TCP = 'TCP'
|
||||
UDP = 'UDP'
|
||||
|
||||
|
||||
def expose(port, protocol='TCP'):
|
||||
cmd = [
|
||||
'open-port',
|
||||
'{}/{}'.format(port, protocol)
|
||||
]
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
|
||||
def juju_log(severity, message):
|
||||
cmd = [
|
||||
'juju-log',
|
||||
'--log-level', severity,
|
||||
message
|
||||
]
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
|
||||
def relation_ids(relation):
|
||||
cmd = [
|
||||
'relation-ids',
|
||||
relation
|
||||
]
|
||||
return subprocess.check_output(cmd).split() # IGNORE:E1103
|
||||
|
||||
|
||||
def relation_list(rid):
|
||||
cmd = [
|
||||
'relation-list',
|
||||
'-r', rid,
|
||||
]
|
||||
return subprocess.check_output(cmd).split() # IGNORE:E1103
|
||||
|
||||
|
||||
def relation_get(attribute, unit=None, rid=None):
|
||||
cmd = [
|
||||
'relation-get',
|
||||
]
|
||||
if rid:
|
||||
cmd.append('-r')
|
||||
cmd.append(rid)
|
||||
cmd.append(attribute)
|
||||
if unit:
|
||||
cmd.append(unit)
|
||||
return subprocess.check_output(cmd).strip() # IGNORE:E1103
|
||||
|
||||
|
||||
def relation_set(**kwargs):
|
||||
cmd = [
|
||||
'relation-set'
|
||||
]
|
||||
for k, v in kwargs.items():
|
||||
cmd.append('{}={}'.format(k, v))
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
|
||||
def unit_get(attribute):
|
||||
cmd = [
|
||||
'unit-get',
|
||||
attribute
|
||||
]
|
||||
return subprocess.check_output(cmd).strip() # IGNORE:E1103
|
||||
|
||||
|
||||
def config_get(attribute):
|
||||
cmd = [
|
||||
'config-get',
|
||||
attribute
|
||||
]
|
||||
return subprocess.check_output(cmd).strip() # IGNORE:E1103
|
||||
|
||||
|
||||
def get_unit_hostname():
|
||||
return socket.gethostname()
|
||||
|
||||
|
||||
def get_host_ip(hostname=unit_get('private-address')):
|
||||
cmd = [
|
||||
'dig',
|
||||
'+short',
|
||||
hostname
|
||||
]
|
||||
return subprocess.check_output(cmd).strip() # IGNORE:E1103
|
15
metadata.yaml
Normal file
15
metadata.yaml
Normal file
@ -0,0 +1,15 @@
|
||||
name: ceph-radosgw
|
||||
summary: Highly scalable distributed storage - RADOS HTTP Gateway
|
||||
maintainer: James Page <james.page@ubuntu.com>
|
||||
description: |
|
||||
Ceph is a distributed storage and network file system designed to provide
|
||||
excellent performance, reliability, and scalability.
|
||||
.
|
||||
This charm provides the RADOS HTTP gateway supporting S3 and Swift protocols
|
||||
for object storage.
|
||||
requires:
|
||||
mon:
|
||||
interface: ceph-radosgw
|
||||
provides:
|
||||
gateway:
|
||||
interface: http
|
9
templates/ceph.conf
Normal file
9
templates/ceph.conf
Normal file
@ -0,0 +1,9 @@
|
||||
[global]
|
||||
auth supported = none
|
||||
mon host = {{ mon_hosts }}
|
||||
|
||||
[client.radosgw.gateway]
|
||||
host = {{ hostname }}
|
||||
keyring = /etc/ceph/keyring.rados.gateway
|
||||
rgw socket path = /tmp/radosgw.sock
|
||||
log file = /var/log/ceph/radosgw.log
|
25
templates/rgw
Normal file
25
templates/rgw
Normal file
@ -0,0 +1,25 @@
|
||||
<IfModule mod_fastcgi.c>
|
||||
FastCgiExternalServer /var/www/s3gw.fcgi -socket /tmp/radosgw.sock
|
||||
</IfModule>
|
||||
|
||||
<VirtualHost *:80>
|
||||
ServerName {{ hostname }}
|
||||
ServerAdmin ceph@ubuntu.com
|
||||
DocumentRoot /var/www
|
||||
RewriteEngine On
|
||||
RewriteRule ^/([a-zA-Z0-9-_.]*)([/]?.*) /s3gw.fcgi?page=$1¶ms=$2&%{QUERY_STRING} [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
|
||||
<IfModule mod_fastcgi.c>
|
||||
<Directory /var/www>
|
||||
Options +ExecCGI
|
||||
AllowOverride All
|
||||
SetHandler fastcgi-script
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
AuthBasicAuthoritative Off
|
||||
</Directory>
|
||||
</IfModule>
|
||||
AllowEncodedSlashes On
|
||||
ErrorLog /var/log/apache2/error.log
|
||||
CustomLog /var/log/apache2/access.log combined
|
||||
ServerSignature Off
|
||||
</VirtualHost>
|
Loading…
x
Reference in New Issue
Block a user