/*
Copyright (C) 2017 Cloudbase Solutions SRL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
// @flow
import cookie from 'js-cookie'
import moment from 'moment'
import Api from '../utils/ApiCaller'
import { servicesUrl } from '../config'
import type { MainItem } from '../types/MainItem'
import type { Execution } from '../types/Execution'
import type { Field } from '../types/Field'
class ReplicaSourceUtils {
static filterDeletedExecutionsInReplicas(replicas) {
return replicas.map(replica => {
replica.executions = ReplicaSourceUtils.filterDeletedExecutions(replica.executions)
return replica
})
}
static filterDeletedExecutions(executions) {
if (!executions || !executions.length) {
return executions
}
return executions.filter(execution => execution.deleted_at === null || execution.deleted_at === undefined)
}
static sortReplicas(replicas) {
if (replicas.length === 1) {
ReplicaSourceUtils.sortExecutions(replicas[0].executions)
return
}
replicas.sort((a, b) => {
ReplicaSourceUtils.sortExecutions(a.executions)
ReplicaSourceUtils.sortExecutions(b.executions)
let aLastExecution = a.executions && a.executions.length ? a.executions[a.executions.length - 1] : null
let bLastExecution = b.executions && b.executions.length ? b.executions[b.executions.length - 1] : null
let aLastTime = aLastExecution ? aLastExecution.updated_at || aLastExecution.created_at : null
let bLastTime = bLastExecution ? bLastExecution.updated_at || bLastExecution.created_at : null
let aTime = aLastTime || a.updated_at || a.created_at
let bTime = bLastTime || b.updated_at || b.created_at
return moment(bTime).diff(moment(aTime))
})
}
static sortExecutions(executions) {
if (executions) {
executions.sort((a, b) => a.number - b.number)
}
}
static sortExecutionsAndTaskUpdates(executions) {
this.sortExecutions(executions)
executions.forEach(execution => {
this.sortTaskUpdates(execution)
})
}
static sortTaskUpdates(execution) {
if (execution.tasks) {
execution.tasks.forEach(task => {
if (task.progress_updates) {
task.progress_updates.sort((a, b) => moment(a.created_at).isBefore(moment(b.created_at)))
}
})
}
}
}
class ReplicaSource {
static getReplicas(): Promise {
return new Promise((resolve, reject) => {
let projectId = cookie.get('projectId')
Api.get(`${servicesUrl.coriolis}/${projectId || 'null'}/replicas/detail`).then(response => {
let replicas = response.data.replicas
replicas = ReplicaSourceUtils.filterDeletedExecutionsInReplicas(replicas)
ReplicaSourceUtils.sortReplicas(replicas)
resolve(replicas)
}).catch(reject)
})
}
static getReplicaExecutions(replicaId: string): Promise {
return new Promise((resolve, reject) => {
let projectId = cookie.get('projectId')
Api.get(`${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}/executions/detail`).then((response) => {
let executions = response.data.executions
ReplicaSourceUtils.sortExecutionsAndTaskUpdates(executions)
resolve(executions)
}).catch(reject)
})
}
static getReplica(replicaId: string): Promise {
return new Promise((resolve, reject) => {
let projectId = cookie.get('projectId')
Api.get(`${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}`).then(response => {
let replica = response.data.replica
replica.executions = ReplicaSourceUtils.filterDeletedExecutions(replica.executions)
ReplicaSourceUtils.sortExecutions(replica.executions)
resolve(replica)
}).catch(reject)
})
}
static execute(replicaId: string, fields?: Field[]): Promise {
return new Promise((resolve, reject) => {
let payload = { execution: { shutdown_instances: false } }
if (fields) {
fields.forEach(f => {
payload.execution[f.name] = f.value || false
})
}
let projectId = cookie.get('projectId')
Api.send({
url: `${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}/executions`,
method: 'POST',
data: payload,
}).then((response) => {
let execution = response.data.execution
ReplicaSourceUtils.sortTaskUpdates(execution)
resolve(execution)
}).catch(reject)
})
}
static cancelExecution(replicaId: string, executionId: string): Promise {
return new Promise((resolve, reject) => {
let projectId = cookie.get('projectId')
Api.send({
url: `${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}/executions/${executionId}/actions`,
method: 'POST',
data: { cancel: null },
}).then(() => {
resolve(replicaId)
}).catch(reject)
})
}
static deleteExecution(replicaId: string, executionId: string): Promise {
return new Promise((resolve, reject) => {
let projectId = cookie.get('projectId')
Api.send({
url: `${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}/executions/${executionId}`,
method: 'DELETE',
}).then(() => {
resolve(replicaId)
}).catch(reject)
})
}
static delete(replicaId: string): Promise {
return new Promise((resolve, reject) => {
let projectId = cookie.get('projectId')
Api.send({
url: `${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}`,
method: 'DELETE',
}).then(() => { resolve(replicaId) }, reject).catch(reject)
})
}
static deleteDisks(replicaId: string): Promise {
return new Promise((resolve, reject) => {
let projectId = cookie.get('projectId')
Api.send({
url: `${servicesUrl.coriolis}/${projectId || 'null'}/replicas/${replicaId}/actions`,
method: 'POST',
data: { 'delete-disks': null },
}).then(response => {
resolve(response.data.execution)
}).catch(reject)
})
}
}
export default ReplicaSource