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 };