init.py 10.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE.  If not, see <http://www.gnu.org/licenses/>.

from __future__ import unicode_literals, absolute_import

20
import logging
21

22
from django.contrib.auth.models import User, Group, Permission
23
from django.core.management.base import BaseCommand
24
from django.db.models import Q
25

26 27
from firewall.models import Vlan, VlanGroup, Domain, Firewall, Rule, Host
from firewall.fields import mac_custom
28
from storage.models import DataStore
29 30 31
from vm.models import Lease, Node
from dashboard.models import GroupProfile, Profile
from netaddr import IPAddress, EUI
32 33


34 35 36
logger = logging.getLogger(__name__)


37
class Command(BaseCommand):
38 39 40 41 42 43 44 45 46 47 48 49
    def add_arguments(self, parser):
        parser.add_argument('--force', action="store_true")
        parser.add_argument('--external-net')
        parser.add_argument('--management-net')
        parser.add_argument('--vm-net')
        parser.add_argument('--external-if')
        parser.add_argument('--management-if')
        parser.add_argument('--vm-if')
        parser.add_argument('--datastore-queue')
        parser.add_argument('--firewall-queue')
        parser.add_argument('--admin-user')
        parser.add_argument('--admin-pass')
50 51 52 53 54
        parser.add_argument('--node-hostname')
        parser.add_argument('--node-mac')
        parser.add_argument('--node-ip')
        parser.add_argument('--node-name')
        parser.add_argument('--kvm-present', action="store_true")
55 56 57 58 59 60

    def create(self, model, field, **kwargs):
        value = kwargs[field]
        qs = model.objects.filter(**{field: value})[:1]
        if not qs.exists():
            obj = model.objects.create(**kwargs)
61 62
            logger.info('New %s: %s', model, obj)
            self.changed = True
63 64 65 66
            return obj
        else:
            return qs[0]

67
    # http://docs.saltstack.com/en/latest/ref/states/all/salt.states.cmd.html
68
    def print_state(self):
69
        self.stdout.write("\nchanged=%s" % ("yes" if self.changed else "no"))
70 71

    def handle(self, *args, **options):
72
        self.changed = False
73
    # from pdb import set_trace; set_trace()
74

75 76
        if (DataStore.objects.exists() and Vlan.objects.exists() and
                not options['force']):
77 78
            self.print_state()
            return
79 80 81 82 83

        admin = self.create(User, 'username', username=options['admin_user'],
                            is_superuser=True, is_staff=True)
        admin.set_password(options['admin_pass'])
        admin.save()
84
        self.create(Profile, 'user', user=admin)
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101

        self.create(DataStore, 'path', path='/datastore', name='default',
                    hostname=options['datastore_queue'])

        # leases
        self.create(Lease, 'name', name='lab',
                    suspend_interval_seconds=3600 * 5,
                    delete_interval_seconds=3600 * 24 * 7)

        self.create(Lease, 'name', name='project',
                    suspend_interval_seconds=3600 * 24 * 30,
                    delete_interval_seconds=3600 * 24 * 30 * 6)

        self.create(Lease, 'name', name='server',
                    suspend_interval_seconds=3600 * 24 * 365,
                    delete_interval_seconds=3600 * 24 * 365 * 3)

102 103 104 105 106 107
        net_domain = self.create(Domain, 'name', name='net.example.com',
                                 owner=admin)
        man_domain = self.create(Domain, 'name', name='man.example.com',
                                 owner=admin)
        vm_domain = self.create(Domain, 'name', name='vm.example.com',
                                owner=admin)
108 109

        # vlans
110 111
        net = self.create(Vlan, 'vid', name=options['external_if'], vid=4,
                          network4=options['external_net'], domain=net_domain)
112

113 114 115 116
        man = self.create(Vlan, 'vid', name=options['management_if'], vid=3,
                          dhcp_pool='manual',
                          network4=options['management_net'],
                          domain=man_domain,
117 118
                          snat_ip=options['external_net'].split('/')[0])
        man.snat_to.add(net)
119
        man.snat_to.add(man)
120

121 122 123
        vm = self.create(Vlan, 'vid', name=options['vm_if'], vid=2,
                         dhcp_pool='manual',
                         network4=options['vm_net'], domain=vm_domain,
124 125
                         snat_ip=options['external_net'].split('/')[0])
        vm.snat_to.add(net)
126
        vm.snat_to.add(vm)
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

        # default vlan groups
        vg_all = self.create(VlanGroup, 'name', name='all')
        vg_all.vlans.add(vm, man, net)

        vg_pf = self.create(VlanGroup, 'name', name='portforward')
        vg_pf.vlans.add(vm, man, net)

        vg_net = self.create(VlanGroup, 'name', name='net')
        vg_net.vlans.add(net)

        # firewall rules
        fw = self.create(Firewall, 'name', name=options['firewall_queue'])

        self.create(Rule, 'description', description='default output rule',
                    direction='out', action='accept',
                    foreign_network=vg_all, firewall=fw)

145 146 147 148 149 150 151 152 153 154
        self.create(Rule, 'description', description='portal https',
                    direction='in', action='accept', proto='tcp', dport=443,
                    foreign_network=vg_all, firewall=fw)

        self.create(Rule, 'description', description='portal http',
                    direction='in', action='accept', proto='tcp', dport=80,
                    foreign_network=vg_all, firewall=fw)

        self.create(Rule, 'description', description='ssh',
                    direction='in', action='accept', proto='tcp', dport=22,
155 156 157 158 159 160 161 162 163 164
                    foreign_network=vg_all, firewall=fw)

        # vlan rules
        self.create(Rule, 'description', description='allow vm->net',
                    direction='out', action='accept',
                    foreign_network=vg_net, vlan=vm)

        self.create(Rule, 'description', description='allow man->net',
                    direction='out', action='accept',
                    foreign_network=vg_net, vlan=man)
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
        node_ip = IPAddress(options['node_ip'])
        node_mac = EUI(options['node_mac'], dialect=mac_custom)
        node_host = Host.objects.filter(ipv4=node_ip).first()
        if node_host is None:
            node_host = self.create(Host, 'mac', mac=node_mac,
                                    hostname=options['node_hostname'],
                                    ipv4=node_ip, vlan=man, owner=admin)
        else:
            Host.objects.filter(pk=node_host.pk).update(
                mac=node_mac,       hostname=options['node_hostname'],
                ipv4=node_ip, vlan=man, owner=admin)
            node_host.refresh_from_db()

        self.create(Node, 'name', name=options['node_name'], host=node_host,
                    priority=1, enabled=True, schedule_enabled=True)

        # creating groups
182
        susers = self.create(Group, 'name', name='Superusers')
183 184 185 186
        pusers = self.create(Group, 'name', name='Powerusers')
        users = self.create(Group, 'name', name='Users')

        # creating group profiles
187
        self.create(GroupProfile, 'group', group=susers)
188 189 190 191 192 193 194 195 196 197
        self.create(GroupProfile, 'group', group=pusers)
        self.create(GroupProfile, 'group', group=users)

        # specifying group permissions
        user_permissions = [
            'create_vm',
            'config_ports',
        ]

        puser_permissions = [
198
            'use_autocomplete',
199 200 201 202 203 204 205 206 207
            'config_ports',
            'create_vm',
            'create_empty_disk',
            'download_disk',
            'resize_disk',
            'access_console',
            'change_resources',
            'set_resources',
            'change_template_resources',
208
            'create_template',
209 210
        ]

211
        suser_permissions = [
212 213 214 215 216 217 218 219 220 221 222 223
            'add_group',
            'use_autocomplete',
            'create_empty_disk',
            'download_disk',
            'access_console',
            'change_resources',
            'config_ports',
            'create_vm',
            'recover',
            'set_resources',
            'change_template_resources',
            'create_base_template',
224
            'create_template'
225 226 227
        ]

        # set group permissions
228
        susers.permissions.set(self._get_permissions(suser_permissions))
229 230 231 232 233 234 235 236 237 238 239
        pusers.permissions.set(self._get_permissions(puser_permissions))
        users.permissions.set(self._get_permissions(user_permissions))

        # creating users and their profiles
        useruser = self.create(User, 'username', username='user',
                               is_superuser=False, is_staff=False)
        useruser.set_password("user")
        useruser.save()
        self.create(Profile, 'user', user=useruser)

        poweruser = self.create(User, 'username', username="poweruser",
240
                                is_superuser=False, is_staff=False)
241 242 243 244
        poweruser.set_password("poweruser")
        poweruser.save()
        self.create(Profile, 'user', user=poweruser)

245 246 247 248 249
        superuser = self.create(User, 'username', username="superuser",
                                is_superuser=False, is_staff=False)
        superuser.set_password("superuser")
        superuser.save()
        self.create(Profile, 'user', user=superuser)
250 251 252 253

        # adding users o groups
        users.user_set.add(useruser)
        pusers.user_set.add(poweruser)
254
        susers.user_set.add(superuser)
255 256 257 258

        # add groups to vm vlan
        vm.set_level(users, 'user')
        vm.set_level(pusers, 'user')
259
        vm.set_level(susers, 'user')
260 261

        # notify admin if there is no harware virtualization
262 263 264 265 266
        if not options['kvm_present']:
            admin.profile.notify("hardware virtualization",
                                 "No hardware virtualization detected, "
                                 "your hardware does not support it or "
                                 "not enabled in BIOS.")
267
        self.print_state()
268 269 270 271 272 273

    def _get_permissions(self, code_names):
        query = Q()
        for cn in code_names:
            query |= Q(codename=cn)
        return Permission.objects.filter(query)