mirror of
https://github.com/donaldzou/WGDashboard.git
synced 2024-11-22 07:10: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))
|
||||
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))
|
||||
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 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 InvalidConfigurationFileException(Exception):
|
||||
@ -1406,6 +1478,27 @@ def API_savePeerScheduleJob():
|
||||
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
|
||||
'''
|
||||
@ -1583,6 +1676,14 @@ def backGroundThread():
|
||||
time.sleep(10)
|
||||
|
||||
|
||||
def peerJobScheduleBackgroundThread():
|
||||
with app.app_context():
|
||||
print("-- Peer Schedule: Waiting 5 sec")
|
||||
while True:
|
||||
AllPeerJobs.runJob()
|
||||
time.sleep(10)
|
||||
|
||||
|
||||
def gunicornConfig():
|
||||
_, app_ip = DashboardConfig.GetConfig("Server", "app_ip")
|
||||
_, app_port = DashboardConfig.GetConfig("Server", "app_port")
|
||||
@ -1600,5 +1701,9 @@ bgThread = threading.Thread(target=backGroundThread)
|
||||
bgThread.daemon = True
|
||||
bgThread.start()
|
||||
|
||||
bg2Thread = threading.Thread(target=peerJobScheduleBackgroundThread)
|
||||
bg2Thread.daemon = True
|
||||
bg2Thread.start()
|
||||
|
||||
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:{
|
||||
|
||||
deleteJob(j, index){
|
||||
if (j.CreationDate){
|
||||
|
||||
}else{
|
||||
this.selectedPeer.jobs = this.selectedPeer.jobs.filter(x => x.JobID !== j.JobID)
|
||||
}
|
||||
deleteJob(j){
|
||||
this.selectedPeer.jobs = this.selectedPeer.jobs.filter(x => x.JobID !== j.JobID)
|
||||
},
|
||||
addJob(){
|
||||
this.selectedPeer.jobs.push(JSON.parse(JSON.stringify({
|
||||
this.selectedPeer.jobs.unshift(JSON.parse(JSON.stringify({
|
||||
JobID: crypto.randomUUID(),
|
||||
Configuration: this.selectedPeer.configuration.Name,
|
||||
Peer: this.selectedPeer.id,
|
||||
@ -100,7 +95,7 @@ export default {
|
||||
<template>
|
||||
<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="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-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2">
|
||||
<h4 class="mb-0 fw-normal">Schedule Jobs
|
||||
@ -108,23 +103,29 @@ export default {
|
||||
</h4>
|
||||
<button type="button" class="btn-close ms-auto" @click="this.$emit('close')"></button>
|
||||
</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">
|
||||
<input class="form-control form-control-sm w-auto rounded-3" placeholder="Search Job...">
|
||||
<button class="btn btn-sm btn-primary rounded-3 ms-auto" @click="this.addJob()">
|
||||
<button class="btn btn-sm btn-primary rounded-3" @click="this.addJob()">
|
||||
<i class="bi bi-plus-lg me-2"></i> Job
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
<TransitionGroup name="fade">
|
||||
<TransitionGroup name="schedulePeerJobTransition" tag="div" class="position-relative">
|
||||
<SchedulePeerJob
|
||||
@refresh="this.$emit('refresh')"
|
||||
@refresh="(j) => job = j"
|
||||
@delete="this.deleteJob(job)"
|
||||
:dropdowns="this.dropdowns"
|
||||
:key="job.JobID"
|
||||
:pjob="job" v-for="(job) in this.selectedPeer.jobs">
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
@ -134,5 +135,22 @@ export default {
|
||||
</template>
|
||||
|
||||
<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>
|
@ -24,11 +24,11 @@ export default {
|
||||
<template>
|
||||
<div class="dropdown scheduleDropdown">
|
||||
<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>
|
||||
</button>
|
||||
<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)">
|
||||
<samp>{{x.display}}</samp>
|
||||
<i class="bi bi-check ms-auto" v-if="x.value === this.currentSelection.value"></i>
|
||||
@ -42,8 +42,7 @@ export default {
|
||||
.btn.disabled{
|
||||
opacity: 1;
|
||||
background-color: rgba(13, 110, 253, 0.09);
|
||||
border-color: transparent;
|
||||
}
|
||||
.btn{
|
||||
//padding: 0.1rem 0.4rem;
|
||||
}
|
||||
|
||||
</style>
|
@ -31,7 +31,9 @@ export default {
|
||||
watch:{
|
||||
pjob: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler(newValue){
|
||||
console.log(newValue)
|
||||
this.job = JSON.parse(JSON.stringify(newValue))
|
||||
}
|
||||
}
|
||||
@ -45,7 +47,8 @@ export default {
|
||||
if (res.status){
|
||||
this.edit = false;
|
||||
this.store.newMessage("Server", "Job Saved!", "success")
|
||||
this.$emit("refresh")
|
||||
this.$emit("refresh", this.data)
|
||||
this.newJob = false;
|
||||
}else{
|
||||
this.store.newMessage("Server", res.message, "danger")
|
||||
}
|
||||
@ -72,6 +75,22 @@ export default {
|
||||
}else{
|
||||
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"
|
||||
@click="this.edit = true">[E] Edit</a>
|
||||
<a role="button"
|
||||
@click="this.delete()"
|
||||
class=" text-danger text-decoration-none">[D] Delete</a>
|
||||
</div>
|
||||
<div class="ms-auto d-flex gap-3" v-else>
|
||||
@ -160,4 +180,9 @@ export default {
|
||||
input{
|
||||
padding: 0.1rem 0.4rem;
|
||||
}
|
||||
input:disabled{
|
||||
border-color: transparent;
|
||||
background-color: rgba(13, 110, 253, 0.09);
|
||||
color: #0d6efd;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user