Skip to content

Instantly share code, notes, and snippets.

@pavlo-yuriychuk
Last active July 18, 2016 17:57
Show Gist options
  • Save pavlo-yuriychuk/f531b542c78001ff5ca3 to your computer and use it in GitHub Desktop.
Save pavlo-yuriychuk/f531b542c78001ff5ca3 to your computer and use it in GitHub Desktop.
OpenStack JS client
'use strict';
angular.module('App')
.service('NetworkService', ['$q', '$http', 'CommonDataService', 'EntitiesCollection', 'servicesNames', function NetworkService($q, $http, CommonDataService, EntitiesCollection, servicesNames) {
var baseUrl = "";
var service = null;
this.setBaseUrl = function (value) {
baseUrl = CommonDataService.adjustUri(value, Environment.PROTOCOL, Environment.PORT);
};
this.getBaseUrl = function () {
return baseUrl;
};
this.init = function (tenantId) {
service = CommonDataService.getServiceByName(servicesNames.NETWORKING, tenantId);
this.setBaseUrl(service.endpoints[0].publicURL + "v2.0");
$http.defaults.headers.common['X-Auth-Token'] = CommonDataService.getAuthorizationToken(tenantId);
};
this.parseErrors = function (status, data) {
var errors, message;
if (data.NeutronError && _.isString(data.NeutronError)) {
message = data.NeutronError;
} else if (data.NeutronError && data.NeutronError.message) {
message = data.NeutronError.message;
} else if (data.proxyFault && data.proxyFault.message) {
message = data.proxyFault.message;
} else {
message = JSON.stringify(data);
}
switch (status) {
case 401:
errors = ["ALERTS.NOT_ENOUGH_PERMISSIONS"];
break;
case 404:
errors = ["ALERTS.RESOURCE_NOT_FOUND"];
break;
case 409:
case 400:
case 403:
default:
errors = [message];
};
return errors;
}
this.list = function (entityType, detail, optType) {
if (!angular.isString(entityType)) {
throw new Error("Entity type should be a string");
}
var entityTypeEndpoint;
var url = baseUrl;
if (/^(pools|members|health_monitors|vips)$/.test(entityType)) {
entityTypeEndpoint = "lb/" + entityType;
} else if (/^(networks|subnets|floatingips|networks|routers|ports)$/.test(entityType)) {
entityTypeEndpoint = entityType;
} else {
throw new Error("Unknown entity type " + entityType);
}
var deferred = $q.defer();
detail = (detail === true) ? "/detail" : "";
if ((_.indexOf(["subnets", "ports"], entityType) > -1) && optType) {
detail += "?network_id=" +optType;
}
$http.get(url + "/" + entityTypeEndpoint + detail).success(function (result) {
var collection = EntitiesCollection.getInstance(entityType);
collection.addAll(result[entityType]);
deferred.resolve(collection);
});
return deferred.promise;
};
this.create = function (entityType, data) {
if (!/(pool|member|vip|health_monitor|network|subnet|port|router)/.test(entityType)) {
throw new Error("Unknown entityType");
}
var dataObj = {};
var entityUrl = entityType + "s";
var adjustedBaseUrl = baseUrl;
var deferred = $q.defer();
dataObj[entityType] = data;
if (/(pool|member|vip|health_monitor)/.test(entityType)) {
adjustedBaseUrl = baseUrl + "/lb";
dataObj[entityType].admin_state_up = true;
};
$http.post(adjustedBaseUrl + "/" + entityUrl, dataObj).then(
function (result) {
deferred.resolve(result);
},
function (result){
deferred.reject(this.parseErrors(result.status, result.data));
}.bind(this)
);
return deferred.promise;
};
this.delete = function (entityType, id) {
if (!/(pool|member|vip|health_monitor|network|subnet|port|router)/.test(entityType)) {
throw new Error("Unknown entityType");
};
if (!id) {
throw new Error("Trying to delete " + entityType + " with unknown id");
}
var deferred = $q.defer();
var entityTypeEndpoint = "/" + entityType + "s";
if (/(pool|member|vip|health_monitor)/.test(entityType)) {
entityTypeEndpoint = "/lb/" + entityType + "s";
};
$http.delete(baseUrl + entityTypeEndpoint + "/" + id).then(
function (result) {
deferred.resolve(result);
},
function (result){
deferred.reject(this.parseErrors(result.status, result.data));
}.bind(this)
);
return deferred.promise;
};
this.get = function (entityName, entityId) {
var entityNameUrl = entityName;
if (/(member|pool|health_monitor|vip)/.test(entityName)) {
entityNameUrl = "lb/" + entityName;
};
if (!entityId) {
throw new Error("Trying to delete " + entityName + " with unknown id");
}
return $http.get(baseUrl + "/" + entityNameUrl + "s/" + entityId).then(function (response) {
return response.data[entityName];
});
};
this.update = function (entityName, entityId, data) {
var dataObj = {};
var entityNameUrl = entityName;
var deferred = $q.defer();
if (/(member|pool|health_monitor|vip)/.test(entityName)) {
entityNameUrl = "lb/" + entityName;
};
dataObj[entityName] = data;
$http.put(baseUrl + "/" + entityNameUrl + "s/" + entityId, dataObj).then(
function (result) {
deferred.resolve(result);
},
function (result){
deferred.reject(this.parseErrors(result.status, result.data));
}.bind(this)
);
return deferred.promise;
};
this.associateHealhMonitorWithPool = function (id, poolId) {
var dataObj = {
"health_monitor": {
"id": id
}
};
var deferred = $q.defer();
$http.post(baseUrl + "/lb/pools/" + poolId + "/health_monitors", dataObj).then(
function (result) {
deferred.resolve(result);
},
function (result){
deferred.reject(this.parseErrors(result.status, result.data));
}.bind(this)
);
return deferred.promise;
}
this.disassociateHealhMonitorWithPool = function (id, poolId) {
var deferred = $q.defer();
$http.delete(baseUrl + "/lb/pools/" + poolId + "/health_monitors/" + id).then(
function (result) {
deferred.resolve(result);
},
function (result){
deferred.reject(this.parseErrors(result.status, result.data));
}.bind(this)
);
return deferred.promise;
}
this.attachSubnetToRouter = function (routerId, subnet, gatewayIp) {
var deferred = $q.defer();
var routerDeferred = $q.defer();
var defer;
if (gatewayIp){
var data = {
port: {
network_id: subnet.network_id,
fixed_ips: [
{
subnet_id: subnet.id,
ip_address: gatewayIp
}
]
}
};
defer = $http.post(baseUrl + "/ports" , data).then(
function (result) {
return result.data.port.id;
}
);
} else {
deferred.resolve();
defer = deferred.promise;
}
defer.then(
function (result) {
var addInterfaceData;
if (result){
addInterfaceData = { port_id: result };
} else {
addInterfaceData = { subnet_id: subnet.id};
}
$http.put(baseUrl + "/routers/" + routerId + "/add_router_interface", addInterfaceData).then(
function (result) {
routerDeferred.resolve(result);
},
function (result){
routerDeferred.reject(this.parseErrors(result.status, result.data));
// deferred.reject(result);
}.bind(this)
);
}.bind(this),
function (result) {
routerDeferred.reject(this.parseErrors(result.status, result.data));
}.bind(this)
);
return routerDeferred.promise;
};
this.detachSubnetFromRouter = function (routerId, subnetId) {
var deferred = $q.defer();
if (angular.isArray(subnetId)) {
return $q.all(_.map(subnetId, function (item) {
return $http.put(baseUrl + "/routers/" + routerId + "/remove_router_interface", {
"subnet_id": item
});
})).then(function (result) {
deferred.resolve(result);
}, function (result){
deferred.reject(this.parseErrors(result.status, result.data));
}.bind(this)
);
} else {
return $http.put(baseUrl + "/routers/" + routerId + "/remove_router_interface", {
"subnet_id": subnetId
}).then(function (result) {
deferred.resolve(result);
}, function (result){
deferred.reject(this.parseErrors(result.status, result.data));
}.bind(this)
);
};
return deferred.promise;
};
this.listAttachedPorts = function (routerId) {
return $http.get(baseUrl + "/ports?device_id=" + routerId).then(
function (result) {
return result.data.ports;
}
);
}
this.listAttachedSubnets = function (routerId) {
return $http.get(baseUrl + "/ports?device_id=" + routerId).then(
function (result) {
return _.map(result.data.ports, function (item) {
return item.fixed_ips[0].subnet_id;
});
}
);
};
this.listAttachedRouters = function (subnetId) {
return this.list("ports").then(function (result) {
return _.pluck(result.where(function (item) {
return item.fixed_ips[0].subnet_id === subnetId;
}), "device_id");
});
};
this.killRouter = function (routerId) {
return this.listAttachedSubnets(routerId).then(function (result) {
return this.detachSubnetFromRouter(routerId, result);
}.bind(this)).then(function (result) {
return this.delete("router", routerId);
}.bind(this));
};
this.killSubnet = function (subnetId) {
return this.listAttachedRouters(subnetId).then(function (result) {
return $q.all(_.map(result, function (item) {
return this.detachSubnetFromRouter(item, subnetId);
}, this));
}.bind(this)).finally(function (result) {
return this.delete("subnet", subnetId);
}.bind(this));
};
this.detachFloatingIp = function (id) {
var actionObj = {
"floatingip": {
"port_id": null
}
};
return $http.put(baseUrl + "/floatingips/" + id, actionObj);
};
this.getLoadBalancer = function (id) {
var deferred = $q.defer();
this.get("pool", id).then(function (result) {
return result;
}).then(function (result) {
return $q.all([this.list("health_monitors"), this.list("members"), this.get("vip", result.vip_id)]).then(function (results) {
result.health_monitors = results[0].where(function (item) {
return result.health_monitors.indexOf(item.id) > -1;
});
result.members = results[1].where(function (item) {
return result.members.indexOf(item.id) > -1;
});
result.vip = results[2];
deferred.resolve(result);
});
}.bind(this));
return deferred.promise;
};
this.syncMembers = function (pool, items) {
var poolId = pool.id;
if (!items || items.length === 0) {
var defer = $q.defer();
defer.resolve();
return defer.promise;
};
var requests = _.chain(items).
filter(function (item) {
return (item.action === "create") || (item.action === "delete");
}).
map(function (item) {
if (item.action === "create") {
// TODO: Use members factory
item = _.pick(item, "address", "protocol_port", "weight");
item.pool_id = poolId;
return this.create("member", item);
} else if (item.action === "delete") {
return this.delete("member", item.id);
};
}, this).value();
if (requests.length == 0) {
var defer = $q.defer();
defer.resolve();
return defer.promise;
};
return $q.all(requests).then(function () {
items = _.filter(items, function (item) {
return item.action !== "create" && item.action !== "delete";
});
return this.getLoadBalancer(pool.id);
}.bind(this));
};
this.syncHealthMonitors = function (pool, items) {
if (!items || items.length === 0) {
var defer = $q.defer();
defer.resolve();
return defer.promise;
};
var requests = _.chain(items).filter(function (item) {
return item.action === "create" || item.action === "delete";
}).map(function (item) {
// TODO: use Helth monitors factory
if (item.action === "create") {
item = _.pick(item, "delay", "max_retries", "timeout", "type");
return this.create("health_monitor", item).then(function (result) {
return this.associateHealhMonitorWithPool(result.data.health_monitor.id, pool.id);
}.bind(this));
} else if (item.action === "delete") {
return this.disassociateHealhMonitorWithPool(item.id, pool.id);
};
}, this).value();
if (requests.length == 0) {
var defer = $q.defer();
defer.resolve();
return defer.promise;
};
return $q.all(requests).then(function () {
items = _.filter(items, function (item) {
return item.action !== "create" && item.action !== "delete";
});
return this.getLoadBalancer(pool.id);
}.bind(this));
};
this.killLoadBalancer = function (pool) {
var defer;
var deferred;
var killMembers = function () {
var actions = _.map(pool.members, function (item) {
return this.delete("member", item);
}, this);
var defer = $q.defer();
if (actions.length > 0) {
$q.all(actions).finally(function () {
defer.resolve();
});
} else {
defer.resolve();
};
return defer.promise;
}.bind(this);
var killHealthMonitors = function () {
var actions = _.map(pool.health_monitors, function (item) {
return this.disassociateHealhMonitorWithPool(item, pool.id);
}, this);
var defer = $q.defer();
if (actions.length > 0) {
$q.all(actions).finally(function () {
defer.resolve();
});
} else {
defer.resolve();
};
return defer.promise;
}.bind(this);
var killPool = function () {
var defer = $q.defer();
this.delete("pool", pool.id).finally(function () {
defer.resolve();
});
return defer.promise;
}.bind(this);
defer = $q.defer();
deferred = defer.promise;
if (!pool.id) {
defer.reject();
} else {
if (pool.vip_id !== null) {
this.delete("vip", pool.vip_id).finally(function () {
defer.resolve();
});
} else {
defer.resolve();
};
};
return deferred.then(killMembers).then(killHealthMonitors).then(killPool);
};
this.listLoadBalancers = function (tenantId, networkId) {
return $q.all([this.list("networks").then(function (response) {
return response.where(function (item) {
return item.tenant_id == tenantId;
});
}),
this.list("subnets").then(function (result) {
return result.all();
}),
this.list("pools").then(function (response) {
return response.all();
})]).then(
function (result) {
var networks = result[0];
var subnets = result[1];
var pools = result[2];
var poolsFiltered = [];
var networksIds = _.chain(networks).pluck("id").value();
var networkSubnets = _.chain(subnets).filter(function (item) {
return item.network_id === networkId;
}).pluck("id").value();
_.each(pools, function (item) {
if (networkSubnets.indexOf(item.subnet_id) > -1) {
poolsFiltered.push(item);
};
});
return poolsFiltered;
}
);
};
}]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment