def get(self, request, *args, **kwargs): """ Return reservation history of machine. """ fqdn = request.GET.get('fqdn', None) option = request.GET.get('option', None) try: result = get_machine(fqdn, redirect_to='api:rescan', data=request.GET) if isinstance(result, Serializer): return result.as_json elif isinstance(result, HttpResponseRedirect): return result machine = result except Exception as e: return ErrorMessage(str(e)).as_json if option not in MachineCheck.Scan.Action.as_list: return ErrorMessage("Unknown option '{}'!".format(option)).as_json try: machine.scan(option) if not machine.collect_system_information: return InfoMessage( "Collecting system information is disabled for this machine." ).as_json except Exception as e: return ErrorMessage(str(e)).as_json return Message("OK.").as_json
def get(self, request, *args, **kwargs): """ Release a machine. """ fqdn = request.GET.get('fqdn', None) try: result = get_machine(fqdn, redirect_to='api:release', data=request.GET) if isinstance(result, Serializer): return result.as_json elif isinstance(result, HttpResponseRedirect): return result machine = result except Exception as e: return ErrorMessage(str(e)).as_json if isinstance(request.user, AnonymousUser) or not request.auth: return AuthRequiredSerializer().as_json try: machine.release(user=request.user) return Message('OK.').as_json except Exception as e: return ErrorMessage(str(e)).as_json
def post(self, request, architecture, *args, **kwargs): """ Add virtual machine for specific `architecture`. """ data = json.loads(request.body.decode('utf-8'))['form'] try: host = Machine.api.get(fqdn__iexact=data['host'], vm_dedicated_host=True) except Machine.DoesNotExist: return ErrorMessage("Host doesn't exist!").as_json except Exception as e: return ErrorMessage(str(e)).as_json if not host.virtualization_api: return ErrorMessage("No virtualization API available!").as_json form = VirtualMachineAPIForm( data, virtualization_api=host.virtualization_api) if form.is_valid(): try: vm = host.virtualization_api.create(**form.cleaned_data) vm.reserve(reason='VM of {}'.format(request.user), until=add_offset_to_date(30), user=request.user) theader = [ { 'fqdn': 'FQDN' }, { 'mac_address': 'MAC address' }, ] if vm.vnc['enabled']: theader.append({'vnc': 'VNC'}) response = { 'header': { 'type': 'TABLE', 'theader': theader }, 'data': [{ 'fqdn': vm.fqdn, 'mac_address': vm.mac_address }], } if vm.vnc['enabled']: response['data'][0]['vnc'] = '{}:{}'.format( host.fqdn, vm.vnc['port']) return JsonResponse(response) except Exception as e: return ErrorMessage(str(e)).as_json return ErrorMessage("\n{}".format( format_cli_form_errors(form))).as_json
def get(self, request, *args, **kwargs): """ Perform machine setup. """ fqdn = request.GET.get('fqdn', None) option_or_choice = request.GET.get('option_or_choice', None) choice = None try: result = get_machine(fqdn, redirect_to='api:setup', data=request.GET) if isinstance(result, Serializer): return result.as_json elif isinstance(result, HttpResponseRedirect): return result machine = result except Exception as e: return ErrorMessage(str(e)).as_json if option_or_choice.lower() == 'list': return self._list(request, machine) else: choice = option_or_choice return self._setup(request, machine, choice) return ErrorMessage("Something went wrong!").as_json
def post(self, request, fqdn, *args, **kwargs): """ Add annotation to machine. """ try: result = get_machine(fqdn, redirect_to='api:annotation_add', data=request.GET) if isinstance(result, Serializer): return result.as_json elif isinstance(result, HttpResponseRedirect): return result machine = result except Exception as e: return ErrorMessage(str(e)).as_json data = json.loads(request.body.decode('utf-8'))['form'] form = AnnotationAPIForm(data, machine=machine) if form.is_valid(): try: cleaned_data = form.cleaned_data annotation = Annotation(machine_id=machine.pk, reporter=request.user, text=cleaned_data['text']) annotation.save() except Exception as e: logger.exception(e) return ErrorMessage("Something went wrong!").as_json return Message('Ok.').as_json return ErrorMessage("\n{}".format( format_cli_form_errors(form))).as_json
def get(self, request, *args, **kwargs): """ Dispatcher for the 'delete' command. """ arguments = request.GET.get('args', None) if arguments: arguments = arguments.split() item = arguments[0].lower() sub_arguments = arguments[1:] else: return ErrorMessage("Item is missing!").as_json if item == Delete.MACHINE: if len(sub_arguments) != 0: return ErrorMessage("Invalid number of arguments for 'machine'!").as_json return redirect(reverse('api:machine_delete')) elif item == Delete.SERIALCONSOLE: if len(sub_arguments) != 0: return ErrorMessage("Invalid number of arguments for 'serialconsole'!").as_json return redirect(reverse('api:serialconsole_delete')) elif item == Delete.REMOTEPOWER: if len(sub_arguments) != 0: return ErrorMessage("Invalid number of arguments for 'remotepower'!").as_json return redirect(reverse('api:remotepower_delete')) return ErrorMessage("Unknown item '{}'!".format(item)).as_json
def get(self, request, *args, **kwargs): """ Return form for adding a remotepower. """ fqdn = request.GET.get('fqdn', None) try: result = get_machine(fqdn, redirect_to='api:remotepower_add', data=request.GET) if isinstance(result, Serializer): return result.as_json elif isinstance(result, HttpResponseRedirect): return result machine = result except Exception as e: return ErrorMessage(str(e)).as_json if isinstance(request.user, AnonymousUser) or not request.auth: return AuthRequiredSerializer().as_json if not request.user.is_superuser: return ErrorMessage( "Only superusers are allowed to perform this action!").as_json if machine.has_remotepower(): return InfoMessage("Machine has already a remote power.").as_json form = RemotePowerAPIForm(machine=machine) input = InputSerializer(form.as_dict(), self.URL_POST.format(fqdn=machine.fqdn), form.get_order()) return input.as_json
def post(self, request, *args, **kwargs): """ Add machine. """ if not request.user.is_superuser: return ErrorMessage( "Only superusers are allowed to perform this action!").as_json data = json.loads(request.body.decode('utf-8'))['form'] form = MachineAPIForm(data) if form.is_valid(): cleaned_data = form.cleaned_data mac_address = cleaned_data['mac_address'] del cleaned_data['mac_address'] new_machine = Machine(**cleaned_data) new_machine.mac_address = mac_address try: new_machine.save() except Exception as e: logger.exception(e) return ErrorMessage("Something went wrong!").as_json return Message('Ok.').as_json return ErrorMessage("\n{}".format( format_cli_form_errors(form))).as_json
def post(self, request, *args, **kwargs): """ Delete machine. """ if not request.user.is_superuser: return ErrorMessage("Only superusers are allowed to perform this action!").as_json data = json.loads(request.body.decode('utf-8'))['form'] form = DeleteMachineAPIForm(data) if form.is_valid(): try: cleaned_data = form.cleaned_data machine = Machine.objects.get(fqdn__iexact=cleaned_data['fqdn']) if machine.is_virtual_machine(): host = machine.get_hypervisor() if host.virtualization_api is None: return ErrorMessage("No virtualization API found!").as_json if host.virtualization_api.remove(machine): result = machine.delete() else: result = machine.delete() theader = [ {'objects': 'Deleted objects'}, {'count': '#'}, ] response = { 'header': {'type': 'TABLE', 'theader': theader}, 'data': [], } for key, value in result[1].items(): response['data'].append( { 'objects': key.replace('data.', ''), 'count': value } ) return JsonResponse(response) except Exception as e: logger.exception(e) return ErrorMessage("Something went wrong!").as_json return ErrorMessage("\n{}".format(format_cli_form_errors(form))).as_json
def get(self, request, *args, **kwargs): """ Return reservation form for valid machine. """ fqdn = request.GET.get('fqdn', None) try: result = get_machine(fqdn, redirect_to='api:reserve', data=request.GET) if isinstance(result, Serializer): return result.as_json elif isinstance(result, HttpResponseRedirect): return result machine = result except Exception as e: return ErrorMessage(str(e)).as_json if isinstance(request.user, AnonymousUser) or not request.auth: return AuthRequiredSerializer().as_json form = ReserveMachineAPIForm(username=request.user.username, reason=machine.reserved_reason) input = InputSerializer(form.as_dict(), self.URL_POST.format(id=machine.pk), form.get_order()) return input.as_json
def _list(self, request, machine): """ Return list of available distributions for `machine`. """ machinegroup = None if not machine.has_setup_capability(): return InfoMessage("Machine has no setup capability.").as_json if machine.group and not machine.group.setup_use_architecture: machinegroup = machine.group.name grouped_records = machine.fqdn_domain.get_setup_records( machine.architecture.name, machinegroup=machinegroup) if not grouped_records: return ErrorMessage("No setup records found!").as_json response = '' theader = [{'full': 'Available Distributions'}] response = { 'header': { 'type': 'TABLE', 'theader': theader }, 'data': [] } for distribution, records in grouped_records.items(): for record in records: response['data'].append({ 'full': record, }) return JsonResponse(response)
def get(self, request, *args, **kwargs): """ Show server configuration. """ if isinstance(request.user, AnonymousUser) or not request.auth: return AuthRequiredSerializer().as_json if not request.user.is_superuser: return ErrorMessage( "Only superusers are allowed to perform this action!").as_json config = ServerConfig.objects.all() if config.count() == 0: return InfoMessage("No configurations available.").as_json theader = [{'key': 'Key'}, {'value': 'Value'}] response = { 'header': { 'type': 'TABLE', 'theader': theader }, 'data': [] } for item in config: response['data'].append({'key': item.key, 'value': item.value}) return JsonResponse(response)
def get(self, request, *args, **kwargs): """ Return form for adding an annotation. """ fqdn = request.GET.get('fqdn', None) try: result = get_machine(fqdn, redirect_to='api:annotation_add', data=request.GET) if isinstance(result, Serializer): return result.as_json elif isinstance(result, HttpResponseRedirect): return result machine = result except Exception as e: return ErrorMessage(str(e)).as_json if isinstance(request.user, AnonymousUser) or not request.auth: return AuthRequiredSerializer().as_json form = AnnotationAPIForm(machine=machine) input = InputSerializer(form.as_dict(), self.URL_POST.format(fqdn=machine.fqdn), form.get_order()) return input.as_json
def get(self, request, *args, **kwargs): """ Return form for adding a virtual machine. """ architectures = self._get_available_architectures() architecture = request.GET.get('arch', None) if architecture.lower() not in architectures: return Message("Available architectures: {}".format( '|'.join(architectures))).as_json if isinstance(request.user, AnonymousUser) or not request.auth: return AuthRequiredSerializer().as_json hosts = Machine.api.filter(vm_dedicated_host=True, architecture__name=architecture) host = None for host_ in hosts: if host_.virtualization_api and ( host_.get_virtual_machines().count() < host_.vm_max): host = host_ break if host is None: return ErrorMessage("No virtual machine hosts left!").as_json form = VirtualMachineAPIForm( virtualization_api=host.virtualization_api) input = InputSerializer(form.as_dict(host), self.URL_POST.format(arch=architecture), form.get_order()) return input.as_json
def post(self, request, id, *args, **kwargs): """ Process reservation. """ try: machine = Machine.objects.get(pk=id) except Machine.DoesNotExist: return ErrorMessage("Machine doesn't exist!").as_json try: data = json.loads(request.body.decode('utf-8'))['form'] if data['until'] == 0 and request.user.is_superuser: # set to 'infinite' data['until'] = datetime.date.max else: # set 'until' field (=offset) to concrete date for form validation data['until'] = add_offset_to_date(data['until'], as_string=True) form = ReserveMachineAPIForm(data) except (KeyError, ValueError): return ErrorMessage("Data format is invalid!").as_json if form.is_valid(): reason = form.cleaned_data['reason'] until = form.cleaned_data['until'] username = form.cleaned_data['username'] try: user = User.objects.get(username=username) except Exception: return ErrorMessage("User doesn't exist!").as_json try: machine.reserve(reason, until, user=request.user, reserve_for_user=user) return Message('OK.').as_json except Exception as e: return ErrorMessage(str(e)).as_json else: return ErrorMessage("\n{}".format( format_cli_form_errors(form))).as_json
def get(self, request, *args, **kwargs): """ Return reservation history of machine. """ fqdn = request.GET.get('fqdn', None) try: result = get_machine(fqdn, redirect_to='api:history', data=request.GET) if isinstance(result, Serializer): return result.as_json elif isinstance(result, HttpResponseRedirect): return result machine = result except Exception as e: return ErrorMessage(str(e)).as_json history = ReservationHistory.objects.filter(machine__fqdn=machine.fqdn) if history.count() == 0: return InfoMessage("No history available yet.").as_json theader = [{ 'user': '******' }, { 'at': 'Reserved at' }, { 'until': 'Reserved until' }, { 'reason': 'Reason' }] response = { 'header': { 'type': 'TABLE', 'theader': theader }, 'data': [] } for item in history: response['data'].append({ 'user': item.reserved_by, 'at': item.reserved_at, 'until': item.reserved_until, 'reason': item.reserved_reason.replace('\n', '') }) return JsonResponse(response)
def get(self, request, *args, **kwargs): """ Dispatcher for the 'add' command. """ arguments = request.GET.get('args', None) if arguments: arguments = arguments.split() item = arguments[0].lower() sub_arguments = arguments[1:] else: return ErrorMessage("Item is missing!").as_json if item == Add.VIRTUALMACHINE: if len(sub_arguments) != 1: return ErrorMessage( "Invalid number of arguments for 'virtualmachine'!" ).as_json return redirect('{}?arch={}'.format(reverse('api:vm_add'), sub_arguments[0])) elif item == Add.MACHINE: if len(sub_arguments) != 0: return ErrorMessage( "Invalid number of arguments for 'machine'!").as_json return redirect(reverse('api:machine_add')) elif item == Add.SERIALCONSOLE: if len(sub_arguments) != 1: return ErrorMessage( "Invalid number of arguments for 'serialconsole'!").as_json return redirect('{}?fqdn={}'.format( reverse('api:serialconsole_add'), sub_arguments[0])) elif item == Add.ANNOTATION: if len(sub_arguments) != 1: return ErrorMessage( "Invalid number of arguments for 'annotation'!").as_json return redirect('{}?fqdn={}'.format(reverse('api:annotation_add'), sub_arguments[0])) elif item == Add.REMOTEPOWER: if len(sub_arguments) != 1: return ErrorMessage( "Invalid number of arguments for 'remotepower'!").as_json return redirect('{}?fqdn={}'.format(reverse('api:remotepower_add'), sub_arguments[0])) return ErrorMessage("Unknown item '{}'!".format(item)).as_json
def post(self, request, fqdn, *args, **kwargs): """ Add remote power to machine. """ if not request.user.is_superuser: return ErrorMessage( "Only superusers are allowed to perform this action!").as_json try: result = get_machine(fqdn, redirect_to='api:remotepower_add', data=request.GET) if isinstance(result, Serializer): return result.as_json elif isinstance(result, HttpResponseRedirect): return result machine = result except Exception as e: return ErrorMessage(str(e)).as_json if machine.has_remotepower(): return InfoMessage("Machine has already a remote power.").as_json data = json.loads(request.body.decode('utf-8'))['form'] form = RemotePowerAPIForm(data, machine=machine) if form.is_valid(): try: remotepower = RemotePower(**form.cleaned_data) remotepower.save() except Exception as e: logger.exception(e) return ErrorMessage("Something went wrong!").as_json return Message('Ok.').as_json return ErrorMessage("\n{}".format( format_cli_form_errors(form))).as_json
def post(self, request, *args, **kwargs): """ Return query result. """ response = {} try: query_str = json.loads(request.body.decode('utf-8'))['data'] except (KeyError, ValueError): return ErrorMessage("Data format is invalid!").as_json try: query = APIQuery(query_str) query.execute(user=request.user) except APIQuery.EmptyResult as e: return InfoMessage(str(e)).as_json except Exception as e: return ErrorMessage(str(e)).as_json response['header'] = {'type': 'TABLE', 'theader': query.get_theader()} response['data'] = query.data return JsonResponse(response, safe=False)
def _setup(self, request, machine, distribution): """ Trigger machine setup for `machine` with `distribution`. """ if isinstance(request.user, AnonymousUser) or not request.auth: return AuthRequiredSerializer().as_json machinegroup = None if machine.group and not machine.group.setup_use_architecture: machinegroup = machine.group.name valid = machine.fqdn_domain.is_valid_setup_choice( distribution, machine.architecture.name, machinegroup=machinegroup) if not valid: return ErrorMessage( "Unknown choice '{}'! Use 'SETUP <fqdn> list'.".format( distribution)).as_json try: result = machine.setup(distribution) if result: message = "OK." if not machine.has_remotepower(): message += " This machine has no remote power - "\ "a manuall reboot may be required." return Message(message).as_json else: return ErrorMessage( "Machine has no setup capability! Please contact '{}'.". format(machine.get_support_contact())).as_json except Exception as e: return ErrorMessage(str(e)).as_json
def get(self, request, *args, **kwargs): """ Return form for adding a machine. """ if isinstance(request.user, AnonymousUser) or not request.auth: return AuthRequiredSerializer().as_json if not request.user.is_superuser: return ErrorMessage( "Only superusers are allowed to perform this action!").as_json form = MachineAPIForm() input = InputSerializer(form.as_dict(), self.URL_POST, form.get_order()) return input.as_json
def get(self, request, *args, **kwargs): """ Perform machine power cycle. """ fqdn = request.GET.get('fqdn', None) action = request.GET.get('action', None) if action.lower() not in RemotePower.Action.as_list: return ErrorMessage("Unknown action '{}'!".format(action)).as_json try: result = get_machine( fqdn, redirect_to='api:powercycle', data=request.GET ) if isinstance(result, Serializer): return result.as_json elif isinstance(result, HttpResponseRedirect): return result machine = result except Exception as e: return ErrorMessage(str(e)).as_json if isinstance(request.user, AnonymousUser) or not request.auth: return AuthRequiredSerializer().as_json if not machine.has_remotepower(): return ErrorMessage("Machine has no remote power!").as_json try: result = machine.powercycle(action.lower(), user=request.user) if action.lower() == RemotePower.Action.STATUS: return Message("Status: {} ({})".format( result.capitalize(), machine.remotepower.name )).as_json if result: return Message("OK.").as_json else: return ErrorMessage("Something went wrong!").as_json except Exception as e: return ErrorMessage(str(e)).as_json return ErrorMessage("Something went wrong!").as_json
def get(self, request, *args, **kwargs): """ Trigger regeneration of machine-related/service files. """ fqdn = request.GET.get('fqdn', None) option = request.GET.get('option', None) service = request.GET.get('service', None) if service and (service.lower() in [Regenerate.COBBLER, Regenerate.SERIALCONSOLE]): if isinstance(request.user, AnonymousUser) or not request.auth: return AuthRequiredSerializer().as_json if not request.user.is_superuser: return ErrorMessage( "Only superusers are allowed to perform this action!" ).as_json # regenerate Cobbler entries if service.lower() == Regenerate.COBBLER: signal_cobbler_regenerate.send(sender=None, domain_id=None) return Message("Regenerate Cobbler entries...").as_json # regenerate serial console entries iterating over all cscreen servers elif service.lower() == Regenerate.SERIALCONSOLE: machines = SerialConsole.objects.all().values_list( 'cscreen_server__fqdn', flat=True) for fqdn in machines.distinct(): signal_serialconsole_regenerate.send( sender=None, cscreen_server_fqdn=fqdn) return Message("Regenerate serial console entries...").as_json elif (fqdn is not None) and (option is not None): try: result = get_machine(fqdn, redirect_to='api:regenerate', data=request.GET) if isinstance(result, Serializer): return result.as_json elif isinstance(result, HttpResponseRedirect): return result machine = result except Exception as e: return ErrorMessage(str(e)).as_json if option.lower() not in [Regenerate.MOTD]: return ErrorMessage( "Unknown option '{}'!".format(option)).as_json if isinstance(request.user, AnonymousUser) or not request.auth: return AuthRequiredSerializer().as_json try: if option.lower() == Regenerate.MOTD: machine.update_motd(user=request.user) return Message("OK.").as_json except Exception as e: return ErrorMessage(str(e)).as_json return ErrorMessage("Unknown service '{}'!".format(service)).as_json
def get(self, request, *args, **kwargs): """ Return machine information. """ fqdn = request.GET.get('fqdn', None) response = {} try: result = get_machine( fqdn, redirect_to='api:machine', data=request.GET ) if isinstance(result, Serializer): return result.as_json elif isinstance(result, HttpResponseRedirect): return result machine = result except Exception as e: return ErrorMessage(str(e)).as_json machine.enclosure.fetch_location(machine.pk) machine = MachineSerializer(machine) order = [ 'fqdn', 'architecture', 'ipv4', 'ipv6', 'serial_number', 'product_code', 'comment', 'nda', None, 'system', 'enclosure', 'group', None, 'location_room', 'location_rack', 'location_rack_position', None, 'reserved_by', 'reserved_reason', 'reserved_at', 'reserved_until', None, 'status_ipv4', 'status_ipv6', 'status_ssh', 'status_login', 'status_abuild', None, 'cpu_model', 'cpu_id', 'cpu_physical', 'cpu_cores', 'cpu_threads', 'cpu_flags', 'ram_amount', None, 'serial_type', 'serial_cscreen_server', 'serial_management_bmc', 'serial_console_server', 'serial_device', 'serial_port', 'serial_command', 'serial_comment', 'serial_baud_rate', 'serial_kernel_device', None, 'power_type', 'power_management_bmc', 'power_host', 'power_port', 'power_device', 'power_comment', [ 'installations', [ 'distribution', 'active', 'partition', 'architecture', 'kernelversion' ] ], [ 'networkinterfaces', [ 'mac_address', 'name', 'ethernet_type', 'driver_module', 'primary', ] ], [ 'annotations', [ 'text', 'reporter', 'created' ] ] ] response['header'] = {'type': 'INFO', 'order': order} response['data'] = machine.data_info return JsonResponse(response)