mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2024-11-22 15:20:09 +01:00
Schedule system is finally running, still need to more testing :)
This commit is contained in:
parent
2d838b69fd
commit
48dc8033f5
109
src/dashboard.py
109
src/dashboard.py
@ -171,10 +171,82 @@ class PeerJobs:
|
|||||||
''', (Job.Field, Job.Operator, Job.Value, Job.Action, Job.JobID))
|
''', (Job.Field, Job.Operator, Job.Value, Job.Action, Job.JobID))
|
||||||
self.jobdb.commit()
|
self.jobdb.commit()
|
||||||
self.__getJobs()
|
self.__getJobs()
|
||||||
return True, list(filter(lambda x: x.Configuration == Job.Configuration and x.Peer == Job.Peer and x.JobID == Job.JobID, self.Jobs))
|
return True, list(
|
||||||
|
filter(lambda x: x.Configuration == Job.Configuration and x.Peer == Job.Peer and x.JobID == Job.JobID,
|
||||||
|
self.Jobs))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return False, str(e)
|
return False, str(e)
|
||||||
|
|
||||||
|
def deleteJob(self, Job: PeerJob) -> tuple[bool, list] | tuple[bool, str]:
|
||||||
|
try:
|
||||||
|
if (len(str(Job.CreationDate))) == 0:
|
||||||
|
return False, "Job does not exist"
|
||||||
|
self.jobdbCursor.execute('''
|
||||||
|
DELETE FROM PeerJobs WHERE JobID = ?
|
||||||
|
''', (Job.JobID,))
|
||||||
|
self.jobdb.commit()
|
||||||
|
self.__getJobs()
|
||||||
|
return True, list(
|
||||||
|
filter(lambda x: x.Configuration == Job.Configuration and x.Peer == Job.Peer and x.JobID == Job.JobID,
|
||||||
|
self.Jobs))
|
||||||
|
except Exception as e:
|
||||||
|
return False, str(e)
|
||||||
|
|
||||||
|
def finishJob(self, Job: PeerJob) -> tuple[bool, list] | tuple[bool, str]:
|
||||||
|
try:
|
||||||
|
if (len(str(Job.CreationDate))) == 0:
|
||||||
|
return False, "Job does not exist"
|
||||||
|
self.jobdbCursor.execute('''
|
||||||
|
UPDATE PeerJobs SET ExpireDate = strftime('%Y-%m-%d %H:%M:%S','now') WHERE JobId = ?
|
||||||
|
''', (Job.JobID,))
|
||||||
|
self.jobdb.commit()
|
||||||
|
self.__getJobs()
|
||||||
|
return True, list(
|
||||||
|
filter(lambda x: x.Configuration == Job.Configuration and x.Peer == Job.Peer and x.JobID == Job.JobID,
|
||||||
|
self.Jobs))
|
||||||
|
except Exception as e:
|
||||||
|
return False, str(e)
|
||||||
|
|
||||||
|
def runJob(self):
|
||||||
|
print("======")
|
||||||
|
needToDelete = []
|
||||||
|
for job in self.Jobs:
|
||||||
|
print(job.toJson())
|
||||||
|
c = WireguardConfigurations.get(job.Configuration)
|
||||||
|
if c is not None:
|
||||||
|
f, fp = c.searchPeer(job.Peer)
|
||||||
|
if f:
|
||||||
|
if job.Field in ["total_receive", "total_sent", "total_data"]:
|
||||||
|
s = job.Field.split("_")[1]
|
||||||
|
x: float = getattr(fp, f"total_{s}") + getattr(fp, f"cumu_{s}")
|
||||||
|
y: float = float(job.Value)
|
||||||
|
else:
|
||||||
|
x: datetime = datetime.now()
|
||||||
|
y: datetime = datetime.fromtimestamp(float(job.Value))
|
||||||
|
|
||||||
|
runAction: bool = self.__runJob_Compare(x, y, job.Operator)
|
||||||
|
print("Running Job:" + str(runAction) + "\n")
|
||||||
|
if runAction:
|
||||||
|
if job.Action == "restrict":
|
||||||
|
print(str(c.restrictPeers([fp.id]).get_json()))
|
||||||
|
elif job.Action == "delete":
|
||||||
|
print(str(c.deletePeers([fp.id]).get_json()))
|
||||||
|
needToDelete.append(job)
|
||||||
|
|
||||||
|
for j in needToDelete:
|
||||||
|
self.deleteJob(j)
|
||||||
|
|
||||||
|
def __runJob_Compare(self, x: float | datetime, y: float | datetime, operator: str):
|
||||||
|
print(x, y, operator)
|
||||||
|
if operator == "eq":
|
||||||
|
return x == y
|
||||||
|
if operator == "neq":
|
||||||
|
return x != y
|
||||||
|
if operator == "lgt":
|
||||||
|
return x > y
|
||||||
|
if operator == "lst":
|
||||||
|
return x < y
|
||||||
|
|
||||||
|
|
||||||
class WireguardConfiguration:
|
class WireguardConfiguration:
|
||||||
class InvalidConfigurationFileException(Exception):
|
class InvalidConfigurationFileException(Exception):
|
||||||
@ -1406,6 +1478,27 @@ def API_savePeerScheduleJob():
|
|||||||
return ResponseObject(s, message=p)
|
return ResponseObject(s, message=p)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/api/deletePeerScheduleJob/', methods=['POST'])
|
||||||
|
def API_deletePeerScheduleJob():
|
||||||
|
data = request.json
|
||||||
|
if "Job" not in data.keys() not in WireguardConfigurations.keys():
|
||||||
|
return ResponseObject(False, "Please specify job")
|
||||||
|
job: dict = data['Job']
|
||||||
|
if "Peer" not in job.keys() or "Configuration" not in job.keys():
|
||||||
|
return ResponseObject(False, "Please specify peer and configuration")
|
||||||
|
configuration = WireguardConfigurations.get(job['Configuration'])
|
||||||
|
f, fp = configuration.searchPeer(job['Peer'])
|
||||||
|
if not f:
|
||||||
|
return ResponseObject(False, "Peer does not exist in this configuration")
|
||||||
|
|
||||||
|
s, p = AllPeerJobs.deleteJob(PeerJob(
|
||||||
|
job['JobID'], job['Configuration'], job['Peer'], job['Field'], job['Operator'], job['Value'],
|
||||||
|
job['CreationDate'], job['ExpireDate'], job['Action']))
|
||||||
|
if s:
|
||||||
|
return ResponseObject(s, data=p)
|
||||||
|
return ResponseObject(s, message=p)
|
||||||
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Tools
|
Tools
|
||||||
'''
|
'''
|
||||||
@ -1583,6 +1676,14 @@ def backGroundThread():
|
|||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
|
|
||||||
|
|
||||||
|
def peerJobScheduleBackgroundThread():
|
||||||
|
with app.app_context():
|
||||||
|
print("-- Peer Schedule: Waiting 5 sec")
|
||||||
|
while True:
|
||||||
|
AllPeerJobs.runJob()
|
||||||
|
time.sleep(10)
|
||||||
|
|
||||||
|
|
||||||
def gunicornConfig():
|
def gunicornConfig():
|
||||||
_, app_ip = DashboardConfig.GetConfig("Server", "app_ip")
|
_, app_ip = DashboardConfig.GetConfig("Server", "app_ip")
|
||||||
_, app_port = DashboardConfig.GetConfig("Server", "app_port")
|
_, app_port = DashboardConfig.GetConfig("Server", "app_port")
|
||||||
@ -1600,5 +1701,9 @@ bgThread = threading.Thread(target=backGroundThread)
|
|||||||
bgThread.daemon = True
|
bgThread.daemon = True
|
||||||
bgThread.start()
|
bgThread.start()
|
||||||
|
|
||||||
|
bg2Thread = threading.Thread(target=peerJobScheduleBackgroundThread)
|
||||||
|
bg2Thread.daemon = True
|
||||||
|
bg2Thread.start()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app.run(host=app_ip, debug=True, port=app_port)
|
app.run(host=app_ip, debug=False, port=app_port)
|
||||||
|
@ -71,16 +71,11 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods:{
|
methods:{
|
||||||
|
deleteJob(j){
|
||||||
deleteJob(j, index){
|
|
||||||
if (j.CreationDate){
|
|
||||||
|
|
||||||
}else{
|
|
||||||
this.selectedPeer.jobs = this.selectedPeer.jobs.filter(x => x.JobID !== j.JobID)
|
this.selectedPeer.jobs = this.selectedPeer.jobs.filter(x => x.JobID !== j.JobID)
|
||||||
}
|
|
||||||
},
|
},
|
||||||
addJob(){
|
addJob(){
|
||||||
this.selectedPeer.jobs.push(JSON.parse(JSON.stringify({
|
this.selectedPeer.jobs.unshift(JSON.parse(JSON.stringify({
|
||||||
JobID: crypto.randomUUID(),
|
JobID: crypto.randomUUID(),
|
||||||
Configuration: this.selectedPeer.configuration.Name,
|
Configuration: this.selectedPeer.configuration.Name,
|
||||||
Peer: this.selectedPeer.id,
|
Peer: this.selectedPeer.id,
|
||||||
@ -100,7 +95,7 @@ export default {
|
|||||||
<template>
|
<template>
|
||||||
<div class="peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll">
|
<div class="peerSettingContainer w-100 h-100 position-absolute top-0 start-0 overflow-y-scroll">
|
||||||
<div class="container d-flex h-100 w-100">
|
<div class="container d-flex h-100 w-100">
|
||||||
<div class="m-auto modal-dialog-centered dashboardModal">
|
<div class="m-auto modal-dialog-centered dashboardModal mt-0">
|
||||||
<div class="card rounded-3 shadow" style="width: 700px">
|
<div class="card rounded-3 shadow" style="width: 700px">
|
||||||
<div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2">
|
<div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2">
|
||||||
<h4 class="mb-0 fw-normal">Schedule Jobs
|
<h4 class="mb-0 fw-normal">Schedule Jobs
|
||||||
@ -108,23 +103,29 @@ export default {
|
|||||||
</h4>
|
</h4>
|
||||||
<button type="button" class="btn-close ms-auto" @click="this.$emit('close')"></button>
|
<button type="button" class="btn-close ms-auto" @click="this.$emit('close')"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body px-4 pb-4 pt-2">
|
<div class="card-body px-4 pb-4 pt-2 position-relative">
|
||||||
<div class="d-flex align-items-center mb-3">
|
<div class="d-flex align-items-center mb-3">
|
||||||
<input class="form-control form-control-sm w-auto rounded-3" placeholder="Search Job...">
|
<button class="btn btn-sm btn-primary rounded-3" @click="this.addJob()">
|
||||||
<button class="btn btn-sm btn-primary rounded-3 ms-auto" @click="this.addJob()">
|
|
||||||
<i class="bi bi-plus-lg me-2"></i> Job
|
<i class="bi bi-plus-lg me-2"></i> Job
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<TransitionGroup name="fade">
|
<TransitionGroup name="schedulePeerJobTransition" tag="div" class="position-relative">
|
||||||
<SchedulePeerJob
|
<SchedulePeerJob
|
||||||
@refresh="this.$emit('refresh')"
|
@refresh="(j) => job = j"
|
||||||
@delete="this.deleteJob(job)"
|
@delete="this.deleteJob(job)"
|
||||||
:dropdowns="this.dropdowns"
|
:dropdowns="this.dropdowns"
|
||||||
:key="job.JobID"
|
:key="job.JobID"
|
||||||
:pjob="job" v-for="(job) in this.selectedPeer.jobs">
|
:pjob="job" v-for="(job) in this.selectedPeer.jobs">
|
||||||
</SchedulePeerJob>
|
</SchedulePeerJob>
|
||||||
|
|
||||||
|
<div class="card" key="none" v-if="this.selectedPeer.jobs.length === 0">
|
||||||
|
<div class="card-body text-muted text-center">
|
||||||
|
<h1><i class="bi bi-emoji-frown-fill"></i></h1>
|
||||||
|
<h6 class="mb-0">This peer does not have any job yet.</h6>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</TransitionGroup>
|
</TransitionGroup>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -134,5 +135,22 @@ export default {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.schedulePeerJobTransition-move, /* apply transition to moving elements */
|
||||||
|
.schedulePeerJobTransition-enter-active,
|
||||||
|
.schedulePeerJobTransition-leave-active {
|
||||||
|
transition: all 0.4s cubic-bezier(0.82, 0.58, 0.17, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.schedulePeerJobTransition-enter-from,
|
||||||
|
.schedulePeerJobTransition-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ensure leaving items are taken out of layout flow so that moving
|
||||||
|
animations can be calculated correctly. */
|
||||||
|
.schedulePeerJobTransition-leave-active {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -24,11 +24,11 @@ export default {
|
|||||||
<template>
|
<template>
|
||||||
<div class="dropdown scheduleDropdown">
|
<div class="dropdown scheduleDropdown">
|
||||||
<button class="btn btn-sm btn-outline-primary rounded-3"
|
<button class="btn btn-sm btn-outline-primary rounded-3"
|
||||||
:class="{'disabled': !edit}" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
:class="{'disabled border-transparent': !edit}" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
<samp>{{this.currentSelection.display}}</samp>
|
<samp>{{this.currentSelection.display}}</samp>
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu rounded-3 shadow" style="font-size: 0.875rem; width: 200px">
|
<ul class="dropdown-menu rounded-3 shadow" style="font-size: 0.875rem; width: 200px">
|
||||||
<li v-for="x in this.options">
|
<li v-for="x in this.options" v-if="edit">
|
||||||
<a class="dropdown-item d-flex align-items-center" role="button" @click="$emit('update', x.value)">
|
<a class="dropdown-item d-flex align-items-center" role="button" @click="$emit('update', x.value)">
|
||||||
<samp>{{x.display}}</samp>
|
<samp>{{x.display}}</samp>
|
||||||
<i class="bi bi-check ms-auto" v-if="x.value === this.currentSelection.value"></i>
|
<i class="bi bi-check ms-auto" v-if="x.value === this.currentSelection.value"></i>
|
||||||
@ -42,8 +42,7 @@ export default {
|
|||||||
.btn.disabled{
|
.btn.disabled{
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
background-color: rgba(13, 110, 253, 0.09);
|
background-color: rgba(13, 110, 253, 0.09);
|
||||||
|
border-color: transparent;
|
||||||
}
|
}
|
||||||
.btn{
|
|
||||||
//padding: 0.1rem 0.4rem;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
@ -31,7 +31,9 @@ export default {
|
|||||||
watch:{
|
watch:{
|
||||||
pjob: {
|
pjob: {
|
||||||
deep: true,
|
deep: true,
|
||||||
|
immediate: true,
|
||||||
handler(newValue){
|
handler(newValue){
|
||||||
|
console.log(newValue)
|
||||||
this.job = JSON.parse(JSON.stringify(newValue))
|
this.job = JSON.parse(JSON.stringify(newValue))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,7 +47,8 @@ export default {
|
|||||||
if (res.status){
|
if (res.status){
|
||||||
this.edit = false;
|
this.edit = false;
|
||||||
this.store.newMessage("Server", "Job Saved!", "success")
|
this.store.newMessage("Server", "Job Saved!", "success")
|
||||||
this.$emit("refresh")
|
this.$emit("refresh", this.data)
|
||||||
|
this.newJob = false;
|
||||||
}else{
|
}else{
|
||||||
this.store.newMessage("Server", res.message, "danger")
|
this.store.newMessage("Server", res.message, "danger")
|
||||||
}
|
}
|
||||||
@ -72,6 +75,22 @@ export default {
|
|||||||
}else{
|
}else{
|
||||||
this.$emit('delete')
|
this.$emit('delete')
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
delete(){
|
||||||
|
if(this.job.CreationDate){
|
||||||
|
fetchPost(`/api/deletePeerScheduleJob/`, {
|
||||||
|
Job: this.job
|
||||||
|
}, (res) => {
|
||||||
|
if (!res.status){
|
||||||
|
this.store.newMessage("Server", res.message, "danger")
|
||||||
|
this.$emit('delete')
|
||||||
|
}else{
|
||||||
|
this.store.newMessage("Server", "Job Deleted!", "success")
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.$emit('delete')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -137,6 +156,7 @@ export default {
|
|||||||
class="ms-auto text-decoration-none"
|
class="ms-auto text-decoration-none"
|
||||||
@click="this.edit = true">[E] Edit</a>
|
@click="this.edit = true">[E] Edit</a>
|
||||||
<a role="button"
|
<a role="button"
|
||||||
|
@click="this.delete()"
|
||||||
class=" text-danger text-decoration-none">[D] Delete</a>
|
class=" text-danger text-decoration-none">[D] Delete</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="ms-auto d-flex gap-3" v-else>
|
<div class="ms-auto d-flex gap-3" v-else>
|
||||||
@ -160,4 +180,9 @@ export default {
|
|||||||
input{
|
input{
|
||||||
padding: 0.1rem 0.4rem;
|
padding: 0.1rem 0.4rem;
|
||||||
}
|
}
|
||||||
|
input:disabled{
|
||||||
|
border-color: transparent;
|
||||||
|
background-color: rgba(13, 110, 253, 0.09);
|
||||||
|
color: #0d6efd;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
Loading…
Reference in New Issue
Block a user