Fix 1475 - Incorrect description in instantiating error
[osm/RO.git] / charms / layers / openmano / reactive / layer_openmano.py
1 from git import Repo as gitrepo
2 from shutil import rmtree
3
4 import os
5 import subprocess
6
7 from charmhelpers.core import host
8 from charmhelpers.core import hookenv
9 from charmhelpers.core import templating
10 from charmhelpers.core.unitdata import kv
11 from charmhelpers.core.hookenv import (
12 config,
13 log,
14 open_port,
15 status_set,
16 )
17
18 from charmhelpers.core.host import (
19 chownr,
20 )
21
22 from charms.reactive import (
23 when,
24 when_not,
25 set_state,
26 is_state,
27 )
28
29 kvdb = kv()
30
31 INSTALL_PATH = '/opt/openmano'
32 USER = 'openmanod'
33
34
35 @when('openmano.installed', 'openmano.available')
36 def openmano_available(openmano):
37 # TODO make this configurable via charm config
38 openmano.configure(port=9090)
39
40
41 @when('openvim-controller.available',
42 'db.available',
43 'db.installed',
44 'openmano.installed',
45 'openmano.running',
46 )
47 def openvim_available(openvim, db):
48 for service in openvim.services():
49 for endpoint in service['hosts']:
50 host = endpoint['hostname']
51 port = endpoint['port']
52 user = endpoint['user']
53
54 openvim_uri = '{}:{}'.format(host, port)
55 if kvdb.get('openvim_uri') == openvim_uri:
56 return
57
58 # TODO: encapsulate the logic in create-datacenter.sh into python
59 try:
60 cmd = './scripts/create-datacenter.sh {} {} {} {}'.format(
61 host, port, user, kvdb.get('openmano-tenant'))
62 out, err = _run(cmd)
63 except subprocess.CalledProcessError as e:
64 # Ignore the error if the datacenter already exists.
65 if e.returncode != 153:
66 raise
67
68 kvdb.set('openvim_uri', openvim_uri)
69 if not is_state('db.available'):
70 status_set('waiting', 'Waiting for database')
71 break
72 break
73
74
75 @when('openmano.installed',
76 'db.installed',
77 'openvim-controller.available')
78 @when_not('openmano.running')
79 def start(*args):
80 # TODO: if the service fails to start, we should raise an error to the op
81 # Right now, it sets the state as running and the charm dies. Because
82 # service-openmano returns 0 when it fails.
83 cmd = "/home/{}/bin/service-openmano start".format(USER)
84 out, err = _run(cmd)
85
86 if not kvdb.get('openmano-tenant'):
87 out, err = _run('./scripts/create-tenant.sh')
88 kvdb.set('openmano-tenant', out.strip())
89
90 status_set(
91 'active',
92 'Up on {host}:{port}'.format(
93 host=hookenv.unit_public_ip(),
94 port='9090'))
95
96 set_state('openmano.running')
97
98
99 @when('db.available', 'openmano.installed')
100 @when_not('db.installed')
101 def setup_db(db):
102 """Setup the database
103
104 """
105 db_uri = 'mysql://{}:{}@{}:{}/{}'.format(
106 db.user(),
107 db.password(),
108 db.host(),
109 db.port(),
110 db.database(),
111 )
112
113 if kvdb.get('db_uri') == db_uri:
114 # We're already configured
115 return
116
117 status_set('maintenance', 'Initializing database')
118
119 try:
120 # HACK: use a packed version of init_mano_db until bug https://osm.etsi.org/bugzilla/show_bug.cgi?id=56 is fixed
121 # cmd = "{}/database_utils/init_mano_db.sh --createdb ".format(kvdb.get('repo'))
122 cmd = "./scripts//init_mano_db.sh --createdb "
123 cmd += "-u {} -p{} -h {} -d {} -P {}".format(
124 db.user(),
125 db.password(),
126 db.host(),
127 db.database(),
128 db.port(),
129 )
130 output, err = _run(cmd)
131 except subprocess.CalledProcessError:
132 # Eat this. init_mano_db.sh will return error code 1 on success
133 pass
134
135 context = {
136 'user': db.user(),
137 'password': db.password(),
138 'host': db.host(),
139 'database': db.database(),
140 'port': db.port(),
141 }
142 templating.render(
143 'openmanod.cfg',
144 os.path.join(kvdb.get('repo'), 'openmanod.cfg'),
145 context,
146 owner=USER,
147 group=USER,
148 )
149 kvdb.set('db_uri', db_uri)
150
151 status_set('active', 'Database installed.')
152 set_state('db.installed')
153
154
155 @when_not('openvim-controller.available')
156 def need_openvim():
157 status_set('waiting', 'Waiting for OpenVIM')
158
159
160 @when_not('db.available')
161 def need_db():
162 status_set('waiting', 'Waiting for database')
163
164
165 @when_not('db.available')
166 @when_not('openvim-controller.available')
167 def need_everything():
168 status_set('waiting', 'Waiting for database and OpenVIM')
169
170
171 @when_not('openmano.installed')
172 def install_layer_openmano():
173 status_set('maintenance', 'Installing')
174
175 cfg = config()
176
177 # TODO change user home
178 # XXX security issue!
179 host.adduser(USER, password=USER)
180
181 if os.path.isdir(INSTALL_PATH):
182 rmtree(INSTALL_PATH)
183
184 gitrepo.clone_from(
185 cfg['repository'],
186 INSTALL_PATH,
187 branch=cfg['branch'],
188 )
189
190 chownr(
191 INSTALL_PATH,
192 owner=USER,
193 group=USER,
194 follow_links=False,
195 chowntopdir=True
196 )
197
198 os.mkdir(os.path.join(INSTALL_PATH, 'logs'))
199 chownr(INSTALL_PATH, USER, USER)
200 kvdb.set('repo', INSTALL_PATH)
201
202 os.mkdir('/home/{}/bin'.format(USER))
203
204 os.symlink(
205 "{}/openmano".format(INSTALL_PATH),
206 "/home/{}/bin/openmano".format(USER))
207 os.symlink(
208 "{}/scripts/openmano-report.sh".format(INSTALL_PATH),
209 "/home/{}/bin/openmano-report.sh".format(USER))
210 os.symlink(
211 "{}/scripts/service-openmano.sh".format(INSTALL_PATH),
212 "/home/{}/bin/service-openmano".format(USER))
213
214 open_port(9090)
215 set_state('openmano.installed')
216
217
218 def _run(cmd, env=None):
219 if isinstance(cmd, str):
220 cmd = cmd.split() if ' ' in cmd else [cmd]
221
222 log(cmd)
223 p = subprocess.Popen(cmd,
224 env=env,
225 stdout=subprocess.PIPE,
226 stderr=subprocess.PIPE)
227 stdout, stderr = p.communicate()
228 retcode = p.poll()
229 if retcode > 0:
230 raise subprocess.CalledProcessError(
231 returncode=retcode,
232 cmd=cmd,
233 output=stderr.decode("utf-8").strip())
234 return (stdout.decode('utf-8'), stderr.decode('utf-8'))