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