~ibmcharmers/ibm-platform-rtm

Owner: kwmonroe
Status: Needs Fixing
Vote: -1 (+2 needed for approval)

CPP?: No
OIL?: No

Migrating from old review queue:

https://bugs.launchpad.net/charms/+bug/1510216


Tests

Substrate Status Results Last Updated
lxc FAIL Test Results 7 months ago
gce FAIL http://juju-ci.vapour.ws/job/charm-bundle-test-gce/154/console 7 months ago
aws FAIL Test Results 7 months ago

Voted: -1
kos.tsakalozos wrote 5 months ago
Thank you for your work on this charm.

There are a couple of points that need improvement before we move forward with this charm:

1. You go and manually change the IP tables of the machine to open port 80.
You should not be doing this. Instead you should start your service at port 80
and then ask juju to expose the port 80 (open-port call). Then you go on
to inform the admin that the firewall was disabled, this is not a message
an admin want to see :) .

2. Your charm is manually tampering with services deployed by other charms.
For example mysql is stopped by this charm. How do you know that there is
no other service using mysql at the time you stopped it?

3. There is a "retun" that will throw a syntax error.

Thank you for your time and effort you spent on this charm.


Add Comment

Login to comment/vote on this review.


Policy Checklist

Description Unreviewed Pass Fail

General

Must verify that any software installed or utilized is verified as coming from the intended source.
  • Any software installed from the Ubuntu or CentOS default archives satisfies this due to the apt and yum sources including cryptographic signing information.
  • Third party repositories must be listed as a configuration option that can be overridden by the user and not hard coded in the charm itself.
  • Launchpad PPAs are acceptable as the add-apt-repository command retrieves the keys securely.
  • Other third party repositories are acceptable if the signing key is embedded in the charm.
Must provide a means to protect users from known security vulnerabilities in a way consistent with best practices as defined by either operating system policies or upstream documentation.
Basically, this means there must be instructions on how to apply updates if you use software not from distribution channels.
Must have hooks that are idempotent.
Should be built using charm layers.
Should use Juju Resources to deliver required payloads.

Testing and Quality

charm proof must pass without errors or warnings.
Must include passing unit, functional, or integration tests.
Tests must exercise all relations.
Tests must exercise config.
set-config, unset-config, and re-set must be tested as a minimum
Must not use anything infrastructure-provider specific (i.e. querying EC2 metadata service).
Must be self contained unless the charm is a proxy for an existing cloud service, e.g. ec2-elb charm.
Must not use symlinks.
Bundles must only use promulgated charms, they cannot reference charms in personal namespaces.
Must call Juju hook tools (relation-*, unit-*, config-*, etc) without a hard coded path.
Should include a tests.yaml for all integration tests.

Metadata

Must include a full description of what the software does.
Must include a maintainer email address for a team or individual who will be responsive to contact.
Must include a license. Call the file 'copyright' and make sure all files' licenses are specified clearly.
Must be under a Free license.
Must have a well documented and valid README.md.
Must describe the service.
Must describe how it interacts with other services, if applicable.
Must document the interfaces.
Must show how to deploy the charm.
Must define external dependencies, if applicable.
Should link to a recommend production usage bundle and recommended configuration if this differs from the default.
Should reference and link to upstream documentation and best practices.

Security

Must not run any network services using default passwords.
Must verify and validate any external payload
  • Known and understood packaging systems that verify packages like apt, pip, and yum are ok.
  • wget | sh style is not ok.
Should make use of whatever Mandatory Access Control system is provided by the distribution.
Should avoid running services as root.

Source Diff

Inline diff comments 0

No comments yet.

Back to file index

Makefile

 1
--- 
 2
+++ Makefile
 3
@@ -0,0 +1,24 @@
 4
+#!/usr/bin/make
 5
+
 6
+all: lint unit_test
 7
+
 8
+
 9
+.PHONY: clean
10
+clean:
11
+	@rm -rf .tox
12
+
13
+.PHONY: apt_prereqs
14
+apt_prereqs:
15
+	@# Need tox, but don't install the apt version unless we have to (don't want to conflict with pip)
16
+	@which tox >/dev/null || (sudo apt-get install -y python-pip && sudo pip install tox)
17
+
18
+.PHONY: lint
19
+lint: apt_prereqs
20
+	@tox --notest
21
+	@PATH=.tox/py34/bin:.tox/py35/bin flake8 $(wildcard hooks reactive lib unit_tests tests)
22
+	@charm proof
23
+
24
+.PHONY: unit_test
25
+unit_test: apt_prereqs
26
+	@echo Starting tests...
27
+	tox
Back to file index

README.md

  1
--- 
  2
+++ README.md
  3
@@ -0,0 +1,130 @@
  4
+# IBM Platform RTM v9.1.4
  5
+
  6
+IBM Platform RTM is an operational dashboard for IBM Platform LSF environments that provides comprehensive workload monitoring, reporting and management. It makes cluster administrators more efficient in their day-to-day activities and provides the information and tools needed to improve cluster efficiency, enable better user productivity, and contain or reduce costs. Unlike other monitoring tools that focus on just one facet of cluster monitoring, Platform RTM provides a complete, integrated monitoring facility that is designed specifically for Platform LSF environments. It enables you to monitor multiple clusters easily and effectively through a single intuitive interface.
  7
+
  8
+Platform RTM provides comprehensive workload monitoring, reporting and management tools to increase productivity, reduce costs and position your employees to work more effectively. Organizations using Platform RTM can benefit from:
  9
+
 10
+- Cluster monitoring and control.
 11
+- Flexible charting options.
 12
+- Job-level profiling.
 13
+- Ability to monitor resource consumption and allocation.
 14
+- Automated alerts and exception handling.
 15
+- License monitoring: support for FlexNet, Reprise License Manager (RLM) license managers
 16
+- IBM Platform LSF performance monitoring
 17
+
 18
+For details on Platform RTM usage and its benefits please visit [RTM Product Page.] [product-page]
 19
+More information available at the [IBM Knowledge Center] [platform-rtm-info]
 20
+
 21
+## Prerequisites
 22
+This charm makes use of resources, a feature only available in Juju 2.0. During deploy, you will need to specify the installable package(s) required by this charm. Download your licensed IBM Platform RTM packages from the [Passport Advantage Site][passport-rtm]
 23
+
 24
+### System Requirements
 25
+
 26
+IBM Platform RTM supports Ubuntu Trusty (14.04) on the ppc64le hardware
 27
+architecture. This charm can only deploy IBM Platform RTM to ppc64le platforms.
 28
+
 29
+### Third party Plugins to be installed along with IBM Platform RTM:
 30
+    
 31
+    plugin:boost-v4.3-1.tgz
 32
+    plugin:clog-v1.6-1.tgz
 33
+    plugin:nectar-v0.34-1.tgz
 34
+    cacti-plugin-0.8.7g-PA-v2.9.tar.gz
 35
+    plugin:settings-v0.71-1.tgz
 36
+    plugin:superlinks-v1.4-2.tgz
 37
+    adodb492.tgz
 38
+    plugin:syslog-v1.22-2.tgz
 39
+
 40
+### Package for Ubuntu on Power (ppc64le):
 41
+
 42
+    rtm-poller-9.1.4-ub14-ppc64le.tar.gz
 43
+    rtm-server-9.1.4-ub14-ppc64le.tar.gz
 44
+
 45
+## Deploy
 46
+
 47
+IBM Platform RTM is deployable on Ubuntu Trusty and ppc64le hardware. This is a
 48
+subordinate charm which needs MariaDB v5.5 for its deployment, but the default
 49
+version from the mariadb charm is v10.1. To install the required version of
 50
+mariadb, create a mariadb.yaml file with the following contents:
 51
+
 52
+    mariadb:
 53
+      series: "5.5"
 54
+
 55
+Specify this config file during deployment:
 56
+
 57
+juju deploy --config ./mariadb.yaml mariadb
 58
+
 59
+MariaDB may fail to start due to aggressive InnoDB buffer pool allocation
 60
+(default is 50% of system memory). If the mariadb charm fails to start,
 61
+please set `dataset-size` and resolve the failed unit as shown below:
 62
+
 63
+    juju config mariadb dataset-size="256M"
 64
+    juju resolved mariadb/0
 65
+
 66
+For more information on MariaDB deployment and configuration, please visit
 67
+[mariadb][mariadb-charm] in the charm store.
 68
+
 69
+With MariaDB deployed, run the following command to deploy IBM Platform RTM:
 70
+
 71
+    juju deploy ibm-platform-rtm \
 72
+      --resource ibm_prtm_installer=</path/to/rtm-poller-9.1.4-ub14-ppc64le.tar.gz> \
 73
+      --resource ibm_prtm_installer1=</path/to/rtm-server-9.1.4-ub14-ppc64le.tar.gz> \
 74
+      --resource ibm_prtm_installers=</path/to/plugin%3Aboost-v4.3-1.tgz> \ 
 75
+      --resource ibm_prtm_installers1=</path/to/plugin%3Aclog-v1.6-1.tgz> \ 
 76
+      --resource ibm_prtm_installers2=</path/to/plugin%3Anectar-v0.34-1.tgz> \ 
 77
+      --resource ibm_prtm_installers3=</path/to/cacti-plugin-0.8.7g-PA-v2.9.tar.gz> \ 
 78
+      --resource ibm_prtm_installers4=</path/to/plugin%3Asettings-v0.71-1.tgz> \
 79
+      --resource ibm_prtm_installers5=</path/to/plugin%3Asuperlinks-v1.4-2.tgz> \ 
 80
+      --resource ibm_prtm_installers6=</path/to/adodb492.tgz> \
 81
+      --resource ibm_prtm_installers7=</path/to/rtm/plugin%3Asyslog-v1.22-2.tgz> \
 82
+
 83
+**Note**: This charm requires acceptance of Terms of Use. When deploying from the Charm Store, these terms will be presented to you for your consideration. To accept the terms:
 84
+
 85
+    juju agree ibm-rtm/1
 86
+
 87
+Platform RTM installation begins when a relation is established between Mariadb and IBM Platform RTM.  Create this relation with:
 88
+
 89
+    juju add-relation mariadb ibm-platform-rtm
 90
+
 91
+To remove the relation between MariaDB and Platform-rtm, run the below command (Please remove-relation between Platform-rtm and Mariadb before uninstalling platform RTM)
 92
+
 93
+	juju remove-relation ibm-platform-rtm mariadb
 94
+
 95
+After installing IBM Platform RTM, Use your web browser to start the Platform RTM Console. The URL for the Platform RTM Console is
 96
+
 97
+	http://rtm_host
 98
+
 99
+Here rtm_host is an ip address where Platform RTM is installed. Specify the Platform RTM administrator name and password. The default administrator name is admin, and the default password for this account is admin
100
+
101
+
102
+<!-- Links -->
103
+
104
+[product-page]: http://www-03.ibm.com/systems/platformcomputing/products/lsf/rtm.html
105
+
106
+[passport-rtm]: http://www-01.ibm.com/software/passportadvantage/
107
+
108
+[license-info]: http://www-03.ibm.com/software/sla/sladb.nsf/searchlis/?searchview&searchorder=4&searchmax=0&query=%28IBM+Platform+RTM%29
109
+
110
+[platform-rtm-info]: http://www-01.ibm.com/support/knowledgecenter/SSVMSD_9.1.4/install/install_rtm_ubuntu.dita
111
+
112
+[mariadb-charm]: https://jujucharms.com/u/ibm-demo/mariadb/trusty/2
113
+
114
+
115
+## Third Party Plugins downloadable links:
116
+
117
+        wget --restrict-file-names=windows http://docs.cacti.net/_media/plugin:boost-v4.3-1.tgz
118
+        wget --restrict-file-names=windows http://docs.cacti.net/_media/plugin:clog-v1.6-1.tgz
119
+        wget --restrict-file-names=windows http://docs.cacti.net/_media/plugin:nectar-v0.34-1.tgz
120
+        wget http://www.cacti.net/downloads/pia/cacti-plugin-0.8.7g-PA-v2.9.tar.gz
121
+        wget --restrict-file-names=windows http://docs.cacti.net/_media/plugin:settings-v0.71-1.tgz
122
+        wget --restrict-file-names=windows http://docs.cacti.net/_media/plugin:superlinks-v1.4-2.tgz
123
+        wget http://sourceforge.net/projects/adodb/files/adodb-php-4-and-5/adodb-492-for-php/adodb492.tgz
124
+        wget --restrict-file-names=windows http://docs.cacti.net/_media/plugin:syslog-v1.22-2.tgz
125
+
126
+## Known Limitations
127
+
128
+This charm makes use of Juju features that are only available in version 2.0 or
129
+greater.
130
+
131
+## Contact Information
132
+
133
+For issues with this charm, please contact [IBM Juju Support Team](mailto:jujusupp@us.ibm.com)
Back to file index

bin/layer_option

 1
--- 
 2
+++ bin/layer_option
 3
@@ -0,0 +1,24 @@
 4
+#!/usr/bin/env python3
 5
+
 6
+import sys
 7
+sys.path.append('lib')
 8
+
 9
+import argparse
10
+from charms.layer import options
11
+
12
+
13
+parser = argparse.ArgumentParser(description='Access layer options.')
14
+parser.add_argument('section',
15
+                    help='the section, or layer, the option is from')
16
+parser.add_argument('option',
17
+                    help='the option to access')
18
+
19
+args = parser.parse_args()
20
+value = options(args.section).get(args.option, '')
21
+if isinstance(value, bool):
22
+    sys.exit(0 if value else 1)
23
+elif isinstance(value, list):
24
+    for val in value:
25
+        print(val)
26
+else:
27
+    print(value)
Back to file index

copyright

 1
--- 
 2
+++ copyright
 3
@@ -0,0 +1,9 @@
 4
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0
 5
+
 6
+Files: *
 7
+Copyright: 2015, Canonical Ltd.
 8
+License: GPL-3
 9
+
10
+License: GPL-3
11
+ On Debian GNU/Linux system you can find the complete text of the
12
+ GPL-3 license in '/usr/share/common-licenses/GPL-3'
Back to file index

hooks/config-changed

 1
--- 
 2
+++ hooks/config-changed
 3
@@ -0,0 +1,19 @@
 4
+#!/usr/bin/env python3
 5
+
 6
+# Load modules from $CHARM_DIR/lib
 7
+import sys
 8
+sys.path.append('lib')
 9
+
10
+from charms.layer import basic
11
+basic.bootstrap_charm_deps()
12
+basic.init_config_states()
13
+
14
+
15
+# This will load and run the appropriate @hook and other decorated
16
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
17
+# and $CHARM_DIR/hooks/relations.
18
+#
19
+# See https://jujucharms.com/docs/stable/authors-charm-building
20
+# for more information on this pattern.
21
+from charms.reactive import main
22
+main()
Back to file index

hooks/db-relation-broken

 1
--- 
 2
+++ hooks/db-relation-broken
 3
@@ -0,0 +1,19 @@
 4
+#!/usr/bin/env python3
 5
+
 6
+# Load modules from $CHARM_DIR/lib
 7
+import sys
 8
+sys.path.append('lib')
 9
+
10
+from charms.layer import basic
11
+basic.bootstrap_charm_deps()
12
+basic.init_config_states()
13
+
14
+
15
+# This will load and run the appropriate @hook and other decorated
16
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
17
+# and $CHARM_DIR/hooks/relations.
18
+#
19
+# See https://jujucharms.com/docs/stable/authors-charm-building
20
+# for more information on this pattern.
21
+from charms.reactive import main
22
+main()
Back to file index

hooks/db-relation-changed

 1
--- 
 2
+++ hooks/db-relation-changed
 3
@@ -0,0 +1,19 @@
 4
+#!/usr/bin/env python3
 5
+
 6
+# Load modules from $CHARM_DIR/lib
 7
+import sys
 8
+sys.path.append('lib')
 9
+
10
+from charms.layer import basic
11
+basic.bootstrap_charm_deps()
12
+basic.init_config_states()
13
+
14
+
15
+# This will load and run the appropriate @hook and other decorated
16
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
17
+# and $CHARM_DIR/hooks/relations.
18
+#
19
+# See https://jujucharms.com/docs/stable/authors-charm-building
20
+# for more information on this pattern.
21
+from charms.reactive import main
22
+main()
Back to file index

hooks/db-relation-departed

 1
--- 
 2
+++ hooks/db-relation-departed
 3
@@ -0,0 +1,19 @@
 4
+#!/usr/bin/env python3
 5
+
 6
+# Load modules from $CHARM_DIR/lib
 7
+import sys
 8
+sys.path.append('lib')
 9
+
10
+from charms.layer import basic
11
+basic.bootstrap_charm_deps()
12
+basic.init_config_states()
13
+
14
+
15
+# This will load and run the appropriate @hook and other decorated
16
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
17
+# and $CHARM_DIR/hooks/relations.
18
+#
19
+# See https://jujucharms.com/docs/stable/authors-charm-building
20
+# for more information on this pattern.
21
+from charms.reactive import main
22
+main()
Back to file index

hooks/db-relation-joined

 1
--- 
 2
+++ hooks/db-relation-joined
 3
@@ -0,0 +1,19 @@
 4
+#!/usr/bin/env python3
 5
+
 6
+# Load modules from $CHARM_DIR/lib
 7
+import sys
 8
+sys.path.append('lib')
 9
+
10
+from charms.layer import basic
11
+basic.bootstrap_charm_deps()
12
+basic.init_config_states()
13
+
14
+
15
+# This will load and run the appropriate @hook and other decorated
16
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
17
+# and $CHARM_DIR/hooks/relations.
18
+#
19
+# See https://jujucharms.com/docs/stable/authors-charm-building
20
+# for more information on this pattern.
21
+from charms.reactive import main
22
+main()
Back to file index

hooks/hook.template

 1
--- 
 2
+++ hooks/hook.template
 3
@@ -0,0 +1,19 @@
 4
+#!/usr/bin/env python3
 5
+
 6
+# Load modules from $CHARM_DIR/lib
 7
+import sys
 8
+sys.path.append('lib')
 9
+
10
+from charms.layer import basic
11
+basic.bootstrap_charm_deps()
12
+basic.init_config_states()
13
+
14
+
15
+# This will load and run the appropriate @hook and other decorated
16
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
17
+# and $CHARM_DIR/hooks/relations.
18
+#
19
+# See https://jujucharms.com/docs/stable/authors-charm-building
20
+# for more information on this pattern.
21
+from charms.reactive import main
22
+main()
Back to file index

hooks/install

 1
--- 
 2
+++ hooks/install
 3
@@ -0,0 +1,19 @@
 4
+#!/usr/bin/env python3
 5
+
 6
+# Load modules from $CHARM_DIR/lib
 7
+import sys
 8
+sys.path.append('lib')
 9
+
10
+from charms.layer import basic
11
+basic.bootstrap_charm_deps()
12
+basic.init_config_states()
13
+
14
+
15
+# This will load and run the appropriate @hook and other decorated
16
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
17
+# and $CHARM_DIR/hooks/relations.
18
+#
19
+# See https://jujucharms.com/docs/stable/authors-charm-building
20
+# for more information on this pattern.
21
+from charms.reactive import main
22
+main()
Back to file index

hooks/leader-elected

 1
--- 
 2
+++ hooks/leader-elected
 3
@@ -0,0 +1,19 @@
 4
+#!/usr/bin/env python3
 5
+
 6
+# Load modules from $CHARM_DIR/lib
 7
+import sys
 8
+sys.path.append('lib')
 9
+
10
+from charms.layer import basic
11
+basic.bootstrap_charm_deps()
12
+basic.init_config_states()
13
+
14
+
15
+# This will load and run the appropriate @hook and other decorated
16
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
17
+# and $CHARM_DIR/hooks/relations.
18
+#
19
+# See https://jujucharms.com/docs/stable/authors-charm-building
20
+# for more information on this pattern.
21
+from charms.reactive import main
22
+main()
Back to file index

hooks/leader-settings-changed

 1
--- 
 2
+++ hooks/leader-settings-changed
 3
@@ -0,0 +1,19 @@
 4
+#!/usr/bin/env python3
 5
+
 6
+# Load modules from $CHARM_DIR/lib
 7
+import sys
 8
+sys.path.append('lib')
 9
+
10
+from charms.layer import basic
11
+basic.bootstrap_charm_deps()
12
+basic.init_config_states()
13
+
14
+
15
+# This will load and run the appropriate @hook and other decorated
16
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
17
+# and $CHARM_DIR/hooks/relations.
18
+#
19
+# See https://jujucharms.com/docs/stable/authors-charm-building
20
+# for more information on this pattern.
21
+from charms.reactive import main
22
+main()
Back to file index

hooks/relations/mysql-root/.gitignore

1
--- 
2
+++ hooks/relations/mysql-root/.gitignore
3
@@ -0,0 +1,4 @@
4
+*.pyc
5
+.venv/
6
+.venv3/
7
+docs/build/
Back to file index

hooks/relations/mysql-root/README.md

 1
--- 
 2
+++ hooks/relations/mysql-root/README.md
 3
@@ -0,0 +1,37 @@
 4
+# Overview
 5
+
 6
+This interface layer handles the communication with MySQL via the `mysql-root`
 7
+interface protocol.
 8
+
 9
+# Usage
10
+
11
+## Requires
12
+
13
+The interface layer will set the following states, as appropriate:
14
+
15
+  * `{relation_name}.connected`  The relation is established, but MySQL has not
16
+    provided the information to use the database
17
+  * `{relation_name}.available`  MySQL is ready for use.  You can get the
18
+    connection information via the following methods:
19
+
20
+    * `host()`
21
+    * `port()`
22
+    * `database()` (the database name)
23
+    * `user()`
24
+    * `password()`
25
+
26
+For example:
27
+
28
+```python
29
+@when('mysql.available')
30
+def setup(mysql):
31
+    render(source='my.conf',
32
+           target='/etc/app/app.conf',
33
+           context={
34
+               'db_host': mysql.host(),
35
+               'db_port': mysql.port(),
36
+               'db_name': mysql.database(),
37
+               'db_user': mysql.user(),
38
+               'db_pass': mysql.password(),
39
+            })
40
+```
Back to file index

hooks/relations/mysql-root/copyright

 1
--- 
 2
+++ hooks/relations/mysql-root/copyright
 3
@@ -0,0 +1,16 @@
 4
+Format: http://dep.debian.net/deps/dep5/
 5
+
 6
+Files: *
 7
+Copyright: Copyright 2015, Canonical Ltd., All Rights Reserved.
 8
+License: Apache License 2.0
 9
+ Licensed under the Apache License, Version 2.0 (the "License");
10
+ you may not use this file except in compliance with the License.
11
+ You may obtain a copy of the License at
12
+ .
13
+     http://www.apache.org/licenses/LICENSE-2.0
14
+ .
15
+ Unless required by applicable law or agreed to in writing, software
16
+ distributed under the License is distributed on an "AS IS" BASIS,
17
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ See the License for the specific language governing permissions and
19
+ limitations under the License.
Back to file index

hooks/relations/mysql-root/docs/Makefile

  1
--- 
  2
+++ hooks/relations/mysql-root/docs/Makefile
  3
@@ -0,0 +1,192 @@
  4
+# Makefile for Sphinx documentation
  5
+#
  6
+
  7
+# You can set these variables from the command line.
  8
+SPHINXOPTS    =
  9
+SPHINXBUILD   = sphinx-build
 10
+PAPER         =
 11
+BUILDDIR      = build
 12
+
 13
+# User-friendly check for sphinx-build
 14
+ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
 15
+$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
 16
+endif
 17
+
 18
+# Internal variables.
 19
+PAPEROPT_a4     = -D latex_paper_size=a4
 20
+PAPEROPT_letter = -D latex_paper_size=letter
 21
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
 22
+# the i18n builder cannot share the environment and doctrees with the others
 23
+I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
 24
+
 25
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
 26
+
 27
+help:
 28
+	@echo "Please use \`make <target>' where <target> is one of"
 29
+	@echo "  html       to make standalone HTML files"
 30
+	@echo "  dirhtml    to make HTML files named index.html in directories"
 31
+	@echo "  singlehtml to make a single large HTML file"
 32
+	@echo "  pickle     to make pickle files"
 33
+	@echo "  json       to make JSON files"
 34
+	@echo "  htmlhelp   to make HTML files and a HTML help project"
 35
+	@echo "  qthelp     to make HTML files and a qthelp project"
 36
+	@echo "  applehelp  to make an Apple Help Book"
 37
+	@echo "  devhelp    to make HTML files and a Devhelp project"
 38
+	@echo "  epub       to make an epub"
 39
+	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
 40
+	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
 41
+	@echo "  latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
 42
+	@echo "  text       to make text files"
 43
+	@echo "  man        to make manual pages"
 44
+	@echo "  texinfo    to make Texinfo files"
 45
+	@echo "  info       to make Texinfo files and run them through makeinfo"
 46
+	@echo "  gettext    to make PO message catalogs"
 47
+	@echo "  changes    to make an overview of all changed/added/deprecated items"
 48
+	@echo "  xml        to make Docutils-native XML files"
 49
+	@echo "  pseudoxml  to make pseudoxml-XML files for display purposes"
 50
+	@echo "  linkcheck  to check all external links for integrity"
 51
+	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
 52
+	@echo "  coverage   to run coverage check of the documentation (if enabled)"
 53
+
 54
+clean:
 55
+	rm -rf $(BUILDDIR)/*
 56
+
 57
+html:
 58
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
 59
+	@echo
 60
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
 61
+
 62
+dirhtml:
 63
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
 64
+	@echo
 65
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
 66
+
 67
+singlehtml:
 68
+	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
 69
+	@echo
 70
+	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
 71
+
 72
+pickle:
 73
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
 74
+	@echo
 75
+	@echo "Build finished; now you can process the pickle files."
 76
+
 77
+json:
 78
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
 79
+	@echo
 80
+	@echo "Build finished; now you can process the JSON files."
 81
+
 82
+htmlhelp:
 83
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
 84
+	@echo
 85
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
 86
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
 87
+
 88
+qthelp:
 89
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
 90
+	@echo
 91
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
 92
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
 93
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/mysqlstub.qhcp"
 94
+	@echo "To view the help file:"
 95
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/mysqlstub.qhc"
 96
+
 97
+applehelp:
 98
+	$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
 99
+	@echo
100
+	@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
101
+	@echo "N.B. You won't be able to view it unless you put it in" \
102
+	      "~/Library/Documentation/Help or install it in your application" \
103
+	      "bundle."
104
+
105
+devhelp:
106
+	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
107
+	@echo
108
+	@echo "Build finished."
109
+	@echo "To view the help file:"
110
+	@echo "# mkdir -p $$HOME/.local/share/devhelp/mysqlstub"
111
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/mysqlstub"
112
+	@echo "# devhelp"
113
+
114
+epub:
115
+	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
116
+	@echo
117
+	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
118
+
119
+latex:
120
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
121
+	@echo
122
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
123
+	@echo "Run \`make' in that directory to run these through (pdf)latex" \
124
+	      "(use \`make latexpdf' here to do that automatically)."
125
+
126
+latexpdf:
127
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
128
+	@echo "Running LaTeX files through pdflatex..."
129
+	$(MAKE) -C $(BUILDDIR)/latex all-pdf
130
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
131
+
132
+latexpdfja:
133
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
134
+	@echo "Running LaTeX files through platex and dvipdfmx..."
135
+	$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
136
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
137
+
138
+text:
139
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
140
+	@echo
141
+	@echo "Build finished. The text files are in $(BUILDDIR)/text."
142
+
143
+man:
144
+	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
145
+	@echo
146
+	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
147
+
148
+texinfo:
149
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
150
+	@echo
151
+	@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
152
+	@echo "Run \`make' in that directory to run these through makeinfo" \
153
+	      "(use \`make info' here to do that automatically)."
154
+
155
+info:
156
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
157
+	@echo "Running Texinfo files through makeinfo..."
158
+	make -C $(BUILDDIR)/texinfo info
159
+	@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
160
+
161
+gettext:
162
+	$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
163
+	@echo
164
+	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
165
+
166
+changes:
167
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
168
+	@echo
169
+	@echo "The overview file is in $(BUILDDIR)/changes."
170
+
171
+linkcheck:
172
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
173
+	@echo
174
+	@echo "Link check complete; look for any errors in the above output " \
175
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
176
+
177
+doctest:
178
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
179
+	@echo "Testing of doctests in the sources finished, look at the " \
180
+	      "results in $(BUILDDIR)/doctest/output.txt."
181
+
182
+coverage:
183
+	$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
184
+	@echo "Testing of coverage in the sources finished, look at the " \
185
+	      "results in $(BUILDDIR)/coverage/python.txt."
186
+
187
+xml:
188
+	$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
189
+	@echo
190
+	@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
191
+
192
+pseudoxml:
193
+	$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
194
+	@echo
195
+	@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
Back to file index

hooks/relations/mysql-root/docs/source/conf.py

  1
--- 
  2
+++ hooks/relations/mysql-root/docs/source/conf.py
  3
@@ -0,0 +1,293 @@
  4
+# -*- coding: utf-8 -*-
  5
+#
  6
+# mysql stub documentation build configuration file, created by
  7
+# sphinx-quickstart on Wed Jun 10 17:13:25 2015.
  8
+#
  9
+# This file is execfile()d with the current directory set to its
 10
+# containing dir.
 11
+#
 12
+# Note that not all possible configuration values are present in this
 13
+# autogenerated file.
 14
+#
 15
+# All configuration values have a default; values that are commented out
 16
+# serve to show the default.
 17
+
 18
+import sys
 19
+import os
 20
+import shlex
 21
+
 22
+# If extensions (or modules to document with autodoc) are in another directory,
 23
+# add these directories to sys.path here. If the directory is relative to the
 24
+# documentation root, use os.path.abspath to make it absolute, like shown here.
 25
+sys.path.insert(0, os.path.abspath('../..'))  # relative to conf.py
 26
+
 27
+# -- General configuration ------------------------------------------------
 28
+
 29
+# If your documentation needs a minimal Sphinx version, state it here.
 30
+#needs_sphinx = '1.0'
 31
+
 32
+# Add any Sphinx extension module names here, as strings. They can be
 33
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 34
+# ones.
 35
+extensions = [
 36
+    'sphinx.ext.autodoc',
 37
+    'sphinx.ext.intersphinx',
 38
+    'sphinx.ext.coverage',
 39
+    'sphinx.ext.viewcode',
 40
+]
 41
+
 42
+# Add any paths that contain templates here, relative to this directory.
 43
+templates_path = ['_templates']
 44
+
 45
+# The suffix(es) of source filenames.
 46
+# You can specify multiple suffix as a list of string:
 47
+# source_suffix = ['.rst', '.md']
 48
+source_suffix = '.rst'
 49
+
 50
+# The encoding of source files.
 51
+#source_encoding = 'utf-8-sig'
 52
+
 53
+# The master toctree document.
 54
+master_doc = 'index'
 55
+
 56
+# General information about the project.
 57
+project = u'mysql stub'
 58
+copyright = u'2015, me'
 59
+author = u'me'
 60
+
 61
+# The version info for the project you're documenting, acts as replacement for
 62
+# |version| and |release|, also used in various other places throughout the
 63
+# built documents.
 64
+#
 65
+# The short X.Y version.
 66
+version = '1.0'
 67
+# The full version, including alpha/beta/rc tags.
 68
+release = '1.0'
 69
+
 70
+# The language for content autogenerated by Sphinx. Refer to documentation
 71
+# for a list of supported languages.
 72
+#
 73
+# This is also used if you do content translation via gettext catalogs.
 74
+# Usually you set "language" from the command line for these cases.
 75
+language = None
 76
+
 77
+# There are two options for replacing |today|: either, you set today to some
 78
+# non-false value, then it is used:
 79
+#today = ''
 80
+# Else, today_fmt is used as the format for a strftime call.
 81
+#today_fmt = '%B %d, %Y'
 82
+
 83
+# List of patterns, relative to source directory, that match files and
 84
+# directories to ignore when looking for source files.
 85
+exclude_patterns = []
 86
+
 87
+# The reST default role (used for this markup: `text`) to use for all
 88
+# documents.
 89
+#default_role = None
 90
+
 91
+# If true, '()' will be appended to :func: etc. cross-reference text.
 92
+#add_function_parentheses = True
 93
+
 94
+# If true, the current module name will be prepended to all description
 95
+# unit titles (such as .. function::).
 96
+#add_module_names = True
 97
+
 98
+# If true, sectionauthor and moduleauthor directives will be shown in the
 99
+# output. They are ignored by default.
100
+#show_authors = False
101
+
102
+# The name of the Pygments (syntax highlighting) style to use.
103
+pygments_style = 'sphinx'
104
+
105
+# A list of ignored prefixes for module index sorting.
106
+#modindex_common_prefix = []
107
+
108
+# If true, keep warnings as "system message" paragraphs in the built documents.
109
+#keep_warnings = False
110
+
111
+# If true, `todo` and `todoList` produce output, else they produce nothing.
112
+todo_include_todos = False
113
+
114
+
115
+# -- Options for HTML output ----------------------------------------------
116
+
117
+# The theme to use for HTML and HTML Help pages.  See the documentation for
118
+# a list of builtin themes.
119
+html_theme = 'alabaster'
120
+
121
+# Theme options are theme-specific and customize the look and feel of a theme
122
+# further.  For a list of options available for each theme, see the
123
+# documentation.
124
+#html_theme_options = {}
125
+
126
+# Add any paths that contain custom themes here, relative to this directory.
127
+#html_theme_path = []
128
+
129
+# The name for this set of Sphinx documents.  If None, it defaults to
130
+# "<project> v<release> documentation".
131
+#html_title = None
132
+
133
+# A shorter title for the navigation bar.  Default is the same as html_title.
134
+#html_short_title = None
135
+
136
+# The name of an image file (relative to this directory) to place at the top
137
+# of the sidebar.
138
+#html_logo = None
139
+
140
+# The name of an image file (within the static path) to use as favicon of the
141
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
142
+# pixels large.
143
+#html_favicon = None
144
+
145
+# Add any paths that contain custom static files (such as style sheets) here,
146
+# relative to this directory. They are copied after the builtin static files,
147
+# so a file named "default.css" will overwrite the builtin "default.css".
148
+html_static_path = ['_static']
149
+
150
+# Add any extra paths that contain custom files (such as robots.txt or
151
+# .htaccess) here, relative to this directory. These files are copied
152
+# directly to the root of the documentation.
153
+#html_extra_path = []
154
+
155
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
156
+# using the given strftime format.
157
+#html_last_updated_fmt = '%b %d, %Y'
158
+
159
+# If true, SmartyPants will be used to convert quotes and dashes to
160
+# typographically correct entities.
161
+#html_use_smartypants = True
162
+
163
+# Custom sidebar templates, maps document names to template names.
164
+#html_sidebars = {}
165
+
166
+# Additional templates that should be rendered to pages, maps page names to
167
+# template names.
168
+#html_additional_pages = {}
169
+
170
+# If false, no module index is generated.
171
+#html_domain_indices = True
172
+
173
+# If false, no index is generated.
174
+#html_use_index = True
175
+
176
+# If true, the index is split into individual pages for each letter.
177
+#html_split_index = False
178
+
179
+# If true, links to the reST sources are added to the pages.
180
+#html_show_sourcelink = True
181
+
182
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
183
+#html_show_sphinx = True
184
+
185
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
186
+#html_show_copyright = True
187
+
188
+# If true, an OpenSearch description file will be output, and all pages will
189
+# contain a <link> tag referring to it.  The value of this option must be the
190
+# base URL from which the finished HTML is served.
191
+#html_use_opensearch = ''
192
+
193
+# This is the file name suffix for HTML files (e.g. ".xhtml").
194
+#html_file_suffix = None
195
+
196
+# Language to be used for generating the HTML full-text search index.
197
+# Sphinx supports the following languages:
198
+#   'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
199
+#   'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
200
+#html_search_language = 'en'
201
+
202
+# A dictionary with options for the search language support, empty by default.
203
+# Now only 'ja' uses this config value
204
+#html_search_options = {'type': 'default'}
205
+
206
+# The name of a javascript file (relative to the configuration directory) that
207
+# implements a search results scorer. If empty, the default will be used.
208
+#html_search_scorer = 'scorer.js'
209
+
210
+# Output file base name for HTML help builder.
211
+htmlhelp_basename = 'mysqlstubdoc'
212
+
213
+# -- Options for LaTeX output ---------------------------------------------
214
+
215
+latex_elements = {
216
+# The paper size ('letterpaper' or 'a4paper').
217
+#'papersize': 'letterpaper',
218
+
219
+# The font size ('10pt', '11pt' or '12pt').
220
+#'pointsize': '10pt',
221
+
222
+# Additional stuff for the LaTeX preamble.
223
+#'preamble': '',
224
+
225
+# Latex figure (float) alignment
226
+#'figure_align': 'htbp',
227
+}
228
+
229
+# Grouping the document tree into LaTeX files. List of tuples
230
+# (source start file, target name, title,
231
+#  author, documentclass [howto, manual, or own class]).
232
+latex_documents = [
233
+  (master_doc, 'mysqlstub.tex', u'mysql stub Documentation',
234
+   u'me', 'manual'),
235
+]
236
+
237
+# The name of an image file (relative to this directory) to place at the top of
238
+# the title page.
239
+#latex_logo = None
240
+
241
+# For "manual" documents, if this is true, then toplevel headings are parts,
242
+# not chapters.
243
+#latex_use_parts = False
244
+
245
+# If true, show page references after internal links.
246
+#latex_show_pagerefs = False
247
+
248
+# If true, show URL addresses after external links.
249
+#latex_show_urls = False
250
+
251
+# Documents to append as an appendix to all manuals.
252
+#latex_appendices = []
253
+
254
+# If false, no module index is generated.
255
+#latex_domain_indices = True
256
+
257
+
258
+# -- Options for manual page output ---------------------------------------
259
+
260
+# One entry per manual page. List of tuples
261
+# (source start file, name, description, authors, manual section).
262
+man_pages = [
263
+    (master_doc, 'mysqlstub', u'mysql stub Documentation',
264
+     [author], 1)
265
+]
266
+
267
+# If true, show URL addresses after external links.
268
+#man_show_urls = False
269
+
270
+
271
+# -- Options for Texinfo output -------------------------------------------
272
+
273
+# Grouping the document tree into Texinfo files. List of tuples
274
+# (source start file, target name, title, author,
275
+#  dir menu entry, description, category)
276
+texinfo_documents = [
277
+  (master_doc, 'mysqlstub', u'mysql stub Documentation',
278
+   author, 'mysqlstub', 'One line description of project.',
279
+   'Miscellaneous'),
280
+]
281
+
282
+# Documents to append as an appendix to all manuals.
283
+#texinfo_appendices = []
284
+
285
+# If false, no module index is generated.
286
+#texinfo_domain_indices = True
287
+
288
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
289
+#texinfo_show_urls = 'footnote'
290
+
291
+# If true, do not generate a @detailmenu in the "Top" node's menu.
292
+#texinfo_no_detailmenu = False
293
+
294
+
295
+# Example configuration for intersphinx: refer to the Python standard library.
296
+intersphinx_mapping = {'https://docs.python.org/': None}
Back to file index

hooks/relations/mysql-root/docs/source/index.rst

 1
--- 
 2
+++ hooks/relations/mysql-root/docs/source/index.rst
 3
@@ -0,0 +1,19 @@
 4
+Juju mysql Relation Interface Implementation Docs
 5
+=================================================
 6
+
 7
+Contents:
 8
+
 9
+.. toctree::
10
+   :maxdepth: 2
11
+
12
+   requires
13
+   provides
14
+
15
+
16
+Indices and tables
17
+==================
18
+
19
+* :ref:`genindex`
20
+* :ref:`modindex`
21
+* :ref:`search`
22
+
Back to file index

hooks/relations/mysql-root/docs/source/provides.rst

 1
--- 
 2
+++ hooks/relations/mysql-root/docs/source/provides.rst
 3
@@ -0,0 +1,48 @@
 4
+Provides: MySQL
 5
+===============
 6
+
 7
+Example Usage
 8
+-------------
 9
+
10
+This is what a charm using this relation would look like:
11
+
12
+.. code-block:: python
13
+
14
+    # in the postgres charm:
15
+    from charmhelpers.core import hookenv  # noqa
16
+    from charmhelpers.core import unitdata
17
+    from charmhelpers.core.reactive import when
18
+    from common import (
19
+        user_name,
20
+        create_user,
21
+        ensure_database,
22
+        get_service_port,
23
+    )
24
+
25
+
26
+    @when('db.database.requested')
27
+    def provide_database(mysql):
28
+        for service in mysql.requested_databases():
29
+            database = service
30
+
31
+            user = user_name(mysql.relation_name(), service)  # generate username
32
+            password = create_user(user)  # get-or-create user
33
+
34
+            ensure_database(user, schema_user, database)
35
+
36
+            mysql.provide_database(
37
+                service=service,
38
+                host=hookenv.unit_private_ip(),
39
+                port=get_service_port(),
40
+                database=database,
41
+                user=user,
42
+                password=password,
43
+            )
44
+
45
+
46
+Reference
47
+---------
48
+
49
+.. autoclass::
50
+    provides.MySQL
51
+    :members:
Back to file index

hooks/relations/mysql-root/docs/source/requires.rst

 1
--- 
 2
+++ hooks/relations/mysql-root/docs/source/requires.rst
 3
@@ -0,0 +1,48 @@
 4
+Requires: MySQLClient
 5
+=====================
 6
+
 7
+Example Usage
 8
+-------------
 9
+
10
+This is what a charm using this relation would look like:
11
+
12
+.. code-block:: python
13
+
14
+    from charmhelpers.core import hookenv
15
+    from charmhelpers.core.reactive import hook
16
+    from charmhelpers.core.reactive import when
17
+    from charmhelpers.core.reactive import when_file_changed
18
+    from charmhelpers.core.reactive import set_state
19
+    from charmhelpers.core.reactive import remove_state
20
+
21
+    @hook('db-relation-joined')
22
+    def request_db(mysql):
23
+        mysql.change_database_name('mydb')
24
+        mysql.request_roles('myrole', 'otherrole')
25
+
26
+    @hook('config-changed')
27
+    def check_admin_pass():
28
+        admin_pass = hookenv.config('admin-pass')
29
+        if admin_pass:
30
+            set_state('admin-pass')
31
+        else:
32
+            remove_state('admin-pass')
33
+
34
+    @when('db.database.available', 'admin-pass')
35
+    def render_config(mysql):
36
+        render_template('app-config.j2', '/etc/app.conf', {
37
+            'db_conn': mysql.connection_string(),
38
+            'admin_pass': hookenv.config('admin-pass'),
39
+        })
40
+
41
+    @when_file_changed('/etc/app.conf')
42
+    def restart_service():
43
+        hookenv.service_restart('myapp')
44
+
45
+
46
+Reference
47
+---------
48
+
49
+.. autoclass::
50
+    requires.MySQLClient
51
+    :members:
Back to file index

hooks/relations/mysql-root/interface.yaml

1
--- 
2
+++ hooks/relations/mysql-root/interface.yaml
3
@@ -0,0 +1,4 @@
4
+name: mysql-root
5
+summary: Interface for relating to MySQL with administrative access
6
+version: 1
7
+maintainer: "MySQL Charmers <kevin.monroe@canonical.com>"
Back to file index

hooks/relations/mysql-root/provides.py

 1
--- 
 2
+++ hooks/relations/mysql-root/provides.py
 3
@@ -0,0 +1,86 @@
 4
+#!/usr/bin/python
 5
+# Licensed under the Apache License, Version 2.0 (the "License");
 6
+# you may not use this file except in compliance with the License.
 7
+# You may obtain a copy of the License at
 8
+#
 9
+#     http://www.apache.org/licenses/LICENSE-2.0
10
+#
11
+# Unless required by applicable law or agreed to in writing, software
12
+# distributed under the License is distributed on an "AS IS" BASIS,
13
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+# See the License for the specific language governing permissions and
15
+# limitations under the License.
16
+
17
+from charms.reactive import RelationBase
18
+from charms.reactive import scopes
19
+from charms.reactive import hook
20
+from charms.reactive import not_unless
21
+
22
+
23
+class MySQLRoot(RelationBase):
24
+    # We expect multiple, separate services to be related, but all units of a
25
+    # given service will share the same database name and connection info.
26
+    # Thus, we use SERVICE scope and will have one converstaion per service.
27
+    scope = scopes.SERVICE
28
+
29
+    @hook('{provides:mysql-root}-relation-joined')
30
+    def joined(self):
31
+        """
32
+        Handles the relation-joined hook.
33
+
34
+        Depending on the state of the conversation, this can trigger the
35
+        following state:
36
+
37
+        * ``{relation_name}.database.requested`` This state will be activated
38
+          if a remote service is awaiting a database.  This state should be
39
+          resolved by calling :meth:`provide_database`.  See also
40
+          :meth:`requested_databases`.
41
+        """
42
+        conversation = self.conversation()
43
+        conversation.set_state('{relation_name}.database.requested')
44
+
45
+    @hook('{provides:mysql-root}-relation-{broken,departed}')
46
+    def departed(self):
47
+        conversation = self.conversation()
48
+
49
+        # if these were requested but not yet fulfilled, cancel the request
50
+        conversation.remove_state('{relation_name}.database.requested')
51
+
52
+    @not_unless('{provides:mysql-root}.database.requested')
53
+    def provide_database(self, service, host, port, database, user, password):
54
+        """
55
+        Provide a database to a requesting service.
56
+
57
+        :param str service: The service which requested the database, as
58
+            returned by :meth:`~provides.MySQL.requested_databases`.
59
+        :param str host: The host where the database can be reached (e.g.,
60
+            the charm's private or public-address).
61
+        :param int port: The port where the database can be reached.
62
+        :param str database: The name of the database being provided.
63
+        :param str user: The username to be used to access the database.
64
+        :param str password: The password to be used to access the database.
65
+        """
66
+        conversation = self.conversation(scope=service)
67
+        conversation.set_remote(
68
+            host=host,
69
+            port=port,
70
+            database=database,
71
+            user=user,
72
+            password=password,
73
+        )
74
+        conversation.set_local('database', database)
75
+        conversation.remove_state('{relation_name}.database.requested')
76
+
77
+    def requested_databases(self):
78
+        """
79
+        Return a list of services requesting databases.
80
+
81
+        Example usage::
82
+
83
+            for service in mysql.requested_databases():
84
+                database = generate_dbname(service)
85
+                mysql.provide_database(**create_database(database))
86
+        """
87
+        for conversation in self.conversations():
88
+            service = conversation.scope
89
+            yield service
Back to file index

hooks/relations/mysql-root/requires.py

 1
--- 
 2
+++ hooks/relations/mysql-root/requires.py
 3
@@ -0,0 +1,67 @@
 4
+#!/usr/bin/python
 5
+# Licensed under the Apache License, Version 2.0 (the "License");
 6
+# you may not use this file except in compliance with the License.
 7
+# You may obtain a copy of the License at
 8
+#
 9
+#     http://www.apache.org/licenses/LICENSE-2.0
10
+#
11
+# Unless required by applicable law or agreed to in writing, software
12
+# distributed under the License is distributed on an "AS IS" BASIS,
13
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+# See the License for the specific language governing permissions and
15
+# limitations under the License.
16
+
17
+from charms.reactive import RelationBase
18
+from charms.reactive import hook
19
+from charms.reactive import scopes
20
+
21
+
22
+class MySQLRootClient(RelationBase):
23
+    # We only expect a single mysql server to be related.  Additionally, if
24
+    # there are multiple units, it would be for replication purposes only,
25
+    # so we would expect a leader to provide our connection info, or at least
26
+    # for all mysql units to agree on the connection info.  Thus, we use a
27
+    # global conversation scope in which all services and units share the
28
+    # same conversation.
29
+    scope = scopes.GLOBAL
30
+
31
+    # These remote data fields will be automatically mapped to accessors
32
+    # with a basic documentation string provided.
33
+    auto_accessors = ['host', 'database', 'user', 'password']
34
+
35
+    def port(self):
36
+        """
37
+        Get the port.
38
+
39
+        If not available, returns the default port of 3306.
40
+        """
41
+        return self.get_remote('port', 3306)
42
+
43
+    @hook('{requires:mysql-root}-relation-{joined,changed}')
44
+    def changed(self):
45
+        self.set_state('{relation_name}.connected')
46
+        if self.connection_string():
47
+            self.set_state('{relation_name}.available')
48
+
49
+    @hook('{requires:mysql-root}-relation-{broken,departed}')
50
+    def departed(self):
51
+        self.remove_state('{relation_name}.connected')
52
+        self.remove_state('{relation_name}.available')
53
+
54
+    def connection_string(self):
55
+        """
56
+        Get the connection string, if available, or None.
57
+        """
58
+        data = {
59
+            'host': self.host(),
60
+            'port': self.port(),
61
+            'database': self.database(),
62
+            'user': self.user(),
63
+            'password': self.password(),
64
+        }
65
+        if all(data.values()):
66
+            return str.format(
67
+                'host={host} port={port} dbname={database} '
68
+                'user={user} password={password}',
69
+                **data)
70
+        return None
Back to file index

hooks/start

 1
--- 
 2
+++ hooks/start
 3
@@ -0,0 +1,19 @@
 4
+#!/usr/bin/env python3
 5
+
 6
+# Load modules from $CHARM_DIR/lib
 7
+import sys
 8
+sys.path.append('lib')
 9
+
10
+from charms.layer import basic
11
+basic.bootstrap_charm_deps()
12
+basic.init_config_states()
13
+
14
+
15
+# This will load and run the appropriate @hook and other decorated
16
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
17
+# and $CHARM_DIR/hooks/relations.
18
+#
19
+# See https://jujucharms.com/docs/stable/authors-charm-building
20
+# for more information on this pattern.
21
+from charms.reactive import main
22
+main()
Back to file index

hooks/stop

 1
--- 
 2
+++ hooks/stop
 3
@@ -0,0 +1,19 @@
 4
+#!/usr/bin/env python3
 5
+
 6
+# Load modules from $CHARM_DIR/lib
 7
+import sys
 8
+sys.path.append('lib')
 9
+
10
+from charms.layer import basic
11
+basic.bootstrap_charm_deps()
12
+basic.init_config_states()
13
+
14
+
15
+# This will load and run the appropriate @hook and other decorated
16
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
17
+# and $CHARM_DIR/hooks/relations.
18
+#
19
+# See https://jujucharms.com/docs/stable/authors-charm-building
20
+# for more information on this pattern.
21
+from charms.reactive import main
22
+main()
Back to file index

hooks/update-status

 1
--- 
 2
+++ hooks/update-status
 3
@@ -0,0 +1,19 @@
 4
+#!/usr/bin/env python3
 5
+
 6
+# Load modules from $CHARM_DIR/lib
 7
+import sys
 8
+sys.path.append('lib')
 9
+
10
+from charms.layer import basic
11
+basic.bootstrap_charm_deps()
12
+basic.init_config_states()
13
+
14
+
15
+# This will load and run the appropriate @hook and other decorated
16
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
17
+# and $CHARM_DIR/hooks/relations.
18
+#
19
+# See https://jujucharms.com/docs/stable/authors-charm-building
20
+# for more information on this pattern.
21
+from charms.reactive import main
22
+main()
Back to file index

hooks/upgrade-charm

 1
--- 
 2
+++ hooks/upgrade-charm
 3
@@ -0,0 +1,28 @@
 4
+#!/usr/bin/env python3
 5
+
 6
+# Load modules from $CHARM_DIR/lib
 7
+import os
 8
+import sys
 9
+sys.path.append('lib')
10
+
11
+# This is an upgrade-charm context, make sure we install latest deps
12
+if not os.path.exists('wheelhouse/.upgrade'):
13
+    open('wheelhouse/.upgrade', 'w').close()
14
+    if os.path.exists('wheelhouse/.bootstrapped'):
15
+        os.unlink('wheelhouse/.bootstrapped')
16
+else:
17
+    os.unlink('wheelhouse/.upgrade')
18
+
19
+from charms.layer import basic
20
+basic.bootstrap_charm_deps()
21
+basic.init_config_states()
22
+
23
+
24
+# This will load and run the appropriate @hook and other decorated
25
+# handlers from $CHARM_DIR/reactive, $CHARM_DIR/hooks/reactive,
26
+# and $CHARM_DIR/hooks/relations.
27
+#
28
+# See https://jujucharms.com/docs/stable/authors-charm-building
29
+# for more information on this pattern.
30
+from charms.reactive import main
31
+main()
Back to file index

icon.svg

 1
--- 
 2
+++ icon.svg
 3
@@ -0,0 +1,67 @@
 4
+<?xml version="1.0" encoding="UTF-8"?>
 5
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
 6
+<!-- Creator: CorelDRAW X6 -->
 7
+<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="1in" height="0.999996in" version="1.1" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd"
 8
+viewBox="0 0 1000 1000"
 9
+ xmlns:xlink="http://www.w3.org/1999/xlink">
10
+ <defs>
11
+    <linearGradient id="id0" gradientUnits="userSpaceOnUse" x1="500.002" y1="999.996" x2="500.002" y2="0">
12
+     <stop offset="0" stop-color="#A1CD3D"/>
13
+     <stop offset="1" stop-color="white"/>
14
+    </linearGradient>
15
+    <mask id="id1">
16
+      <linearGradient id="id2" gradientUnits="userSpaceOnUse" x1="500.002" y1="58.4805" x2="500.002" y2="307.017">
17
+       <stop offset="0" stop-opacity="1" stop-color="white"/>
18
+       <stop offset="0.141176" stop-opacity="46.6784" stop-color="white"/>
19
+       <stop offset="1" stop-opacity="0" stop-color="white"/>
20
+      </linearGradient>
21
+     <rect fill="url(#id2)" width="1000" height="365"/>
22
+    </mask>
23
+ </defs>
24
+ <g id="Layer_x0020_1">
25
+  <metadata id="CorelCorpID_0Corel-Layer"/>
26
+  <g id="_692158304">
27
+   <path id="Background" fill="url(#id0)" d="M0 676l0 -352c0,-283 41,-324 324,-324l352 0c284,0 324,41 324,324l0 352c0,283 -40,324 -324,324l-352 0c-283,0 -324,-41 -324,-324z"/>
28
+   <path fill="#999999" mask="url(#id1)" d="M0 365l0 -41c0,-283 41,-324 324,-324l352 0c284,0 324,41 324,324l0 41c0,-283 -40,-324 -324,-324l-352 0c-283,0 -324,41 -324,324z"/>
29
+   <g>
30
+    <circle fill="#03729F" cx="734" cy="509" r="42"/>
31
+    <polygon fill="#03729F" fill-rule="nonzero" points="215,309 734,309 742,309 742,317 742,632 742,640 734,640 521,640 521,695 521,703 512,703 436,703 428,703 428,695 428,640 215,640 206,640 206,632 206,317 206,309 "/>
32
+    <polygon fill="#E4F5FD" fill-rule="nonzero" points="726,325 223,325 223,624 436,624 445,624 445,632 445,687 504,687 504,632 504,624 512,624 726,624 "/>
33
+    <path fill="#03729F" d="M696 541l-57 9c-1,1 -2,3 -3,4l5 29c12,7 20,20 20,36 0,7 -2,15 -6,21l-68 0c-4,-6 -6,-14 -6,-21 0,-11 4,-21 11,-28l-5 -30c-8,-5 -14,-13 -16,-23l-50 -27c-5,2 -11,3 -16,3 -22,0 -40,-18 -40,-40 0,-22 18,-40 40,-40 8,0 16,2 23,7l46 -14c2,-3 4,-6 7,-9l-5 -41c-14,-8 -23,-22 -23,-39 0,-11 5,-22 12,-29l64 0c7,7 11,18 11,29 0,13 -5,25 -15,33l5 41c7,5 12,13 15,22l63 33c7,-5 16,-8 26,-8 3,0 6,1 8,1l0 98c-2,1 -5,1 -8,1 -15,0 -29,-7 -38,-18zm-75 -63c-4,1 -8,2 -13,2 -7,0 -13,-2 -19,-5l-20 6 26 14c4,-2 8,-2 13,-2 8,0 17,3 23,8l26 -4 -36 -19z"/>
34
+    <path fill="#03729F" d="M299 493l-44 -110c33,0 60,-24 65,-56l92 56 34 -56c8,15 24,25 42,25l-40 67 42 108c-2,0 -5,0 -7,0 -28,0 -50,22 -50,50 0,2 0,4 0,6l-79 -34c-5,2 -11,4 -17,5l-40 59c-8,-16 -23,-26 -41,-28l40 -59c-1,-4 -2,-8 -2,-13 0,-7 2,-14 5,-20zm46 -18c14,4 25,14 28,28l65 27 -38 -96 -94 -57 39 98z"/>
35
+    <path fill="#03729F" d="M546 679c34,6 57,16 57,28 0,19 -58,34 -129,34 -71,0 -128,-15 -128,-34 0,-12 22,-22 57,-28 -8,3 -12,8 -12,12 0,13 37,23 83,23 47,0 84,-10 84,-23 0,-4 -4,-9 -12,-12z"/>
36
+    <circle fill="#03729F" cx="621" cy="619" r="32"/>
37
+    <circle fill="white" cx="621" cy="619" r="24"/>
38
+    <circle fill="white" cx="505" cy="474" r="24"/>
39
+    <circle fill="#03729F" cx="420" cy="417" r="40"/>
40
+    <circle fill="white" cx="608" cy="530" r="21"/>
41
+    <path fill="#03729F" d="M539 309c-3,24 -24,44 -50,44 -25,0 -46,-20 -49,-44l99 0z"/>
42
+    <circle fill="#03729F" cx="489" cy="303" r="42"/>
43
+    <circle fill="white" cx="734" cy="509" r="33"/>
44
+    <circle fill="#03729F" cx="483" cy="577" r="50"/>
45
+    <path fill="#03729F" d="M250 584c30,0 54,25 54,54 0,1 0,2 0,2l-98 0 0 -34c10,-13 26,-22 44,-22z"/>
46
+    <circle fill="#03729F" cx="250" cy="638" r="46"/>
47
+    <path fill="#03729F" d="M320 309c1,2 1,5 1,8 0,37 -30,66 -67,66 -18,0 -35,-8 -48,-20l0 -54 114 0z"/>
48
+    <circle fill="#03729F" cx="254" cy="317" r="58"/>
49
+    <path fill="white" d="M450 572l-99 -42c4,-4 7,-10 7,-16l99 42c1,-2 4,-4 6,-6l0 0 -42 -109 0 0 -1 0c-13,0 -23,-11 -23,-24 0,-1 0,-3 0,-4l-105 -64c-3,4 -7,8 -11,10l53 131c-6,0 -12,2 -16,6l-53 -130c-3,0 -7,1 -11,1 -27,0 -49,-23 -49,-50 0,-28 22,-50 49,-50 28,0 50,22 50,50 0,6 -1,13 -3,18l105 63c4,-3 9,-5 14,-5 2,0 3,0 5,1l40 -68 0 0c-5,-6 -9,-14 -9,-23 0,-19 15,-33 33,-33 18,0 33,14 33,33 0,18 -15,33 -33,33 -3,0 -6,-1 -9,-1l-41 67 0 0c3,4 5,9 5,15 0,7 -3,13 -8,18l43 109 0 0c1,-1 3,-1 4,-1 18,0 33,15 33,34 0,18 -15,33 -33,33 -18,0 -33,-15 -33,-33 0,-2 0,-4 0,-5zm-200 29c5,0 9,1 14,2l0 0 51 -76c3,5 8,8 14,9l-52 77c7,6 10,15 10,25 0,21 -16,38 -37,38 -21,0 -37,-17 -37,-38 0,-20 16,-37 37,-37zm50 -265c0,1 0,1 0,1 0,0 0,0 0,-1zm0 2c0,0 -1,0 -1,0 0,0 1,0 1,0zm-1 1c0,0 0,0 0,1 0,-1 0,-1 0,-1zm0 1c0,0 -1,0 -1,1 0,-1 1,-1 1,-1zm-1 1c0,0 0,0 0,1 0,-1 0,-1 0,-1zm-1 1c0,0 0,0 0,1 0,-1 0,-1 0,-1zm0 1c0,0 0,0 -1,1 1,-1 1,-1 1,-1zm-1 1c0,0 0,0 0,1 0,-1 0,-1 0,-1zm4 -8c0,0 1,0 1,-1"/>
50
+    <path fill="white" fill-rule="nonzero" d="M610 598l-8 -48c2,0 4,1 6,1 4,0 7,-1 11,-3l7 47c-2,0 -3,0 -5,0 -4,0 -8,1 -11,3zm-82 -121l67 37c-5,3 -8,8 -8,14l-67 -36c5,-4 7,-9 8,-15zm65 -21l-65 20c0,-1 0,-1 0,-2 0,-5 -1,-10 -4,-14l64 -20c0,1 0,2 0,3 0,5 1,10 5,13zm5 -31l-7 -60c2,0 4,0 6,0 4,0 7,-1 11,-2l6 60c-1,-1 -4,-1 -6,-1 -3,0 -7,1 -10,3zm104 77l-81 -43c5,-3 8,-9 8,-15l81 43c-4,4 -7,9 -8,15zm-77 17l76 -13c0,1 0,2 0,3 0,5 1,10 3,14l-76 12c0,-2 0,-3 0,-5 0,-4 -1,-8 -3,-11z"/>
51
+    <circle fill="#03729F" cx="489" cy="303" r="17"/>
52
+    <circle fill="#03729F" cx="254" cy="317" r="25"/>
53
+    <circle fill="#03729F" cx="250" cy="638" r="25"/>
54
+    <circle fill="#03729F" cx="483" cy="577" r="21"/>
55
+    <circle fill="#03729F" cx="420" cy="417" r="11"/>
56
+    <circle fill="white" cx="334" cy="513" r="24"/>
57
+    <circle fill="#03729F" cx="334" cy="513" r="11"/>
58
+    <circle fill="white" cx="597" cy="338" r="27"/>
59
+    <circle fill="#03729F" cx="597" cy="338" r="15"/>
60
+    <circle fill="white" cx="608" cy="443" r="21"/>
61
+    <circle fill="#03729F" cx="608" cy="443" r="8"/>
62
+    <circle fill="#03729F" cx="505" cy="474" r="11"/>
63
+    <circle fill="#03729F" cx="608" cy="530" r="8"/>
64
+    <circle fill="#03729F" cx="734" cy="509" r="17"/>
65
+    <circle fill="#03729F" cx="621" cy="619" r="11"/>
66
+    <path fill="#03729F" d="M767 535c98,62 156,115 145,139 -18,39 -218,-15 -445,-121 -228,-106 -397,-224 -379,-264 8,-17 51,-16 116,-1 -1,2 -2,4 -3,6 -50,-10 -83,-8 -90,6 -17,38 143,149 357,249 215,100 403,151 421,114 10,-22 -40,-69 -126,-124 1,-1 3,-3 4,-4z"/>
67
+   </g>
68
+  </g>
69
+ </g>
70
+</svg>
Back to file index

layer.yaml

 1
--- 
 2
+++ layer.yaml
 3
@@ -0,0 +1,14 @@
 4
+"options":
 5
+  "basic":
 6
+    "packages":
 7
+    - "unzip"
 8
+    - "rpm"
 9
+    - "php5-snmp"
10
+    "use_venv": !!bool "false"
11
+    "include_system_packages": !!bool "false"
12
+  "ibm-platform-rtm": {}
13
+"repo": "bzr+ssh://bazaar.launchpad.net/~ibmcharmers/charms/trusty/layer-ibm-platform-rtm/trunk/"
14
+"includes":
15
+- "layer:basic"
16
+- "interface:mysql-root"
17
+"is": "ibm-platform-rtm"
Back to file index

lib/charms/layer/__init__.py

 1
--- 
 2
+++ lib/charms/layer/__init__.py
 3
@@ -0,0 +1,21 @@
 4
+import os
 5
+
 6
+
 7
+class LayerOptions(dict):
 8
+    def __init__(self, layer_file, section=None):
 9
+        import yaml  # defer, might not be available until bootstrap
10
+        with open(layer_file) as f:
11
+            layer = yaml.safe_load(f.read())
12
+        opts = layer.get('options', {})
13
+        if section and section in opts:
14
+            super(LayerOptions, self).__init__(opts.get(section))
15
+        else:
16
+            super(LayerOptions, self).__init__(opts)
17
+
18
+
19
+def options(section=None, layer_file=None):
20
+    if not layer_file:
21
+        base_dir = os.environ.get('CHARM_DIR', os.getcwd())
22
+        layer_file = os.path.join(base_dir, 'layer.yaml')
23
+
24
+    return LayerOptions(layer_file, section)
Back to file index

lib/charms/layer/basic.py

  1
--- 
  2
+++ lib/charms/layer/basic.py
  3
@@ -0,0 +1,159 @@
  4
+import os
  5
+import sys
  6
+import shutil
  7
+import platform
  8
+from glob import glob
  9
+from subprocess import check_call
 10
+
 11
+from charms.layer.execd import execd_preinstall
 12
+
 13
+
 14
+def bootstrap_charm_deps():
 15
+    """
 16
+    Set up the base charm dependencies so that the reactive system can run.
 17
+    """
 18
+    # execd must happen first, before any attempt to install packages or
 19
+    # access the network, because sites use this hook to do bespoke
 20
+    # configuration and install secrets so the rest of this bootstrap
 21
+    # and the charm itself can actually succeed. This call does nothing
 22
+    # unless the operator has created and populated $CHARM_DIR/exec.d.
 23
+    execd_preinstall()
 24
+    # ensure that $CHARM_DIR/bin is on the path, for helper scripts
 25
+    os.environ['PATH'] += ':%s' % os.path.join(os.environ['CHARM_DIR'], 'bin')
 26
+    venv = os.path.abspath('../.venv')
 27
+    vbin = os.path.join(venv, 'bin')
 28
+    vpip = os.path.join(vbin, 'pip')
 29
+    vpy = os.path.join(vbin, 'python')
 30
+    if os.path.exists('wheelhouse/.bootstrapped'):
 31
+        from charms import layer
 32
+        cfg = layer.options('basic')
 33
+        if cfg.get('use_venv') and '.venv' not in sys.executable:
 34
+            # activate the venv
 35
+            os.environ['PATH'] = ':'.join([vbin, os.environ['PATH']])
 36
+            reload_interpreter(vpy)
 37
+        return
 38
+    # bootstrap wheelhouse
 39
+    if os.path.exists('wheelhouse'):
 40
+        with open('/root/.pydistutils.cfg', 'w') as fp:
 41
+            # make sure that easy_install also only uses the wheelhouse
 42
+            # (see https://github.com/pypa/pip/issues/410)
 43
+            charm_dir = os.environ['CHARM_DIR']
 44
+            fp.writelines([
 45
+                "[easy_install]\n",
 46
+                "allow_hosts = ''\n",
 47
+                "find_links = file://{}/wheelhouse/\n".format(charm_dir),
 48
+            ])
 49
+        apt_install(['python3-pip', 'python3-setuptools', 'python3-yaml'])
 50
+        from charms import layer
 51
+        cfg = layer.options('basic')
 52
+        # include packages defined in layer.yaml
 53
+        apt_install(cfg.get('packages', []))
 54
+        # if we're using a venv, set it up
 55
+        if cfg.get('use_venv'):
 56
+            if not os.path.exists(venv):
 57
+                distname, version, series = platform.linux_distribution()
 58
+                if series in ('precise', 'trusty'):
 59
+                    apt_install(['python-virtualenv'])
 60
+                else:
 61
+                    apt_install(['virtualenv'])
 62
+                cmd = ['virtualenv', '-ppython3', '--never-download', venv]
 63
+                if cfg.get('include_system_packages'):
 64
+                    cmd.append('--system-site-packages')
 65
+                check_call(cmd)
 66
+            os.environ['PATH'] = ':'.join([vbin, os.environ['PATH']])
 67
+            pip = vpip
 68
+        else:
 69
+            pip = 'pip3'
 70
+            # save a copy of system pip to prevent `pip3 install -U pip`
 71
+            # from changing it
 72
+            if os.path.exists('/usr/bin/pip'):
 73
+                shutil.copy2('/usr/bin/pip', '/usr/bin/pip.save')
 74
+        # need newer pip, to fix spurious Double Requirement error:
 75
+        # https://github.com/pypa/pip/issues/56
 76
+        check_call([pip, 'install', '-U', '--no-index', '-f', 'wheelhouse',
 77
+                    'pip'])
 78
+        # install the rest of the wheelhouse deps
 79
+        check_call([pip, 'install', '-U', '--no-index', '-f', 'wheelhouse'] +
 80
+                   glob('wheelhouse/*'))
 81
+        if not cfg.get('use_venv'):
 82
+            # restore system pip to prevent `pip3 install -U pip`
 83
+            # from changing it
 84
+            if os.path.exists('/usr/bin/pip.save'):
 85
+                shutil.copy2('/usr/bin/pip.save', '/usr/bin/pip')
 86
+                os.remove('/usr/bin/pip.save')
 87
+        os.remove('/root/.pydistutils.cfg')
 88
+        # flag us as having already bootstrapped so we don't do it again
 89
+        open('wheelhouse/.bootstrapped', 'w').close()
 90
+        # Ensure that the newly bootstrapped libs are available.
 91
+        # Note: this only seems to be an issue with namespace packages.
 92
+        # Non-namespace-package libs (e.g., charmhelpers) are available
 93
+        # without having to reload the interpreter. :/
 94
+        reload_interpreter(vpy if cfg.get('use_venv') else sys.argv[0])
 95
+
 96
+
 97
+def reload_interpreter(python):
 98
+    """
 99
+    Reload the python interpreter to ensure that all deps are available.
100
+
101
+    Newly installed modules in namespace packages sometimes seemt to
102
+    not be picked up by Python 3.
103
+    """
104
+    os.execle(python, python, sys.argv[0], os.environ)
105
+
106
+
107
+def apt_install(packages):
108
+    """
109
+    Install apt packages.
110
+
111
+    This ensures a consistent set of options that are often missed but
112
+    should really be set.
113
+    """
114
+    if isinstance(packages, (str, bytes)):
115
+        packages = [packages]
116
+
117
+    env = os.environ.copy()
118
+
119
+    if 'DEBIAN_FRONTEND' not in env:
120
+        env['DEBIAN_FRONTEND'] = 'noninteractive'
121
+
122
+    cmd = ['apt-get',
123
+           '--option=Dpkg::Options::=--force-confold',
124
+           '--assume-yes',
125
+           'install']
126
+    check_call(cmd + packages, env=env)
127
+
128
+
129
+def init_config_states():
130
+    import yaml
131
+    from charmhelpers.core import hookenv
132
+    from charms.reactive import set_state
133
+    from charms.reactive import toggle_state
134
+    config = hookenv.config()
135
+    config_defaults = {}
136
+    config_defs = {}
137
+    config_yaml = os.path.join(hookenv.charm_dir(), 'config.yaml')
138
+    if os.path.exists(config_yaml):
139
+        with open(config_yaml) as fp:
140
+            config_defs = yaml.safe_load(fp).get('options', {})
141
+            config_defaults = {key: value.get('default')
142
+                               for key, value in config_defs.items()}
143
+    for opt in config_defs.keys():
144
+        if config.changed(opt):
145
+            set_state('config.changed')
146
+            set_state('config.changed.{}'.format(opt))
147
+        toggle_state('config.set.{}'.format(opt), config.get(opt))
148
+        toggle_state('config.default.{}'.format(opt),
149
+                     config.get(opt) == config_defaults[opt])
150
+    hookenv.atexit(clear_config_states)
151
+
152
+
153
+def clear_config_states():
154
+    from charmhelpers.core import hookenv, unitdata
155
+    from charms.reactive import remove_state
156
+    config = hookenv.config()
157
+    remove_state('config.changed')
158
+    for opt in config.keys():
159
+        remove_state('config.changed.{}'.format(opt))
160
+        remove_state('config.set.{}'.format(opt))
161
+        remove_state('config.default.{}'.format(opt))
162
+    unitdata.kv().flush()
Back to file index

lib/charms/layer/execd.py

  1
--- 
  2
+++ lib/charms/layer/execd.py
  3
@@ -0,0 +1,138 @@
  4
+# Copyright 2014-2016 Canonical Limited.
  5
+#
  6
+# This file is part of layer-basic, the reactive base layer for Juju.
  7
+#
  8
+# charm-helpers is free software: you can redistribute it and/or modify
  9
+# it under the terms of the GNU Lesser General Public License version 3 as
 10
+# published by the Free Software Foundation.
 11
+#
 12
+# charm-helpers is distributed in the hope that it will be useful,
 13
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
 14
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15
+# GNU Lesser General Public License for more details.
 16
+#
 17
+# You should have received a copy of the GNU Lesser General Public License
 18
+# along with charm-helpers.  If not, see <http://www.gnu.org/licenses/>.
 19
+
 20
+# This module may only import from the Python standard library.
 21
+import os
 22
+import sys
 23
+import subprocess
 24
+import time
 25
+
 26
+'''
 27
+execd/preinstall
 28
+
 29
+It is often necessary to configure and reconfigure machines
 30
+after provisioning, but before attempting to run the charm.
 31
+Common examples are specialized network configuration, enabling
 32
+of custom hardware, non-standard disk partitioning and filesystems,
 33
+adding secrets and keys required for using a secured network.
 34
+
 35
+The reactive framework's base layer invokes this mechanism as
 36
+early as possible, before any network access is made or dependencies
 37
+unpacked or non-standard modules imported (including the charms.reactive
 38
+framework itself).
 39
+
 40
+Operators needing to use this functionality may branch a charm and
 41
+create an exec.d directory in it. The exec.d directory in turn contains
 42
+one or more subdirectories, each of which contains an executable called
 43
+charm-pre-install and any other required resources. The charm-pre-install
 44
+executables are run, and if successful, state saved so they will not be
 45
+run again.
 46
+
 47
+    $CHARM_DIR/exec.d/mynamespace/charm-pre-install
 48
+
 49
+An alternative to branching a charm is to compose a new charm that contains
 50
+the exec.d directory, using the original charm as a layer,
 51
+
 52
+A charm author could also abuse this mechanism to modify the charm
 53
+environment in unusual ways, but for most purposes it is saner to use
 54
+charmhelpers.core.hookenv.atstart().
 55
+'''
 56
+
 57
+
 58
+def default_execd_dir():
 59
+    return os.path.join(os.environ['CHARM_DIR'], 'exec.d')
 60
+
 61
+
 62
+def execd_module_paths(execd_dir=None):
 63
+    """Generate a list of full paths to modules within execd_dir."""
 64
+    if not execd_dir:
 65
+        execd_dir = default_execd_dir()
 66
+
 67
+    if not os.path.exists(execd_dir):
 68
+        return
 69
+
 70
+    for subpath in os.listdir(execd_dir):
 71
+        module = os.path.join(execd_dir, subpath)
 72
+        if os.path.isdir(module):
 73
+            yield module
 74
+
 75
+
 76
+def execd_submodule_paths(command, execd_dir=None):
 77
+    """Generate a list of full paths to the specified command within exec_dir.
 78
+    """
 79
+    for module_path in execd_module_paths(execd_dir):
 80
+        path = os.path.join(module_path, command)
 81
+        if os.access(path, os.X_OK) and os.path.isfile(path):
 82
+            yield path
 83
+
 84
+
 85
+def execd_sentinel_path(submodule_path):
 86
+    module_path = os.path.dirname(submodule_path)
 87
+    execd_path = os.path.dirname(module_path)
 88
+    module_name = os.path.basename(module_path)
 89
+    submodule_name = os.path.basename(submodule_path)
 90
+    return os.path.join(execd_path,
 91
+                        '.{}_{}.done'.format(module_name, submodule_name))
 92
+
 93
+
 94
+def execd_run(command, execd_dir=None, stop_on_error=True, stderr=None):
 95
+    """Run command for each module within execd_dir which defines it."""
 96
+    if stderr is None:
 97
+        stderr = sys.stdout
 98
+    for submodule_path in execd_submodule_paths(command, execd_dir):
 99
+        # Only run each execd once. We cannot simply run them in the
100
+        # install hook, as potentially storage hooks are run before that.
101
+        # We cannot rely on them being idempotent.
102
+        sentinel = execd_sentinel_path(submodule_path)
103
+        if os.path.exists(sentinel):
104
+            continue
105
+
106
+        try:
107
+            subprocess.check_call([submodule_path], stderr=stderr,
108
+                                  universal_newlines=True)
109
+            with open(sentinel, 'w') as f:
110
+                f.write('{} ran successfully {}\n'.format(submodule_path,
111
+                                                          time.ctime()))
112
+                f.write('Removing this file will cause it to be run again\n')
113
+        except subprocess.CalledProcessError as e:
114
+            # Logs get the details. We can't use juju-log, as the
115
+            # output may be substantial and exceed command line
116
+            # length limits.
117
+            print("ERROR ({}) running {}".format(e.returncode, e.cmd),
118
+                  file=stderr)
119
+            print("STDOUT<<EOM", file=stderr)
120
+            print(e.output, file=stderr)
121
+            print("EOM", file=stderr)
122
+
123
+            # Unit workload status gets a shorter fail message.
124
+            short_path = os.path.relpath(submodule_path)
125
+            block_msg = "Error ({}) running {}".format(e.returncode,
126
+                                                       short_path)
127
+            try:
128
+                subprocess.check_call(['status-set', 'blocked', block_msg],
129
+                                      universal_newlines=True)
130
+                if stop_on_error:
131
+                    sys.exit(0)  # Leave unit in blocked state.
132
+            except Exception:
133
+                pass  # We care about the exec.d/* failure, not status-set.
134
+
135
+            if stop_on_error:
136
+                sys.exit(e.returncode or 1)  # Error state for pre-1.24 Juju
137
+
138
+
139
+def execd_preinstall(execd_dir=None):
140
+    """Run charm-pre-install for each module within execd_dir."""
141
+    execd_run('charm-pre-install', execd_dir=execd_dir)
Back to file index

metadata.yaml

 1
--- 
 2
+++ metadata.yaml
 3
@@ -0,0 +1,62 @@
 4
+"name": "ibm-platform-rtm"
 5
+"summary": "IBM Platform RTM is a dashboard for IBM Platform LSF"
 6
+"maintainer": "IBM Juju Support Team <jujusupp@us.ibm.com>"
 7
+"description": |
 8
+  IBM Platform RTM is an operational dashboard for IBM Platform LSF environments that provides comprehensive workload monitoring, reporting and management.
 9
+  It makes cluster administrators more efficient in their day-to-day activities and provides the information and tools needed to improve cluster efficiency,
10
+  enable better user productivity, and contain or reduce costs.
11
+"tags":
12
+- "ibm"
13
+- "apt"
14
+- "leadership"
15
+- "lsf_dashboard"
16
+- "workload_management"
17
+- "job_scheduler"
18
+"requires":
19
+  "db":
20
+    "interface": "mysql-root"
21
+    "scope": "container"
22
+"resources":
23
+  "ibm_prtm_installer":
24
+    "type": "file"
25
+    "filename": "rtm-poller-9.1.4-ub14-ppc64le.tar.gz"
26
+    "description": "IBM Platform RTM installation package"
27
+  "ibm_prtm_installer1":
28
+    "type": "file"
29
+    "filename": "rtm-server-9.1.4-ub14-ppc64le.tar.gz"
30
+    "description": "IBM Platform RTm file."
31
+  "ibm_prtm_installers":
32
+    "type": "file"
33
+    "filename": "plugin%3Aboost-v4.3-1.tgz"
34
+    "description": "Plugin"
35
+  "ibm_prtm_installers1":
36
+    "type": "file"
37
+    "filename": "plugin%3Aclog-v1.6-1.tgz"
38
+    "description": "Plugin"
39
+  "ibm_prtm_installers2":
40
+    "type": "file"
41
+    "filename": "plugin%3Anectar-v0.34-1.tgz"
42
+    "description": "Plugin"
43
+  "ibm_prtm_installers3":
44
+    "type": "file"
45
+    "filename": "cacti-plugin-0.8.7g-PA-v2.9.tar.gz"
46
+    "description": "Plugin"
47
+  "ibm_prtm_installers4":
48
+    "type": "file"
49
+    "filename": "plugin%3Asettings-v0.71-1.tgz"
50
+    "description": "Plugin"
51
+  "ibm_prtm_installers5":
52
+    "type": "file"
53
+    "filename": "plugin%3Asuperlinks-v1.4-2.tgz"
54
+    "description": "Plugin"
55
+  "ibm_prtm_installers6":
56
+    "type": "file"
57
+    "filename": "adodb492.tgz"
58
+    "description": "Plugin"
59
+  "ibm_prtm_installers7":
60
+    "type": "file"
61
+    "filename": "plugin%3Asyslog-v1.22-2.tgz"
62
+    "description": "Plugin"
63
+"subordinate": !!bool "true"
64
+"terms":
65
+- "ibm-rtm/1"
Back to file index

reactive/ibm-platform-rtm.sh

  1
--- 
  2
+++ reactive/ibm-platform-rtm.sh
  3
@@ -0,0 +1,187 @@
  4
+#!/bin/bash
  5
+set -ex
  6
+source charms.reactive.sh
  7
+ARCHITECTURE=`uname -m`
  8
+# Installation Manager install path
  9
+PRTM_INSTALL_PATH="/opt/IBM/InstallationManager"
 10
+RTM_TOP="/opt/IBM/rtm"
 11
+
 12
+@when_not 'ibm-prtm-prerequisite.install'
 13
+function ibm_prtm_prerequisite(){
 14
+        juju-log "IBM PLATFORM RTM: Begin Prerequisite Install "
 15
+        # To check for supported platform
 16
+        if [ "$ARCHITECTURE" != "ppc64le" ]; then
 17
+                juju-log "IBM PLATFORM RTM: Unsupported platform. IBM Platform RTM installed with this Charm supports only the POWER LE (ppc64le) platforms."
 18
+                status-set blocked "Unsupported Platform"
 19
+                retun 0
 20
+        fi
 21
+        ARCHIVE_DIR=/var/lib/juju/agents/*rtm*/charm/files/archives
 22
+        status-set maintenance "Installing prerequisite packages"
 23
+        juju-log "IBM PLATFORM RTM : Opening port 80 "
 24
+        iptables -A INPUT -p tcp --dport 80 -j ACCEPT
 25
+        juju-log "IBM PLATFORM RTM : Port number 80 opened and firewall has been disabled successfully."
 26
+
 27
+        # Install tar
 28
+        juju-log "IBM PLATFORM RTM : Download and Install tar"
 29
+        apt-get -y install tar
 30
+        juju-log "IBM PLATFORM RTM : tar downloaded and installed successfully."
 31
+        juju-log "IBM PLATFORM RTM: End Prerequisite Install "
 32
+        status-set active "Prerequisite Packages Installed"
 33
+
 34
+        # Get the installable resource
 35
+        juju-log "IBM PLATFORM RTM: fetching the ibm_prtm_installer resource"
 36
+        status-set maintenance "fetching the ibm_prtm_installer resource"
 37
+        cfg_prtm_pkg_name=`resource-get 'ibm_prtm_installer' || echo unavailable`
 38
+        cfg_prtm_pkg_name1=`resource-get 'ibm_prtm_installer1' || echo unavailable`
 39
+        cfg_prtm_plugin_name=`resource-get 'ibm_prtm_installers' || echo unavailable`
 40
+        cfg_prtm_plugin_name1=`resource-get 'ibm_prtm_installers1' || echo unavailable`
 41
+        cfg_prtm_plugin_name2=`resource-get 'ibm_prtm_installers2' || echo unavailable`
 42
+        cfg_prtm_plugin_name3=`resource-get 'ibm_prtm_installers3' || echo unavailable`
 43
+        cfg_prtm_plugin_name4=`resource-get 'ibm_prtm_installers4' || echo unavailable`
 44
+        cfg_prtm_plugin_name5=`resource-get 'ibm_prtm_installers5' || echo unavailable`
 45
+        cfg_prtm_plugin_name6=`resource-get 'ibm_prtm_installers6' || echo unavailable`
 46
+        cfg_prtm_plugin_name7=`resource-get 'ibm_prtm_installers7' || echo unavailable`
 47
+        # If we don't have a package, report blocked status; we can't proceed.
 48
+        if [ "$cfg_prtm_pkg_name1" = "unavailable" -a "$cfg_prtm_pkg_name" = "unavailable" -a "$cfg_prtm_plugin_name" = "unavailable" -a "$cfg_prtm_plugin_name1" = "unavailable" -a "$cfg_prtm_plugin_name2" = "unavailable" -a "$cfg_prtm_plugin_name3" = "unavailable" -a "$cfg_prtm_plugin_name4" = "unavailable" -a "$cfg_prtm_plugin_name5" = "unavailable" -a "$cfg_prtm_plugin_name6" = "unavailable" -a "$cfg_prtm_plugin_name7" = "unavailable" ]; then
 49
+                juju-log "IBM PLATFORM RTM: missing required ibm_prtm_installer resource"
 50
+                status-set blocked "missing required ibm_prtm_installer resource"
 51
+                return 0
 52
+        fi
 53
+        set_state 'ibm-prtm-prerequisite.install'
 54
+}
 55
+
 56
+check_mariadb_inst(){
 57
+        mysql -u root -p`sudo cat /var/lib/mysql/mysql.passwd`
 58
+        if [ $? == 0 ]
 59
+        then 
 60
+                echo "True"
 61
+        else
 62
+                service mysql start
 63
+                mysql -u root -p`sudo cat /var/lib/mysql/mysql.passwd`
 64
+                if [ $? == 0 ]; then
 65
+                        echo "True"
 66
+                else
 67
+                        echo "False"
 68
+                fi
 69
+        fi
 70
+}
 71
+
 72
+check_database_inst(){
 73
+        db_inst=`check_mariadb_inst`
 74
+        if [ $db_inst == False ]; then
 75
+                juju-log "IBM PLATFORM RTM : Database is not installed"
 76
+                status-set blocked "Database is not installed"
 77
+        return 1
 78
+        fi
 79
+}
 80
+
 81
+@when 'ibm-prtm-prerequisite.install' 
 82
+@when_not 'ibm-prtm-database.available'
 83
+function mariadb_install_check(){
 84
+        check_database_inst
 85
+        set_state 'ibm-prtm-database.available'
 86
+        status-set active "Mariadb is Installed"
 87
+}
 88
+#check whethere RTM is installed
 89
+is_prtm_installed(){
 90
+        if [ -d $RTM_TOP/bin ]; then
 91
+                echo "True"
 92
+        else
 93
+                echo "False"
 94
+        fi
 95
+}
 96
+update_install_file()
 97
+{
 98
+        juju-log  "IBM PLATFORM RTM : Updation install file for $1 $2 $3"
 99
+        if grep -q "# $1" $3
100
+        then
101
+                sed -i "/# $1/c$1='$2'" $3
102
+        else
103
+                sed -i "s|$1.*|$1='$2'|" $3
104
+        fi
105
+}
106
+
107
+ibm_prtm_INSTALL()
108
+{
109
+        db_pass=`sudo cat /var/lib/mysql/mysql.passwd`
110
+        mysql_password=$db_pass
111
+        juju-log "IBM PLATFORM RTM : Begin RTM INSTALL"
112
+        prtm_inst=`is_prtm_installed`
113
+        if [ $prtm_inst == False ]; then
114
+                juju-log "IBM PLATFORM RTM : Rtm is not installed"
115
+                cfg_prtm_pkg_name1="/var/lib/juju/agents/*rtm*/resources/ibm_prtm_installer1/*"
116
+                cp $cfg_prtm_pkg_name1 /var/lib/juju/agents/*rtm*/resources
117
+                cfg_prtm_plugin_name="/var/lib/juju/agents/*rtm*/resources/ibm_prtm_installers/*"
118
+                cp $cfg_prtm_plugin_name /var/lib/juju/agents/*rtm*/resources
119
+                cfg_prtm_plugin_name1="/var/lib/juju/agents/*rtm*/resources/ibm_prtm_installers1/*"
120
+                cp $cfg_prtm_plugin_name1 /var/lib/juju/agents/*rtm*/resources
121
+                cfg_prtm_plugin_name2="/var/lib/juju/agents/*rtm*/resources/ibm_prtm_installers2/*"
122
+                cp $cfg_prtm_plugin_name2 /var/lib/juju/agents/*rtm*/resources
123
+                cfg_prtm_plugin_name3="/var/lib/juju/agents/*rtm*/resources/ibm_prtm_installers3/*"
124
+                cp $cfg_prtm_plugin_name3 /var/lib/juju/agents/*rtm*/resources
125
+                cfg_prtm_plugin_name4="/var/lib/juju/agents/*rtm*/resources/ibm_prtm_installers4/*"
126
+                cp $cfg_prtm_plugin_name4 /var/lib/juju/agents/*rtm*/resources
127
+                cfg_prtm_plugin_name5="/var/lib/juju/agents/*rtm*/resources/ibm_prtm_installers5/*"
128
+		cp $cfg_prtm_plugin_name5 /var/lib/juju/agents/*rtm*/resources
129
+		cfg_prtm_plugin_name6="/var/lib/juju/agents/*rtm*/resources/ibm_prtm_installers6/*"
130
+		cp $cfg_prtm_plugin_name6 /var/lib/juju/agents/*rtm*/resources
131
+                cfg_prtm_plugin_name7="/var/lib/juju/agents/*rtm*/resources/ibm_prtm_installers7/*"
132
+                cp $cfg_prtm_plugin_name7 /var/lib/juju/agents/*rtm*/resources
133
+                cd /var/lib/juju/agents/*rtm*/resources 
134
+  
135
+                juju-log " IBM PLATFORM RTM : Extracting the Installer packages"           
136
+                res_name=`resource-get 'ibm_prtm_installer'`
137
+                tar -zxvf $res_name
138
+                if [ $? != 0 ]; then
139
+                        juju-log "IBM PLATFORM RTM : Unable to extract the RTM installer package content. Verify whether the package is corrupt."
140
+                        # Remove corrupt archive file
141
+                        rm *poller*.tar.gz
142
+                        return 0
143
+                 else 
144
+                        juju-log "IBM PLATFORM RTM : installer packages extracted successfully"
145
+                        juju-log "IBM PLATFORM RTM : Platform RTM will be installed if you run (juju add-relation mariadb platform-rtm) command."
146
+                        status-set active "IBM PLATFORM RTM : installer packages extraced"
147
+
148
+                 fi
149
+                 rm -f /var/lib/mysql/ib_logfile*
150
+                 service mysql stop
151
+                 rm -f /var/lib/mysql/ibdata*
152
+                 cd /var/lib/juju/agents/*rtm*/resources/NOOSS/ppc64
153
+                 juju-log "IBM PLATFORM RTM : Installing Platformat RTM"
154
+                 update_install_file "OPTIMIZE_MYSQL" "N" "install.config"
155
+                 update_install_file "DB_PASSWORD" "$mysql_password" "install.config"
156
+                 #Running install command
157
+                 juju-log "IBM PLATFORM RTM: Running installation command for platform RTM"
158
+                sed -i '/LAPApp.jar/,+8d' rtm_install.sh
159
+                sed -i 's/rsyslog-mysql//g' rtm_install.sh
160
+                ln -sf bash /bin/sh
161
+                echo "Y" | sh rtm_install.sh -f install.config
162
+                if [ $? == 0 ]; then
163
+                        juju-log "IBM PLATFORM RTM :  installed successfully"
164
+                        status-set active "RTM Installed"
165
+                else
166
+                        juju-log "IBM PLATFORM RTM : Error while installing IBM pLATFORM rtm"
167
+                        status-set blocked "Error while installing IBM Platform RTM"
168
+                        return 1
169
+                fi
170
+                service lsfpollerd status; service licpollerd status; service advocate status
171
+                if [ $? == 0 ]; then
172
+                        juju-log "IBM PLATFORM RTM : RTM installed successfully and RTM services are up and running!"
173
+                else
174
+                        juju-log "IBM PLATFROM RTM : Error while installing IBM Platform RTM"
175
+                        status-set blocked "Error"
176
+                        return 1
177
+                fi
178
+         else
179
+                juju-log "IBM PLATFORM RTM : RTM IS ALREADY INSTALLED"
180
+         fi
181
+}
182
+
183
+@when 'ibm-prtm-database.available'
184
+@when_not 'ibm-prtm.available'
185
+function ibm_prtm_install(){
186
+         ibm_prtm_INSTALL
187
+         set_state 'ibm-prtm.available'
188
+         status-set active "ibm platform rtm installed"
189
+}
190
+reactive_handler_main
Back to file index

requirements.txt

1
--- 
2
+++ requirements.txt
3
@@ -0,0 +1,2 @@
4
+flake8
5
+pytest
Back to file index

revision

1
--- 
2
+++ revision
3
@@ -0,0 +1 @@
4
+0
Back to file index

tests/01-deploy.py

 1
--- 
 2
+++ tests/01-deploy.py
 3
@@ -0,0 +1,30 @@
 4
+#!/usr/bin/env python3
 5
+
 6
+import unittest
 7
+import amulet
 8
+import re
 9
+
10
+
11
+class TestDeploy(unittest.TestCase):
12
+    """
13
+    Deployment test for the IBM PLATFORM RTM charm.
14
+    This charm install Mariadb RTM and then add relation between them.
15
+    """
16
+    def setUp(self):
17
+        self.d = amulet.Deployment(series='trusty')
18
+        self.d.add('mariadb')
19
+        self.d.configure('mariadb', {'series': '5.5'})
20
+        self.d.add('cs:~ibmcharmers/trusty/ibm-platform-rtm')
21
+        self.d.relate('ibm-platform-rtm', 'mariadb')
22
+        self.d.setup(timeout=900)
23
+        self.d.sentry.wait(timeout=1800)
24
+
25
+
26
+def test_deploy_with_placeholder_resource(self):
27
+        # The status message when using placeholder resources will include the
28
+        # string "ibm_platform_rtm_installer resource".
29
+        sentry_re = re.compile('ibm_platform_rtm_installer resource')
30
+        self.d.sentry.wait_for_messages({"ibm-platform-rtm": sentry_re})
31
+
32
+if __name__ == '__main__':
33
+    unittest.main()
Back to file index

tests/tests.yaml

1
--- 
2
+++ tests/tests.yaml
3
@@ -0,0 +1,5 @@
4
+packages:
5
+  - amulet
6
+  - python3
7
+  - unzip
8
+
Back to file index

tox.ini

 1
--- 
 2
+++ tox.ini
 3
@@ -0,0 +1,12 @@
 4
+[tox]
 5
+skipsdist=True
 6
+envlist = py34, py35
 7
+skip_missing_interpreters = True
 8
+
 9
+[testenv]
10
+commands = py.test -v
11
+deps =
12
+    -r{toxinidir}/requirements.txt
13
+
14
+[flake8]
15
+exclude=docs