diff --git a/README.md b/README.md
index 1f4b885eb..b9ff96aad 100644
--- a/README.md
+++ b/README.md
@@ -530,7 +530,7 @@ $ iofog-controller catalog <*command*> <*options*>
"config": "string",
"catalogItemId": 0,
"flowId": 0,
- "ioFogNodeId": "string",
+ "iofogUuid": "string",
"rootHostAccess": true,
"logLimit": 0,
"volumeMappings": [
@@ -558,7 +558,7 @@ $ iofog-controller catalog <*command*> <*options*>
"name": "string",
"config": "string",
"rebuild": true,
- "ioFogNodeId": "string",
+ "iofogUuid": "string",
"rootHostAccess": true,
"logLimit": 0,
"volumeMappings": [
diff --git a/specs/swagger.yml b/specs/swagger.yml
index 6e75fb688..47dd9b939 100644
--- a/specs/swagger.yml
+++ b/specs/swagger.yml
@@ -2907,7 +2907,7 @@ definitions:
type: integer
flowId:
type: integer
- ioFogNodeId:
+ iofogUuid:
type: string
rootHostAccess:
type: boolean
@@ -2934,7 +2934,7 @@ definitions:
type: string
rebuild:
type: boolean
- ioFogNodeId:
+ iofogUuid:
type: string
rootHostAccess:
type: boolean
diff --git a/src/cli/microservice.js b/src/cli/microservice.js
index edabe1d2a..d33e3cce3 100644
--- a/src/cli/microservice.js
+++ b/src/cli/microservice.js
@@ -26,7 +26,7 @@ const JSON_SCHEMA_ADD = AppHelper.stringifyCliJsonSchema(
config: "string",
catalogItemId: 0,
flowId: 0,
- ioFogNodeId: "string",
+ iofogUuid: "string",
rootHostAccess: true,
logLimit: 0,
volumeMappings: [
@@ -54,7 +54,7 @@ const JSON_SCHEMA_UPDATE = AppHelper.stringifyCliJsonSchema(
name: "string",
config: "string",
rebuild: true,
- ioFogNodeId: "string",
+ iofogUuid: "string",
rootHostAccess: true,
logLimit: 0,
volumeMappings: [
@@ -370,7 +370,7 @@ const _updateMicroserviceObject = function (obj) {
const microserviceObj = {
name: obj.name,
config: obj.config,
- ioFogNodeId: obj.iofogId,
+ iofogUuid: obj.iofogId,
rootHostAccess: AppHelper.validateBooleanCliOptions(obj.rootEnable, obj.rootDisable),
logLimit: obj.logLimit,
rebuild: obj.rebuild
@@ -389,7 +389,7 @@ const _createMicroserviceObject = function (obj) {
config: obj.config,
catalogItemId: parseInt(obj.catalogId),
flowId: parseInt(obj.flowId),
- ioFogNodeId: obj.iofogId,
+ iofogUuid: obj.iofogId,
rootHostAccess: AppHelper.validateBooleanCliOptions(obj.rootEnable, obj.rootDisable),
logLimit: obj.logLimit,
routes: obj.routes
diff --git a/src/enums/microservice-state.js b/src/enums/microservice-state.js
new file mode 100644
index 000000000..4661b0171
--- /dev/null
+++ b/src/enums/microservice-state.js
@@ -0,0 +1,9 @@
+const microserviceState = {
+ NOT_RUNNING: 'NOT_RUNNING',
+ RUNNING: 'RUNNING',
+ RESTARTING: 'RESTARTING',
+ STUCK_IN_RESTART: 'STUCK_IN_RESTART',
+}
+
+module.exports = microserviceState;
+
diff --git a/src/schemas/microservice.js b/src/schemas/microservice.js
index 05de1f720..29a1e6239 100644
--- a/src/schemas/microservice.js
+++ b/src/schemas/microservice.js
@@ -9,7 +9,7 @@ const microserviceCreate = {
"config": {"type": "string"},
"catalogItemId": {"type": "integer"},
"flowId": {"type": "integer"},
- "ioFogNodeId": {"type": "string"},
+ "iofogUuid": {"type": "string"},
"rootHostAccess": {"type": "boolean"},
"logSize": {"type": "integer"},
"imageSnapshot": {"type": "string"},
@@ -36,7 +36,7 @@ const microserviceUpdate = {
},
"config": {"type": "string"},
"rebuild": {"type": "boolean"},
- "ioFogNodeId": {"type": "string"},
+ "iofogUuid": {"type": "string"},
"rootHostAccess": {"type": "boolean"},
"logSize": {"type": "integer", "minimum" : 0},
"volumeMappings": {
diff --git a/src/sequelize/managers/microservice-manager.js b/src/sequelize/managers/microservice-manager.js
index 4b07377af..186e8640b 100644
--- a/src/sequelize/managers/microservice-manager.js
+++ b/src/sequelize/managers/microservice-manager.js
@@ -24,6 +24,7 @@ const Flow = models.Flow;
const User = models.User;
const Routing = models.Routing;
const Registry = models.Registry;
+const MicroserviceStatus = models.MicroserviceStatus;
class MicroserviceManager extends BaseManager {
getEntity() {
@@ -194,6 +195,31 @@ class MicroserviceManager extends BaseManager {
}, {transaction: transaction})
}
+ findOneWithStatus(where, transaction) {
+ return Microservice.findOne({
+ include: [
+ {
+ model: MicroserviceStatus,
+ as: 'microserviceStatus',
+ required: true
+ }
+ ],
+ where: where
+ }, {transaction: transaction})
+ }
+
+ findAllWithStatuses(transaction) {
+ return Microservice.findAll({
+ include: [
+ {
+ model: MicroserviceStatus,
+ as: 'microserviceStatus',
+ required: true
+ }
+ ]
+ }, {transaction: transaction})
+ }
+
findMicroserviceOnGet(where, transaction) {
return Microservice.findOne({
include: [
diff --git a/src/sequelize/managers/microservice-status-manager.js b/src/sequelize/managers/microservice-status-manager.js
new file mode 100644
index 000000000..77ad85df4
--- /dev/null
+++ b/src/sequelize/managers/microservice-status-manager.js
@@ -0,0 +1,25 @@
+/*
+ * *******************************************************************************
+ * * Copyright (c) 2018 Edgeworx, Inc.
+ * *
+ * * This program and the accompanying materials are made available under the
+ * * terms of the Eclipse Public License v. 2.0 which is available at
+ * * http://www.eclipse.org/legal/epl-2.0
+ * *
+ * * SPDX-License-Identifier: EPL-2.0
+ * *******************************************************************************
+ *
+ */
+
+const BaseManager = require('../managers/base-manager')
+const models = require('./../models');
+const MicroserviceStatus = models.MicroserviceStatus;
+
+class MicroserviceStatusManager extends BaseManager {
+ getEntity() {
+ return MicroserviceStatus;
+ }
+}
+
+const instance = new MicroserviceStatusManager();
+module.exports = instance;
\ No newline at end of file
diff --git a/src/sequelize/migrations/20181001062956-create-microservice.js b/src/sequelize/migrations/20181001062956-create-microservice.js
index a81ba6043..0d6117b37 100644
--- a/src/sequelize/migrations/20181001062956-create-microservice.js
+++ b/src/sequelize/migrations/20181001062956-create-microservice.js
@@ -44,7 +44,7 @@ module.exports = {
type: Sequelize.TEXT,
field: 'image_snapshot'
},
- deleteWithCleanUp: {
+ deleteWithCleanup: {
type: Sequelize.BOOLEAN,
field: 'delete_with_cleanup'
},
diff --git a/src/sequelize/migrations/20181031094923-drop_need_update_col_microservices.js.js b/src/sequelize/migrations/20181031094923-drop-need-update-col-microservices.js
similarity index 100%
rename from src/sequelize/migrations/20181031094923-drop_need_update_col_microservices.js.js
rename to src/sequelize/migrations/20181031094923-drop-need-update-col-microservices.js
diff --git a/src/sequelize/migrations/20181102105758-microservice-status-add-missing-time-cols.js b/src/sequelize/migrations/20181102105758-microservice-status-add-missing-time-cols.js
new file mode 100644
index 000000000..0844e5fe6
--- /dev/null
+++ b/src/sequelize/migrations/20181102105758-microservice-status-add-missing-time-cols.js
@@ -0,0 +1,18 @@
+'use strict';
+
+module.exports = {
+ up: (queryInterface, Sequelize) => {
+ return queryInterface.addColumn('MicroserviceStatuses',
+ 'operating_duration',
+ Sequelize.BIGINT
+ )
+ .then(() => queryInterface.addColumn('MicroserviceStatuses',
+ 'start_time',
+ Sequelize.BIGINT));
+ },
+
+ down: (queryInterface, Sequelize) => {
+ return queryInterface.removeColumn('MicroserviceStatuses', 'operating_duration')
+ .then(() => queryInterface.removeColumn('MicroserviceStatuses', 'start_time'));
+ }
+};
diff --git a/src/sequelize/migrations/20181102163657-microservice-add-col-remove.js b/src/sequelize/migrations/20181102163657-microservice-add-col-remove.js
new file mode 100644
index 000000000..6138b1178
--- /dev/null
+++ b/src/sequelize/migrations/20181102163657-microservice-add-col-remove.js
@@ -0,0 +1,14 @@
+'use strict';
+
+module.exports = {
+ up: (queryInterface, Sequelize) => {
+ return queryInterface.addColumn('Microservices',
+ 'delete',
+ Sequelize.BOOLEAN
+ )
+ },
+
+ down: (queryInterface, Sequelize) => {
+ return queryInterface.removeColumn('Microservices', 'delete')
+ }
+};
diff --git a/src/sequelize/models/microservice.js b/src/sequelize/models/microservice.js
index df5d29245..5e64cb234 100644
--- a/src/sequelize/models/microservice.js
+++ b/src/sequelize/models/microservice.js
@@ -46,7 +46,12 @@ module.exports = (sequelize, DataTypes) => {
field: 'image_snapshot',
defaultValue: ""
},
- deleteWithCleanUp: {
+ delete: {
+ type: DataTypes.BOOLEAN,
+ field: 'delete',
+ defaultValue: false
+ },
+ deleteWithCleanup: {
type: DataTypes.BOOLEAN,
field: 'delete_with_cleanup',
defaultValue: false
@@ -112,7 +117,12 @@ module.exports = (sequelize, DataTypes) => {
Microservice.hasMany(models.Routing, {
foreignKey: 'source_microservice_uuid',
as: 'routes'
- })
+ });
+
+ Microservice.hasOne(models.MicroserviceStatus, {
+ foreignKey: 'microservice_uuid',
+ as: 'microserviceStatus'
+ });
};
return Microservice;
};
\ No newline at end of file
diff --git a/src/sequelize/models/microservicestatus.js b/src/sequelize/models/microservicestatus.js
index 5db6d080a..c886603a3 100644
--- a/src/sequelize/models/microservicestatus.js
+++ b/src/sequelize/models/microservicestatus.js
@@ -10,8 +10,19 @@ module.exports = (sequelize, DataTypes) => {
},
status: {
type: DataTypes.TEXT,
+ defaultValue: 'NOT_RUNNING',
field: 'status'
},
+ operatingDuration: {
+ type: DataTypes.BIGINT,
+ defaultValue: 0,
+ field: 'operating_duration'
+ },
+ startTime: {
+ type: DataTypes.BIGINT,
+ defaultValue: 0,
+ field: 'start_time'
+ },
cpuUsage: {
type: DataTypes.FLOAT,
defaultValue: 0.000,
@@ -24,6 +35,7 @@ module.exports = (sequelize, DataTypes) => {
},
containerId: {
type: DataTypes.TEXT,
+ defaultValue: '',
field: 'container_id'
}
}, {
@@ -32,7 +44,6 @@ module.exports = (sequelize, DataTypes) => {
underscored: true
});
MicroserviceStatus.associate = function (models) {
-
MicroserviceStatus.belongsTo(models.Microservice, {
foreignKey: {
name: 'microserviceUuid',
diff --git a/src/services/agent-service.js b/src/services/agent-service.js
index 48ff590b7..ccc679ba3 100644
--- a/src/services/agent-service.js
+++ b/src/services/agent-service.js
@@ -21,6 +21,7 @@ const ChangeTrackingManager = require('../sequelize/managers/change-tracking-man
const FogVersionCommandManager = require('../sequelize/managers/iofog-version-command-manager');
const StraceManager = require('../sequelize/managers/strace-manager');
const RegistryManager = require('../sequelize/managers/registry-manager');
+const MicroserviceStatusManager = require('../sequelize/managers/microservice-status-manager')
const Validator = require('../schemas');
const Errors = require('../helpers/errors');
const AppHelper = require('../helpers/app-helper');
@@ -174,7 +175,7 @@ const getAgentConfigChanges = async function (fog, transaction) {
const updateAgentStatus = async function (agentStatus, fog, transaction) {
await Validator.validate(agentStatus, Validator.schemas.updateAgentStatus);
- let update = {
+ let fogStatus = {
daemonStatus: agentStatus.daemonStatus,
daemonOperatingDuration: agentStatus.daemonOperatingDuration,
daemonLastStart: agentStatus.daemonLastStart,
@@ -184,7 +185,6 @@ const updateAgentStatus = async function (agentStatus, fog, transaction) {
memoryViolation: agentStatus.memoryViolation,
diskViolation: agentStatus.diskViolation,
cpuViolation: agentStatus.cpuViolation,
- microserviceStatus: agentStatus.microserviceStatus,
repositoryCount: agentStatus.repositoryCount,
repositoryStatus: agentStatus.repositoryStatus,
systemTime: agentStatus.systemTime,
@@ -199,11 +199,34 @@ const updateAgentStatus = async function (agentStatus, fog, transaction) {
isReadyToUpgrade: agentStatus.isReadyToUpgrade,
isReadyToRollback: agentStatus.isReadyToRollback
};
- update = AppHelper.deleteUndefinedFields(update);
+
+ fogStatus = AppHelper.deleteUndefinedFields(fogStatus);
await FogManager.update({
uuid: fog.uuid
- }, update, transaction);
+ }, fogStatus, transaction);
+
+ await _updateMicroserviceStatuses(JSON.parse(agentStatus.microserviceStatus), transaction);
+ await MicroserviceService.deleteNotRunningMicroservices(transaction);
+};
+
+
+const _updateMicroserviceStatuses = async function (microserviceStatus, transaction) {
+ for (status of microserviceStatus) {
+ let microserviceStatus = {
+ containerId: status.containerId,
+ status: status.status,
+ startTime: status.startTime,
+ operatingDuration: status.operatingDuration,
+ cpuUsage: status.cpuUsage,
+ memoryUsage: status.memoryUsage
+ };
+ microserviceStatus = AppHelper.deleteUndefinedFields(microserviceStatus);
+
+ await MicroserviceStatusManager.update({
+ microserviceUuid: status.id
+ }, microserviceStatus, transaction);
+ }
};
const getAgentMicroservices = async function (fog, transaction) {
@@ -230,7 +253,8 @@ const getAgentMicroservices = async function (fog, transaction) {
portMappings: microservice.ports,
volumeMappings: microservice.volumeMappings,
imageSnapshot: microservice.imageSnapshot,
- deleteWithCleanUp: microservice.deleteWithCleanUp,
+ delete: microservice.delete,
+ deleteWithCleanup: microservice.deleteWithCleanup,
routes: routes
};
diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js
index ab94b91ee..17cabb45c 100644
--- a/src/services/microservices-service.js
+++ b/src/services/microservices-service.js
@@ -13,7 +13,9 @@
const TransactionDecorator = require('../decorators/transaction-decorator');
const MicroserviceManager = require('../sequelize/managers/microservice-manager');
+const MicroserviceStatusManager = require('../sequelize/managers/microservice-status-manager');
const MicroservicePortManager = require('../sequelize/managers/microservice-port-manager');
+const MicroserviceStates = require('../enums/microservice-state');
const VolumeMappingManager = require('../sequelize/managers/volume-mapping-manager');
const ConnectorManager = require('../sequelize/managers/connector-manager');
const ConnectorPortManager = require('../sequelize/managers/connector-port-manager');
@@ -34,7 +36,7 @@ const _listMicroservices = async function (flowId, user, isCLI, transaction) {
if (!isCLI) {
await FlowService.getFlow(flowId, user, isCLI, transaction);
}
- const where = isCLI ? {} : {flowId: flowId};
+ const where = isCLI ? {delete: false} : {flowId: flowId, delete: false};
const microservices = await MicroserviceManager.findAllExcludeFields(where, transaction);
return {
@@ -48,7 +50,7 @@ const _getMicroservice = async function (microserviceUuid, user, isCLI, transact
}
const microservice = await MicroserviceManager.findOneExcludeFields({
- uuid: microserviceUuid
+ uuid: microserviceUuid, delete: false
}, transaction);
if (!microservice) {
@@ -75,10 +77,12 @@ const _createMicroserviceOnFog = async function (microserviceData, user, isCLI,
await _createRoutes(microserviceData.routes, microservice.uuid, user, transaction);
}
- if (microserviceData.ioFogNodeId) {
- await _updateChangeTracking(false, microservice.uuid, microserviceData.ioFogNodeId, user, isCLI, transaction);
+ if (microserviceData.iofogUuid) {
+ await _updateChangeTracking(microserviceData.iofogUuid, transaction);
}
+ await _createMicroserviceStatus(microservice.uuid, transaction);
+
return {
uuid: microservice.uuid
}
@@ -92,7 +96,7 @@ const _createMicroservice = async function (microserviceData, user, isCLI, trans
config: microserviceData.config,
catalogItemId: microserviceData.catalogItemId,
flowId: microserviceData.flowId,
- iofogUuid: microserviceData.ioFogNodeId,
+ iofogUuid: microserviceData.iofogUuid,
rootHostAccess: microserviceData.rootHostAccess,
logSize: microserviceData.logLimit,
updatedBy: user.id
@@ -114,17 +118,10 @@ const _createMicroservice = async function (microserviceData, user, isCLI, trans
return await MicroserviceManager.create(newMicroservice, transaction);
};
-const _createMicroservicePorts = async function (ports, microserviceUuid, transaction) {
- const microservicePortToCreate = {
- portInternal: ports.internal,
- portExternal: ports.external,
- publicMode: ports.publicMode,
- microserviceUuid: microserviceUuid
- };
-
- const microservicePortDataCreate = AppHelper.deleteUndefinedFields(microservicePortToCreate);
-
- await MicroservicePortManager.create(microservicePortDataCreate, transaction);
+const _createMicroserviceStatus = function (uuid, transaction) {
+ return MicroserviceStatusManager.create({
+ microserviceUuid: uuid
+ }, transaction);
};
const _createVolumeMappings = async function (volumeMappings, microserviceUuid, transaction) {
@@ -149,7 +146,7 @@ const _updateMicroservice = async function (microserviceUuid, microserviceData,
name: microserviceData.name,
config: microserviceData.config,
rebuild: microserviceData.rebuild,
- iofogUuid: microserviceData.ioFogNodeId,
+ iofogUuid: microserviceData.iofogUuid,
rootHostAccess: microserviceData.rootHostAccess,
logSize: microserviceData.logLimit,
volumeMappings: microserviceData.volumeMappings,
@@ -180,13 +177,13 @@ const _updateMicroservice = async function (microserviceUuid, microserviceData,
await _updateVolumeMappings(microserviceDataUpdate.volumeMappings, microserviceUuid, transaction);
}
- if (microserviceDataUpdate.ioFogNodeId) {
+ if (microserviceDataUpdate.iofogUuid) {
await _deleteRoutes(microserviceData.routes, microserviceUuid, transaction);
await _createRoutes(microserviceData.routes, microserviceUuid, user, transaction);
- await _updateChangeTracking(false, microserviceUuid, microserviceDataUpdate.ioFogNodeId, user, isCLI, transaction)
+ await _updateChangeTracking(microserviceDataUpdate.iofogUuid, transaction)
}
- await _updateChangeTracking(microserviceData.config ? true : false, microserviceUuid, microservice.ioFogNodeId, user, isCLI, transaction);
+ await _updateChangeTracking(microservice.iofogUuid, transaction);
};
const _updateVolumeMappings = async function (volumeMappings, microserviceUuid, transaction) {
@@ -197,42 +194,65 @@ const _updateVolumeMappings = async function (volumeMappings, microserviceUuid,
}
};
-const _updateChangeTracking = async function (configUpdated, microserviceUuid, fogNodeUuid, user, isCLI, transaction) {
+const _updateChangeTracking = async function (iofogUuid, transaction) {
const trackingData = {
containerList: true,
- containerConfig: configUpdated,
- iofogUuid: fogNodeUuid
+ containerConfig: true,
+ routing: true
};
- await ChangeTrackingManager.update({iofogUuid: fogNodeUuid}, trackingData, transaction);
+ await ChangeTrackingManager.update({iofogUuid: iofogUuid}, trackingData, transaction);
};
const _deleteMicroservice = async function (microserviceUuid, deleteWithCleanUp, user, isCLI, transaction) {
- if (deleteWithCleanUp) {
- return await MicroserviceManager.update({
+
+ const where = isCLI
+ ?
+ {
+ uuid: microserviceUuid,
+ updatedBy: user.id
+ }
+ :
+ {
+ uuid: microserviceUuid
+ };
+
+
+ const microservice = await MicroserviceManager.findOneWithStatus(where, transaction);
+
+ if (microservice.microserviceStatus.status === MicroserviceStates.NOT_RUNNING) {
+ const affectedRows = await MicroserviceManager.delete({
+ uuid: microserviceUuid
+ }, transaction);
+ if (affectedRows === 0) {
+ throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid));
+ }
+ } else {
+ await MicroserviceManager.update({
uuid: microserviceUuid
},
{
- deleteWithCleanUp: deleteWithCleanUp
+ delete: true,
+ deleteWithCleanUp: !!deleteWithCleanUp
}, transaction);
}
- const microservice = await MicroserviceManager.findOne({
- uuid: microserviceUuid,
- updatedBy: user.id
- }, transaction);
-
- const affectedRows = await MicroserviceManager.delete({
- uuid: microserviceUuid
- }, transaction);
- if (affectedRows === 0) {
- throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid));
- }
-
- await _updateChangeTracking(false, microserviceUuid, microservice.ioFogNodeId, user, isCLI, transaction)
+ await _updateChangeTracking(microservice.iofogUuid, transaction)
};
+const _deleteNotRunningMicroservices = async function (transaction) {
+ const microservices = await MicroserviceManager.findAllWithStatuses(transaction);
+ microservices
+ .filter(microservice => !!microservice.delete)
+ .filter(microservice => microservice.microserviceStatus.status === MicroserviceStates.NOT_RUNNING)
+ .forEach(microservice => {
+ MicroserviceManager.delete({
+ uuid: microservice.uuid
+ }, transaction);
+ });
+}
+
const _checkForDuplicateName = async function (name, item, userId, transaction) {
if (name) {
const where = item.id
@@ -811,5 +831,6 @@ module.exports = {
getMicroservicePortMappingListWithTransaction: TransactionDecorator.generateTransaction(_getPortMappingList),
deletePortMappingWithTransaction: TransactionDecorator.generateTransaction(_deletePortMapping),
getPhysicalConections: getPhysicalConections,
- getListMicroservices: _listMicroservices
+ listMicroservices: _listMicroservices,
+ deleteNotRunningMicroservices: _deleteNotRunningMicroservices
};