cli
This commit is contained in:
53
dist/qmi-cloud/main.js
vendored
53
dist/qmi-cloud/main.js
vendored
File diff suppressed because one or more lines are too long
2
dist/qmi-cloud/main.js.map
vendored
2
dist/qmi-cloud/main.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -56,21 +56,17 @@ async function init(type) {
|
||||
}
|
||||
|
||||
let provisions = await db.provision.get(filter);
|
||||
let scenarios = await db.scenario.get();
|
||||
|
||||
await asyncForEach(provisions.results, async function(p) {
|
||||
var _scenario = scenarios.results.filter(s=>{
|
||||
return s.name === p.scenario
|
||||
});
|
||||
if ( _scenario.length ){
|
||||
p._scenario = _scenario[0];
|
||||
}
|
||||
timeRunning(p);
|
||||
if (!IS_REAL) {
|
||||
console.log(`${p._id} - limit: ${limit} hs - actual duration: ${p.duration.hours} hs`);
|
||||
}
|
||||
if ( p.duration && p.duration.hours >= limit) {
|
||||
await cb(p);
|
||||
//Only if 24x7
|
||||
if ( !p.autoShutdown || p.autoShutdown.is24x7 ) {
|
||||
timeRunning(p);
|
||||
if (!IS_REAL) {
|
||||
console.log(`${p._id} - limit: ${limit} hs - actual duration: ${p.duration.hours} hs`);
|
||||
}
|
||||
if ( p.duration && p.duration.hours >= limit) {
|
||||
await cb(p);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -79,11 +75,11 @@ const doSendEmailWarning = async function(p) {
|
||||
if ( p.pendingNextAction === 'stopVms') {
|
||||
console.log(`Warning email Stop already sent. Wait for pending action to complete.`);
|
||||
} else {
|
||||
let msg = `Send warning STOP email - ${p.user.displayName} (${p.user.upn}) about provision '${p._scenario.title}' (${p._id}) being 'Running' more than ${RUNNING_LIMIT_HOURS_WARNING} hours (exactly ${p.duration.complete})`;
|
||||
let msg = `Send warning STOP email - ${p.user.displayName} (${p.user.upn}) about provision '${p._scenarioDoc.title}' (${p._id}) being 'Running' more than ${RUNNING_LIMIT_HOURS_WARNING} hours (exactly ${p.duration.complete})`;
|
||||
console.log(msg);
|
||||
if ( IS_REAL ) {
|
||||
await db.provision.update(p._id, {"pendingNextAction": "stopVms"});
|
||||
await sendEmail.sendWillStopIn24(p, p._scenario);
|
||||
await sendEmail.sendWillStopIn24(p, p._scenarioDoc);
|
||||
await db.notification.add({ provision: p._id.toString(), type: 'warningStop', message: msg });
|
||||
}
|
||||
}
|
||||
@@ -91,11 +87,17 @@ const doSendEmailWarning = async function(p) {
|
||||
|
||||
const doStop = async function(p) {
|
||||
try {
|
||||
let msg = `VMs stopped - ${p.user.displayName} (${p.user.upn}) about provision '${p._scenario.title}' (${p._id}) being 'Running' more than ${RUNNING_LIMIT_HOURS_STOP} hours (exactly ${p.duration.complete})`
|
||||
let msg = `VMs stopped - ${p.user.displayName} (${p.user.upn}) about provision '${p._scenarioDoc.title}' (${p._id}) being 'Running' more than ${RUNNING_LIMIT_HOURS_STOP} hours (exactly ${p.duration.complete})`
|
||||
console.log(msg);
|
||||
|
||||
if ( IS_REAL ) {
|
||||
await azurecli.deallocate(p, true);
|
||||
if ( IS_REAL ) {
|
||||
//Disable Divvy
|
||||
await azurecli.updateVmsTags(p, {
|
||||
"24x7": false,
|
||||
"StartupTime": false
|
||||
});
|
||||
//Stop VMs
|
||||
await azurecli.deallocate(p, true);
|
||||
await db.notification.add({ provision: p._id.toString(), type: 'stop', message: msg });
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,17 @@ async function start(provision){
|
||||
let rgName = _getRgName(provision);
|
||||
console.log("Starting VMs for resource group: "+rgName);
|
||||
|
||||
//Re-enable Divvy according to what's in database
|
||||
if (provision.autoShutdown){
|
||||
console.log("Re-enabling Divvy Tags according to database");
|
||||
var tagsEdit = {
|
||||
"24x7": provision.autoShutdown.is24x7? " " : false,
|
||||
"StartupTime": provision.autoShutdown.utcTagStartupTime || false,
|
||||
"ShutdownTime": provision.autoShutdown.utcTagShutdownTime || false
|
||||
}
|
||||
await updateVmsTags(provision, tagsEdit);
|
||||
}
|
||||
|
||||
var computeClient = await _getClient(provision.scenario);
|
||||
let finalResult = await computeClient.virtualMachines.list(rgName);
|
||||
|
||||
|
||||
@@ -208,6 +208,71 @@ router.post('/:userId/provisions', passport.ensureAuthenticatedAndIsMe, async (r
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /users/{userId}/provisions/{id}:
|
||||
* put:
|
||||
* description: Update Provision by ID
|
||||
* summary: Update Provision by ID
|
||||
* parameters:
|
||||
* - name: userId
|
||||
* in: path
|
||||
* type: string
|
||||
* required: true
|
||||
* - name: id
|
||||
* in: path
|
||||
* type: string
|
||||
* required: true
|
||||
* - in: body
|
||||
* name: body
|
||||
* description: Provision object
|
||||
* required: true
|
||||
* produces:
|
||||
* - application/json
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Provision
|
||||
*/
|
||||
router.put('/:userId/provisions/:id', passport.ensureAuthenticatedAndIsMe, async (req, res, next) => {
|
||||
const provision = await db.provision.getById(req.params.id);
|
||||
if (!provision){
|
||||
return res.status(404).json({"msg": "Not found privision with id "+req.params.id});
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
var resSchedule;
|
||||
if ( req.body.autoShutdownData ) {
|
||||
if ( req.body.autoShutdownData._id ) {
|
||||
resSchedule = await db.provisionAutoShutdown.update(req.body.autoShutdownData._id, req.body.autoShutdownData);
|
||||
} else {
|
||||
resSchedule = await db.provisionAutoShutdown.add(req.body.autoShutdownData);
|
||||
}
|
||||
var tagsEdit = {
|
||||
"24x7": resSchedule.is24x7? " " : false,
|
||||
"StartupTime": resSchedule.utcTagStartupTime || false,
|
||||
"ShutdownTime": resSchedule.utcTagShutdownTime || false
|
||||
}
|
||||
azurecli.updateVmsTags(provision, tagsEdit);
|
||||
}
|
||||
|
||||
var patch = {};
|
||||
if ( req.body.user ) {
|
||||
patch.user = req.body.user;
|
||||
}
|
||||
if ( resSchedule ) {
|
||||
patch.autoShutdown = resSchedule._id;
|
||||
}
|
||||
var result = {
|
||||
provision: await db.provision.update(provision._id, patch)
|
||||
}
|
||||
return res.json(result);
|
||||
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /users/{userId}/provisions/{id}:
|
||||
|
||||
@@ -7,14 +7,6 @@
|
||||
<h4 class="modal-title w-100 font-weight-bold">Edit Provision</h4>
|
||||
</div>
|
||||
<div class="modal-body" style="max-height: 650px; overflow: auto;">
|
||||
<div>
|
||||
<section style="padding: 20px 0px;">
|
||||
<label>Change Owner (*):</label>
|
||||
<select class="browser-default custom-select custom-select-sm" [(ngModel)]="selectedUser">
|
||||
<option *ngFor="let item of users" [value]="item._id">{{item.displayName}}</option>
|
||||
</select>
|
||||
</section>
|
||||
</div>
|
||||
<div *ngIf="provision._scenarioDoc && provision._scenarioDoc.isDivvyEnabled" style="background: #f0f0f0; padding: 15px 15px; margin: 7px 0px;">
|
||||
<div>
|
||||
<h5><mdb-icon far icon="calendar-alt"></mdb-icon> Scenario schedule <small style="font-size: 50%;">(everyday this scenario will startup and shutdown as scheduled bellow:)</small></h5>
|
||||
@@ -22,17 +14,17 @@
|
||||
<div>
|
||||
<b>Timezone:</b> {{getUTCTimes().timezone}} <i>(times relative to this timezone)</i>
|
||||
</div>
|
||||
<div class="md-form row" *ngIf="!autoShutdownData.is24x7">
|
||||
<div class="md-form row" [ngClass]="{'disabled': autoShutdownData.is24x7}">
|
||||
<div class="col-sm-6">
|
||||
<label>Startup time:</label>
|
||||
<ngb-timepicker style="font-size: 10px;" [(ngModel)]="autoShutdownData.startupTime" [meridian]="true" [minuteStep]="15"></ngb-timepicker>
|
||||
<ngb-timepicker readonly="true" style="font-size: 10px;" [(ngModel)]="autoShutdownData.startupTime" [meridian]="true" [minuteStep]="15" [disabled]="autoShutdownData.is24x7"></ngb-timepicker>
|
||||
<div class="utc">
|
||||
<i>UTC time: {{getUTCTimes().startupTime}}</i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label>Shutdown time:</label>
|
||||
<ngb-timepicker style="font-size: 10px;" [(ngModel)]="autoShutdownData.shutdownTime" [meridian]="true" [minuteStep]="15"></ngb-timepicker>
|
||||
<ngb-timepicker style="font-size: 10px;" [(ngModel)]="autoShutdownData.shutdownTime" [meridian]="true" [minuteStep]="15" [disabled]="autoShutdownData.is24x7"></ngb-timepicker>
|
||||
<div class="utc">
|
||||
<i>UTC time: {{getUTCTimes().shutdownTime}}</i>
|
||||
</div>
|
||||
@@ -42,6 +34,14 @@
|
||||
<mdb-checkbox [default]="false" [checked]="autoShutdownData.is24x7" (change)="checkOnchangeAutoshutdown($event)">Run 24x7 <i>(<mdb-icon fas icon="exclamation-triangle"></mdb-icon> requires permission from regional manager)</i></mdb-checkbox>
|
||||
</section>
|
||||
</div>
|
||||
<!--<div>
|
||||
<section style="padding: 20px 0px;">
|
||||
<label>Change Owner (*):</label>
|
||||
<select class="browser-default custom-select custom-select-sm" [(ngModel)]="selectedUser">
|
||||
<option *ngFor="let item of users" [value]="item._id">{{item.displayName}}</option>
|
||||
</select>
|
||||
</section>
|
||||
</div>-->
|
||||
</div>
|
||||
|
||||
<div class="modal-footer d-flex justify-content-center">
|
||||
|
||||
@@ -12,4 +12,8 @@ label {
|
||||
padding-left: 20px;
|
||||
padding-top: 5px;
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
.disabled {
|
||||
opacity: 0.2;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { MDBModalRef } from 'angular-bootstrap-md';
|
||||
import { Subject } from 'rxjs';
|
||||
import { UsersService } from '../services/users.service';
|
||||
import { ProvisionsService } from '../services/provisions.service';
|
||||
import * as moment from 'moment-timezone';
|
||||
|
||||
@Component({
|
||||
selector: 'qmi-edit-provision',
|
||||
@@ -49,6 +50,7 @@ export class ProvisionModalComponent implements OnInit, OnDestroy {
|
||||
"hour": parseInt(this.provision.autoShutdown.localeStartupTime.split(":")[0]),
|
||||
"minute": parseInt(this.provision.autoShutdown.localeStartupTime.split(":")[1])
|
||||
}
|
||||
this.autoShutdownData.is24x7 = this.provision.autoShutdown.is24x7;
|
||||
} else {
|
||||
this.autoShutdownData.is24x7 = true;
|
||||
}
|
||||
@@ -59,8 +61,23 @@ export class ProvisionModalComponent implements OnInit, OnDestroy {
|
||||
|
||||
}
|
||||
|
||||
confirm() : void {
|
||||
this._provisionsService.updateProvisionAdmin(this.provision._id, { user: this.selectedUser } ).subscribe( res=>{
|
||||
confirm() : void {
|
||||
|
||||
this.sendData.user = this.selectedUser;
|
||||
|
||||
let autoShutdownUTC = this.getUTCTimes();
|
||||
this.sendData.autoShutdownData = this.provision.autoShutdown || {};
|
||||
this.sendData.autoShutdownData.is24x7 = this.autoShutdownData.is24x7;
|
||||
this.sendData.autoShutdownData.utcTagStartupTime = autoShutdownUTC.tagStartup;
|
||||
this.sendData.autoShutdownData.utcTagShutdownTime = autoShutdownUTC.tagShutdown;
|
||||
this.sendData.autoShutdownData.localeStartupTime = this.autoShutdownData.startupTime.hour+":"+this._provisionsService.addZero(this.autoShutdownData.startupTime.minute);
|
||||
this.sendData.autoShutdownData.localeShutdownTime = this.autoShutdownData.shutdownTime.hour+":"+this._provisionsService.addZero(this.autoShutdownData.shutdownTime.minute);
|
||||
this.sendData.autoShutdownData.localTimezone = autoShutdownUTC.timezone;
|
||||
this.sendData.autoShutdownData.timezoneOffset = autoShutdownUTC.timezoneOffset;
|
||||
|
||||
console.log("SendData", this.sendData);
|
||||
|
||||
this._provisionsService.updateProvisionUser(this.provision._id, this.provision.user._id, this.sendData ).subscribe( res=>{
|
||||
this.action.next(res);
|
||||
this.modalRef.hide();
|
||||
});
|
||||
@@ -71,7 +88,8 @@ export class ProvisionModalComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
getUTCTimes() {
|
||||
return this._provisionsService.getUTCTimes(this.autoShutdownData, this.provision.autoShutdown.localTimezone);
|
||||
const zone = this.provision.autoShutdown? this.provision.autoShutdown.localTimezone : moment.tz.guess(true);
|
||||
return this._provisionsService.getUTCTimes(this.autoShutdownData, zone);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,17 +22,17 @@
|
||||
<div>
|
||||
<b>Local timezone:</b> {{zone}} <i>(times relative to this timezone)</i>
|
||||
</div>
|
||||
<div class="md-form row" *ngIf="!autoShutdown.is24x7">
|
||||
<div class="md-form row" [ngClass]="{'disabled': autoShutdown.is24x7}">
|
||||
<div class="col-sm-6">
|
||||
<label>Startup time:</label>
|
||||
<ngb-timepicker style="font-size: 10px;" [(ngModel)]="autoShutdown.startupTime" [meridian]="true" [minuteStep]="15"></ngb-timepicker>
|
||||
<ngb-timepicker style="font-size: 10px;" [(ngModel)]="autoShutdown.startupTime" [meridian]="true" [minuteStep]="15" [disabled]="autoShutdown.is24x7"></ngb-timepicker>
|
||||
<div class="utc">
|
||||
<i>UTC time: {{getUTCTimes().startupTime}}</i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label>Shutdown time:</label>
|
||||
<ngb-timepicker style="font-size: 10px;" [(ngModel)]="autoShutdown.shutdownTime" [meridian]="true" [minuteStep]="15"></ngb-timepicker>
|
||||
<ngb-timepicker style="font-size: 10px;" [(ngModel)]="autoShutdown.shutdownTime" [meridian]="true" [minuteStep]="15" [disabled]="autoShutdown.is24x7"></ngb-timepicker>
|
||||
<div class="utc">
|
||||
<i>UTC time: {{getUTCTimes().shutdownTime}}</i>
|
||||
</div>
|
||||
|
||||
@@ -16,4 +16,8 @@ label {
|
||||
padding-left: 20px;
|
||||
padding-top: 5px;
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
.disabled {
|
||||
opacity: 0.2;
|
||||
}
|
||||
@@ -110,7 +110,7 @@ export class NewProvisionConfirmComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
if ( this.scenario.isDivvyEnabled ) {
|
||||
if ( !this.autoShutdown.is24x7 ) {
|
||||
let autoShutdownUTC = this._provisionsService.getUTCTimes(this.autoShutdown, this);
|
||||
let autoShutdownUTC = this._provisionsService.getUTCTimes(this.autoShutdown, this.zone);
|
||||
this.sendData.autoShutdownData = {
|
||||
is24x7: false,
|
||||
utcTagStartupTime: autoShutdownUTC.tagStartup,
|
||||
|
||||
@@ -32,7 +32,9 @@
|
||||
<mdb-icon far icon="clock"></mdb-icon> Accumulated running time: <span style="font-weight: bold;">{{provision.runningAsDays}}</span>
|
||||
</div>
|
||||
<div *ngIf="provision.statusVms === 'Running' || provision.statusVms === 'Stopping'">
|
||||
<mdb-icon fas icon="stopwatch"></mdb-icon> VMs auto-shutdown in ~
|
||||
<mdb-icon fas icon="stopwatch"></mdb-icon>
|
||||
<span *ngIf="!provision.autoShutdown || provision.autoShutdown.is24x7"> 24x7 ends in ~</span>
|
||||
<span *ngIf="provision.autoShutdown && !provision.autoShutdown.is24x7"> Scheduled shutdown in ~</span>
|
||||
<span style="font-weight: bold;">{{provision.autoshutdownAsDays}}</span>
|
||||
</div>
|
||||
<div *ngIf="provision.statusVms === 'Stopped' || provision.statusVms === 'Starting'">
|
||||
@@ -77,7 +79,7 @@
|
||||
<button style="margin-right: 5px;" mdbTooltip="Start VMs" *ngIf="provision.status === 'provisioned' && provision.statusVms === 'Stopped'" (click)="openConfirmStartModal(provision)" class="lui-button">
|
||||
<span class="lui-icon lui-icon--run" aria-hidden="true"></span>
|
||||
</button>
|
||||
<button style="margin-right: 5px;" mdbTooltip="Edit running schedule" *ngIf="provision.status === 'provisioned'" (click)="openScheduleModal(provision)" class="lui-button">
|
||||
<button style="margin-right: 5px;" mdbTooltip="Edit running schedule" *ngIf="provision._scenarioDoc.isDivvyEnabled && provision.status === 'provisioned'" (click)="openScheduleModal(provision)" class="lui-button">
|
||||
<mdb-icon far icon="calendar-alt"></mdb-icon>
|
||||
</button>
|
||||
<button style="float: right;" mdbTooltip="Destroy provision" *ngIf="!provision.isDestroyed && (provision.status === 'provisioned' || provision.status === 'error') && (!provision.destroy || provision.destroy.status !== 'destroying')" (click)="openConfirmDestroyModal(provision)" class="lui-button">
|
||||
|
||||
@@ -12,7 +12,8 @@ import * as moment from 'moment-timezone';
|
||||
export class ProvisionsService {
|
||||
|
||||
selectedProv;
|
||||
RUNNING_PERIOD : number = 4; //days
|
||||
RUNNING_PERIOD : number = 7; //days
|
||||
STOP_PERIOR_IS_EXTERNAL = 10; //days;
|
||||
STOP_PERIOD : number = 20; //days
|
||||
|
||||
constructor( private httpClient: HttpClient ) { }
|
||||
@@ -55,6 +56,10 @@ export class ProvisionsService {
|
||||
return this.httpClient.put(`${environment.apiVersionPath}/provisions/${id}`, patch);
|
||||
}
|
||||
|
||||
updateProvisionUser(id, userId, patch): Observable<any> {
|
||||
return this.httpClient.put(`${environment.apiVersionPath}/users/${userId}/provisions/${id}`, patch);
|
||||
}
|
||||
|
||||
newDestroy(id, userId) : Observable<any> {
|
||||
return this.httpClient.post(`${environment.apiVersionPath}/users/${userId}/provisions/${id}/destroy`, null);
|
||||
}
|
||||
@@ -117,15 +122,16 @@ export class ProvisionsService {
|
||||
totalRunningTime = totalRunningTime + Math.abs(now.getTime() - runningFromTime);
|
||||
}
|
||||
|
||||
let runningFromDate = new Date(runningFromTime);
|
||||
var runningPeriodMils = this.RUNNING_PERIOD*24*60*60*1000;
|
||||
|
||||
let durationRunningLeft;
|
||||
if ( !p.isDestroyed && p.statusVms !== 'Stopped' && p.autoShutdown && !p.autoShutdown.is24x7 ) {
|
||||
let split = p.autoShutdown.localeShutdownTime.split(":");
|
||||
let runningToDate = new Date(runningFromTime);
|
||||
let runningToDate = new Date();
|
||||
runningToDate.setHours(split[0], split[1]);
|
||||
durationRunningLeft = moment.duration(runningToDate.getTime()- now.getTime())
|
||||
durationRunningLeft = moment.duration(runningToDate.getTime() - now.getTime())
|
||||
} else {
|
||||
let runningFromDate = new Date(runningFromTime);
|
||||
var runningPeriodMils = this.RUNNING_PERIOD*24*60*60*1000; //7 days
|
||||
runningFromDate.setTime(runningFromDate.getTime()+runningPeriodMils);
|
||||
durationRunningLeft = moment.duration(runningFromDate.getTime() - now.getTime());
|
||||
}
|
||||
@@ -140,7 +146,7 @@ export class ProvisionsService {
|
||||
p.runningAsDays = (runningDays? (runningDays+"d "):"") + (runningHours? runningHours+"h ": "") + runningMinutes+"m";
|
||||
p.runningAsHours = (runningAsHours? runningAsHours+"h ": "")+runningMinutes+"m";
|
||||
|
||||
let autoshutdownDays = Math.floor(durationRunningLeft.asDays());
|
||||
let autoshutdownDays = Math.abs(Math.floor(durationRunningLeft.asDays()));
|
||||
let autoshutdownHours = durationRunningLeft.hours();
|
||||
let autoshutdownAsHours = Math.floor(durationRunningLeft.asHours())
|
||||
let autoshutdownMinutes = durationRunningLeft.minutes();
|
||||
@@ -150,7 +156,11 @@ export class ProvisionsService {
|
||||
|
||||
if ( (p.statusVms === 'Stopped' || p.statusVms === 'Starting') && !p.isDestroyed ) {
|
||||
let autoDestroyDate = new Date(p.stoppedFrom);
|
||||
autoDestroyDate.setTime(autoDestroyDate.getTime() + this.STOP_PERIOD*24*60*60*1000);
|
||||
if (p.isExternalAccess){
|
||||
autoDestroyDate.setTime(autoDestroyDate.getTime() + this.STOP_PERIOR_IS_EXTERNAL*24*60*60*1000);
|
||||
} else {
|
||||
autoDestroyDate.setTime(autoDestroyDate.getTime() + this.STOP_PERIOD*24*60*60*1000);
|
||||
}
|
||||
let autoDestroy = autoDestroyDate.getTime() - now.getTime();
|
||||
let durationStop = moment.duration(autoDestroy);
|
||||
let autoDestroyDays = Math.floor(durationStop.asDays());
|
||||
|
||||
Reference in New Issue
Block a user