def run(job, server, **kwargs): duration = kwargs.get('snapshot_duration') if duration >= 0: set_progress(f"Requested snapshot retention is {duration} minutes") else: set_progress("Requested snapshot will be set to never expire") tintri = Tintri() session_id = tintri.get_session_id(None, save_to_self=True) set_progress(f"Calls to Tintri API will be using session ID: {session_id}") snapshot_name_template = "{{ server.hostname }}-snapshot-00X" snapshot_name = generate_string_from_template_for_server( snapshot_name_template, server ) resp = tintri.create_snapshot( "CRASH_CONSISTENT", kwargs.get( 'snapshot_duration'), snapshot_name, server.tintri_vm_uuid ) set_progress(f"Tintri API response: {resp}") if isinstance(resp, dict): if "code" in resp and resp["code"].startswith("ERR"): return "FAILURE", "", resp["message"]
def clone_from_tintri_snapshot(request, server_id, snapshot_uuid): profile = request.get_user_profile() server = get_object_or_404(Server, pk=server_id) if request.method == 'POST': form = TintriCloneSnapshotForm(request.POST, server=server) action = Tintri().get_or_create_clone_from_snapshot_server_action() if form.is_valid(): context = form.save() context["snapshot_uuid"] = snapshot_uuid action_response = action.run_hook_as_job( owner=profile, servers=[server], context=context ) action_kwargs = { "action": action, "server": server, "profile": profile, "request": request, } _format_action_html_response( action_response=action_response, **action_kwargs ) return HttpResponseRedirect(request.META['HTTP_REFERER']) else: form = TintriCloneSnapshotForm(server=server) return { 'title': "Clone VM from Tintri Snapshot", 'content': f"Cloning from snapshot with UUID {snapshot_uuid}", 'form': form, 'use_ajax': True, 'action_url': reverse('clone_from_tintri_snapshot', args=[server_id, snapshot_uuid]), 'submit': 'Clone', }
def delete_tintri_snapshot(request, server_id, snapshot_uuid): profile = request.get_user_profile() server = get_object_or_404(Server, pk=server_id) if request.method == 'POST': action = Tintri().get_or_create_delete_snapshot_server_action() context = {'snapshot_uuid': snapshot_uuid} action_response = action.run_hook_as_job( owner=profile, servers=[server], context=context ) action_kwargs = { "action": action, "server": server, "profile": profile, "request": request, } _format_action_html_response( action_response=action_response, **action_kwargs ) return HttpResponseRedirect(request.META['HTTP_REFERER']) return { 'title': "Delete Tintri Snapshot", "theme": "danger", "content": ( f"Are you sure you want to delete snapshot with uuid '{snapshot_uuid}' from Tintri?" " This action cannot be undone!" ), 'use_ajax': True, 'action_url': reverse('delete_tintri_snapshot', args=[server_id, snapshot_uuid]), 'submit': 'Delete', }
def verify_tintri_endpoint(request): tintri = Tintri() endpoint = tintri.get_connection_info() if not endpoint: messages.warn( request, "No Tintri Connection Endpoint found! Nothing to verify") return HttpResponseRedirect(request.META['HTTP_REFERER']) try: tintri.verify_connection() except Exception as err: status = 'danger' msg = format_html('Could not make a connection to the Tintri Appliance ' '<b>"{}"</b>:<br>{}', endpoint, str(err)) else: status = 'success' msg = format_html('Successfully connected to the Tintri Appliance at ' '<b>"{}"</b>.', endpoint) # The alert helper tag will escape the state and msg if they aren't properly # marked safe (after any necessary escaping with format_html) here content = helper_tags.alert(status, msg) return { 'title': "Verify connection to Tintri Appliance's Connection Endpoint", 'content': content, 'submit': None, 'cancel': "OK", }
def get_ci(server): tintri = Tintri() ci = tintri.get_connection_info() if not ci: return None t = {} t['ip'] = ci.ip t['username'] = ci.username t['password'] = ci.password return t
def delete_tintri_endpoint(request): endpoint = Tintri().get_connection_info() if request.method == 'POST': endpoint.delete() msg = "The Tintri Appliance's Endpoint has been deleted." messages.success(request, msg) return HttpResponseRedirect(request.META['HTTP_REFERER']) return { 'title': "Remove Tintri Appliance's Endpoint?", 'content': 'Are you sure you want to delete Tintri Appliance\'s endpoint \'{}\'?'.format(endpoint), 'use_ajax': True, 'action_url': reverse('delete_tintri_endpoint'), 'submit': 'Remove' }
def run(job, server, **kwargs): snapshot_uuid = kwargs.get('snapshot_uuid') set_progress( f"Attempting to delete snapshot wiht uuid '{snapshot_uuid}' for server '{server}'" ) tintri = Tintri() session_id = tintri.get_session_id(None, save_to_self=True) set_progress(f"Calls to Tintri API will be using session ID: {session_id}") resp = tintri.delete_snapshot(snapshot_uuid) set_progress(f"Tintri API response: {resp}") if isinstance(resp, dict): if "code" in resp and resp["code"].startswith("ERR"): return "FAILURE", "", resp["message"]
def edit_tintri_endpoint(request, endpoint_id=None): """ Create and edit dialog for a Tintri Appliance endpoint. If `endpoint_id` is None, creates a new one """ endpoint = Tintri().get_connection_info() action_url = reverse('create_tintri_endpoint') if endpoint or endpoint_id: action_url = reverse('edit_tintri_endpoint', args=[endpoint.id]) if request.method == 'POST': form = TintriEndpointForm(request.POST, instance=endpoint) if form.is_valid(): form.save() msg = "The Tintri Appliance Endpoint settings have been saved." messages.success(request, msg) profile = request.get_user_profile() logger.info("Endpoint set to {} by {}.".format(endpoint, profile.user.username)) return HttpResponseRedirect(request.META['HTTP_REFERER']) else: form = TintriEndpointForm(instance=endpoint) return { 'title': "Modify Tintri Appliance's Endpoint Settings", 'form': form, 'use_ajax': True, 'action_url': action_url, 'top_content': "Tintri Appliance Endpoint, Used to support advanced server metrics and actions", 'submit': 'Save', }
def clean(self): try: from xui.tintri.tintri_api import Tintri tintri = Tintri() tintri.verify_connection( self.cleaned_data.get('protocol'), self.cleaned_data.get('ip'), self.cleaned_data.get('port'), self.cleaned_data.get('username'), self.cleaned_data.get('password'), ) except: raise forms.ValidationError( "Unable to connect to Tintri Appliance's Endpoint using the parameters provided " ) return self.cleaned_data
def run(job, server, **kwargs): snapshot_uuid = kwargs.get('snapshot_uuid') new_vm_name = kwargs.get('new_vm_name') set_progress( f"New vm '{new_vm_name} will be created by cloning from Tintri snapshot with uuid '{snapshot_uuid}" ) tintri = Tintri() session_id = tintri.get_session_id(None, save_to_self=True) set_progress(f"Calls to Tintri API will be using session ID: {session_id}") resp = tintri.clone_from_snapshot(server.tintri_vm_uuid, snapshot_uuid, new_vm_name) set_progress(f"Tintri API response: {resp}") if isinstance(resp, dict): if "code" in resp and resp["code"].startswith("ERR"): return "FAILURE", "", resp["message"]
def admin_page(request): tintri = Tintri() tintri_context = { 'tabs': TabGroup( template_dir='tintri/templates', context={ "endpoint": tintri.get_connection_info(), "clone_from_snapshot": tintri.get_or_create_clone_from_snapshot_server_action(), "take_snapshot": tintri.get_or_create_take_snapshot_server_action(), "delete_snapshot": tintri.get_or_create_delete_snapshot_server_action() }, request=request, tabs=[ # First tab uses template 'groups/tabs/tab-main.html' #(_("Configuration"), 'configuration', {}), # Tab 2 is conditionally-shown in this slot and # uses template 'groups/tabs/tab-related-items.html' (_("Overview"), 'overview', {}), ], ) } return render(request, 'tintri/templates/admin_page.html', tintri_context)
def get_session(server): """ Get authenticated Tintri Session for the given server Requires: ConnectionInfo object with name 'Tintri VMstore for Environment X' Otherwise return None Args: server (obj): CB server object Returns: tintri: Tintri object """ # instantiate the Tintri server. tintri = Tintri() tintri.get_session_id(None, save_to_self=True) # Login to VMstore conn = tintri.get_connection_info() if not conn: return None return tintri