示例#1
0
def choose_ip_addr(request):
    if 'network' not in request.GET:
        servers = list(
            Query(
                {'servertype': 'route_network'},
                ['hostname', 'intern_ip'],
                ['hostname'],
            ))

        return TemplateResponse(request, 'servershell/choose_ip_addr.html',
                                {'servers': servers})

    network = request.GET['network']
    servers = list(
        Query(
            {
                'servertype':
                Any(*(s.servertype_id for s in Servertype.objects.filter(
                    ip_addr_type='network'))),
                'intern_ip':
                ContainedOnlyBy(network),
            },
            ['hostname', 'intern_ip'],
            ['hostname'],
        ))

    if servers:
        return TemplateResponse(request, 'servershell/choose_ip_addr.html',
                                {'servers': servers})

    network_query = Query({'intern_ip': network}, ['intern_ip'])

    return TemplateResponse(
        request, 'servershell/choose_ip_addr.html',
        {'ip_addrs': islice(network_query.get_free_ip_addrs(), 1000)})
示例#2
0
def _create_serveradmin_domain():
    serveradmin_domain = Query().new_object('domain')
    serveradmin_domain['hostname'] = 'innogames.net'
    serveradmin_domain['type'] = 'NATIVE'
    serveradmin_domain.commit(user=User.objects.first())

    return serveradmin_domain
    def test_change_server_hostname(self):
        server = self._get_server('network')
        server['intern_ip'] = '10.0.0.0/30'
        server.commit(user=User.objects.first())

        to_rename = Query({'hostname': server['hostname']}, ['hostname'])
        to_rename.update(hostname=self.faker.hostname())
        self.assertIsNone(to_rename.commit(user=User.objects.first()))
    def test_change_server_network_overlaps(self):
        first = self._get_server('network')
        first['intern_ip'] = '10.0.0.0/30'
        first['ip_config'] = '10.0.1.0/30'
        first.commit(user=User.objects.first())

        host = Query({'hostname': first['hostname']}, ['ip_config'])
        host.update(ip_config=IPv4Network('10.0.1.0/28'))
        self.assertIsNone(host.commit(user=User.objects.first()))
    def test_change_server_hostname(self):
        server = self._get_server('loadbalancer')
        server['intern_ip'] = '10.0.0.1/32'
        server['ip_config'] = '10.0.0.2/32'
        server.commit(user=User.objects.first())

        to_rename = Query({'hostname': server['hostname']}, ['hostname'])
        to_rename.update(hostname=self.faker.hostname())
        self.assertIsNone(to_rename.commit(user=User.objects.first()))
示例#6
0
def edit(request):
    if 'object_id' in request.GET:
        server = Query({'object_id': request.GET['object_id']}, None).get()
    else:
        servertype = request.POST.get('attr_servertype')
        if not Servertype.objects.filter(pk=servertype).exists():
            raise Http404('Servertype {} does not exist'.format(servertype))
        server = Query().new_object(servertype)

    return _edit(request, server, True)
示例#7
0
def inspect(request):
    if 'object_id' in request.GET:
        query = Query({'object_id': request.GET['object_id']}, None)
    elif 'hostname' in request.GET:
        query = Query({'hostname': request.GET['hostname']}, None)
    else:
        return HttpResponseBadRequest(
            'object_id or hostname parameter is mandatory')

    if not query:
        return HttpResponseNotFound('No such object exists')

    return _edit(request, query.get(), template='inspect')
示例#8
0
def graph_popup(request):
    try:
        hostname = request.GET['hostname']
        graph_id = request.GET['graph']
    except KeyError:
        return HttpResponseBadRequest('Hostname and graph not supplied')

    # It would be more efficient to filter the collections on the database,
    # but we don't bother because they are unlikely to be more than a few
    # marked as overview.
    for collection in Collection.objects.filter(overview=True):
        servers = list(
            Query({
                GRAPHITE_ATTRIBUTE_ID: collection.name,
                'hostname': hostname,
            }))
        if servers:
            table = collection.graph_table(servers[0])
            params = [v2 for k1, v1 in table for k2, v2 in v1][int(graph_id)]
            url = reverse(graph) + '?' + params

            return TemplateResponse(request, 'resources/graph_popup.html',
                                    {'image': url})

    return HttpResponseBadRequest('No graph found')
示例#9
0
    def handle(self, *args, **kwargs):
        """The entry point of the command"""

        start = time.time()

        sprite_params = settings.GRAPHITE_SPRITE_PARAMS
        sprite_dir = settings.MEDIA_ROOT + '/graph_sprite'
        if not isdir(sprite_dir):
            mkdir(sprite_dir)

        # We will make sure to generate a single sprite for a single hostname.
        for collection in Collection.objects.filter(overview=True):
            collection_start = time.time()

            collection_dir = sprite_dir + '/' + collection.name
            if not isdir(collection_dir):
                mkdir(collection_dir)

            for server in Query({
                    GRAPHITE_ATTRIBUTE_ID: collection.name,
                    'state': filters.Not('retired'),
            }):
                graph_table = collection.graph_table(server, sprite_params)
                if graph_table:
                    self.generate_sprite(collection_dir, graph_table, server)
                self.cache_numerics(collection, server)

            collection_duration = time.time() - collection_start
            print('[{}] Collection {} finished after {} seconds'.format(
                datetime.now(), collection.name, collection_duration))

        duration = time.time() - start
        print('[{}] Finished after {} seconds'.format(datetime.now(),
                                                      duration))
示例#10
0
def create_domains(sender, **kwargs):
    """Create PowerDNS domain for newly created objects

    :param sender:
    :param kwargs:
    :return:
    """

    if not kwargs['created']:
        return

    domain_settings = settings.PDNS.get('domain')
    for new_object in kwargs['created']:
        servertype = new_object['servertype']

        for domain_setting in domain_settings:
            if servertype != domain_setting['servertype']:
                continue

            # The Serveradmin attribute object_id is not present in the
            # post_commit created data so we query the data again.
            attrs = domain_setting['attributes']
            queried_object = Query({
                'hostname': new_object[attrs['name']]
            }, list(attrs.values())).get()

            # All attributes are mandatory
            domain = Domain()
            domain.id = queried_object['object_id']
            domain.name = queried_object[attrs['name']]
            domain.type = queried_object[attrs['type']]
            domain.save()
示例#11
0
def new_object(request):
    try:
        servertype = request.GET.get('servertype')
        new_object = Query().new_object(servertype)
    except Servertype.DoesNotExist:
        raise Http404

    return _edit(request, new_object)
示例#12
0
    def test_filter_regexp(self):
        hostnames = set()
        for s in Query({'hostname': Regexp('^test[02]$')}):
            hostnames.add(s['hostname'])

        self.assertIn('test0', hostnames)
        self.assertNotIn('test1', hostnames)
        self.assertIn('test2', hostnames)
示例#13
0
def get_results(request):
    term = request.GET.get('term', '')
    shown_attributes = request.GET.get('shown_attributes').split(',')

    # We need servertypes to return the attribute properties.
    if 'servertype' not in shown_attributes:
        shown_attributes.append('servertype')

    try:
        offset = int(request.GET.get('offset', '0'))
        limit = int(request.GET.get('limit', '0'))
    except ValueError:
        offset = 0
        limit = NUM_SERVERS_DEFAULT

    if 'order_by' in request.GET:
        order_by = [request.GET['order_by']]
    else:
        order_by = None

    try:
        query = Query(parse_query(term), shown_attributes, order_by)
        num_servers = len(query)
    except (DatatypeError, ObjectDoesNotExist, ValidationError) as error:
        return HttpResponse(
            json.dumps({
                'status': 'error',
                'message': str(error)
            }))

    servers = list(islice(query, offset, offset + limit))

    request.session['term'] = term
    request.session['per_page'] = limit

    # Add information about available, editable attributes on servertypes
    servertype_ids = {s['servertype'] for s in servers}
    editable_attributes = dict()
    for servertype_id in servertype_ids:
        editable_attributes[servertype_id] = list(Attribute.specials)
    for sa in ServertypeAttribute.objects.filter(
            servertype_id__in=servertype_ids,
            attribute_id__in=shown_attributes,
            related_via_attribute_id__isnull=True,
            attribute__readonly=False,
    ):
        editable_attributes[sa.servertype_id].append(sa.attribute_id)

    return HttpResponse(json.dumps(
        {
            'status': 'success',
            'understood': repr(query),
            'servers': servers,
            'num_servers': num_servers,
            'editable_attributes': editable_attributes,
        },
        default=json_encode_extra),
                        content_type='application/x-json')
示例#14
0
def export(request):
    term = request.GET.get('term', '')
    try:
        query = Query(parse_query(term), ['hostname'])
    except (DatatypeError, ObjectDoesNotExist, ValidationError) as error:
        return HttpResponse(str(error), status=400)

    hostnames = ' '.join(server['hostname'] for server in query)
    return HttpResponse(hostnames, content_type='text/plain')
示例#15
0
def clone_object(request):
    try:
        old_object = Query(
            {'object_id': request.GET.get('object_id')},
            list(Attribute.specials) + list(
                Attribute.objects.filter(clone=True)
                    .values_list('attribute_id', flat=True)
            ),
        ).get()
    except ValidationError as e:
        messages.error(request, e.message)
        return redirect('servershell_index')

    new_object = Query().new_object(old_object['servertype'])
    for attribute_id, value in old_object.items():
        new_object[attribute_id] = value

    return _edit(request, new_object)
示例#16
0
def clone_object(request):
    try:
        old_object = Query(
            {
                'hostname': request.GET.get('hostname')
            },
            list(Attribute.specials) + list(
                Attribute.objects.filter(clone=True).values_list(
                    'attribute_id', flat=True)),
        ).get()
    except ValidationError:
        raise Http404

    new_object = Query().new_object(old_object['servertype'])
    for attribute_id, value in old_object.items():
        new_object[attribute_id] = value

    return _edit(request, new_object)
示例#17
0
    def test_query_iterate(self):
        hostnames = set()
        for server in Query({}):
            hostnames.add(server['hostname'])

        self.assertIn('test0', hostnames)
        self.assertIn('test1', hostnames)
        self.assertIn('test2', hostnames)
        self.assertIn('test3', hostnames)
示例#18
0
    def test_filter_any(self):
        hostnames = set()
        for s in Query({'hostname': Any('test1', 'test3')}):
            hostnames.add(s['hostname'])

        self.assertNotIn('test0', hostnames)
        self.assertIn('test1', hostnames)
        self.assertNotIn('test2', hostnames)
        self.assertIn('test3', hostnames)
示例#19
0
def new_object(request):
    servertype = request.GET.get('servertype')

    try:
        new_object = Query().new_object(servertype)
    except Servertype.DoesNotExist:
        messages.error(request,
                       'The servertype {} does not exist!'.format(servertype))
        return redirect('servershell_index')

    return _edit(request, new_object)
示例#20
0
def clone_object(request):
    try:
        cloned_attributes = list(Attribute.specials)
        # intern_ip is usually unique (except for loadbalancers) therefore it
        # makes sense to not clone it.
        cloned_attributes.remove('intern_ip')
        cloned_attributes.extend(
            list(
                Attribute.objects.filter(clone=True).values_list(
                    'attribute_id', flat=True)))

        old_object = Query({
            'object_id': request.GET.get('object_id')
        }, cloned_attributes).get()
    except ValidationError as e:
        messages.error(request, e.message)
        return redirect('servershell_index')

    new_object = Query().new_object(old_object['servertype'])
    for attribute_id, value in old_object.items():
        new_object[attribute_id] = value

    return _edit(request, new_object)
示例#21
0
def autocomplete(request):
    autocomplete_list = []
    if 'hostname' in request.GET:
        hostname = request.GET['hostname']
        try:
            query = Query({'hostname': StartsWith(hostname)}, ['hostname'])
            autocomplete_list += islice((h['hostname'] for h in query), 100)
        except (DatatypeError, ValidationError):
            pass  # If there is no valid query, just don't auto-complete

    return HttpResponse(
        json.dumps({'autocomplete': autocomplete_list}),
        content_type='application/x-json',
    )
示例#22
0
def diff(request: HttpRequest) -> HttpResponse:
    attrs = request.GET.getlist('attr')
    objects = request.GET.getlist('object')

    if not objects or not all([o.isnumeric() for o in objects]):
        return bad_request(request, HttpResponseBadRequest)

    # Can raise ApiError for unknown attributes - let it flow ...
    qs = Query({'object_id': Any(*objects)}, attrs if attrs else None)

    diff_data = []
    for attribute in sorted(set(chain(*[o.keys() for o in qs]))):
        # object_id is always different and special
        if attribute == 'object_id':
            continue

        # Show hostname only if request by user
        if attribute == 'hostname' and attrs != [] and attribute not in attrs:
            continue

        values = []
        for obj in qs:
            values.append(obj[attribute])

        diff_data.append([attribute, values])

    # Fetch hostnames if not requested by user to display as header in result.
    if 'hostname' in attrs:
        hosts = qs
    else:
        hosts = Query({'object_id': Any(*objects)}, ['hostname'])

    context = {
        'hosts': hosts,
        'diff_data': diff_data,
    }
    return render(request, 'servershell/diff.html', context)
示例#23
0
    def test_commit_query(self):
        q = Query({'hostname': 'test1'}, ['os', 'intern_ip'])
        s = q.get()
        s['os'] = 'wheezy'
        s['intern_ip'] = IPv4Address('10.16.2.1')
        q.commit(user=User.objects.first())

        s = Query({'hostname': 'test1'}, ['os', 'intern_ip']).get()
        self.assertEqual(s['os'], 'wheezy')
        self.assertEqual(s['intern_ip'], IPv4Address('10.16.2.1'))
示例#24
0
    def test_set_attribute(self):
        """Try to set and retrieve a datetime attribute"""
        dt = datetime.utcnow().replace(tzinfo=timezone.utc)
        q = Query({'hostname': 'test0'}, ['last_edited'])
        s = q.get()
        s['last_edited'] = dt
        q.commit(user=User.objects.first())

        s = Query({'hostname': 'test0'}, ['last_edited']).get()
        self.assertEqual(s['last_edited'], dt)
示例#25
0
    def handle(self, *args, **kwargs):
        """The entry point of the command"""
        sprite_params = settings.GRAPHITE_SPRITE_PARAMS
        sprite_dir = settings.MEDIA_ROOT + '/graph_sprite'
        if not isdir(sprite_dir):
            mkdir(sprite_dir)

        # We will make sure to generate a single sprite for a single hostname.
        for collection in Collection.objects.filter(overview=True):
            collection_dir = sprite_dir + '/' + collection.name
            if not isdir(collection_dir):
                mkdir(collection_dir)

            for server in Query({GRAPHITE_ATTRIBUTE_ID: collection.name}):
                graph_table = collection.graph_table(server, sprite_params)
                if graph_table:
                    self.generate_sprite(collection_dir, graph_table, server)
                self.cache_numerics(collection, server)
示例#26
0
    def test_utc_conversion(self):
        """Ensure datetimes are converted to UTC

        Users can pass datetimes in any timezone they want. Serveradmin will
        transform them to UTC and only ever return them in UTC form.
        """

        class TZ(tzinfo):
            def utcoffset(self, dt):
                return timedelta(minutes=+3)

        q = Query({'hostname': 'test0'}, ['last_edited'])
        s = q.get()
        s['last_edited'] = datetime(1970, 1, 1, 0, 3, 0).replace(tzinfo=TZ())
        q.commit(user=User.objects.first())

        s = Query({'hostname': 'test0'}, ['last_edited']).get()
        self.assertEqual(str(s['last_edited']), '1970-01-01 00:00:00+00:00')
示例#27
0
def update_domains(sender, **kwargs):
    """Update PowerDNS domain when changed

    :param sender:
    :param kwargs:
    :return:
    """

    if not kwargs['changed']:
        return

    # Is any of the updated objects mapped to PowerDNS domain ?
    object_ids = [changed['object_id'] for changed in kwargs['changed']]
    domains_to_update = Domain.objects.filter(id__in=object_ids)
    if not domains_to_update.exists():
        return

    domain_settings = DomainSettings()
    for domain in domains_to_update:
        attributes = domain_settings.get_attributes() + ['servertype']
        # @TODO Find a way to avoid this extra Query if possible
        queried_object = Query({'object_id': domain.id}, attributes).get()
        servertype = queried_object['servertype']
        this_settings = domain_settings.get_settings(servertype)
        changed_object = next(
            filter(lambda o: o['object_id'] == domain.id, kwargs['changed']))

        has_changed = False
        for pdns_key, sa_key in this_settings['attributes'].items():
            if sa_key not in changed_object.keys():
                continue

            has_changed = True
            setattr(domain, pdns_key, changed_object[sa_key]['new'])

        if has_changed:
            domain.save()
示例#28
0
def index(request):
    """The hardware resources page"""
    term = request.GET.get('term', request.session.get('term', ''))
    collections = list(Collection.objects.filter(overview=True))

    # If a graph collection was specified, use it.  Otherwise use the first
    # one.
    for collection in collections:
        if request.GET.get('current_collection'):
            if str(collection.id) != request.GET['current_collection']:
                continue
        current_collection = collection
        break
    else:
        return HttpResponseBadRequest('No matching current collection')

    template_info = {
        'search_term': term,
        'collections': collections,
        'current_collection': current_collection.id,
    }

    # TODO: Generalize this part using the relations
    hostnames = []
    matched_hostnames = []
    if term:
        try:
            query_args = parse_query(term)
            host_query = Query(query_args, ['hostname', 'hypervisor'])
            for host in host_query:
                matched_hostnames.append(host['hostname'])
                if host.get('hypervisor'):
                    hostnames.append(host['hypervisor'])
                else:
                    # If it's not guest, it might be a server, so we add it
                    hostnames.append(host['hostname'])
            understood = repr(host_query)
            request.session['term'] = term

            if len(hostnames) == 0:
                template_info.update({
                    'understood': understood,
                })
                return TemplateResponse(request, 'resources/index.html',
                                        template_info)
        except (DatatypeError, ValidationError) as error:
            template_info.update({'error': str(error)})
            return TemplateResponse(request, 'resources/index.html',
                                    template_info)
    else:
        understood = repr(Query({}))

    variations = list(current_collection.variation_set.all())
    columns = []
    attribute_ids = ['hostname', 'servertype']
    graph_index = 0
    sprite_width = settings.GRAPHITE_SPRITE_WIDTH
    for template in current_collection.template_set.all():
        for variation in variations:
            columns.append({
                'name': str(template) + ' ' + str(variation),
                'type': 'graph',
                'graph_index': graph_index,
                'sprite_offset': graph_index * sprite_width,
            })
            graph_index += 1
    for numeric in current_collection.numeric_set.all():
        columns.append({
            'name': str(numeric),
            'type': 'numeric',
        })
        attribute_ids.append(numeric.attribute_id)
    for relation in current_collection.relation_set.all():
        columns.append({
            'name': str(relation),
            'type': 'relation',
        })
        attribute_ids.append(relation.attribute_id)

    hosts = OrderedDict()
    filters = {GRAPHITE_ATTRIBUTE_ID: collection.name}
    if len(hostnames) > 0:
        filters['hostname'] = Any(*hostnames)
    for server in Query(filters, attribute_ids):
        hosts[server['hostname']] = dict(server)

    sprite_url = settings.MEDIA_URL + 'graph_sprite/' + collection.name
    template_info.update({
        'columns': columns,
        'hosts': hosts.values(),
        'matched_hostnames': matched_hostnames,
        'understood': understood,
        'error': None,
        'sprite_url': sprite_url,
    })
    return TemplateResponse(request, 'resources/index.html', template_info)
示例#29
0
 def test_startswith_servertype(self):
     q = Query({'servertype': StartsWith('tes')})
     self.assertEqual(len(q), 4)
示例#30
0
 def test_startswith(self):
     s = Query({'os': StartsWith('whee')}).get()
     self.assertEqual(s['hostname'], 'test0')