def dashboard(request): context = {} # active projects... mapper = ProjectAllocationMapper(request) active_projects = mapper.get_user_projects( request.user.username, alloc_status=["Active", "Approved", "Pending"], to_pytas_model=True, ) context["active_projects"] = active_projects context["show_migration_info"] = request.session.get( "has_legacy_account", False) # open tickets... rt = rtUtil.DjangoRt() context["open_tickets"] = rt.getUserTickets(request.user.email) # ongoing outages... outages = [ o for o in Outage.objects.order_by("-end_date", "-start_date") if not o.resolved ] # silly ORM quirk context["outages"] = outages webinars = Webinar.objects.filter(end_date__gte=timezone.now()) context["webinars"] = webinars return render(request, "dashboard.html", context)
def ticketreply(request, ticketId): rt = rtUtil.DjangoRt() ticket = rt.getTicket(ticketId) data = {} if request.method == 'POST': form = forms.ReplyForm(request.POST, request.FILES) if form.is_valid(): if 'attachment' in request.FILES: if rt.replyToTicket(ticketId, text=form.cleaned_data['reply'],\ files=([request.FILES['attachment'].name, request.FILES['attachment'], mimetypes.guess_type(request.FILES['attachment'].name)],)): return HttpResponseRedirect( reverse('djangoRT:ticketdetail', args=[ticketId])) else: data['reply'] = form.cleaned_data['reply'] form = forms.ReplyForm(data) else: if rt.replyToTicket(ticketId, text=form.cleaned_data['reply']): return HttpResponseRedirect( reverse('djangoRT:ticketdetail', args=[ticketId])) else: data['reply'] = form.cleaned_data['reply'] form = forms.ReplyForm(data) else: form = forms.ReplyForm(initial=data) return render( request, 'djangoRT/ticketReply.html', { 'ticket_id': ticketId, 'ticket': ticket, 'form': form, 'hasAccess': rt.hasAccess(ticketId, request.user.email) })
def ticketclose(request, ticket_id): rt = rtUtil.DjangoRt() ticket = rt.getTicket(ticket_id) if request.method == "POST": form = forms.CloseForm(request.POST) if form.is_valid(): reply = form.cleaned_data["reply"] if rt.commentOnTicket(ticket_id, text=reply) and rt.closeTicket(ticket_id): return HttpResponseRedirect( reverse("djangoRT:ticketdetail", args=[ticket_id]) ) else: form = forms.CloseForm() return render( request, "djangoRT/ticketClose.html", { "ticket_id": ticket_id, "ticket": ticket, "form": form, "hasAccess": rt.hasAccess(ticket_id, request.user.email), }, )
def mytickets(request): rt = rtUtil.DjangoRt() show_resolved = 'show_resolved' in request.GET tickets = rt.getUserTickets(request.user.email, show_resolved=show_resolved) return render(request, 'djangoRT/ticketList.html', { 'tickets': tickets, 'show_resolved': show_resolved })
def _create_ticket_for_pi_request(user): """ This is a stop-gap solution for https://collab.tacc.utexas.edu/issues/8327. """ rt = rtUtil.DjangoRt() subject = "Chameleon PI Eligibility Request: %s" % user['username'] ticket = rtModels.Ticket(subject=subject, problem_description="", requestor="*****@*****.**") rt.createTicket(ticket)
def add_openstack_data(self, **kwargs): ticket_id = kwargs.get("ticket_id") username = kwargs.get("username") messages = [] bound_task = self def write_message(progress_pct, message): LOG.info(message) messages.append(message) bound_task.update_state( state="PROGRESS", meta={ "messages": messages, "progress_pct": progress_pct, }, ) try: if username: keycloak_client = KeycloakClient() projects = keycloak_client.get_full_user_projects_by_username( username) regions = list(settings.OPENSTACK_AUTH_REGIONS.keys()) region_list = [] for i, region in enumerate(regions): try: factor = (1.0 / len(regions)) * 100 write_message(factor * i, f'Processing region "{region}"') region_list.append( get_openstack_data(username, region, projects)) except Exception as err: LOG.error( f"Failed to get OpenStack data for region {region}: {err}" ) openstack_user_data = remove_empty_lines( render_to_string("djangoRT/project_details.txt", {"regions": region_list})) else: openstack_user_data = "No openstack data for anonymous user." rt = rtUtil.DjangoRt() rt.commentOnTicket(ticket_id, openstack_user_data) except Exception as exc: LOG.exception("Failed to gather data") exc_message = getattr(exc, "message", None) if exc_message: messages.append(exc_message) raise OpenstackDataError(messages=messages) from exc # Return current state as last action return { "messages": messages, "progress_pct": 100.0, }
def mytickets(request): rt = rtUtil.DjangoRt() show_resolved = "show_resolved" in request.GET tickets = rt.getUserTickets(request.user.email, show_resolved=show_resolved) return render( request, "djangoRT/ticketList.html", { "tickets": tickets, "show_resolved": show_resolved, }, )
def ticketdetail(request, ticketId): rt = rtUtil.DjangoRt() ticket = rt.getTicket(ticketId) ticket_history = rt.getTicketHistory(ticketId) # remove bogus "untitled" attachments for history in ticket_history: history['Attachments'] = [ a for a in history['Attachments'] if not a[1].startswith('untitled (') ] return render(request, 'djangoRT/ticketDetail.html',\ { 'ticket' : ticket, 'ticket_history' : ticket_history, 'ticket_id' : ticketId, 'hasAccess' : rt.hasAccess(ticketId, request.user.email) })
def _create_ticket_for_pi_request(self, user): """ This is a stop-gap solution for https://collab.tacc.utexas.edu/issues/8327. """ rt = rtUtil.DjangoRt() subject = f"Chameleon PI Eligibility Request: {user.username}" problem_description = ( "This PI Eligibility request can be reviewed at " "https://www.chameleoncloud.org/admin/chameleon/pieligibility/") ticket = rtModels.Ticket( subject=subject, problem_description=problem_description, requestor="*****@*****.**", ) rt.createTicket(ticket)
def ticketcreateguest(request): rt = rtUtil.DjangoRt() data = {} if request.user.is_authenticated(): return HttpResponseRedirect(reverse('djangoRT:ticketcreate'), ) if request.method == 'POST': form = forms.TicketGuestForm(request.POST, request.FILES) if form.is_valid(): ticket = rtModels.Ticket( subject=form.cleaned_data['subject'], problem_description=form.cleaned_data['problem_description'], requestor=form.cleaned_data['email']) ticket_id = rt.createTicket(ticket) if ticket_id > -1: if 'attachment' in request.FILES: rt.replyToTicket(ticket_id, files=([ request.FILES['attachment'].name, request.FILES['attachment'], mimetypes.guess_type( request.FILES['attachment'].name) ], )) messages.add_message( request, messages.SUCCESS, 'Ticket #%s has been successfully created. We will respond to your request as soon as possible.' % ticket_id) form = forms.TicketGuestForm() return render(request, 'djangoRT/ticketCreateGuest.html', {'form': form}) else: # make this cleaner probably messages.error( 'An unexpected error occurred while creating your ticket. Please try again.' ) data['first_name'] = form.cleaned_data['first_name'] data['last_name'] = form.cleaned_data['last_name'] data['requestor'] = ticket.requestor data['subject'] = ticket.subject data['problem_description'] = ticket.problem_description data['cc'] = ticket.cc form = forms.TicketGuestForm(data) else: form = forms.TicketGuestForm(initial=data) return render(request, 'djangoRT/ticketCreateGuest.html', {'form': form})
def ticketattachment(request, ticketId, attachmentId): title, attachment = rtUtil.DjangoRt().getAttachment(ticketId, attachmentId) if attachment['Headers']['Content-Disposition'] == 'inline': return render( request, 'djangoRT/attachment.html', { 'attachment': attachment['Content'], 'ticketId': ticketId, 'title': title }) else: response = HttpResponse( attachment['Content'], content_type=attachment['Headers']['Content-Type']) response['Content-Disposition'] = attachment['Headers'][ 'Content-Disposition'] return response
def _create_ticket_for_pending_allocation(self, requestor, problem_description, owner): rt = rtUtil.DjangoRt() subject = ( "More information required to approve your Chameleon allocation request" ) ticket = rtModels.Ticket( subject=subject, problem_description= "Ticket created to contact the PI for more information.", requestor=requestor, owner=owner, ) ticket_id = rt.createTicket(ticket) rt.replyToTicket(ticket_id, text=problem_description) return ticket_id
def ticketattachment(request, ticket_id, attachment_id): title, attachment = rtUtil.DjangoRt().getAttachment(ticket_id, attachment_id) content = attachment["Content"] content_disposition = attachment["Headers"]["Content-Disposition"] content_type = attachment["Headers"]["Content-Type"] if content_disposition == "inline": return render( request, "djangoRT/attachment.html", { "attachment": content, "ticket_id": ticket_id, "title": title, }, ) else: response = HttpResponse(content, content_type=content_type) response["Content-Disposition"] = content_disposition return response
def ticketdetail(request, ticket_id): rt = rtUtil.DjangoRt() ticket = rt.getTicket(ticket_id) ticket_history = rt.getTicketHistory(ticket_id) # remove bogus "untitled" attachments for history in ticket_history: history["Attachments"] = [ a for a in history["Attachments"] if not a[1].startswith("untitled (") ] return render( request, "djangoRT/ticketDetail.html", { "ticket": ticket, "ticket_history": ticket_history, "ticket_id": ticket_id, "hasAccess": rt.hasAccess(ticket_id, request.user.email), }, )
def dashboard(request): context = {} # active projects... projects = Project.list(username=request.user) context['active_projects'] = [p for p in projects \ if p.source == 'Chameleon' and \ any(a.status in ['Active', 'Approved', 'Pending'] for a in p.allocations)] # open tickets... rt = rtUtil.DjangoRt() context['open_tickets'] = rt.getUserTickets(request.user.email) # ongoing outages... outages = [ o for o in Outage.objects.order_by('-end_date', '-start_date') if not o.resolved ] # silly ORM quirk context['outages'] = outages webinars = Webinar.objects.filter(end_date__gte=timezone.now()) context['webinars'] = webinars # federation status... if 'openid' in request.session: on_geni_project, on_chameleon_project = _check_geni_federation_status( request) context['geni_federation'] = { 'on_geni_project': on_geni_project, 'on_chameleon_project': on_chameleon_project, 'geni_project_name': settings.GENI_FEDERATION_PROJECTS['geni']['name'], 'chameleon_project_name': settings.GENI_FEDERATION_PROJECTS['chameleon']['name'], } return render(request, 'dashboard.html', context)
def ticketclose(request, ticketId): rt = rtUtil.DjangoRt() ticket = rt.getTicket(ticketId) data = {} if request.method == 'POST': form = forms.CloseForm(request.POST) if form.is_valid(): if rt.commentOnTicket(ticketId, text=form.cleaned_data['reply'] ) and rt.closeTicket(ticketId): return HttpResponseRedirect( reverse('djangoRT:ticketdetail', args=[ticketId])) else: form = forms.CloseForm(initial=data) return render( request, 'djangoRT/ticketClose.html', { 'ticket_id': ticketId, 'ticket': ticket, 'form': form, 'hasAccess': rt.hasAccess(ticketId, request.user.email) })
def ticketreply(request, ticket_id): rt = rtUtil.DjangoRt() ticket = rt.getTicket(ticket_id) if request.method == "POST": form = forms.ReplyForm(request.POST, request.FILES) if form.is_valid(): if "attachment" in request.FILES: attachment = request.FILES["attachment"] mime_type, encoding = mimetypes.guess_type(attachment.name) files = [(attachment.name, attachment, mime_type)] success = rt.replyToTicket( ticket_id, text=form.cleaned_data["reply"], files=files ) if success: return HttpResponseRedirect( reverse("djangoRT:ticketdetail", args=[ticket_id]) ) else: if rt.replyToTicket(ticket_id, text=form.cleaned_data["reply"]): return HttpResponseRedirect( reverse("djangoRT:ticketdetail", args=[ticket_id]) ) else: form = forms.ReplyForm() return render( request, "djangoRT/ticketReply.html", { "ticket_id": ticket_id, "ticket": ticket, "form": form, "hasAccess": rt.hasAccess(ticket_id, request.user.email), }, )
def _handle_ticket_form(request, form): """Generic ticket handling helper function. If the form is invalid: render an error to the user. If the ticket cannot be created: render an error to the user. If the ticket could be created but the attachment could not be attached: just log an error. Args: request (Request): The parent request. form (Form): The TicketForm to process. It is assumed this already has the POST/FILES data attached. Returns: The ID of the ticket created, if successful. Returns None on error. """ if not form.is_valid(): messages.error( request, "The form is invalid, ensure all required fields are provided." ) return None requestor = form.cleaned_data["email"] requestor_meta = " ".join( [ form.cleaned_data["first_name"], form.cleaned_data["last_name"], requestor, ] ) header = "\n".join( [ f"[{key}] {value}" for key, value in [ ("Opened by", request.user), ("Category", form.cleaned_data["category"]), ("Resource", "Chameleon"), ] ] ) ticket_body = f"""{header} {form.cleaned_data["problem_description"]} --- {requestor_meta} """ rt = rtUtil.DjangoRt() ticket = rtModels.Ticket( subject=form.cleaned_data["subject"], problem_description=ticket_body, requestor=requestor, cc=form.cleaned_data.get("cc", []), ) ticket_id = rt.createTicket(ticket) if ticket_id < 0: logger.error(f"Error creating ticket for {requestor}") messages.error( request, ("There was an error creating your ticket. Please try again.") ) return None logger.info(f"Created ticket #{ticket_id} for {requestor}") if "attachment" in request.FILES: attachment = request.FILES["attachment"] mime_type, encoding = mimetypes.guess_type(attachment.name) files = [(attachment.name, attachment, mime_type)] success = rt.replyToTicket(ticket_id, files=files) if not success: logger.error(f"Error adding attachment to #{ticket_id}") add_openstack_data.apply_async( kwargs={ "username": request.user.username, "ticket_id": ticket_id, }, ) messages.success( request, ( f"Ticket #{ticket_id} has been successfully created. " "We will respond to your request as soon as possible." ), ) return ticket_id
def ticketcreate(request): rt = rtUtil.DjangoRt() if not request.user.is_authenticated(): return HttpResponseRedirect(reverse('djangoRT:ticketcreateguest'), ) data = { 'email': request.user.email, 'first_name': request.user.first_name, 'last_name': request.user.last_name } # header = "[Ticket created from Chameleon Portal by " + request.user.first_name + " " + request.user.last_name + " (" + request.user.email + ")]\n\n" if request.method == 'POST': form = forms.TicketForm(request.POST, request.FILES) if form.is_valid(): requestor_meta = '%s %s <%s>' % ( form.cleaned_data['first_name'], form.cleaned_data['last_name'], form.cleaned_data['email']) meta = ( ('Opened by', request.user), ('Category', form.cleaned_data['category']), ('Resource', 'Chameleon'), ) header = '\n'.join('[%s] %s' % m for m in meta) ticket_body = '%s\n\n%s\n\n---\n%s' % ( header, form.cleaned_data['problem_description'], requestor_meta) ticket = rtModels.Ticket(subject=form.cleaned_data['subject'], problem_description=ticket_body, requestor=form.cleaned_data['email'], cc=form.cleaned_data['cc']) logger.debug('Creating ticket for user: %s' % form.cleaned_data) ticket_id = rt.createTicket(ticket) if ticket_id > -1: if 'attachment' in request.FILES: rt.replyToTicket(ticket_id, files=([ request.FILES['attachment'].name, request.FILES['attachment'], mimetypes.guess_type( request.FILES['attachment'].name) ], )) return HttpResponseRedirect( reverse('djangoRT:ticketdetail', args=[ticket_id])) else: messages.error( request, 'There was an error creating your ticket. Please try again.' ) else: messages.error(request, 'Invalid') else: form = forms.TicketForm( initial={ 'email': request.user.email, 'first_name': request.user.first_name, 'last_name': request.user.last_name }) return render(request, 'djangoRT/ticketCreate.html', {'form': form})
def ticketcreate(request): rt = rtUtil.DjangoRt() if not request.user.is_authenticated(): return HttpResponseRedirect(reverse('djangoRT:ticketcreateguest'), ) data = { 'email': request.user.email, 'first_name': request.user.first_name, 'last_name': request.user.last_name } if request.method == 'POST': form = forms.TicketForm(request.POST, request.FILES) if form.is_valid(): requestor_meta = '%s %s %s' % (form.cleaned_data['first_name'], form.cleaned_data['last_name'], form.cleaned_data['email']) meta = ( ('Opened by', request.user), ('Category', form.cleaned_data['category']), ('Resource', 'Chameleon'), ) header = '\n'.join('[%s] %s' % m for m in meta) ticket_body = '%s\n\n%s\n\n---\n%s' % ( header, form.cleaned_data['problem_description'], requestor_meta) region_list = [] for region in list(settings.OPENSTACK_AUTH_REGIONS.keys()): try: token = get_token(request, region=region) region_list.append( get_openstack_data(request.user.username, token, region)) except Exception as err: logger.error( f'Failed to get OpenStack data for region {region}: {err}' ) user_details = render_to_string('djangoRT/project_details.txt', {'regions': region_list}) ticket_body = ticket_body + user_details ticket = rtModels.Ticket(subject=form.cleaned_data['subject'], problem_description=ticket_body, requestor=form.cleaned_data['email'], cc=form.cleaned_data['cc']) logger.debug('Creating ticket for user: %s' % form.cleaned_data + ' with project details: ' + user_details) ticket_id = rt.createTicket(ticket) if ticket_id > -1: if 'attachment' in request.FILES: rt.replyToTicket(ticket_id, files=([request.FILES['attachment'].name,\ request.FILES['attachment'], mimetypes.guess_type(request.FILES['attachment'].name)],)) return HttpResponseRedirect( reverse('djangoRT:ticketdetail', args=[ticket_id])) else: messages.error( request, 'There was an error creating your ticket. Please try again.' ) else: messages.error(request, 'Invalid') else: form = forms.TicketForm( initial={ 'email': request.user.email, 'first_name': request.user.first_name, 'last_name': request.user.last_name }) return render(request, 'djangoRT/ticketCreate.html', {'form': form})