Skip to content

Commit b7d7927

Browse files
author
root
committed
initial commit of the proxmox lists widget
1 parent ff5b2d5 commit b7d7927

File tree

3 files changed

+216
-0
lines changed

3 files changed

+216
-0
lines changed

docs/widgets.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ Dashy has support for displaying dynamic content in the form of widgets. There a
5858
- [Nextcloud System](#nextcloud-system)
5959
- [Nextcloud Stats](#nextcloud-stats)
6060
- [Nextcloud PHP OPcache](#nextcloud-php-opcache-stats)
61+
- [Proxmox lists](#proxmox-lists)
6162
- [Sabnzbd](#sabnzbd)
6263
- [Gluetun VPN Info](#gluetun-vpn-info)
6364
- [Drone CI Build](#drone-ci-builds)
@@ -1967,6 +1968,64 @@ Shows statistics about PHP OPcache performance on your Nextcloud server.
19671968
- **Host**: Self-Hosted (see [Nextcloud](https://nextcloud.com))
19681969
- **Privacy**: _See [Nextcloud Privacy Policy](https://nextcloud.com/privacy)_
19691970

1971+
1972+
---
1973+
1974+
### Proxmox lists
1975+
1976+
Shows lists of nodes, containers, and VMs in a Proxmox virtual environment cluster, with a status indicator.
1977+
1978+
#### Options
1979+
**Field** | **Type** | **Required** | **Description**
1980+
--- | --- | --- | ---
1981+
**`cluster_url`** | `string` | Required | The URL of the proxmox cluster server. No trailing `/`. for example: `https://proxmox.lan:8006`
1982+
**`user_name`** | `string` | Required | A Proxmox API Username, for example `root@pam` or `dashy@pve`.
1983+
**`token_name`** | `string` | Required | A Proxmox API token name. You can get a token in the API section of the cluster management interface.
1984+
**`token_uuid`** | `string` | Required | The value of the token entered above. This is normally a UUID.
1985+
**`node`** | `string` | optional | A Proxmox node name. If empty or not supplied, a list of nodes will be shown.
1986+
**`node_data`** | `string` | optional | This is required if a node is selected, Currently this accepts two values, either `lxc` or `qemu` but the widget can be improved to get other types of data from the Proxmox API.
1987+
**`title`** | `string` | optional | A widget title.
1988+
**`title_as_link`** | `boolean` | optional | When this is set to anything other than 0 or false, the title will be linked to the value entered in the `cluster_url` option.
1989+
**`footer`** | `string` | optional | A widget footer.
1990+
**`footer_as_link`** | `boolean` | optional | When this is set to anything other than 0 or false, the title will be linked to the value entered in the `cluster_url` option.
1991+
**`hide_templates`** | `boolean` | optional | When this is set to anything other than 0 or false, templates will be filtered out of the result list.
1992+
1993+
#### Example
1994+
This will show the list of nodes.
1995+
```yaml
1996+
- type: proxmox-lists
1997+
useProxy: true
1998+
options:
1999+
cluster_url: https://proxmox.lan:8006
2000+
user_name: root@pam
2001+
token_name: dashy
2002+
token_uuid: bfb152df-abcd-abcd-abcd-ccb95a472d01
2003+
```
2004+
This will show the list of VMs, with a title and a linked fotter, hiding VM templates.
2005+
```yaml
2006+
- type: proxmox-lists
2007+
useProxy: true
2008+
options:
2009+
cluster_url: https://proxmox.lan:8006
2010+
user_name: root@pam
2011+
token_name: dashy
2012+
token_uuid: bfb152df-abcd-abcd-abcd-ccb95a472d01
2013+
node: proxmox
2014+
node_data: qemu
2015+
title: Proxmox VMs
2016+
title_as_link: false
2017+
footer: Proxmox
2018+
footer_as_link: true
2019+
hide_templates: 1
2020+
```
2021+
#### Info
2022+
2023+
- **CORS**: 🟠 Proxied
2024+
- **Auth**: 🟢 Required
2025+
- **Price**: 🟢 Free
2026+
- **Host**: Self-Hosted (see [Proxmox Virtual Environment](https://proxmox.com/en/proxmox-ve))
2027+
- **Privacy**: _See [Proxmox's Privacy Policy](https://proxmox.com/en/privacy-policy)_
2028+
19702029
---
19712030

19722031
### Sabnzbd

src/components/Widgets/Proxmox.vue

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
<template>
2+
<div class="proxmox-list">
3+
<div class="proxmox-title" v-if="title">
4+
<a v-if="titleAsLink" class="proxmox-link" :href="clusterUrl" target="_blank">
5+
{{ title }}
6+
</a>
7+
<span v-if="!titleAsLink">{{ title }}</span>
8+
</div>
9+
<div v-for="(item, key) in data" :key="key" class="proxmox-row">
10+
<div v-if="item.node" class="proxmox-cell">{{ item.node }}</div>
11+
<div v-if="item.name" class="proxmox-cell">{{ item.name }}</div>
12+
<div class="proxmox-cell proxmox-status"><span :class="item.status"></span></div>
13+
</div>
14+
<div class="proxmox-footer" v-if="footer">
15+
<a v-if="footerAsLink" class="proxmox-link" :href="clusterUrl" target="_blank">
16+
{{ footer }}
17+
</a>
18+
<span v-if="!footerAsLink">{{ title }}</span>
19+
</div>
20+
</div>
21+
</template>
22+
23+
<script>
24+
import WidgetMixin from '@/mixins/WidgetMixin';
25+
26+
export default {
27+
mixins: [WidgetMixin],
28+
components: {},
29+
data() {
30+
return {
31+
data: [],
32+
};
33+
},
34+
computed: {
35+
clusterUrl() {
36+
if (!this.options.cluster_url) this.error('The cluster URL is required.');
37+
return this.options.cluster_url || '';
38+
},
39+
userName() {
40+
if (!this.options.user_name) this.error('The user name is required.');
41+
return this.options.user_name || '';
42+
},
43+
tokenName() {
44+
if (!this.options.token_name) this.error('The token name is required.');
45+
return this.options.token_name || '';
46+
},
47+
tokenUuid() {
48+
if (!this.options.token_uuid) this.error('The token uuid is required.');
49+
return this.options.token_uuid || '';
50+
},
51+
node() {
52+
return this.options.node || '';
53+
},
54+
nodeData() {
55+
return this.options.node_data || false;
56+
},
57+
hideTemplates() {
58+
return this.options.hide_templates || false;
59+
},
60+
title() {
61+
return this.options.title || '';
62+
},
63+
titleAsLink() {
64+
return this.options.title_as_link || false;
65+
},
66+
footer() {
67+
return this.options.footer || '';
68+
},
69+
footerAsLink() {
70+
return this.options.footer_as_link || false;
71+
},
72+
endpoint() {
73+
if (!this.node) {
74+
return `${this.clusterUrl}/api2/json/nodes`;
75+
}
76+
if (this.nodeData) {
77+
return `${this.clusterUrl}/api2/json/nodes/${this.node}/${this.nodeData}`;
78+
}
79+
return '';
80+
},
81+
authHeaders() {
82+
if (this.userName && this.tokenName && this.tokenUuid) {
83+
return { Authorization: `PVEAPIToken=${this.userName}!${this.tokenName}=${this.tokenUuid}` };
84+
}
85+
return false;
86+
},
87+
},
88+
methods: {
89+
fetchData() {
90+
const auth = this.authHeaders;
91+
if (auth) {
92+
this.startLoading();
93+
this.makeRequest(this.endpoint, auth).then(this.processData);
94+
}
95+
},
96+
processData(data) {
97+
this.data = data.data.sort((a, b) => a.vmid > b.vmid);
98+
if (this.hideTemplates) {
99+
this.data = this.data.filter(item => item.template !== 1);
100+
}
101+
this.finishLoading();
102+
},
103+
},
104+
};
105+
106+
</script>
107+
108+
<style scoped lang="scss">
109+
110+
.proxmox-list {
111+
.proxmox-title, .proxmox-footer {
112+
outline: 2px solid transparent;
113+
border: 1px solid var(--outline-color);
114+
border-radius: var(--curve-factor);
115+
box-shadow: var(--item-shadow);
116+
color: var(--item-text-color);
117+
margin: .5rem;
118+
padding: 0.3rem;
119+
background: var(--item-background);
120+
text-align: center;
121+
122+
a {
123+
text-decoration: none;
124+
color: var(--item-text-color);
125+
}
126+
}
127+
.proxmox-row {
128+
display: flex;
129+
align-items: center;
130+
justify-content: space-between;
131+
color: var(--widget-text-color);
132+
font-size: 1.1rem;
133+
.proxmox-cell {
134+
display: inline-block;
135+
}
136+
.proxmox-status{
137+
.online, .running {
138+
width: 0.8rem;
139+
height: 0.8rem;
140+
border-radius: 50%;
141+
background-color: var(--success);
142+
display: block;
143+
}
144+
}
145+
.proxmox-link {
146+
display: inline-block;
147+
padding: 0.2rem;
148+
margin: 0.1rem 0.2rem;
149+
150+
}
151+
&:not(:last-child) {
152+
border-bottom: 1px dashed var(--widget-text-color);
153+
}
154+
}
155+
}
156+
</style>

src/components/Widgets/WidgetBase.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ const COMPAT = {
9999
'pi-hole-stats': 'PiHoleStats',
100100
'pi-hole-top-queries': 'PiHoleTopQueries',
101101
'pi-hole-traffic': 'PiHoleTraffic',
102+
'proxmox-lists': 'Proxmox',
102103
'public-holidays': 'PublicHolidays',
103104
'public-ip': 'PublicIp',
104105
'rss-feed': 'RssFeed',

0 commit comments

Comments
 (0)