Minor tweak to copyright
This commit is contained in:
commit
b183a9d41f
|
@ -0,0 +1,2 @@
|
||||||
|
.project
|
||||||
|
.pydevproject
|
|
@ -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.
|
|
@ -0,0 +1,5 @@
|
||||||
|
RADOS Gateway Charm
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
* cephx support
|
||||||
|
* Improved process control of radosgw daemon (to many restarts)
|
|
@ -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.
|
|
@ -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'
|
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/sh
|
||||||
|
exec /usr/bin/radosgw -c /etc/ceph/ceph.conf -n client.rados.gateway
|
|
@ -0,0 +1 @@
|
||||||
|
hooks.py
|
|
@ -0,0 +1 @@
|
||||||
|
hooks.py
|
|
@ -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)
|
|
@ -0,0 +1 @@
|
||||||
|
hooks.py
|
|
@ -0,0 +1 @@
|
||||||
|
hooks.py
|
|
@ -0,0 +1 @@
|
||||||
|
hooks.py
|
|
@ -0,0 +1 @@
|
||||||
|
hooks.py
|
|
@ -0,0 +1 @@
|
||||||
|
hooks.py
|
|
@ -0,0 +1 @@
|
||||||
|
hooks.py
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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…
Reference in New Issue