357 lines
8.2 KiB
JavaScript
357 lines
8.2 KiB
JavaScript
const { Instance, InstanceSnapshot, InstanceEvent, Customer, Product, AuditLog } = require('../models');
|
|
const { Op } = require('sequelize');
|
|
|
|
// Get all instances for reseller
|
|
const getInstances = async (req, res) => {
|
|
try {
|
|
const { page = 1, limit = 20, status, type, customerId, region } = req.query;
|
|
const resellerId = req.user.resellerId;
|
|
const offset = (page - 1) * limit;
|
|
|
|
const where = { resellerId };
|
|
if (status) where.status = status;
|
|
if (type) where.type = type;
|
|
if (customerId) where.customerId = customerId;
|
|
if (region) where.region = region;
|
|
|
|
const { count, rows: instances } = await Instance.findAndCountAll({
|
|
where,
|
|
include: [
|
|
{
|
|
model: Customer,
|
|
as: 'customer',
|
|
attributes: ['id', 'companyName', 'contactPerson']
|
|
}
|
|
],
|
|
limit: parseInt(limit),
|
|
offset: parseInt(offset),
|
|
order: [['createdAt', 'DESC']]
|
|
});
|
|
|
|
res.json({
|
|
success: true,
|
|
data: {
|
|
instances,
|
|
pagination: {
|
|
total: count,
|
|
page: parseInt(page),
|
|
pages: Math.ceil(count / limit),
|
|
limit: parseInt(limit)
|
|
}
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('Get instances error:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Failed to fetch instances'
|
|
});
|
|
}
|
|
};
|
|
|
|
// Create new instance
|
|
const createInstance = async (req, res) => {
|
|
try {
|
|
const {
|
|
customerId,
|
|
name,
|
|
template,
|
|
size,
|
|
region,
|
|
zone,
|
|
specifications,
|
|
configuration = {},
|
|
tags = []
|
|
} = req.body;
|
|
const resellerId = req.user.resellerId;
|
|
|
|
// Verify customer belongs to reseller
|
|
const customer = await Customer.findOne({
|
|
where: { id: customerId, resellerId }
|
|
});
|
|
|
|
if (!customer) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: 'Customer not found'
|
|
});
|
|
}
|
|
|
|
// Create instance record
|
|
const instance = await Instance.create({
|
|
customerId,
|
|
resellerId,
|
|
name,
|
|
template,
|
|
size,
|
|
region,
|
|
zone,
|
|
specifications,
|
|
configuration,
|
|
tags,
|
|
status: 'pending'
|
|
});
|
|
|
|
// Log creation event
|
|
await InstanceEvent.create({
|
|
instanceId: instance.id,
|
|
eventType: 'created',
|
|
status: 'completed',
|
|
message: 'Instance created successfully',
|
|
triggeredBy: req.user.id,
|
|
source: 'user',
|
|
startedAt: new Date(),
|
|
completedAt: new Date()
|
|
});
|
|
|
|
// Log audit
|
|
await AuditLog.create({
|
|
userId: req.user.id,
|
|
action: 'INSTANCE_CREATED',
|
|
resource: 'instance',
|
|
resourceId: instance.id,
|
|
newValues: instance.toJSON(),
|
|
ipAddress: req.ip,
|
|
userAgent: req.get('User-Agent')
|
|
});
|
|
|
|
// TODO: Integrate with Cloudtopiaa IaaS API to actually provision the instance
|
|
// This would be an async operation that updates the instance status
|
|
|
|
res.status(201).json({
|
|
success: true,
|
|
message: 'Instance creation initiated',
|
|
data: { instance }
|
|
});
|
|
} catch (error) {
|
|
console.error('Create instance error:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Failed to create instance'
|
|
});
|
|
}
|
|
};
|
|
|
|
// Start instance
|
|
const startInstance = async (req, res) => {
|
|
try {
|
|
const { instanceId } = req.params;
|
|
const resellerId = req.user.resellerId;
|
|
|
|
const instance = await Instance.findOne({
|
|
where: { id: instanceId, resellerId }
|
|
});
|
|
|
|
if (!instance) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: 'Instance not found'
|
|
});
|
|
}
|
|
|
|
if (!instance.canStart()) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: 'Instance cannot be started in current state'
|
|
});
|
|
}
|
|
|
|
// Update instance status
|
|
await instance.update({ status: 'starting' });
|
|
|
|
// Log event
|
|
await InstanceEvent.create({
|
|
instanceId: instance.id,
|
|
eventType: 'started',
|
|
status: 'in_progress',
|
|
message: 'Starting instance',
|
|
triggeredBy: req.user.id,
|
|
source: 'user',
|
|
startedAt: new Date()
|
|
});
|
|
|
|
// TODO: Call Cloudtopiaa IaaS API to start the instance
|
|
// This would be an async operation
|
|
|
|
res.json({
|
|
success: true,
|
|
message: 'Instance start initiated',
|
|
data: { instance }
|
|
});
|
|
} catch (error) {
|
|
console.error('Start instance error:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Failed to start instance'
|
|
});
|
|
}
|
|
};
|
|
|
|
// Stop instance
|
|
const stopInstance = async (req, res) => {
|
|
try {
|
|
const { instanceId } = req.params;
|
|
const resellerId = req.user.resellerId;
|
|
|
|
const instance = await Instance.findOne({
|
|
where: { id: instanceId, resellerId }
|
|
});
|
|
|
|
if (!instance) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: 'Instance not found'
|
|
});
|
|
}
|
|
|
|
if (!instance.canStop()) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: 'Instance cannot be stopped in current state'
|
|
});
|
|
}
|
|
|
|
// Update instance status
|
|
await instance.update({ status: 'stopping' });
|
|
|
|
// Log event
|
|
await InstanceEvent.create({
|
|
instanceId: instance.id,
|
|
eventType: 'stopped',
|
|
status: 'in_progress',
|
|
message: 'Stopping instance',
|
|
triggeredBy: req.user.id,
|
|
source: 'user',
|
|
startedAt: new Date()
|
|
});
|
|
|
|
res.json({
|
|
success: true,
|
|
message: 'Instance stop initiated',
|
|
data: { instance }
|
|
});
|
|
} catch (error) {
|
|
console.error('Stop instance error:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Failed to stop instance'
|
|
});
|
|
}
|
|
};
|
|
|
|
// Create snapshot
|
|
const createSnapshot = async (req, res) => {
|
|
try {
|
|
const { instanceId } = req.params;
|
|
const { name, description, type = 'manual' } = req.body;
|
|
const resellerId = req.user.resellerId;
|
|
|
|
const instance = await Instance.findOne({
|
|
where: { id: instanceId, resellerId }
|
|
});
|
|
|
|
if (!instance) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: 'Instance not found'
|
|
});
|
|
}
|
|
|
|
// Create snapshot record
|
|
const snapshot = await InstanceSnapshot.create({
|
|
instanceId,
|
|
name,
|
|
description,
|
|
type,
|
|
status: 'creating'
|
|
});
|
|
|
|
// Log event
|
|
await InstanceEvent.create({
|
|
instanceId: instance.id,
|
|
eventType: 'snapshot_created',
|
|
status: 'in_progress',
|
|
message: `Creating snapshot: ${name}`,
|
|
triggeredBy: req.user.id,
|
|
source: 'user',
|
|
startedAt: new Date()
|
|
});
|
|
|
|
res.status(201).json({
|
|
success: true,
|
|
message: 'Snapshot creation initiated',
|
|
data: { snapshot }
|
|
});
|
|
} catch (error) {
|
|
console.error('Create snapshot error:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Failed to create snapshot'
|
|
});
|
|
}
|
|
};
|
|
|
|
// Get instance events
|
|
const getInstanceEvents = async (req, res) => {
|
|
try {
|
|
const { instanceId } = req.params;
|
|
const { page = 1, limit = 20 } = req.query;
|
|
const resellerId = req.user.resellerId;
|
|
const offset = (page - 1) * limit;
|
|
|
|
// Verify instance belongs to reseller
|
|
const instance = await Instance.findOne({
|
|
where: { id: instanceId, resellerId }
|
|
});
|
|
|
|
if (!instance) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: 'Instance not found'
|
|
});
|
|
}
|
|
|
|
const { count, rows: events } = await InstanceEvent.findAndCountAll({
|
|
where: { instanceId },
|
|
include: [
|
|
{
|
|
model: require('../models').User,
|
|
as: 'user',
|
|
attributes: ['id', 'firstName', 'lastName']
|
|
}
|
|
],
|
|
limit: parseInt(limit),
|
|
offset: parseInt(offset),
|
|
order: [['createdAt', 'DESC']]
|
|
});
|
|
|
|
res.json({
|
|
success: true,
|
|
data: {
|
|
events,
|
|
pagination: {
|
|
total: count,
|
|
page: parseInt(page),
|
|
pages: Math.ceil(count / limit),
|
|
limit: parseInt(limit)
|
|
}
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('Get instance events error:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Failed to fetch instance events'
|
|
});
|
|
}
|
|
};
|
|
|
|
module.exports = {
|
|
getInstances,
|
|
createInstance,
|
|
startInstance,
|
|
stopInstance,
|
|
createSnapshot,
|
|
getInstanceEvents
|
|
};
|