# 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/>. import logging from django.contrib.auth.models import User, Group, Permission from django.core.management.base import BaseCommand from django.db.models import Q from firewall.models import Vlan, VlanGroup, Domain, Firewall, Rule, Host from firewall.fields import mac_custom from storage.models import DataStore from vm.models import Lease, Node from dashboard.models import GroupProfile, Profile from netaddr import IPAddress, EUI logger = logging.getLogger(__name__) class Command(BaseCommand): 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') 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") 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) logger.info('New %s: %s', model, obj) self.changed = True return obj else: return qs[0] # http://docs.saltstack.com/en/latest/ref/states/all/salt.states.cmd.html def print_state(self): self.stdout.write("\nchanged=%s" % ("yes" if self.changed else "no")) def handle(self, *args, **options): self.changed = False # from pdb import set_trace; set_trace() if (DataStore.objects.exists() and Vlan.objects.exists() and not options['force']): self.print_state() return admin = self.create(User, 'username', username=options['admin_user'], is_superuser=True, is_staff=True) admin.set_password(options['admin_pass']) admin.save() self.create(Profile, 'user', user=admin) 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) 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) # vlans net = self.create(Vlan, 'vid', name=options['external_if'], vid=4, network4=options['external_net'], domain=net_domain) man = self.create(Vlan, 'vid', name=options['management_if'], vid=3, dhcp_pool='manual', network4=options['management_net'], domain=man_domain, snat_ip=options['external_net'].split('/')[0]) man.snat_to.add(net) man.snat_to.add(man) vm = self.create(Vlan, 'vid', name=options['vm_if'], vid=2, dhcp_pool='manual', network4=options['vm_net'], domain=vm_domain, snat_ip=options['external_net'].split('/')[0]) vm.snat_to.add(net) vm.snat_to.add(vm) # 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) 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, 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) 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 susers = self.create(Group, 'name', name='Superusers') pusers = self.create(Group, 'name', name='Powerusers') users = self.create(Group, 'name', name='Users') # creating group profiles self.create(GroupProfile, 'group', group=susers) self.create(GroupProfile, 'group', group=pusers) self.create(GroupProfile, 'group', group=users) # specifying group permissions user_permissions = [ 'create_vm', 'config_ports', ] puser_permissions = [ 'use_autocomplete', 'config_ports', 'create_vm', 'create_empty_disk', 'download_disk', 'resize_disk', 'access_console', 'change_resources', 'set_resources', 'change_template_resources', 'create_template', ] suser_permissions = [ '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', 'create_template' ] # set group permissions susers.permissions.set(self._get_permissions(suser_permissions)) 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", is_superuser=False, is_staff=False) poweruser.set_password("poweruser") poweruser.save() self.create(Profile, 'user', user=poweruser) 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) # adding users o groups users.user_set.add(useruser) pusers.user_set.add(poweruser) susers.user_set.add(superuser) # add groups to vm vlan vm.set_level(users, 'user') vm.set_level(pusers, 'user') vm.set_level(susers, 'user') # notify admin if there is no harware virtualization 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.") self.print_state() def _get_permissions(self, code_names): query = Q() for cn in code_names: query |= Q(codename=cn) return Permission.objects.filter(query)