Minor tweak to copyright

This commit is contained in:
James Page 2012-10-08 16:58:16 +01:00
commit b183a9d41f
20 changed files with 472 additions and 0 deletions

2
.bzrignore Normal file
View File

@ -0,0 +1,2 @@
.project
.pydevproject

58
README Normal file
View 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
View File

@ -0,0 +1,5 @@
RADOS Gateway Charm
-------------------
* cephx support
* Improved process control of radosgw daemon (to many restarts)

22
config.yaml Normal file
View 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
View 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
View 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
View File

@ -0,0 +1 @@
hooks.py

View File

@ -0,0 +1 @@
hooks.py

139
hooks/hooks.py Executable file
View 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
View File

@ -0,0 +1 @@
hooks.py

1
hooks/mon-relation-changed Symbolic link
View File

@ -0,0 +1 @@
hooks.py

1
hooks/mon-relation-departed Symbolic link
View File

@ -0,0 +1 @@
hooks.py

1
hooks/start Symbolic link
View File

@ -0,0 +1 @@
hooks.py

1
hooks/stop Symbolic link
View File

@ -0,0 +1 @@
hooks.py

1
hooks/upgrade-charm Symbolic link
View File

@ -0,0 +1 @@
hooks.py

177
hooks/utils.py Normal file
View 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
View 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

1
revision Normal file
View File

@ -0,0 +1 @@
11

9
templates/ceph.conf Normal file
View 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
View 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&params=$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>