Commit 9d86cfb8 by Karsa Zoltán István

jinja templating for cloud-init

parent 467a447e
......@@ -7,19 +7,43 @@
</p>
<div class="collapse" id="collapseExample">
<div class="card card-body">
<b> {% trans "Use keys in ci-data:" %}</b>
<b> {% trans "Use Jinja2 template syntax, values: " %}</b>
<ul>
<li>{% trans "<strong>{{hostname}}</strong> - vm hostname" %}</li>
<li>{% trans "<strong>{{sysuser}}</strong> - vm system default user (cloud)" %}</li>
<li>{% trans "<strong>{{password}}</strong> - default user sha512 password" %}</li>
<li>{% trans "<strong>{{owner}}</strong> - vm owner django username" %}</li>
<li>{% trans "<strong>{{acl.allusers}}</strong> - get all associated user's username to vm" %}</li>
<li>{% trans "<strong>{{acl.operators}}</strong> - get all associated operator level user's username to vm" %}</li>
<li>{% trans "<strong>{{acl.users}}</strong> - get all associated operator user user's username to vm" %}</li>
<li>{% trans "<strong>{{net.ipv4}}</strong> - default host ip address" %}</li>
<li>{% trans "<strong>{{net.ipv6}}</strong> - default host ipv6 address" %}</li>
<li>{% trans "<strong>{{net.[vlan_name].ipv4/ipv6}}</strong> - associated vlan ([vlan_name]) host ip addresses, example: when vm associated to vlan 'public' and vlan 'internal', we can get these ips: {{net.public.ipv4}} and {{net.internal.ipv4}}" %}</li>
<li>{% trans "<strong>{{rndstr%[length]}}</strong> - make random string with [length] charachters lenght" %}</li>
<li>{% trans "<strong>hostname</strong> - vm hostname" %}</li>
<li>{% trans "<strong>sysuser</strong> - vm system default user (cloud)" %}</li>
<li>{% trans "<strong>password</strong> - default user sha512 password" %}</li>
<li>{% trans "<strong>owner</strong> - vm owner django username" %}</li>
<li>{% trans "<strong>acl.allusers</strong> - get all associated user's username to vm (list)" %}</li>
<li>{% trans "<strong>acl.operators</strong> - get all associated operator level user's username to vm (list)" %}</li>
<li>{% trans "<strong>acl.users</strong> - get all associated operator user user's username to vm (list)" %}</li>
<li>{% trans "<strong>net.ipv4</strong> - default host ip address" %}</li>
<li>{% trans "<strong>net.ipv6</strong> - default host ipv6 address" %}</li>
<li>{% trans "<strong>net.[vlan_name].ipv4/ipv6</strong> - associated vlan ([vlan_name]) host ip addresses, example: when vm associated to vlan 'public' and vlan 'internal', we can get these ips: {{net.public.ipv4}} and {{net.internal.ipv4}}" %}</li>
<li>{% trans "<strong>ci.rndstr(len: int)</strong> - function: make random string with 'len' charachters lenght" %}</li>
</ul>
<b>Example:</b>
<pre>{% verbatim %}
#cloud-config
users:
- default
- name: {{sysuser}}
sudo: ['ALL=(ALL) NOPASSWD:ALL']
groups: sudo
shell: /bin/bash
ssh_pwauth: True
chpasswd: { expire: False }
lock-passwd: false
passwd: "{{password}}"
{% for u in acl.operators %}
- name: {{i}}
- shell: /bin/bash
{% endfor %}
chpasswd:
expire: False
list: |
{% for u in acl.operators %}
{{u}} : {{ci.rndstr(10)}}
{% endfor %}
{% endverbatim %}</pre>
</div>
</div>
\ No newline at end of file
......@@ -86,11 +86,7 @@
<h3>
{% trans "Cloud-init" %}
</h3>
{% crispy ci_data %}
<p>Keys (in "{{ ci_key }}") mapping for cloud-init:</p>
<small>
{{ci_data_mapping}}
</small>
{% crispy ci_data %}
</div>
</div>
{% endif %}
......
......@@ -146,7 +146,7 @@ class VmDetailView(GraphMixin, CheckedDetailView):
'connect_commands': user.profile.get_connect_commands(instance),
'hide_tutorial': hide_tutorial,
'fav': instance.favourite_set.filter(user=user).exists(),
'ci_data_mapping' : json.dumps(instance.get_ci_data_dict()),
# 'ci_data_mapping' : json.dumps(instance.get_ci_data_dict()),
'ci_key': '{{key}}'
})
......
......@@ -39,6 +39,8 @@ from django.urls import reverse
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _, ugettext_noop
import jinja2
from passlib.hash import sha512_crypt
import yaml
import re
......@@ -251,6 +253,19 @@ class InstanceTemplate(AclBase, VirtualMachineDescModel, TimeStampedModel):
return 'template.%d' % self.pk
class CITemplate:
def rndstr(self, len):
return ''.join(random.choice(string.ascii_letters) for i in range(int(len)))
class AclTemplate:
def __init__(self, instance):
self.user_levels = list({ 'username': u.username, 'level': l } for u, l in instance.get_users_with_level())
self.allusers = list(k['username'] for k in self.user_levels)
self.operators = list(k['username'] for k in self.user_levels if k['level'] == 'operator')
self.users = list(k['username'] for k in self.user_levels if k['level'] == 'user')
class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
TimeStampedModel):
......@@ -380,45 +395,27 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
if net.host:
datas["net.%s.ipv4" % net.vlan.name] = str(net.host.ipv4)
datas["net.%s.ipv6" % net.vlan.name] = str(net.host.ipv6)
user_levels = list({ 'username': u.username, 'level': l } for u, l in self.get_users_with_level())
datas['acl.allusers'] = yaml.dump(list(k['username'] for k in user_levels), default_flow_style=None)
datas['acl.operators'] = yaml.dump(list(k['username'] for k in user_levels if k['level'] == 'operator'), default_flow_style=None)
datas['acl.users'] = yaml.dump(list(k['username'] for k in user_levels if k['level'] == 'user'), default_flow_style=None)
datas['acl'] = AclTemplate(self)
return datas
@property
def get_user_data(self):
data = str(self.ci_user_data)
ci_datas = self.get_ci_data_dict()
for k, v in ci_datas.items():
repl = '{{%s}}' % k
data = data.replace(repl, v)
data = Instance.__replace_rndstr(data)
return data
template = jinja2.Template(data, trim_blocks=True, lstrip_blocks=True)
return template.render(ci_datas)
@property
def get_meta_data(self):
data = str(self.ci_meta_data)
ci_datas = self.get_ci_data_dict()
for k, v in ci_datas.items():
repl = '{{%s}}' % k
data = data.replace(repl, v)
data = Instance.__replace_rndstr(data)
return data
@classmethod
def __replace_rndstr(cls, data):
search = re.search(r'\{\{rndstr%(\d+)\}\}', data)
while search:
randomstr = ''.join(random.choice(string.ascii_letters) for i in range(int(search.group(1))))
data = data.replace(search.group(0), randomstr, 1)
search = re.search(r'\{\{rndstr%(\d+)\}\}', data)
return data
template = jinja2.Template(data, trim_blocks=True, lstrip_blocks=True)
return template.render(ci_datas)
@classmethod
def validate_ci_data(cls, meta_data):
data = re.sub(r'\{\{([a-zA-Z_.0-9%]+)\}\}', 'ci-data', meta_data)
yaml.dump(yaml.load(data, Loader=yaml.Loader))
# data = re.sub(r'\{\{([a-zA-Z_.0-9()%]+)\}\}', 'ci-data', meta_data)
# yaml.dump(yaml.load(data, Loader=yaml.Loader))
return True
def _update_status(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment