netbox-vcenter-server 0.3.1__py3-none-any.whl → 0.4.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,7 @@ Supports multiple vCenter servers with per-server caching and VM import to NetBo
7
7
 
8
8
  from netbox.plugins import PluginConfig
9
9
 
10
- __version__ = "0.3.1"
10
+ __version__ = "0.4.1"
11
11
 
12
12
 
13
13
  class VcenterConfig(PluginConfig):
@@ -52,7 +52,13 @@
52
52
  </div>
53
53
  {% endif %}
54
54
 
55
- <form method="post">
55
+ <!-- Error/status messages from htmx -->
56
+ <div id="sync-status"></div>
57
+
58
+ <form hx-post="{% url 'plugins:netbox_vcenter:sync' %}"
59
+ hx-target="#sync-status"
60
+ hx-indicator="#sync-btn"
61
+ class="vcenter-sync-form">
56
62
  {% csrf_token %}
57
63
 
58
64
  <div class="mb-3">
@@ -78,8 +84,14 @@
78
84
  <br><small class="text-muted">{{ form.verify_ssl.help_text }}</small>
79
85
  </div>
80
86
 
81
- <button type="submit" class="btn btn-primary">
82
- <i class="mdi mdi-sync"></i> Connect & Sync
87
+ <button type="submit" class="btn btn-primary" id="sync-btn">
88
+ <span id="sync-loading" class="htmx-indicator">
89
+ <span class="spinner-border spinner-border-sm me-1" role="status"></span>
90
+ Connecting...
91
+ </span>
92
+ <span class="sync-ready">
93
+ <i class="mdi mdi-sync"></i> Connect & Sync
94
+ </span>
83
95
  </button>
84
96
  </form>
85
97
  </div>
@@ -144,6 +156,21 @@
144
156
  </div>
145
157
  </div>
146
158
 
159
+ <!-- Sync Loading Indicator (shown during htmx request) -->
160
+ <div id="sync-loading-panel" class="card mb-4">
161
+ <div class="card-body">
162
+ <div class="d-flex justify-content-center align-items-center py-5">
163
+ <div class="text-center">
164
+ <div class="spinner-border text-primary mb-3" role="status" style="width: 3rem; height: 3rem;">
165
+ <span class="visually-hidden">Loading...</span>
166
+ </div>
167
+ <p class="text-muted mb-0">Connecting to vCenter and fetching VMs...</p>
168
+ <p class="text-muted small">This may take a moment if MFA is required.</p>
169
+ </div>
170
+ </div>
171
+ </div>
172
+ </div>
173
+
147
174
  <!-- VM List -->
148
175
  {% if vms %}
149
176
  <div class="card">
@@ -247,12 +274,26 @@
247
274
  </div>
248
275
  {% elif selected_server and selected_server != 'all' and not cached_data|get_key:selected_server %}
249
276
  <div class="alert alert-info">
250
- <i class="mdi mdi-information"></i>
251
- No cached data for <strong>{{ selected_server }}</strong>.
252
- Enter your credentials and click "Connect & Sync" to fetch VMs.
277
+ <i class="mdi mdi-information"></i> No cached data for <strong>{{ selected_server }}</strong>. Enter your credentials and click "Connect & Sync" to fetch VMs.
253
278
  </div>
254
279
  {% endif %}
255
280
 
281
+ <style>
282
+ /* htmx indicator on the sync button */
283
+ #sync-btn .htmx-indicator { display: none; }
284
+ #sync-btn.htmx-request .htmx-indicator { display: inline; }
285
+ #sync-btn.htmx-request .sync-ready { display: none; }
286
+ #sync-btn.htmx-request { pointer-events: none; opacity: 0.7; }
287
+ /* Disable form inputs while syncing */
288
+ .vcenter-sync-form:has(#sync-btn.htmx-request) input,
289
+ .vcenter-sync-form:has(#sync-btn.htmx-request) select { pointer-events: none; opacity: 0.7; }
290
+ /* Loading panel - hidden by default, shown during sync */
291
+ #sync-loading-panel { display: none; }
292
+ body:has(#sync-btn.htmx-request) #sync-loading-panel { display: block; }
293
+ /* Hide "no cached data" alerts during sync */
294
+ body:has(#sync-btn.htmx-request) .alert-info { display: none; }
295
+ </style>
296
+
256
297
  <script>
257
298
  document.addEventListener('DOMContentLoaded', function() {
258
299
  const selectAll = document.getElementById('select-all');
netbox_vcenter/urls.py CHANGED
@@ -6,6 +6,7 @@ from . import views
6
6
 
7
7
  urlpatterns = [
8
8
  path("", views.VCenterDashboardView.as_view(), name="dashboard"),
9
+ path("sync/", views.VCenterSyncView.as_view(), name="sync"),
9
10
  path("refresh/<str:server>/", views.VCenterRefreshView.as_view(), name="refresh"),
10
11
  path("import/", views.VMImportView.as_view(), name="import"),
11
12
  path("compare/", views.VMComparisonView.as_view(), name="compare"),
netbox_vcenter/views.py CHANGED
@@ -310,6 +310,55 @@ class VCenterRefreshView(View):
310
310
  return redirect(f"/plugins/vcenter/?server={server}")
311
311
 
312
312
 
313
+ class VCenterSyncView(View):
314
+ """Async sync endpoint for htmx - connects to vCenter and caches VMs."""
315
+
316
+ def post(self, request):
317
+ """Connect to vCenter and fetch VMs, return htmx response."""
318
+ from django.http import HttpResponse
319
+
320
+ form = VCenterConnectForm(request.POST)
321
+
322
+ if not form.is_valid():
323
+ return HttpResponse(
324
+ '<div class="alert alert-danger"><i class="mdi mdi-alert-circle"></i> '
325
+ "Invalid form data. Please check your inputs.</div>",
326
+ status=400,
327
+ )
328
+
329
+ server = form.cleaned_data["server"]
330
+ username = form.cleaned_data["username"]
331
+ password = form.cleaned_data["password"]
332
+ verify_ssl = form.cleaned_data.get("verify_ssl", False)
333
+
334
+ # Connect and fetch VMs (this is the slow part with Duo MFA)
335
+ vms, error = connect_and_fetch(server, username, password, verify_ssl)
336
+
337
+ if error:
338
+ return HttpResponse(
339
+ f'<div class="alert alert-danger"><i class="mdi mdi-alert-circle"></i> '
340
+ f"<strong>Connection Failed:</strong> {error}</div>",
341
+ status=400,
342
+ )
343
+
344
+ # Cache the data (no timeout - persists until manual refresh)
345
+ cache_data = {
346
+ "vms": vms,
347
+ "timestamp": timezone.now().isoformat(),
348
+ "server": server,
349
+ "count": len(vms),
350
+ }
351
+ cache.set(get_cache_key(server), cache_data, None)
352
+
353
+ # Add success message for the redirected page
354
+ messages.success(request, f"Successfully synced {len(vms)} VMs from {server}")
355
+
356
+ # Return HX-Redirect header to trigger page reload with new data
357
+ response = HttpResponse(status=200)
358
+ response["HX-Redirect"] = f"/plugins/vcenter/?server={server}"
359
+ return response
360
+
361
+
313
362
  class VMImportView(View):
314
363
  """Import selected VMs from vCenter to NetBox."""
315
364
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: netbox-vcenter-server
3
- Version: 0.3.1
3
+ Version: 0.4.1
4
4
  Summary: NetBox plugin for viewing and importing VMs from VMware vCenter servers
5
5
  Author-email: sieteunoseis <jeremy.worden@gmail.com>
6
6
  License: Apache-2.0
@@ -1,18 +1,18 @@
1
- netbox_vcenter/__init__.py,sha256=KZyIADe4OvKcDaLOCxTfKZcG7k-ItLnQgplFBJgP-uY,3386
1
+ netbox_vcenter/__init__.py,sha256=dzyA5vBqt3PcYPtGRGOB4kxGDIr6tqWcjEzaeaaWlNo,3386
2
2
  netbox_vcenter/client.py,sha256=_zRJQpZ-zlDwvVk87At-SHF7jTHBfP6Q3Z8CTvGV7GA,8422
3
3
  netbox_vcenter/forms.py,sha256=WYjv1U37SimAoRTYLbHGfqVR0-QF1km02fUwLeu84GI,3131
4
4
  netbox_vcenter/navigation.py,sha256=iQ5on_klzEI5rUsT4xXNTvP9vmtitiKVPiUd0r4HyuA,757
5
- netbox_vcenter/urls.py,sha256=EOu8qCSq_lAkN56SmPaHMidHPTzu-Jb13_NfxlaUOfI,509
6
- netbox_vcenter/views.py,sha256=j9bMK2DhlQDHzTEaSHvY-uj-0OETyy4GWbWWQmoVm5Q,29635
5
+ netbox_vcenter/urls.py,sha256=GUxbJMqRtFIPZ_592jfovT1CGY62xPA7IW8MjSHmmJA,574
6
+ netbox_vcenter/views.py,sha256=xXUkQqAWA40oF4CU7NKk4XtQzxd1quoG1-Q_C2wQrwI,31469
7
7
  netbox_vcenter/api/__init__.py,sha256=f5d-0NprTQjL9t0TC9RuDlwCvkA7974Dbm_cuPI5FBY,44
8
8
  netbox_vcenter/api/urls.py,sha256=84-OcoT5K1jzckWIsFpAfstfFn8BCuMgMwE1tH8XtMY,103
9
9
  netbox_vcenter/templates/netbox_vcenter/compare.html,sha256=5b6bGQnxKlgB5OvTeHuBf53_c4mLIahTV_OB99Soai4,10412
10
- netbox_vcenter/templates/netbox_vcenter/dashboard.html,sha256=umeT184bPDoWgA_8t2mz0_YFuOLjQcj2rNY39A74nAc,12897
10
+ netbox_vcenter/templates/netbox_vcenter/dashboard.html,sha256=ehmKh1HQkpDlDYMMMh8F-FRlTK01pFSQfp9CstGz968,14954
11
11
  netbox_vcenter/templates/netbox_vcenter/import.html,sha256=Gv_e0VOEQnUxW6wxuLNIdzAYB-JW5CLeL7Afxz7b3lo,8052
12
12
  netbox_vcenter/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  netbox_vcenter/templatetags/vcenter_tags.py,sha256=Ca6X3yyH43M-YqbEkZqapnqM_4hOqf0g-N1PikfY9xY,327
14
- netbox_vcenter_server-0.3.1.dist-info/licenses/LICENSE,sha256=8-I2jh8bMe_hkWX6XfGtHF1aA6y1oqRusoMnkdmFzNA,10761
15
- netbox_vcenter_server-0.3.1.dist-info/METADATA,sha256=SpVCQd9GZtTKD8niCdV2rQapiKWx9Qi7SUYJtFA5llI,6374
16
- netbox_vcenter_server-0.3.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
17
- netbox_vcenter_server-0.3.1.dist-info/top_level.txt,sha256=jvm95otBzT6WKAfIM_UXVqOeHYYL59zgpyEcLEk3G8g,15
18
- netbox_vcenter_server-0.3.1.dist-info/RECORD,,
14
+ netbox_vcenter_server-0.4.1.dist-info/licenses/LICENSE,sha256=8-I2jh8bMe_hkWX6XfGtHF1aA6y1oqRusoMnkdmFzNA,10761
15
+ netbox_vcenter_server-0.4.1.dist-info/METADATA,sha256=f82jzMZBIeNRJwa_5iTPYugrWMedUIxtmxOQWI2UW3I,6374
16
+ netbox_vcenter_server-0.4.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
17
+ netbox_vcenter_server-0.4.1.dist-info/top_level.txt,sha256=jvm95otBzT6WKAfIM_UXVqOeHYYL59zgpyEcLEk3G8g,15
18
+ netbox_vcenter_server-0.4.1.dist-info/RECORD,,