nearing install
This commit is contained in:
parent
a08a3ca71e
commit
f961745319
104
config.yaml
104
config.yaml
@ -1,14 +1,100 @@
|
||||
options:
|
||||
string-option:
|
||||
loglevel:
|
||||
default: 1
|
||||
type: int
|
||||
description: OSD debug level. Max is 20.
|
||||
source:
|
||||
type: string
|
||||
default: "Default Value"
|
||||
description: "A short description of the configuration option"
|
||||
boolean-option:
|
||||
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: "A short description of the configuration option"
|
||||
int-option:
|
||||
type: int
|
||||
default: 9001
|
||||
description: "A short description of the configuration option"
|
||||
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.
|
||||
ceph-cluster-network:
|
||||
type: string
|
||||
default:
|
||||
description: |
|
||||
The IP address and netmask of the cluster (back-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.
|
||||
sysctl:
|
||||
type: string
|
||||
default: '{ kernel.pid_max : 2097152, vm.max_map_count : 524288,
|
||||
kernel.threads-max: 2097152 }'
|
||||
description: |
|
||||
YAML-formatted associative array of sysctl key/value pairs to be set
|
||||
persistently. By default we set pid_max, max_map_count and
|
||||
threads-max to a high value to avoid problems with large numbers (>20)
|
||||
of OSDs recovering. very large clusters should set those values even
|
||||
higher (e.g. max for kernel.pid_max is 4194303).
|
||||
nagios_context:
|
||||
type: string
|
||||
default: "juju"
|
||||
type: string
|
||||
description: |
|
||||
Used by the nrpe-external-master subordinate charm.
|
||||
A string that will be prepended to instance name to set the host name
|
||||
in nagios. So for instance the hostname would be something like:
|
||||
juju-myservice-0
|
||||
If you're running multiple environments with the same services in them
|
||||
this allows you to differentiate between them.
|
||||
nagios_servicegroups:
|
||||
default: ""
|
||||
type: string
|
||||
description: |
|
||||
A comma-separated list of nagios servicegroups.
|
||||
If left empty, the nagios_context will be used as the servicegroup
|
||||
use-direct-io:
|
||||
default: True
|
||||
type: boolean
|
||||
description: Configure use of direct IO for OSD journals.
|
||||
harden:
|
||||
default:
|
||||
type: string
|
||||
description: |
|
||||
Apply system hardening. Supports a space-delimited list of modules
|
||||
to run. Supported modules currently include os, ssh, apache and mysql.
|
||||
|
||||
|
693
icon.svg
693
icon.svg
@ -1,279 +1,414 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="96"
|
||||
height="96"
|
||||
id="svg6517"
|
||||
version="1.1"
|
||||
inkscape:version="0.48+devel r12274"
|
||||
sodipodi:docname="Juju_charm_icon_template.svg">
|
||||
<defs
|
||||
id="defs6519">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#Background"
|
||||
id="linearGradient6461"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="0"
|
||||
y1="970.29498"
|
||||
x2="144"
|
||||
y2="970.29498"
|
||||
gradientTransform="matrix(0,-0.66666669,0.6660448,0,-866.25992,731.29077)" />
|
||||
<linearGradient
|
||||
id="Background">
|
||||
<stop
|
||||
id="stop4178"
|
||||
offset="0"
|
||||
style="stop-color:#b8b8b8;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop4180"
|
||||
offset="1"
|
||||
style="stop-color:#c9c9c9;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB;"
|
||||
inkscape:label="Inner Shadow"
|
||||
id="filter1121">
|
||||
<feFlood
|
||||
flood-opacity="0.59999999999999998"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
id="feFlood1123" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="out"
|
||||
result="composite1"
|
||||
id="feComposite1125" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="1"
|
||||
result="blur"
|
||||
id="feGaussianBlur1127" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="2"
|
||||
result="offset"
|
||||
id="feOffset1129" />
|
||||
<feComposite
|
||||
in="offset"
|
||||
in2="SourceGraphic"
|
||||
operator="atop"
|
||||
result="composite2"
|
||||
id="feComposite1131" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB;"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter950">
|
||||
<feFlood
|
||||
flood-opacity="0.25"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
id="feFlood952" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite954" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="1"
|
||||
result="blur"
|
||||
id="feGaussianBlur956" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="1"
|
||||
result="offset"
|
||||
id="feOffset958" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="composite2"
|
||||
id="feComposite960" />
|
||||
</filter>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath873">
|
||||
<g
|
||||
transform="matrix(0,-0.66666667,0.66604479,0,-258.25992,677.00001)"
|
||||
id="g875"
|
||||
inkscape:label="Layer 1"
|
||||
style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline">
|
||||
<path
|
||||
style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline"
|
||||
d="m 46.702703,898.22775 50.594594,0 C 138.16216,898.22775 144,904.06497 144,944.92583 l 0,50.73846 c 0,40.86071 -5.83784,46.69791 -46.702703,46.69791 l -50.594594,0 C 5.8378378,1042.3622 0,1036.525 0,995.66429 L 0,944.92583 C 0,904.06497 5.8378378,898.22775 46.702703,898.22775 Z"
|
||||
id="path877"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="sssssssss" />
|
||||
</g>
|
||||
</clipPath>
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
id="filter891"
|
||||
inkscape:label="Badge Shadow">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.71999962"
|
||||
id="feGaussianBlur893" />
|
||||
</filter>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="4.0745362"
|
||||
inkscape:cx="18.514671"
|
||||
inkscape:cy="49.018169"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1029"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="1"
|
||||
showborder="true"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:showpageshadow="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid821" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="16,48"
|
||||
id="guide823" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="64,80"
|
||||
id="guide825" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="80,40"
|
||||
id="guide827" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="64,16"
|
||||
id="guide829" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata6522">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="BACKGROUND"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(268,-635.29076)"
|
||||
style="display:inline">
|
||||
<path
|
||||
style="fill:url(#linearGradient6461);fill-opacity:1;stroke:none;display:inline;filter:url(#filter1121)"
|
||||
d="m -268,700.15563 0,-33.72973 c 0,-27.24324 3.88785,-31.13513 31.10302,-31.13513 l 33.79408,0 c 27.21507,0 31.1029,3.89189 31.1029,31.13513 l 0,33.72973 c 0,27.24325 -3.88783,31.13514 -31.1029,31.13514 l -33.79408,0 C -264.11215,731.29077 -268,727.39888 -268,700.15563 Z"
|
||||
id="path6455"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="sssssssss" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer3"
|
||||
inkscape:label="PLACE YOUR PICTOGRAM HERE"
|
||||
style="display:inline" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="BADGE"
|
||||
style="display:none"
|
||||
sodipodi:insensitive="true">
|
||||
<g
|
||||
style="display:inline"
|
||||
transform="translate(-340.00001,-581)"
|
||||
id="g4394"
|
||||
clip-path="none">
|
||||
<g
|
||||
id="g855">
|
||||
<g
|
||||
inkscape:groupmode="maskhelper"
|
||||
id="g870"
|
||||
clip-path="url(#clipPath873)"
|
||||
style="opacity:0.6;filter:url(#filter891)">
|
||||
<path
|
||||
transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-237.54282)"
|
||||
d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"
|
||||
sodipodi:ry="12"
|
||||
sodipodi:rx="12"
|
||||
sodipodi:cy="552.36218"
|
||||
sodipodi:cx="252"
|
||||
id="path844"
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
sodipodi:type="arc" />
|
||||
</g>
|
||||
<g
|
||||
id="g862">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="color:#000000;fill:#f5f5f5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="path4398"
|
||||
sodipodi:cx="252"
|
||||
sodipodi:cy="552.36218"
|
||||
sodipodi:rx="12"
|
||||
sodipodi:ry="12"
|
||||
d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"
|
||||
transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-238.54282)" />
|
||||
<path
|
||||
transform="matrix(1.25,0,0,1.25,33,-100.45273)"
|
||||
d="m 264,552.36218 a 12,12 0 1 1 -24,0 A 12,12 0 1 1 264,552.36218 Z"
|
||||
sodipodi:ry="12"
|
||||
sodipodi:rx="12"
|
||||
sodipodi:cy="552.36218"
|
||||
sodipodi:cx="252"
|
||||
id="path4400"
|
||||
style="color:#000000;fill:#dd4814;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="color:#000000;fill:#f5f5f5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="path4459"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="666.19574"
|
||||
sodipodi:cy="589.50385"
|
||||
sodipodi:r1="7.2431178"
|
||||
sodipodi:r2="4.3458705"
|
||||
sodipodi:arg1="1.0471976"
|
||||
sodipodi:arg2="1.6755161"
|
||||
inkscape:flatsided="false"
|
||||
inkscape:rounded="0.1"
|
||||
inkscape:randomized="0"
|
||||
d="m 669.8173,595.77657 c -0.39132,0.22593 -3.62645,-1.90343 -4.07583,-1.95066 -0.44938,-0.0472 -4.05653,1.36297 -4.39232,1.06062 -0.3358,-0.30235 0.68963,-4.03715 0.59569,-4.47913 -0.0939,-0.44198 -2.5498,-3.43681 -2.36602,-3.8496 0.18379,-0.41279 4.05267,-0.59166 4.44398,-0.81759 0.39132,-0.22593 2.48067,-3.48704 2.93005,-3.4398 0.44938,0.0472 1.81505,3.67147 2.15084,3.97382 0.3358,0.30236 4.08294,1.2817 4.17689,1.72369 0.0939,0.44198 -2.9309,2.86076 -3.11469,3.27355 C 669.9821,591.68426 670.20862,595.55064 669.8173,595.77657 Z"
|
||||
transform="matrix(1.511423,-0.16366377,0.16366377,1.511423,-755.37346,-191.93651)" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="96"
|
||||
height="96"
|
||||
id="svg6517"
|
||||
version="1.1"
|
||||
inkscape:version="0.48+devel r12304"
|
||||
sodipodi:docname="ceph01.svg.2013_04_25_16_07_37.0.svg">
|
||||
<defs
|
||||
id="defs6519">
|
||||
<linearGradient
|
||||
id="Background">
|
||||
<stop
|
||||
id="stop4178"
|
||||
offset="0"
|
||||
style="stop-color:#22779e;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop4180"
|
||||
offset="1"
|
||||
style="stop-color:#2991c0;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB;"
|
||||
inkscape:label="Inner Shadow"
|
||||
id="filter1121">
|
||||
<feFlood
|
||||
flood-opacity="0.59999999999999998"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
id="feFlood1123" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="out"
|
||||
result="composite1"
|
||||
id="feComposite1125" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="1"
|
||||
result="blur"
|
||||
id="feGaussianBlur1127" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="2"
|
||||
result="offset"
|
||||
id="feOffset1129" />
|
||||
<feComposite
|
||||
in="offset"
|
||||
in2="SourceGraphic"
|
||||
operator="atop"
|
||||
result="composite2"
|
||||
id="feComposite1131" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB;"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter950">
|
||||
<feFlood
|
||||
flood-opacity="0.25"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
id="feFlood952" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite954" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="1"
|
||||
result="blur"
|
||||
id="feGaussianBlur956" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="1"
|
||||
result="offset"
|
||||
id="feOffset958" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="composite2"
|
||||
id="feComposite960" />
|
||||
</filter>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath873">
|
||||
<g
|
||||
transform="matrix(0,-0.66666667,0.66604479,0,-258.25992,677.00001)"
|
||||
id="g875"
|
||||
inkscape:label="Layer 1"
|
||||
style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline">
|
||||
<path
|
||||
style="fill:#ff00ff;fill-opacity:1;stroke:none;display:inline"
|
||||
d="m 46.702703,898.22775 50.594594,0 C 138.16216,898.22775 144,904.06497 144,944.92583 l 0,50.73846 c 0,40.86071 -5.83784,46.69791 -46.702703,46.69791 l -50.594594,0 C 5.8378378,1042.3622 0,1036.525 0,995.66429 L 0,944.92583 C 0,904.06497 5.8378378,898.22775 46.702703,898.22775 Z"
|
||||
id="path877"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="sssssssss" />
|
||||
</g>
|
||||
</clipPath>
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
id="filter891"
|
||||
inkscape:label="Badge Shadow">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.71999962"
|
||||
id="feGaussianBlur893" />
|
||||
</filter>
|
||||
<style
|
||||
id="style867"
|
||||
type="text/css"><![CDATA[
|
||||
.fil0 {fill:#1F1A17}
|
||||
]]></style>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4439"
|
||||
id="linearGradient908"
|
||||
x1="-220"
|
||||
y1="731.29077"
|
||||
x2="-220"
|
||||
y2="635.29077"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<clipPath
|
||||
id="clipPath16">
|
||||
<path
|
||||
id="path18"
|
||||
d="m -9,-9 614,0 0,231 -614,0 0,-231 z" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
id="clipPath116">
|
||||
<path
|
||||
id="path118"
|
||||
d="m 91.7368,146.3253 -9.7039,-1.577 -8.8548,-3.8814 -7.5206,-4.7308 -7.1566,-8.7335 -4.0431,-4.282 -3.9093,-1.4409 -1.034,2.5271 1.8079,2.6096 0.4062,3.6802 1.211,-0.0488 1.3232,-1.2069 -0.3569,3.7488 -1.4667,0.9839 0.0445,1.4286 -3.4744,-1.9655 -3.1462,-3.712 -0.6559,-3.3176 1.3453,-2.6567 1.2549,-4.5133 2.5521,-1.2084 2.6847,0.1318 2.5455,1.4791 -1.698,-8.6122 1.698,-9.5825 -1.8692,-4.4246 -6.1223,-6.5965 1.0885,-3.941 2.9002,-4.5669 5.4688,-3.8486 2.9007,-0.3969 3.225,-0.1094 -2.012,-8.2601 7.3993,-3.0326 9.2188,-1.2129 3.1535,2.0619 0.2427,5.5797 3.5178,5.8224 0.2426,4.6094 8.4909,-0.6066 7.8843,0.7279 -7.8843,-4.7307 1.3343,-5.701 4.9731,-7.763 4.8521,-2.0622 3.8814,1.5769 1.577,3.1538 8.1269,6.1861 1.5769,-1.3343 12.7363,-0.485 2.5473,2.0619 0.2426,3.6391 -0.849,1.5767 -0.6066,9.8251 -4.2454,8.4909 0.7276,3.7605 2.5475,-1.3343 7.1566,-6.6716 3.5175,-0.2424 3.8815,1.5769 3.8818,2.9109 1.9406,6.3077 11.4021,-0.7277 6.914,2.6686 5.5797,5.2157 4.0028,7.5206 0.9706,8.8546 -0.8493,10.3105 -2.1832,9.2185 -2.1836,2.9112 -3.0322,0.9706 -5.3373,-5.8224 -4.8518,-1.6982 -4.2455,7.0353 -4.2454,3.8815 -2.3049,1.4556 -9.2185,7.6419 -7.3993,4.0028 -7.3993,0.6066 -8.6119,-1.4556 -7.5206,-2.7899 -5.2158,-4.2454 -4.1241,-4.9734 -4.2454,-1.2129" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
id="clipPath128">
|
||||
<path
|
||||
id="path130"
|
||||
d="m 91.7368,146.3253 -9.7039,-1.577 -8.8548,-3.8814 -7.5206,-4.7308 -7.1566,-8.7335 -4.0431,-4.282 -3.9093,-1.4409 -1.034,2.5271 1.8079,2.6096 0.4062,3.6802 1.211,-0.0488 1.3232,-1.2069 -0.3569,3.7488 -1.4667,0.9839 0.0445,1.4286 -3.4744,-1.9655 -3.1462,-3.712 -0.6559,-3.3176 1.3453,-2.6567 1.2549,-4.5133 2.5521,-1.2084 2.6847,0.1318 2.5455,1.4791 -1.698,-8.6122 1.698,-9.5825 -1.8692,-4.4246 -6.1223,-6.5965 1.0885,-3.941 2.9002,-4.5669 5.4688,-3.8486 2.9007,-0.3969 3.225,-0.1094 -2.012,-8.2601 7.3993,-3.0326 9.2188,-1.2129 3.1535,2.0619 0.2427,5.5797 3.5178,5.8224 0.2426,4.6094 8.4909,-0.6066 7.8843,0.7279 -7.8843,-4.7307 1.3343,-5.701 4.9731,-7.763 4.8521,-2.0622 3.8814,1.5769 1.577,3.1538 8.1269,6.1861 1.5769,-1.3343 12.7363,-0.485 2.5473,2.0619 0.2426,3.6391 -0.849,1.5767 -0.6066,9.8251 -4.2454,8.4909 0.7276,3.7605 2.5475,-1.3343 7.1566,-6.6716 3.5175,-0.2424 3.8815,1.5769 3.8818,2.9109 1.9406,6.3077 11.4021,-0.7277 6.914,2.6686 5.5797,5.2157 4.0028,7.5206 0.9706,8.8546 -0.8493,10.3105 -2.1832,9.2185 -2.1836,2.9112 -3.0322,0.9706 -5.3373,-5.8224 -4.8518,-1.6982 -4.2455,7.0353 -4.2454,3.8815 -2.3049,1.4556 -9.2185,7.6419 -7.3993,4.0028 -7.3993,0.6066 -8.6119,-1.4556 -7.5206,-2.7899 -5.2158,-4.2454 -4.1241,-4.9734 -4.2454,-1.2129" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
id="linearGradient3850"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop3852"
|
||||
offset="0"
|
||||
style="stop-color:#000000;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3854"
|
||||
offset="1"
|
||||
style="stop-color:#000000;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3095">
|
||||
<path
|
||||
d="m 976.648,389.551 -842.402,0 0,839.999 842.402,0 0,-839.999"
|
||||
id="path3097"
|
||||
inkscape:connector-curvature="0" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
id="linearGradient4439"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop4441"
|
||||
offset="0"
|
||||
style="stop-color:#e3e3e3;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop4443"
|
||||
offset="1"
|
||||
style="stop-color:#efefef;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3195">
|
||||
<path
|
||||
d="m 611.836,756.738 -106.34,105.207 c -8.473,8.289 -13.617,20.102 -13.598,33.379 L 598.301,790.207 c -0.031,-13.418 5.094,-25.031 13.535,-33.469"
|
||||
id="path3197"
|
||||
inkscape:connector-curvature="0" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3235">
|
||||
<path
|
||||
d="m 1095.64,1501.81 c 35.46,-35.07 70.89,-70.11 106.35,-105.17 4.4,-4.38 7.11,-10.53 7.11,-17.55 l -106.37,105.21 c 0,7 -2.71,13.11 -7.09,17.51"
|
||||
id="path3237"
|
||||
inkscape:connector-curvature="0" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
id="clipPath4591"
|
||||
clipPathUnits="userSpaceOnUse">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="m 1106.6009,730.43734 -0.036,21.648 c -0.01,3.50825 -2.8675,6.61375 -6.4037,6.92525 l -83.6503,7.33162 c -3.5205,0.30763 -6.3812,-2.29987 -6.3671,-5.8145 l 0.036,-21.6475 20.1171,-1.76662 -0.011,4.63775 c 0,1.83937 1.4844,3.19925 3.3262,3.0395 l 49.5274,-4.33975 c 1.8425,-0.166 3.3425,-1.78125 3.3538,-3.626 l 0.01,-4.63025 20.1,-1.7575"
|
||||
style="fill:#ff00ff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4593" />
|
||||
</clipPath>
|
||||
<radialGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-1.4333926,-2.2742838,1.1731823,-0.73941125,-174.08025,98.374394)"
|
||||
r="20.40658"
|
||||
fy="93.399292"
|
||||
fx="-26.508606"
|
||||
cy="93.399292"
|
||||
cx="-26.508606"
|
||||
id="radialGradient3856"
|
||||
xlink:href="#linearGradient3850"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
gradientTransform="translate(-318.48033,212.32022)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="993.19702"
|
||||
x2="-51.879555"
|
||||
y1="593.11615"
|
||||
x1="348.20132"
|
||||
id="linearGradient3895"
|
||||
xlink:href="#linearGradient3850"
|
||||
inkscape:collect="always" />
|
||||
<clipPath
|
||||
id="clipPath3906"
|
||||
clipPathUnits="userSpaceOnUse">
|
||||
<rect
|
||||
transform="scale(1,-1)"
|
||||
style="opacity:0.8;color:#000000;fill:#ff00ff;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="rect3908"
|
||||
width="1019.1371"
|
||||
height="1019.1371"
|
||||
x="357.9816"
|
||||
y="-1725.8152" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="3.2596289"
|
||||
inkscape:cx="55.171524"
|
||||
inkscape:cy="27.879339"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1029"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="1"
|
||||
showborder="true"
|
||||
showguides="false"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:snap-global="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="true"
|
||||
inkscape:snap-object-midpoints="true"
|
||||
inkscape:snap-center="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid821" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="16,48"
|
||||
id="guide823" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="64,80"
|
||||
id="guide825" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="80,40"
|
||||
id="guide827" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="64,16"
|
||||
id="guide829" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata6522">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="BACKGROUND"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(268,-635.29076)"
|
||||
style="display:inline">
|
||||
<path
|
||||
style="fill:url(#linearGradient908);fill-opacity:1.0;stroke:none;display:inline;filter:url(#filter1121)"
|
||||
d="m -268,700.15563 0,-33.72973 c 0,-27.24324 3.88785,-31.13513 31.10302,-31.13513 l 33.79408,0 c 27.21507,0 31.1029,3.89189 31.1029,31.13513 l 0,33.72973 c 0,27.24325 -3.88783,31.13514 -31.1029,31.13514 l -33.79408,0 C -264.11215,731.29077 -268,727.39888 -268,700.15563 Z"
|
||||
id="path6455"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="sssssssss" />
|
||||
<path
|
||||
style="color:#000000;fill:#f05c56;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:12;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 48 17 C 30.879173 17 17 30.879173 17 48 C 17 58.205647 21.921021 67.257453 29.53125 72.90625 C 31.106248 70.853104 31.792246 69.428164 32 68.65625 C 32.24185 67.75765 32.1873 67.60443 31.96875 66.875 C 31.775272 66.229265 30.9225 65.268196 29.5625 63.40625 C 29.543376 63.380067 29.519319 63.339038 29.5 63.3125 C 29.490587 63.301137 29.478142 63.29263 29.46875 63.28125 C 28.411032 61.999592 27.526437 60.578409 26.75 59.09375 C 25.013179 55.772698 24 52.007471 24 48 C 24 40.95011 27.065992 34.640853 31.90625 30.25 C 36.166391 26.385401 41.795056 24 48 24 C 54.213203 24 59.862908 26.376233 64.125 30.25 C 64.693279 30.766502 65.233498 31.306721 65.75 31.875 C 65.76468 31.891254 65.766619 31.92121 65.78125 31.9375 C 69.628213 36.193847 72 41.810964 72 48 C 72 53.79899 69.954991 59.132635 66.53125 63.28125 C 66.523757 63.291557 66.507464 63.302247 66.5 63.3125 C 66.476288 63.341126 66.461343 63.377737 66.4375 63.40625 C 65.0775 65.268196 64.224728 66.229265 64.03125 66.875 C 63.8127 67.60443 63.75815 67.75765 64 68.65625 C 64.207754 69.428164 64.893752 70.853104 66.46875 72.90625 C 74.078979 67.257453 79 58.205647 79 48 C 79 30.879173 65.120827 17 48 17 z M 48 30 C 44.47123 30.006 41.00461 31.05306 38.0625 33 C 29.81314 38.45904 27.5261 49.65783 32.96875 57.90625 C 32.97675 57.91845 32.992 57.9254 33 57.9375 C 34.69385 60.49644 36.81536 62.34977 37.65625 65.15625 C 38.417511 67.69696 38.464725 70.888363 34.6875 76 C 36.843125 77.026739 39.136156 77.803912 41.53125 78.3125 C 45.121429 72.505399 45.6 67.244681 44.375 63.15625 C 42.8785 58.16169 39.28615 54.78175 38.8125 54.0625 L 38.84375 54.0625 C 35.46092 48.96255 36.83156 42.19137 41.9375 38.8125 C 43.73298 37.62434 45.84671 37.00604 48 37 C 48.0104 37 48.02095 36.99997 48.03125 37 C 50.18163 37.006 52.26946 37.62456 54.0625 38.8125 C 59.16152 42.19075 60.56575 48.96347 57.1875 54.0625 C 56.71385 54.78175 53.1215 58.16169 51.625 63.15625 C 50.4 67.244681 50.878571 72.505399 54.46875 78.3125 C 56.863844 77.803912 59.156875 77.026739 61.3125 76 C 57.535275 70.888363 57.582489 67.69696 58.34375 65.15625 C 59.18464 62.34977 61.30615 60.49644 63 57.9375 C 68.46768 49.68475 66.19025 38.46769 57.9375 33 C 54.99872 31.05298 51.55602 30.00613 48.03125 30 C 48.0209 30.00003 48.0105 30 48 30 z M 48 43 C 45.238576 43 43 45.238576 43 48 C 43 50.761424 45.238576 53 48 53 C 50.761424 53 53 50.761424 53 48 C 53 45.238576 50.761424 43 48 43 z M 48 78.6875 C 47.94945 78.791177 47.895343 78.896359 47.84375 79 C 47.896122 79.00026 47.947567 79 48 79 C 48.052433 79 48.103878 79.00026 48.15625 79 C 48.104657 78.896359 48.05055 78.791177 48 78.6875 z "
|
||||
transform="translate(-268,635.29076)"
|
||||
id="path939" />
|
||||
<path
|
||||
style="color:#000000;fill:#dd322b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:12;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
d="M 48 17 C 30.879173 17 17 30.879173 17 48 C 17 48.125345 16.99852 48.250008 17 48.375 C 17.334303 31.543929 31.088903 18 48 18 C 64.911097 18 78.665697 31.543929 79 48.375 C 79.00148 48.250008 79 48.125345 79 48 C 79 30.879173 65.120827 17 48 17 z M 48 30 C 44.47123 30.006 41.00461 31.05306 38.0625 33 C 32.70971 36.542226 29.880485 42.49862 30.03125 48.5 C 30.204405 42.846736 33.009903 37.343572 38.0625 34 C 41.00461 32.05306 44.47123 31.006 48 31 C 48.0105 31 48.02105 31.00008 48.03125 31 C 51.55602 31.00613 54.99872 32.05298 57.9375 34 C 62.975581 37.337877 65.755795 42.827998 65.9375 48.46875 C 66.07621 42.48142 63.273758 36.535428 57.9375 33 C 54.99872 31.05298 51.55602 30.00613 48.03125 30 C 48.0209 30.00003 48.0105 30 48 30 z M 48 43 C 45.238576 43 43 45.238576 43 48 C 43 48.172589 43.01418 48.331915 43.03125 48.5 C 43.2873 45.978722 45.411169 44 48 44 C 50.588831 44 52.7127 45.978722 52.96875 48.5 C 52.98582 48.331915 53 48.172589 53 48 C 53 45.238576 50.761424 43 48 43 z M 24 48.375 C 23.994609 48.583358 24 48.790301 24 49 C 24 53.00747 25.01318 56.7727 26.75 60.09375 C 27.52644 61.57841 28.41103 62.99959 29.46875 64.28125 C 29.47805 64.29255 29.491 64.3011 29.5 64.3125 C 29.5193 64.339 29.5434 64.38005 29.5625 64.40625 C 30.9225 66.2682 31.77527 67.22927 31.96875 67.875 C 32.016575 68.034657 32.063023 68.162945 32.09375 68.28125 C 32.215432 67.710404 32.150661 67.482143 31.96875 66.875 C 31.775272 66.229265 30.9225 65.268196 29.5625 63.40625 C 29.543376 63.380067 29.519319 63.339038 29.5 63.3125 C 29.490587 63.301137 29.478142 63.29263 29.46875 63.28125 C 28.411032 61.999592 27.526437 60.578409 26.75 59.09375 C 25.067361 55.876301 24.060969 52.242622 24 48.375 z M 71.96875 48.375 C 71.881931 54.027547 69.880433 59.222978 66.53125 63.28125 C 66.523757 63.291557 66.507464 63.302247 66.5 63.3125 C 66.476288 63.341126 66.461343 63.377737 66.4375 63.40625 C 65.0775 65.268196 64.224728 66.229265 64.03125 66.875 C 63.849339 67.482143 63.784568 67.710404 63.90625 68.28125 C 63.936983 68.162945 63.983414 68.034657 64.03125 67.875 C 64.22473 67.22927 65.0775 66.2682 66.4375 64.40625 C 66.4613 64.37775 66.4763 64.3411 66.5 64.3125 C 66.5074 64.3023 66.52425 64.29155 66.53125 64.28125 C 69.95499 60.13264 72 54.79899 72 49 C 72 48.790781 71.974136 48.582881 71.96875 48.375 z M 37.03125 48.5625 C 36.950597 50.780966 37.510968 53.053199 38.84375 55.0625 L 38.8125 55.0625 C 39.28615 55.78175 42.8785 59.16169 44.375 64.15625 C 44.74962 65.406541 44.953039 66.767092 44.96875 68.21875 C 45.062756 66.388889 44.834375 64.689412 44.375 63.15625 C 42.8785 58.16169 39.28615 54.78175 38.8125 54.0625 L 38.84375 54.0625 C 37.712059 52.356364 37.137075 50.453131 37.03125 48.5625 z M 59 48.5625 C 58.899597 50.453201 58.317659 52.356672 57.1875 54.0625 C 56.71385 54.78175 53.1215 58.16169 51.625 63.15625 C 51.165625 64.689412 50.937244 66.388889 51.03125 68.21875 C 51.046961 66.767092 51.25038 65.406541 51.625 64.15625 C 53.1215 59.16169 56.71385 55.78175 57.1875 55.0625 C 58.518478 53.053561 59.087212 50.781084 59 48.5625 z M 38.03125 68.5 C 37.866539 70.476556 36.990243 72.883747 34.6875 76 C 34.858955 76.081665 35.045574 76.140252 35.21875 76.21875 C 37.469311 72.948813 38.106912 70.501999 38.03125 68.5 z M 57.96875 68.5 C 57.893088 70.501999 58.530689 72.948813 60.78125 76.21875 C 60.954426 76.140252 61.141045 76.081665 61.3125 76 C 59.009757 72.883747 58.133461 70.476556 57.96875 68.5 z M 48 78.6875 C 47.94945 78.791177 47.895343 78.896359 47.84375 79 C 47.896122 79.00026 47.947567 79 48 79 C 48.052433 79 48.103878 79.00026 48.15625 79 C 48.104657 78.896359 48.05055 78.791177 48 78.6875 z "
|
||||
transform="translate(-268,635.29076)"
|
||||
id="path899" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer3"
|
||||
inkscape:label="PLACE YOUR PICTOGRAM HERE"
|
||||
style="display:inline" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="BADGE"
|
||||
style="display:none"
|
||||
sodipodi:insensitive="true">
|
||||
<g
|
||||
style="display:inline"
|
||||
transform="translate(-340.00001,-581)"
|
||||
id="g4394"
|
||||
clip-path="none">
|
||||
<g
|
||||
id="g855">
|
||||
<g
|
||||
inkscape:groupmode="maskhelper"
|
||||
id="g870"
|
||||
clip-path="url(#clipPath873)"
|
||||
style="opacity:0.6;filter:url(#filter891)">
|
||||
<path
|
||||
transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-237.54282)"
|
||||
d="m 264,552.36218 c 0,6.62742 -5.37258,12 -12,12 -6.62742,0 -12,-5.37258 -12,-12 0,-6.62741 5.37258,-12 12,-12 C 258.62742,540.36218 264,545.73477 264,552.36218 Z"
|
||||
sodipodi:ry="12"
|
||||
sodipodi:rx="12"
|
||||
sodipodi:cy="552.36218"
|
||||
sodipodi:cx="252"
|
||||
id="path844"
|
||||
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
sodipodi:type="arc" />
|
||||
</g>
|
||||
<g
|
||||
id="g862">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="color:#000000;fill:#f5f5f5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="path4398"
|
||||
sodipodi:cx="252"
|
||||
sodipodi:cy="552.36218"
|
||||
sodipodi:rx="12"
|
||||
sodipodi:ry="12"
|
||||
d="m 264,552.36218 c 0,6.62742 -5.37258,12 -12,12 -6.62742,0 -12,-5.37258 -12,-12 0,-6.62741 5.37258,-12 12,-12 C 258.62742,540.36218 264,545.73477 264,552.36218 Z"
|
||||
transform="matrix(1.4999992,0,0,1.4999992,-29.999795,-238.54282)" />
|
||||
<path
|
||||
transform="matrix(1.25,0,0,1.25,33,-100.45273)"
|
||||
d="m 264,552.36218 c 0,6.62742 -5.37258,12 -12,12 -6.62742,0 -12,-5.37258 -12,-12 0,-6.62741 5.37258,-12 12,-12 C 258.62742,540.36218 264,545.73477 264,552.36218 Z"
|
||||
sodipodi:ry="12"
|
||||
sodipodi:rx="12"
|
||||
sodipodi:cy="552.36218"
|
||||
sodipodi:cx="252"
|
||||
id="path4400"
|
||||
style="color:#000000;fill:#dd4814;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="color:#000000;fill:#f5f5f5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||
id="path4459"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="666.19574"
|
||||
sodipodi:cy="589.50385"
|
||||
sodipodi:r1="7.2431178"
|
||||
sodipodi:r2="4.3458705"
|
||||
sodipodi:arg1="1.0471976"
|
||||
sodipodi:arg2="1.6755161"
|
||||
inkscape:flatsided="false"
|
||||
inkscape:rounded="0.1"
|
||||
inkscape:randomized="0"
|
||||
d="m 669.8173,595.77657 c -0.39132,0.22593 -3.62645,-1.90343 -4.07583,-1.95066 -0.44938,-0.0472 -4.05653,1.36297 -4.39232,1.06062 -0.3358,-0.30235 0.68963,-4.03715 0.59569,-4.47913 -0.0939,-0.44198 -2.5498,-3.43681 -2.36602,-3.8496 0.18379,-0.41279 4.05267,-0.59166 4.44398,-0.81759 0.39132,-0.22593 2.48067,-3.48704 2.93005,-3.4398 0.44938,0.0472 1.81505,3.67147 2.15084,3.97382 0.3358,0.30236 4.08294,1.2817 4.17689,1.72369 0.0939,0.44198 -2.9309,2.86076 -3.11469,3.27355 C 669.9821,591.68426 670.20862,595.55064 669.8173,595.77657 Z"
|
||||
transform="matrix(1.511423,-0.16366377,0.16366377,1.511423,-755.37346,-191.93651)" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 23 KiB |
@ -1 +1 @@
|
||||
includes: ['layer:basic'] # if you use any interfaces, add them here
|
||||
includes: ['layer:basic', 'layer:apt', 'interface:nrpe-external-master'] # if you use any interfaces, add them here
|
||||
|
998
lib/charms/ceph_base.py
Normal file
998
lib/charms/ceph_base.py
Normal file
@ -0,0 +1,998 @@
|
||||
|
||||
#
|
||||
# Copyright 2012-2016 Canonical Ltd.
|
||||
#
|
||||
# Authors:
|
||||
# James Page <james.page@ubuntu.com>
|
||||
# Paul Collins <paul.collins@canonical.com>
|
||||
# Chris MacNaughton <chris.macnaughton@canonical.com>
|
||||
#
|
||||
|
||||
# Imports from ceph.py
|
||||
import ctypes
|
||||
import ctypes.util
|
||||
import errno
|
||||
import json
|
||||
import subprocess
|
||||
import time
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import shutil
|
||||
from charmhelpers.cli.host import mounts
|
||||
from charmhelpers.core.host import (
|
||||
mkdir,
|
||||
chownr,
|
||||
cmp_pkgrevno,
|
||||
lsb_release,
|
||||
service_stop,
|
||||
service_restart)
|
||||
from charmhelpers.core.hookenv import (
|
||||
log,
|
||||
ERROR,
|
||||
WARNING,
|
||||
DEBUG,
|
||||
cached,
|
||||
status_set,
|
||||
)
|
||||
from charmhelpers.fetch import (
|
||||
apt_cache
|
||||
)
|
||||
from charmhelpers.contrib.storage.linux.utils import (
|
||||
zap_disk,
|
||||
is_block_device,
|
||||
is_device_mounted,
|
||||
)
|
||||
# from utils import (
|
||||
# get_unit_hostname,
|
||||
# )
|
||||
|
||||
# Imports from utils.py
|
||||
import socket
|
||||
import re
|
||||
from charmhelpers.core.hookenv import (
|
||||
unit_get,
|
||||
cached,
|
||||
config,
|
||||
status_set,
|
||||
)
|
||||
from charmhelpers.fetch import (
|
||||
apt_install,
|
||||
filter_installed_packages
|
||||
)
|
||||
|
||||
from charmhelpers.core.host import (
|
||||
lsb_release
|
||||
)
|
||||
|
||||
from charmhelpers.contrib.network.ip import (
|
||||
get_address_in_network,
|
||||
get_ipv6_addr
|
||||
)
|
||||
|
||||
# try:
|
||||
# import dns.resolver
|
||||
# except ImportError:
|
||||
# apt_install(filter_installed_packages(['python-dnspython']),
|
||||
# fatal=True)
|
||||
# import dns.resolver
|
||||
import dns.resolver
|
||||
### This is migrated from hooks/utils.py
|
||||
|
||||
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)
|
||||
|
||||
|
||||
@cached
|
||||
def get_unit_hostname():
|
||||
return socket.gethostname()
|
||||
|
||||
|
||||
@cached
|
||||
def get_host_ip(hostname=None):
|
||||
if config('prefer-ipv6'):
|
||||
return get_ipv6_addr()[0]
|
||||
|
||||
hostname = hostname or unit_get('private-address')
|
||||
try:
|
||||
# Test to see if already an IPv4 address
|
||||
socket.inet_aton(hostname)
|
||||
return hostname
|
||||
except socket.error:
|
||||
# This may throw an NXDOMAIN exception; in which case
|
||||
# things are badly broken so just let it kill the hook
|
||||
answers = dns.resolver.query(hostname, 'A')
|
||||
if answers:
|
||||
return answers[0].address
|
||||
|
||||
|
||||
def get_networks(config_opt='ceph-public-network'):
|
||||
"""Get all configured networks from provided config option.
|
||||
|
||||
If public network(s) are provided, go through them and return those for
|
||||
which we have an address configured.
|
||||
"""
|
||||
networks = config(config_opt)
|
||||
if networks:
|
||||
networks = networks.split()
|
||||
return [n for n in networks if get_address_in_network(n)]
|
||||
|
||||
return []
|
||||
|
||||
|
||||
def get_public_addr():
|
||||
return get_network_addrs('ceph-public-network')[0]
|
||||
|
||||
|
||||
def get_network_addrs(config_opt):
|
||||
"""Get all configured public networks addresses.
|
||||
|
||||
If public network(s) are provided, go through them and return the
|
||||
addresses we have configured on any of those networks.
|
||||
"""
|
||||
addrs = []
|
||||
networks = config(config_opt)
|
||||
if networks:
|
||||
networks = networks.split()
|
||||
addrs = [get_address_in_network(n) for n in networks]
|
||||
addrs = [a for a in addrs if a]
|
||||
|
||||
if not addrs:
|
||||
if networks:
|
||||
msg = ("Could not find an address on any of '%s' - resolve this "
|
||||
"error to retry" % (networks))
|
||||
status_set('blocked', msg)
|
||||
raise Exception(msg)
|
||||
else:
|
||||
return [get_host_ip()]
|
||||
|
||||
return addrs
|
||||
|
||||
|
||||
def assert_charm_supports_ipv6():
|
||||
"""Check whether we are able to support charms ipv6."""
|
||||
if lsb_release()['DISTRIB_CODENAME'].lower() < "trusty":
|
||||
raise Exception("IPv6 is not supported in the charms for Ubuntu "
|
||||
"versions less than Trusty 14.04")
|
||||
|
||||
|
||||
### This is migrated from hooks/ceph.py
|
||||
|
||||
LEADER = 'leader'
|
||||
PEON = 'peon'
|
||||
QUORUM = [LEADER, PEON]
|
||||
|
||||
PACKAGES = ['ceph', 'gdisk', 'ntp', 'btrfs-tools', 'python-ceph', 'xfsprogs']
|
||||
|
||||
|
||||
def ceph_user():
|
||||
if get_version() > 1:
|
||||
return 'ceph'
|
||||
else:
|
||||
return "root"
|
||||
|
||||
|
||||
class CrushLocation(object):
|
||||
def __init__(self,
|
||||
name,
|
||||
identifier,
|
||||
host,
|
||||
rack,
|
||||
row,
|
||||
datacenter,
|
||||
chassis,
|
||||
root):
|
||||
self.name = name
|
||||
self.identifier = identifier
|
||||
self.host = host
|
||||
self.rack = rack
|
||||
self.row = row
|
||||
self.datacenter = datacenter
|
||||
self.chassis = chassis
|
||||
self.root = root
|
||||
|
||||
def __str__(self):
|
||||
return "name: {} id: {} host: {} rack: {} row: {} datacenter: {} " \
|
||||
"chassis :{} root: {}".format(self.name, self.identifier,
|
||||
self.host, self.rack, self.row,
|
||||
self.datacenter, self.chassis,
|
||||
self.root)
|
||||
|
||||
def __eq__(self, other):
|
||||
return not self.name < other.name and not other.name < self.name
|
||||
|
||||
def __ne__(self, other):
|
||||
return self.name < other.name or other.name < self.name
|
||||
|
||||
def __gt__(self, other):
|
||||
return self.name > other.name
|
||||
|
||||
def __ge__(self, other):
|
||||
return not self.name < other.name
|
||||
|
||||
def __le__(self, other):
|
||||
return self.name < other.name
|
||||
|
||||
|
||||
def get_osd_tree(service):
|
||||
"""
|
||||
Returns the current osd map in JSON.
|
||||
:return: List. :raise: ValueError if the monmap fails to parse.
|
||||
Also raises CalledProcessError if our ceph command fails
|
||||
"""
|
||||
try:
|
||||
tree = subprocess.check_output(
|
||||
['ceph', '--id', service,
|
||||
'osd', 'tree', '--format=json'])
|
||||
try:
|
||||
json_tree = json.loads(tree)
|
||||
crush_list = []
|
||||
# Make sure children are present in the json
|
||||
if not json_tree['nodes']:
|
||||
return None
|
||||
child_ids = json_tree['nodes'][0]['children']
|
||||
for child in json_tree['nodes']:
|
||||
if child['id'] in child_ids:
|
||||
crush_list.append(
|
||||
CrushLocation(
|
||||
name=child.get('name'),
|
||||
identifier=child['id'],
|
||||
host=child.get('host'),
|
||||
rack=child.get('rack'),
|
||||
row=child.get('row'),
|
||||
datacenter=child.get('datacenter'),
|
||||
chassis=child.get('chassis'),
|
||||
root=child.get('root')
|
||||
)
|
||||
)
|
||||
return crush_list
|
||||
except ValueError as v:
|
||||
log("Unable to parse ceph tree json: {}. Error: {}".format(
|
||||
tree, v.message))
|
||||
raise
|
||||
except subprocess.CalledProcessError as e:
|
||||
log("ceph osd tree command failed with message: {}".format(
|
||||
e.message))
|
||||
raise
|
||||
|
||||
|
||||
def get_local_osd_ids():
|
||||
"""
|
||||
This will list the /var/lib/ceph/osd/* directories and try
|
||||
to split the ID off of the directory name and return it in
|
||||
a list
|
||||
|
||||
:return: list. A list of osd identifiers :raise: OSError if
|
||||
something goes wrong with listing the directory.
|
||||
"""
|
||||
osd_ids = []
|
||||
osd_path = os.path.join(os.sep, 'var', 'lib', 'ceph', 'osd')
|
||||
if os.path.exists(osd_path):
|
||||
try:
|
||||
dirs = os.listdir(osd_path)
|
||||
for osd_dir in dirs:
|
||||
osd_id = osd_dir.split('-')[1]
|
||||
osd_ids.append(osd_id)
|
||||
except OSError:
|
||||
raise
|
||||
return osd_ids
|
||||
|
||||
|
||||
def get_local_mon_ids():
|
||||
"""
|
||||
This will list the /var/lib/ceph/mon/* directories and try
|
||||
to split the ID off of the directory name and return it in
|
||||
a list
|
||||
|
||||
:return: list. A list of monitor identifiers :raise: OSError if
|
||||
something goes wrong with listing the directory.
|
||||
"""
|
||||
mon_ids = []
|
||||
mon_path = os.path.join(os.sep, 'var', 'lib', 'ceph', 'mon')
|
||||
if os.path.exists(mon_path):
|
||||
try:
|
||||
dirs = os.listdir(mon_path)
|
||||
for mon_dir in dirs:
|
||||
# Basically this takes everything after ceph- as the monitor ID
|
||||
match = re.search('ceph-(?P<mon_id>.*)', mon_dir)
|
||||
if match:
|
||||
mon_ids.append(match.group('mon_id'))
|
||||
except OSError:
|
||||
raise
|
||||
return mon_ids
|
||||
|
||||
|
||||
def get_version():
|
||||
'''Derive Ceph release from an installed package.'''
|
||||
import apt_pkg as apt
|
||||
|
||||
cache = apt_cache()
|
||||
package = "ceph"
|
||||
try:
|
||||
pkg = cache[package]
|
||||
except:
|
||||
# the package is unknown to the current apt cache.
|
||||
e = 'Could not determine version of package with no installation ' \
|
||||
'candidate: %s' % package
|
||||
error_out(e)
|
||||
|
||||
if not pkg.current_ver:
|
||||
# package is known, but no version is currently installed.
|
||||
e = 'Could not determine version of uninstalled package: %s' % package
|
||||
error_out(e)
|
||||
|
||||
vers = apt.upstream_version(pkg.current_ver.ver_str)
|
||||
|
||||
# x.y match only for 20XX.X
|
||||
# and ignore patch level for other packages
|
||||
match = re.match('^(\d+)\.(\d+)', vers)
|
||||
|
||||
if match:
|
||||
vers = match.group(0)
|
||||
return float(vers)
|
||||
|
||||
|
||||
def error_out(msg):
|
||||
log("FATAL ERROR: %s" % msg,
|
||||
level=ERROR)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def is_quorum():
|
||||
asok = "/var/run/ceph/ceph-mon.{}.asok".format(get_unit_hostname())
|
||||
cmd = [
|
||||
"sudo",
|
||||
"-u",
|
||||
ceph_user(),
|
||||
"ceph",
|
||||
"--admin-daemon",
|
||||
asok,
|
||||
"mon_status"
|
||||
]
|
||||
if os.path.exists(asok):
|
||||
try:
|
||||
result = json.loads(subprocess.check_output(cmd))
|
||||
except subprocess.CalledProcessError:
|
||||
return False
|
||||
except ValueError:
|
||||
# Non JSON response from mon_status
|
||||
return False
|
||||
if result['state'] in QUORUM:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def is_leader():
|
||||
asok = "/var/run/ceph/ceph-mon.{}.asok".format(get_unit_hostname())
|
||||
cmd = [
|
||||
"sudo",
|
||||
"-u",
|
||||
ceph_user(),
|
||||
"ceph",
|
||||
"--admin-daemon",
|
||||
asok,
|
||||
"mon_status"
|
||||
]
|
||||
if os.path.exists(asok):
|
||||
try:
|
||||
result = json.loads(subprocess.check_output(cmd))
|
||||
except subprocess.CalledProcessError:
|
||||
return False
|
||||
except ValueError:
|
||||
# Non JSON response from mon_status
|
||||
return False
|
||||
if result['state'] == LEADER:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def wait_for_quorum():
|
||||
while not is_quorum():
|
||||
time.sleep(3)
|
||||
|
||||
|
||||
def add_bootstrap_hint(peer):
|
||||
asok = "/var/run/ceph/ceph-mon.{}.asok".format(get_unit_hostname())
|
||||
cmd = [
|
||||
"sudo",
|
||||
"-u",
|
||||
ceph_user(),
|
||||
"ceph",
|
||||
"--admin-daemon",
|
||||
asok,
|
||||
"add_bootstrap_peer_hint",
|
||||
peer
|
||||
]
|
||||
if os.path.exists(asok):
|
||||
# Ignore any errors for this call
|
||||
subprocess.call(cmd)
|
||||
|
||||
|
||||
DISK_FORMATS = [
|
||||
'xfs',
|
||||
'ext4',
|
||||
'btrfs'
|
||||
]
|
||||
|
||||
CEPH_PARTITIONS = [
|
||||
'4FBD7E29-9D25-41B8-AFD0-5EC00CEFF05D', # ceph encrypted osd data
|
||||
'4FBD7E29-9D25-41B8-AFD0-062C0CEFF05D', # ceph osd data
|
||||
'45B0969E-9B03-4F30-B4C6-B4B80CEFF106', # ceph osd journal
|
||||
]
|
||||
|
||||
|
||||
def umount(mount_point):
|
||||
"""
|
||||
This function unmounts a mounted directory forcibly. This will
|
||||
be used for unmounting broken hard drive mounts which may hang.
|
||||
If umount returns EBUSY this will lazy unmount.
|
||||
:param mount_point: str. A String representing the filesystem mount point
|
||||
:return: int. Returns 0 on success. errno otherwise.
|
||||
"""
|
||||
libc_path = ctypes.util.find_library("c")
|
||||
libc = ctypes.CDLL(libc_path, use_errno=True)
|
||||
|
||||
# First try to umount with MNT_FORCE
|
||||
ret = libc.umount(mount_point, 1)
|
||||
if ret < 0:
|
||||
err = ctypes.get_errno()
|
||||
if err == errno.EBUSY:
|
||||
# Detach from try. IE lazy umount
|
||||
ret = libc.umount(mount_point, 2)
|
||||
if ret < 0:
|
||||
err = ctypes.get_errno()
|
||||
return err
|
||||
return 0
|
||||
else:
|
||||
return err
|
||||
return 0
|
||||
|
||||
|
||||
def replace_osd(dead_osd_number,
|
||||
dead_osd_device,
|
||||
new_osd_device,
|
||||
osd_format,
|
||||
osd_journal,
|
||||
reformat_osd=False,
|
||||
ignore_errors=False):
|
||||
"""
|
||||
This function will automate the replacement of a failed osd disk as much
|
||||
as possible. It will revoke the keys for the old osd, remove it from the
|
||||
crush map and then add a new osd into the cluster.
|
||||
:param dead_osd_number: The osd number found in ceph osd tree. Example: 99
|
||||
:param dead_osd_device: The physical device. Example: /dev/sda
|
||||
:param osd_format:
|
||||
:param osd_journal:
|
||||
:param reformat_osd:
|
||||
:param ignore_errors:
|
||||
"""
|
||||
host_mounts = mounts()
|
||||
mount_point = None
|
||||
for mount in host_mounts:
|
||||
if mount[1] == dead_osd_device:
|
||||
mount_point = mount[0]
|
||||
# need to convert dev to osd number
|
||||
# also need to get the mounted drive so we can tell the admin to
|
||||
# replace it
|
||||
try:
|
||||
# Drop this osd out of the cluster. This will begin a
|
||||
# rebalance operation
|
||||
status_set('maintenance', 'Removing osd {}'.format(dead_osd_number))
|
||||
subprocess.check_output(['ceph', 'osd', 'out',
|
||||
'osd.{}'.format(dead_osd_number)])
|
||||
|
||||
# Kill the osd process if it's not already dead
|
||||
if systemd():
|
||||
service_stop('ceph-osd@{}'.format(dead_osd_number))
|
||||
else:
|
||||
subprocess.check_output(['stop', 'ceph-osd', 'id={}'.format(
|
||||
dead_osd_number)]),
|
||||
# umount if still mounted
|
||||
ret = umount(mount_point)
|
||||
if ret < 0:
|
||||
raise RuntimeError('umount {} failed with error: {}'.format(
|
||||
mount_point, os.strerror(ret)))
|
||||
# Clean up the old mount point
|
||||
shutil.rmtree(mount_point)
|
||||
subprocess.check_output(['ceph', 'osd', 'crush', 'remove',
|
||||
'osd.{}'.format(dead_osd_number)])
|
||||
# Revoke the OSDs access keys
|
||||
subprocess.check_output(['ceph', 'auth', 'del',
|
||||
'osd.{}'.format(dead_osd_number)])
|
||||
subprocess.check_output(['ceph', 'osd', 'rm',
|
||||
'osd.{}'.format(dead_osd_number)])
|
||||
status_set('maintenance', 'Setting up replacement osd {}'.format(
|
||||
new_osd_device))
|
||||
osdize(new_osd_device,
|
||||
osd_format,
|
||||
osd_journal,
|
||||
reformat_osd,
|
||||
ignore_errors)
|
||||
except subprocess.CalledProcessError as e:
|
||||
log('replace_osd failed with error: ' + e.output)
|
||||
|
||||
|
||||
def is_osd_disk(dev):
|
||||
try:
|
||||
info = subprocess.check_output(['sgdisk', '-i', '1', dev])
|
||||
info = info.split("\n") # IGNORE:E1103
|
||||
for line in info:
|
||||
for ptype in CEPH_PARTITIONS:
|
||||
sig = 'Partition GUID code: {}'.format(ptype)
|
||||
if line.startswith(sig):
|
||||
return True
|
||||
except subprocess.CalledProcessError:
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
def start_osds(devices):
|
||||
# Scan for ceph block devices
|
||||
rescan_osd_devices()
|
||||
if cmp_pkgrevno('ceph', "0.56.6") >= 0:
|
||||
# Use ceph-disk activate for directory based OSD's
|
||||
for dev_or_path in devices:
|
||||
if os.path.exists(dev_or_path) and os.path.isdir(dev_or_path):
|
||||
subprocess.check_call(['ceph-disk', 'activate', dev_or_path])
|
||||
|
||||
|
||||
def rescan_osd_devices():
|
||||
cmd = [
|
||||
'udevadm', 'trigger',
|
||||
'--subsystem-match=block', '--action=add'
|
||||
]
|
||||
|
||||
subprocess.call(cmd)
|
||||
|
||||
|
||||
_bootstrap_keyring = "/var/lib/ceph/bootstrap-osd/ceph.keyring"
|
||||
_upgrade_keyring = "/var/lib/ceph/osd/ceph.client.osd-upgrade.keyring"
|
||||
|
||||
|
||||
def is_bootstrapped():
|
||||
return os.path.exists(_bootstrap_keyring)
|
||||
|
||||
|
||||
def wait_for_bootstrap():
|
||||
while (not is_bootstrapped()):
|
||||
time.sleep(3)
|
||||
|
||||
|
||||
def import_osd_bootstrap_key(key):
|
||||
if not os.path.exists(_bootstrap_keyring):
|
||||
cmd = [
|
||||
"sudo",
|
||||
"-u",
|
||||
ceph_user(),
|
||||
'ceph-authtool',
|
||||
_bootstrap_keyring,
|
||||
'--create-keyring',
|
||||
'--name=client.bootstrap-osd',
|
||||
'--add-key={}'.format(key)
|
||||
]
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
|
||||
def import_osd_upgrade_key(key):
|
||||
if not os.path.exists(_upgrade_keyring):
|
||||
cmd = [
|
||||
"sudo",
|
||||
"-u",
|
||||
ceph_user(),
|
||||
'ceph-authtool',
|
||||
_upgrade_keyring,
|
||||
'--create-keyring',
|
||||
'--name=client.osd-upgrade',
|
||||
'--add-key={}'.format(key)
|
||||
]
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
|
||||
def generate_monitor_secret():
|
||||
cmd = [
|
||||
'ceph-authtool',
|
||||
'/dev/stdout',
|
||||
'--name=mon.',
|
||||
'--gen-key'
|
||||
]
|
||||
res = subprocess.check_output(cmd)
|
||||
|
||||
return "{}==".format(res.split('=')[1].strip())
|
||||
|
||||
|
||||
# OSD caps taken from ceph-create-keys
|
||||
_osd_bootstrap_caps = {
|
||||
'mon': [
|
||||
'allow command osd create ...',
|
||||
'allow command osd crush set ...',
|
||||
r'allow command auth add * osd allow\ * mon allow\ rwx',
|
||||
'allow command mon getmap'
|
||||
]
|
||||
}
|
||||
|
||||
_osd_bootstrap_caps_profile = {
|
||||
'mon': [
|
||||
'allow profile bootstrap-osd'
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def parse_key(raw_key):
|
||||
# get-or-create appears to have different output depending
|
||||
# on whether its 'get' or 'create'
|
||||
# 'create' just returns the key, 'get' is more verbose and
|
||||
# needs parsing
|
||||
key = None
|
||||
if len(raw_key.splitlines()) == 1:
|
||||
key = raw_key
|
||||
else:
|
||||
for element in raw_key.splitlines():
|
||||
if 'key' in element:
|
||||
key = element.split(' = ')[1].strip() # IGNORE:E1103
|
||||
return key
|
||||
|
||||
|
||||
def get_osd_bootstrap_key():
|
||||
try:
|
||||
# Attempt to get/create a key using the OSD bootstrap profile first
|
||||
key = get_named_key('bootstrap-osd',
|
||||
_osd_bootstrap_caps_profile)
|
||||
except:
|
||||
# If that fails try with the older style permissions
|
||||
key = get_named_key('bootstrap-osd',
|
||||
_osd_bootstrap_caps)
|
||||
return key
|
||||
|
||||
|
||||
_radosgw_keyring = "/etc/ceph/keyring.rados.gateway"
|
||||
|
||||
|
||||
def import_radosgw_key(key):
|
||||
if not os.path.exists(_radosgw_keyring):
|
||||
cmd = [
|
||||
"sudo",
|
||||
"-u",
|
||||
ceph_user(),
|
||||
'ceph-authtool',
|
||||
_radosgw_keyring,
|
||||
'--create-keyring',
|
||||
'--name=client.radosgw.gateway',
|
||||
'--add-key={}'.format(key)
|
||||
]
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
# OSD caps taken from ceph-create-keys
|
||||
_radosgw_caps = {
|
||||
'mon': ['allow rw'],
|
||||
'osd': ['allow rwx']
|
||||
}
|
||||
_upgrade_caps = {
|
||||
'mon': ['allow rwx']
|
||||
}
|
||||
|
||||
def get_radosgw_key():
|
||||
return get_named_key('radosgw.gateway', _radosgw_caps)
|
||||
|
||||
|
||||
_default_caps = {
|
||||
'mon': ['allow rw'],
|
||||
'osd': ['allow rwx']
|
||||
}
|
||||
admin_caps = {
|
||||
'mds': ['allow'],
|
||||
'mon': ['allow *'],
|
||||
'osd': ['allow *']
|
||||
}
|
||||
osd_upgrade_caps = {
|
||||
'mon': ['allow command "config-key"',
|
||||
'allow command "osd tree"',
|
||||
'allow command "config-key list"',
|
||||
'allow command "config-key put"',
|
||||
'allow command "config-key get"',
|
||||
'allow command "config-key exists"',
|
||||
]
|
||||
}
|
||||
def get_upgrade_key():
|
||||
return get_named_key('upgrade-osd', _upgrade_caps)
|
||||
|
||||
|
||||
def get_named_key(name, caps=None):
|
||||
caps = caps or _default_caps
|
||||
cmd = [
|
||||
"sudo",
|
||||
"-u",
|
||||
ceph_user(),
|
||||
'ceph',
|
||||
'--name', 'mon.',
|
||||
'--keyring',
|
||||
'/var/lib/ceph/mon/ceph-{}/keyring'.format(
|
||||
get_unit_hostname()
|
||||
),
|
||||
'auth', 'get-or-create', 'client.{}'.format(name),
|
||||
]
|
||||
# Add capabilities
|
||||
for subsystem, subcaps in caps.iteritems():
|
||||
cmd.extend([
|
||||
subsystem,
|
||||
'; '.join(subcaps),
|
||||
])
|
||||
return parse_key(subprocess.check_output(cmd).strip()) # IGNORE:E1103
|
||||
|
||||
|
||||
def upgrade_key_caps(key, caps):
|
||||
""" Upgrade key to have capabilities caps """
|
||||
if not is_leader():
|
||||
# Not the MON leader OR not clustered
|
||||
return
|
||||
cmd = [
|
||||
"sudo", "-u", ceph_user(), 'ceph', 'auth', 'caps', key
|
||||
]
|
||||
for subsystem, subcaps in caps.iteritems():
|
||||
cmd.extend([subsystem, '; '.join(subcaps)])
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
|
||||
@cached
|
||||
def systemd():
|
||||
return (lsb_release()['DISTRIB_CODENAME'] >= 'vivid')
|
||||
|
||||
|
||||
def bootstrap_monitor_cluster(secret):
|
||||
hostname = get_unit_hostname()
|
||||
path = '/var/lib/ceph/mon/ceph-{}'.format(hostname)
|
||||
done = '{}/done'.format(path)
|
||||
if systemd():
|
||||
init_marker = '{}/systemd'.format(path)
|
||||
else:
|
||||
init_marker = '{}/upstart'.format(path)
|
||||
|
||||
keyring = '/var/lib/ceph/tmp/{}.mon.keyring'.format(hostname)
|
||||
|
||||
if os.path.exists(done):
|
||||
log('bootstrap_monitor_cluster: mon already initialized.')
|
||||
else:
|
||||
# Ceph >= 0.61.3 needs this for ceph-mon fs creation
|
||||
mkdir('/var/run/ceph', owner=ceph_user(),
|
||||
group=ceph_user(), perms=0o755)
|
||||
mkdir(path, owner=ceph_user(), group=ceph_user())
|
||||
# end changes for Ceph >= 0.61.3
|
||||
try:
|
||||
subprocess.check_call(['ceph-authtool', keyring,
|
||||
'--create-keyring', '--name=mon.',
|
||||
'--add-key={}'.format(secret),
|
||||
'--cap', 'mon', 'allow *'])
|
||||
|
||||
subprocess.check_call(['ceph-mon', '--mkfs',
|
||||
'-i', hostname,
|
||||
'--keyring', keyring])
|
||||
chownr(path, ceph_user(), ceph_user())
|
||||
with open(done, 'w'):
|
||||
pass
|
||||
with open(init_marker, 'w'):
|
||||
pass
|
||||
|
||||
if systemd():
|
||||
subprocess.check_call(['systemctl', 'enable', 'ceph-mon'])
|
||||
service_restart('ceph-mon')
|
||||
else:
|
||||
service_restart('ceph-mon-all')
|
||||
except:
|
||||
raise
|
||||
finally:
|
||||
os.unlink(keyring)
|
||||
|
||||
|
||||
def update_monfs():
|
||||
hostname = get_unit_hostname()
|
||||
monfs = '/var/lib/ceph/mon/ceph-{}'.format(hostname)
|
||||
if systemd():
|
||||
init_marker = '{}/systemd'.format(monfs)
|
||||
else:
|
||||
init_marker = '{}/upstart'.format(monfs)
|
||||
if os.path.exists(monfs) and not os.path.exists(init_marker):
|
||||
# Mark mon as managed by upstart so that
|
||||
# it gets start correctly on reboots
|
||||
with open(init_marker, 'w'):
|
||||
pass
|
||||
|
||||
|
||||
def maybe_zap_journal(journal_dev):
|
||||
if is_osd_disk(journal_dev):
|
||||
log('Looks like {} is already an OSD data'
|
||||
' or journal, skipping.'.format(journal_dev))
|
||||
return
|
||||
zap_disk(journal_dev)
|
||||
log("Zapped journal device {}".format(journal_dev))
|
||||
|
||||
|
||||
def get_partitions(dev):
|
||||
cmd = ['partx', '--raw', '--noheadings', dev]
|
||||
try:
|
||||
out = subprocess.check_output(cmd).splitlines()
|
||||
log("get partitions: {}".format(out), level=DEBUG)
|
||||
return out
|
||||
except subprocess.CalledProcessError as e:
|
||||
log("Can't get info for {0}: {1}".format(dev, e.output))
|
||||
return []
|
||||
|
||||
|
||||
def find_least_used_journal(journal_devices):
|
||||
usages = map(lambda a: (len(get_partitions(a)), a), journal_devices)
|
||||
least = min(usages, key=lambda t: t[0])
|
||||
return least[1]
|
||||
|
||||
|
||||
def osdize(dev, osd_format, osd_journal, reformat_osd=False,
|
||||
ignore_errors=False, encrypt=False):
|
||||
if dev.startswith('/dev'):
|
||||
osdize_dev(dev, osd_format, osd_journal,
|
||||
reformat_osd, ignore_errors, encrypt)
|
||||
else:
|
||||
osdize_dir(dev, encrypt)
|
||||
|
||||
|
||||
def osdize_dev(dev, osd_format, osd_journal, reformat_osd=False,
|
||||
ignore_errors=False, encrypt=False):
|
||||
if not os.path.exists(dev):
|
||||
log('Path {} does not exist - bailing'.format(dev))
|
||||
return
|
||||
|
||||
if not is_block_device(dev):
|
||||
log('Path {} is not a block device - bailing'.format(dev))
|
||||
return
|
||||
|
||||
if is_osd_disk(dev) and not reformat_osd:
|
||||
log('Looks like {} is already an'
|
||||
' OSD data or journal, skipping.'.format(dev))
|
||||
return
|
||||
|
||||
if is_device_mounted(dev):
|
||||
log('Looks like {} is in use, skipping.'.format(dev))
|
||||
return
|
||||
|
||||
status_set('maintenance', 'Initializing device {}'.format(dev))
|
||||
cmd = ['ceph-disk', 'prepare']
|
||||
# Later versions of ceph support more options
|
||||
if cmp_pkgrevno('ceph', '0.60') >= 0:
|
||||
if encrypt:
|
||||
cmd.append('--dmcrypt')
|
||||
if cmp_pkgrevno('ceph', '0.48.3') >= 0:
|
||||
if osd_format:
|
||||
cmd.append('--fs-type')
|
||||
cmd.append(osd_format)
|
||||
if reformat_osd:
|
||||
cmd.append('--zap-disk')
|
||||
cmd.append(dev)
|
||||
if osd_journal:
|
||||
least_used = find_least_used_journal(osd_journal)
|
||||
cmd.append(least_used)
|
||||
else:
|
||||
# Just provide the device - no other options
|
||||
# for older versions of ceph
|
||||
cmd.append(dev)
|
||||
if reformat_osd:
|
||||
zap_disk(dev)
|
||||
|
||||
try:
|
||||
log("osdize cmd: {}".format(cmd))
|
||||
subprocess.check_call(cmd)
|
||||
except subprocess.CalledProcessError as e:
|
||||
if ignore_errors:
|
||||
log('Unable to initialize device: {}'.format(dev), WARNING)
|
||||
else:
|
||||
log('Unable to initialize device: {}'.format(dev), ERROR)
|
||||
raise e
|
||||
|
||||
|
||||
def osdize_dir(path, encrypt=False):
|
||||
if os.path.exists(os.path.join(path, 'upstart')):
|
||||
log('Path {} is already configured as an OSD - bailing'.format(path))
|
||||
return
|
||||
|
||||
if cmp_pkgrevno('ceph', "0.56.6") < 0:
|
||||
log('Unable to use directories for OSDs with ceph < 0.56.6',
|
||||
level=ERROR)
|
||||
raise
|
||||
|
||||
mkdir(path, owner=ceph_user(), group=ceph_user(), perms=0o755)
|
||||
chownr('/var/lib/ceph', ceph_user(), ceph_user())
|
||||
cmd = [
|
||||
'sudo', '-u', ceph_user(),
|
||||
'ceph-disk',
|
||||
'prepare',
|
||||
'--data-dir',
|
||||
path
|
||||
]
|
||||
if cmp_pkgrevno('ceph', '0.60') >= 0:
|
||||
if encrypt:
|
||||
cmd.append('--dmcrypt')
|
||||
log("osdize dir cmd: {}".format(cmd))
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
|
||||
def filesystem_mounted(fs):
|
||||
return subprocess.call(['grep', '-wqs', fs, '/proc/mounts']) == 0
|
||||
|
||||
|
||||
def get_running_osds():
|
||||
"""Returns a list of the pids of the current running OSD daemons"""
|
||||
cmd = ['pgrep', 'ceph-osd']
|
||||
try:
|
||||
result = subprocess.check_output(cmd)
|
||||
return result.split()
|
||||
except subprocess.CalledProcessError:
|
||||
return []
|
||||
|
||||
|
||||
|
||||
def emit_cephconf(mon_hosts):
|
||||
networks = get_networks('ceph-public-network')
|
||||
public_network = ', '.join(networks)
|
||||
|
||||
networks = get_networks('ceph-cluster-network')
|
||||
cluster_network = ', '.join(networks)
|
||||
|
||||
cephcontext = {
|
||||
'auth_supported': config('auth-supported'),
|
||||
'mon_hosts': ' '.join(mon_hosts),
|
||||
'fsid': leader_get('fsid'),
|
||||
'old_auth': cmp_pkgrevno('ceph', "0.51") < 0,
|
||||
'osd_journal_size': config('osd-journal-size'),
|
||||
'use_syslog': str(config('use-syslog')).lower(),
|
||||
'ceph_public_network': public_network,
|
||||
'ceph_cluster_network': cluster_network,
|
||||
'loglevel': config('loglevel'),
|
||||
'dio': str(config('use-direct-io')).lower(),
|
||||
}
|
||||
|
||||
if config('prefer-ipv6'):
|
||||
dynamic_ipv6_address = get_ipv6_addr()[0]
|
||||
if not public_network:
|
||||
cephcontext['public_addr'] = dynamic_ipv6_address
|
||||
if not cluster_network:
|
||||
cephcontext['cluster_addr'] = dynamic_ipv6_address
|
||||
|
||||
if az_info():
|
||||
cephcontext['crush_location'] = "root=default rack={} host={}" \
|
||||
.format(az_info(), socket.gethostname())
|
||||
|
||||
# Install ceph.conf as an alternative to support
|
||||
# co-existence with other charms that write this file
|
||||
charm_ceph_conf = "/var/lib/charm/{}/ceph.conf".format(service_name())
|
||||
mkdir(os.path.dirname(charm_ceph_conf), owner=ceph.ceph_user(),
|
||||
group=ceph.ceph_user())
|
||||
render('ceph.conf', charm_ceph_conf, cephcontext, perms=0o644)
|
||||
install_alternative('ceph.conf', '/etc/ceph/ceph.conf',
|
||||
charm_ceph_conf, 100)
|
||||
|
||||
|
||||
def get_fsid():
|
||||
return get_conf('fsid')
|
||||
|
||||
|
||||
def get_auth():
|
||||
return get_conf('auth')
|
||||
|
||||
|
||||
def get_conf(name):
|
||||
for relid in relation_ids('mon'):
|
||||
for unit in related_units(relid):
|
||||
conf = relation_get(name,
|
||||
unit, relid)
|
||||
if conf:
|
||||
return conf
|
||||
return None
|
@ -1,19 +1,27 @@
|
||||
name: ceph-base
|
||||
summary: <Fill in summary here>
|
||||
maintainer: Chris <chris.macnaughton@canonical.com>
|
||||
summary: Highly scalable distributed storage
|
||||
maintainer: OpenStack Charmers <openstack-charmers@lists.ubuntu.com>
|
||||
description: |
|
||||
<Multi-line description here>
|
||||
Ceph is a distributed storage and network file system designed to provide
|
||||
excellent performance, reliability, and scalability.
|
||||
tags:
|
||||
# Replace "misc" with one or more whitelisted tags from this list:
|
||||
# https://jujucharms.com/docs/stable/authors-charm-metadata
|
||||
- openstack
|
||||
- storage
|
||||
- file-servers
|
||||
- misc
|
||||
subordinate: false
|
||||
provides:
|
||||
provides-relation:
|
||||
interface: interface-name
|
||||
requires:
|
||||
requires-relation:
|
||||
interface: interface-name
|
||||
peers:
|
||||
peer-relation:
|
||||
interface: interface-name
|
||||
mon:
|
||||
interface: ceph
|
||||
provides:
|
||||
nrpe-external-master:
|
||||
interface: nrpe-external-master
|
||||
scope: container
|
||||
client:
|
||||
interface: ceph-client
|
||||
osd:
|
||||
interface: ceph-osd
|
||||
radosgw:
|
||||
interface: ceph-radosgw
|
||||
nrpe-external-master:
|
||||
interface: nrpe-external-master
|
||||
scope: container
|
||||
|
@ -1,17 +1,38 @@
|
||||
from charms.reactive import when, when_not, set_state
|
||||
import charms.apt
|
||||
|
||||
from charms.ceph_base import (
|
||||
get_networks,
|
||||
get_public_addr,
|
||||
assert_charm_supports_ipv6
|
||||
)
|
||||
|
||||
from charmhelpers.contrib.hardening.harden import harden
|
||||
|
||||
@when_not('ceph.installed')
|
||||
@harden()
|
||||
def install_ceph_base():
|
||||
charms.apt.add_source(config('source'), key=config('key'))
|
||||
charms.apt.queue_install(['ceph', 'gdisk', 'ntp', 'btrfs-tools', 'python3-ceph', 'xfsprogs'])
|
||||
|
||||
set_state('ceph.installed')
|
||||
|
||||
|
||||
@when_not('ceph-base.installed')
|
||||
def install_ceph-base():
|
||||
# Do your setup here.
|
||||
#
|
||||
# If your charm has other dependencies before it can install,
|
||||
# add those as @when() clauses above., or as additional @when()
|
||||
# decorated handlers below
|
||||
#
|
||||
# See the following for information about reactive charms:
|
||||
#
|
||||
# * https://jujucharms.com/docs/devel/developer-getting-started
|
||||
# * https://github.com/juju-solutions/layer-basic#overview
|
||||
#
|
||||
set_state('ceph-base.installed')
|
||||
@when('config.changed')
|
||||
@harden()
|
||||
def config_changed():
|
||||
# # Check if an upgrade was requested
|
||||
# check_for_upgrade()
|
||||
# ^^ Need to handle this in the dependant charms
|
||||
|
||||
if config('prefer-ipv6'):
|
||||
assert_charm_supports_ipv6()
|
||||
|
||||
sysctl_dict = config('sysctl')
|
||||
if sysctl_dict:
|
||||
create_sysctl(sysctl_dict, '/etc/sysctl.d/50-ceph-osd-charm.conf')
|
||||
|
||||
e_mountpoint = config('ephemeral-unmount')
|
||||
if e_mountpoint and ceph.filesystem_mounted(e_mountpoint):
|
||||
umount(e_mountpoint)
|
||||
prepare_disks_and_activate()
|
||||
|
2
wheelhouse.txt
Normal file
2
wheelhouse.txt
Normal file
@ -0,0 +1,2 @@
|
||||
netifaces
|
||||
dnspython3
|
Loading…
Reference in New Issue
Block a user