changed/added license heading. Moved some json files to yaml
[osm/openvim.git] / charm / openvim / layer-openvim / reactive / openvim.py
1 ##
2 # Copyright 2016
3 # This file is part of openvim
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License"); you may
6 # not use this file except in compliance with the License. You may obtain
7 # 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, WITHOUT
13 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 # License for the specific language governing permissions and limitations
15 # under the License.
16 #
17 ##
18
19 import os
20 import json
21 import time
22 import subprocess
23 from git import Repo as gitrepo
24 from shutil import rmtree
25
26 from charms.reactive import when, when_not, set_state
27 from charmhelpers.core.templating import render
28 from charmhelpers.core.hookenv import (
29 status_set,
30 leader_set,
31 leader_get,
32 unit_public_ip,
33 )
34 from charmhelpers.core.unitdata import kv
35 from charmhelpers.core.host import (
36 symlink,
37 mkdir,
38 chownr,
39 service_start,
40 )
41 from charmhelpers.contrib.unison import (
42 create_private_key,
43 create_public_key,
44 ensure_user,
45 )
46
47
48 def sh(cmd):
49 return subprocess.check_output(cmd, shell=True)
50
51
52 def sh_as_openvim(cmd):
53 return sh('sudo -iu openvim ' + cmd)
54
55
56 def create_openvim_user():
57 status_set("maintenance", "Creating OpenVIM user")
58 ensure_user('openvim')
59
60
61 def initialize_openvim_database(db):
62 status_set("maintenance", "Initializing OpenVIM database")
63 sh_as_openvim("/opt/openmano/openvim/database_utils/init_vim_db.sh -u %s -p %s -d %s -h %s" % (
64 db.user(),
65 db.password(),
66 db.database(),
67 db.host()
68 ))
69
70
71 def generate_ssh_key():
72 status_set("maintenance", "Generating ssh key")
73 user = "openvim"
74 folder = "/home/%s/.ssh" % user
75 mkdir(folder, owner=user, group=user, perms=0o775)
76 private_path = "%s/id_rsa" % folder
77 public_path = "%s.pub" % private_path
78 create_private_key(user, private_path)
79 create_public_key(user, private_path, public_path)
80
81
82 def add_openvim_to_path():
83 status_set("maintenance", "Adding OpenVIM to path")
84 symlink(
85 '/opt/openmano/scripts/service-openmano.sh',
86 '/usr/bin/service-openmano')
87 symlink('/opt/openmano/openvim/openvim', '/usr/bin/openvim')
88
89
90 def download_openvim():
91 status_set("maintenance", "Downloading OpenVIM")
92 if os.path.isdir("/opt/openmano"):
93 rmtree("/opt/openmano")
94 gitrepo.clone_from('https://github.com/tvansteenburgh/openmano.git', '/opt/openmano')
95 chownr('/opt/openmano', owner='openvim', group='openvim', follow_links=False, chowntopdir=True)
96
97
98 def configure_openvim(db):
99 status_set("maintenance", "Configuring OpenVIM")
100 render(
101 source="openvimd.cfg",
102 target="/opt/openmano/openvim/openvimd.cfg",
103 owner="openvim",
104 perms=0o664,
105 context={"db": db}
106 )
107
108
109 # TODO: possibly combine all of these create functions?
110 def create_tenant():
111 status_set("maintenance", "Creating tenant")
112 render(source="tenant.yaml", target="/tmp/tenant.yaml", owner="openvim", perms=0o664, context={})
113 cmd = 'openvim tenant-create /tmp/tenant.yaml'
114 tenant_uuid = sh_as_openvim(cmd).split()[0]
115 tenant_uuid = str(tenant_uuid, 'utf-8')
116 leader_set({'tenant': tenant_uuid})
117 return tenant_uuid
118
119
120 def create_image():
121 status_set("maintenance", "Creating image")
122 render(source="image.yaml", target="/tmp/image.yaml", owner="openvim", perms=0o664, context={})
123 cmd = 'openvim image-create /tmp/image.yaml'
124 image_uuid = sh_as_openvim(cmd).split()[0]
125 image_uuid = str(image_uuid, 'utf-8')
126 return image_uuid
127
128
129 def create_flavor():
130 status_set("maintenance", "Creating flavor")
131 render(source="flavor.yaml", target="/tmp/flavor.yaml", owner="openvim", perms=0o664, context={})
132 cmd = 'openvim flavor-create /tmp/flavor.yaml'
133 flavor_uuid = sh_as_openvim(cmd).split()[0]
134 flavor_uuid = str(flavor_uuid, 'utf-8')
135 return flavor_uuid
136
137
138 # TODO: especially combine these stupid network functions
139 def create_default_network():
140 status_set("maintenance", "Creating default network")
141 render(source="net-default.yaml", target="/tmp/net-default.yaml", owner="openvim", perms=0o664, context={})
142 cmd = 'openvim net-create /tmp/net-default.yaml'
143 net_default_uuid = sh_as_openvim(cmd).split()[0]
144 net_default_uuid = str(net_default_uuid, 'utf-8')
145 return net_default_uuid
146
147
148 def create_virbr_network():
149 status_set("maintenance", "Creating virbr0 network")
150 render(source="net-virbr0.yaml", target="/tmp/net-virbr0.yaml", owner="openvim", perms=0o664, context={})
151 cmd = 'openvim net-create /tmp/net-virbr0.yaml'
152 net_virbr0_uuid = sh_as_openvim(cmd).split()[0]
153 net_virbr0_uuid = str(net_virbr0_uuid, 'utf-8')
154 return net_virbr0_uuid
155
156
157 def create_vm_yaml(image_uuid, flavor_uuid, net_default_uuid, net_virbr0_uuid):
158 status_set("maintenance", "Creating default VM yaml file")
159 render(
160 source="server.yaml",
161 target="/tmp/server.yaml",
162 owner="openvim",
163 perms=0o664,
164 context={
165 "image_uuid": image_uuid,
166 "flavor_uuid": flavor_uuid,
167 "net_default_uuid": net_default_uuid,
168 "net_virbr0_uuid": net_virbr0_uuid
169 }
170 )
171
172
173 def create_sane_defaults():
174 tenant_uuid = create_tenant()
175 add_openvim_tenant_env_var(tenant_uuid)
176 image_uuid = create_image()
177 flavor_uuid = create_flavor()
178 net_default_uuid = create_default_network()
179 net_virbr0_uuid = create_virbr_network()
180 create_vm_yaml(
181 image_uuid=image_uuid,
182 flavor_uuid=flavor_uuid,
183 net_default_uuid=net_default_uuid,
184 net_virbr0_uuid=net_virbr0_uuid
185 )
186
187
188 def install_openvim_service():
189 status_set("maintenance", "Installing OpenVIM service")
190 if not os.path.exists('/etc/systemd/system'):
191 os.makedirs('/etc/systemd/system')
192 render(
193 source="openvim.service",
194 target="/etc/systemd/system/openvim.service",
195 owner="root",
196 perms=0o644,
197 context={}
198 )
199
200
201 def add_openvim_tenant_env_var(tenant_uuid):
202 status_set("maintenance", "Adding OPENVIM_TENANT environment variable")
203 env_line = 'export OPENVIM_TENANT=%s\n' % tenant_uuid
204 with open('/home/openvim/.profile', 'w+') as f:
205 lines = f.readlines()
206 for line in lines:
207 if env_line == line:
208 return
209 f.seek(0)
210 f.truncate()
211 for line in lines:
212 f.write(line)
213 f.write(env_line)
214
215
216 def openvim_running():
217 try:
218 sh_as_openvim('openvim tenant-list')
219 return True
220 except:
221 return False
222
223
224 def start_openvim():
225 status_set("maintenance", "Starting OpenVIM")
226 service_start('openvim')
227 t0 = time.time()
228 while not openvim_running():
229 if time.time() - t0 > 60:
230 raise Exception('Failed to start openvim.')
231 time.sleep(0.25)
232
233
234 @when_not('db.available')
235 def not_ready():
236 status_set('waiting', 'MySQL database required')
237
238
239 @when('db.available')
240 @when_not('openvim-controller.installed')
241 def install_openvim_controller(mysql):
242 create_openvim_user()
243 download_openvim()
244 add_openvim_to_path()
245 configure_openvim(mysql)
246 initialize_openvim_database(mysql)
247 generate_ssh_key()
248 install_openvim_service()
249 start_openvim()
250 create_sane_defaults()
251 status_set(
252 'active',
253 'Up on {host}:{port}'.format(
254 host=unit_public_ip(),
255 port='9080'))
256 set_state('openvim-controller.installed')
257
258
259 @when('compute.connected', 'openvim-controller.installed')
260 def send_ssh_key(compute):
261 with open('/home/openvim/.ssh/id_rsa.pub', 'r') as f:
262 key = f.read().strip()
263 compute.send_ssh_key(key)
264
265
266 @when('compute.available', 'openvim-controller.installed')
267 def host_add(compute):
268 cache = kv()
269 for node in compute.authorized_nodes():
270 if cache.get("compute:" + node['address']):
271 continue
272 cmd = "ssh -n -o 'StrictHostKeyChecking no' %s@%s"
273 sh_as_openvim(cmd % (node['user'], node['address']))
274 data = {
275 'host': {
276 'name': 'compute-0',
277 'user': node['user'],
278 'ip_name': node['address'],
279 'description': 'compute-0'
280 }
281 }
282 with open('/tmp/compute-0.json', 'w') as f:
283 json.dump(data, f, indent=4, sort_keys=True)
284 # TODO: openvim run function!
285 sh_as_openvim('openvim host-add /tmp/compute-0.json')
286 cache.set('compute:' + node['address'], True)
287
288
289 @when('openvim-controller.available')
290 def openvim_available(openvim):
291 openvim.configure(port=9080, user=leader_get('tenant'))