Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

initial commit of the proxmox lists widget #1210

Merged
merged 1 commit into from
Jun 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions docs/widgets.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ Dashy has support for displaying dynamic content in the form of widgets. There a
- [Nextcloud System](#nextcloud-system)
- [Nextcloud Stats](#nextcloud-stats)
- [Nextcloud PHP OPcache](#nextcloud-php-opcache-stats)
- [Proxmox lists](#proxmox-lists)
- [Sabnzbd](#sabnzbd)
- [Gluetun VPN Info](#gluetun-vpn-info)
- [Drone CI Build](#drone-ci-builds)
Expand Down Expand Up @@ -1967,6 +1968,64 @@ Shows statistics about PHP OPcache performance on your Nextcloud server.
- **Host**: Self-Hosted (see [Nextcloud](https://nextcloud.com))
- **Privacy**: _See [Nextcloud Privacy Policy](https://nextcloud.com/privacy)_


---

### Proxmox lists

Shows lists of nodes, containers, and VMs in a Proxmox virtual environment cluster, with a status indicator.

#### Options
**Field** | **Type** | **Required** | **Description**
--- | --- | --- | ---
**`cluster_url`** | `string` | Required | The URL of the proxmox cluster server. No trailing `/`. for example: `https://proxmox.lan:8006`
**`user_name`** | `string` | Required | A Proxmox API Username, for example `root@pam` or `dashy@pve`.
**`token_name`** | `string` | Required | A Proxmox API token name. You can get a token in the API section of the cluster management interface.
**`token_uuid`** | `string` | Required | The value of the token entered above. This is normally a UUID.
**`node`** | `string` | optional | A Proxmox node name. If empty or not supplied, a list of nodes will be shown.
**`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.
**`title`** | `string` | optional | A widget title.
**`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.
**`footer`** | `string` | optional | A widget footer.
**`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.
**`hide_templates`** | `boolean` | optional | When this is set to anything other than 0 or false, templates will be filtered out of the result list.

#### Example
This will show the list of nodes.
```yaml
- type: proxmox-lists
useProxy: true
options:
cluster_url: https://proxmox.lan:8006
user_name: root@pam
token_name: dashy
token_uuid: bfb152df-abcd-abcd-abcd-ccb95a472d01
```
This will show the list of VMs, with a title and a linked fotter, hiding VM templates.
```yaml
- type: proxmox-lists
useProxy: true
options:
cluster_url: https://proxmox.lan:8006
user_name: root@pam
token_name: dashy
token_uuid: bfb152df-abcd-abcd-abcd-ccb95a472d01
node: proxmox
node_data: qemu
title: Proxmox VMs
title_as_link: false
footer: Proxmox
footer_as_link: true
hide_templates: 1
```
#### Info

- **CORS**: 🟠 Proxied
- **Auth**: 🟢 Required
- **Price**: 🟢 Free
- **Host**: Self-Hosted (see [Proxmox Virtual Environment](https://proxmox.com/en/proxmox-ve))
- **Privacy**: _See [Proxmox's Privacy Policy](https://proxmox.com/en/privacy-policy)_

---

### Sabnzbd
Expand Down
156 changes: 156 additions & 0 deletions src/components/Widgets/Proxmox.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
<template>
<div class="proxmox-list">
<div class="proxmox-title" v-if="title">
<a v-if="titleAsLink" class="proxmox-link" :href="clusterUrl" target="_blank">
{{ title }}
</a>
<span v-if="!titleAsLink">{{ title }}</span>
</div>
<div v-for="(item, key) in data" :key="key" class="proxmox-row">
<div v-if="item.node" class="proxmox-cell">{{ item.node }}</div>
<div v-if="item.name" class="proxmox-cell">{{ item.name }}</div>
<div class="proxmox-cell proxmox-status"><span :class="item.status"></span></div>
</div>
<div class="proxmox-footer" v-if="footer">
<a v-if="footerAsLink" class="proxmox-link" :href="clusterUrl" target="_blank">
{{ footer }}
</a>
<span v-if="!footerAsLink">{{ title }}</span>
</div>
</div>
</template>

<script>
import WidgetMixin from '@/mixins/WidgetMixin';

export default {
mixins: [WidgetMixin],
components: {},
data() {
return {
data: [],
};
},
computed: {
clusterUrl() {
if (!this.options.cluster_url) this.error('The cluster URL is required.');
return this.options.cluster_url || '';
},
userName() {
if (!this.options.user_name) this.error('The user name is required.');
return this.options.user_name || '';
},
tokenName() {
if (!this.options.token_name) this.error('The token name is required.');
return this.options.token_name || '';
},
tokenUuid() {
if (!this.options.token_uuid) this.error('The token uuid is required.');
return this.options.token_uuid || '';
},
node() {
return this.options.node || '';
},
nodeData() {
return this.options.node_data || false;
},
hideTemplates() {
return this.options.hide_templates || false;
},
title() {
return this.options.title || '';
},
titleAsLink() {
return this.options.title_as_link || false;
},
footer() {
return this.options.footer || '';
},
footerAsLink() {
return this.options.footer_as_link || false;
},
endpoint() {
if (!this.node) {
return `${this.clusterUrl}/api2/json/nodes`;
}
if (this.nodeData) {
return `${this.clusterUrl}/api2/json/nodes/${this.node}/${this.nodeData}`;
}
return '';
},
authHeaders() {
if (this.userName && this.tokenName && this.tokenUuid) {
return { Authorization: `PVEAPIToken=${this.userName}!${this.tokenName}=${this.tokenUuid}` };
}
return false;
},
},
methods: {
fetchData() {
const auth = this.authHeaders;
if (auth) {
this.startLoading();
this.makeRequest(this.endpoint, auth).then(this.processData);
}
},
processData(data) {
this.data = data.data.sort((a, b) => a.vmid > b.vmid);
if (this.hideTemplates) {
this.data = this.data.filter(item => item.template !== 1);
}
this.finishLoading();
},
},
};

</script>

<style scoped lang="scss">

.proxmox-list {
.proxmox-title, .proxmox-footer {
outline: 2px solid transparent;
border: 1px solid var(--outline-color);
border-radius: var(--curve-factor);
box-shadow: var(--item-shadow);
color: var(--item-text-color);
margin: .5rem;
padding: 0.3rem;
background: var(--item-background);
text-align: center;

a {
text-decoration: none;
color: var(--item-text-color);
}
}
.proxmox-row {
display: flex;
align-items: center;
justify-content: space-between;
color: var(--widget-text-color);
font-size: 1.1rem;
.proxmox-cell {
display: inline-block;
}
.proxmox-status{
.online, .running {
width: 0.8rem;
height: 0.8rem;
border-radius: 50%;
background-color: var(--success);
display: block;
}
}
.proxmox-link {
display: inline-block;
padding: 0.2rem;
margin: 0.1rem 0.2rem;

}
&:not(:last-child) {
border-bottom: 1px dashed var(--widget-text-color);
}
}
}
</style>
1 change: 1 addition & 0 deletions src/components/Widgets/WidgetBase.vue
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ const COMPAT = {
'pi-hole-stats': 'PiHoleStats',
'pi-hole-top-queries': 'PiHoleTopQueries',
'pi-hole-traffic': 'PiHoleTraffic',
'proxmox-lists': 'Proxmox',
'public-holidays': 'PublicHolidays',
'public-ip': 'PublicIp',
'rss-feed': 'RssFeed',
Expand Down