diff options
Diffstat (limited to 'ncomp-openstack-controller/src/main/java')
4 files changed, 1556 insertions, 0 deletions
diff --git a/ncomp-openstack-controller/src/main/java/org/openecomp/ncomp/openstack/controller/tools/Generator.java b/ncomp-openstack-controller/src/main/java/org/openecomp/ncomp/openstack/controller/tools/Generator.java new file mode 100644 index 0000000..397b827 --- /dev/null +++ b/ncomp-openstack-controller/src/main/java/org/openecomp/ncomp/openstack/controller/tools/Generator.java @@ -0,0 +1,76 @@ + +/*- + * ============LICENSE_START========================================== + * OPENECOMP - DCAE + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property. All rights reserved. + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + */ + +package org.openecomp.ncomp.openstack.controller.tools;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+
+import org.openecomp.utils.YamlToJava;
+import org.openecomp.ncomp.openstack.OpenstackFactory;
+import org.openecomp.ncomp.openstack.location.LocationFactory;
+import org.openecomp.ncomp.sirius.manager.controllermodel.ControllerModel;
+import org.openecomp.ncomp.sirius.manager.controllermodel.ControllermodelFactory;
+import org.openecomp.ncomp.sirius.manager.generator.ControllerGenerator;
+//import org.openecomp.ncomp.sirius.manager.gui.GuiFactory;
+import org.openecomp.ncomp.sirius.manager.server.ServerPackage;
+
+
+public class Generator {
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ @SuppressWarnings("unused")
+ ServerPackage f = ServerPackage.eINSTANCE;
+ EObject o = OpenstackFactory.eINSTANCE.createOpenStackController();
+ EPackage p = o.eClass().getEPackage();
+ String dir = p.getNsURI().replace(p.getNsPrefix(),"") + "servers." + p.getNsPrefix();
+ dir= "src/main/sirius-gen/" + dir.replace('.', '/');
+ ControllerModel m = ControllermodelFactory.eINSTANCE.createControllerModel();
+ m.setTemplateDirectory("../../dcae-org.openecomp.ncomp.sirius.manager/ncomp-sirius-manager-generator/src/main/templates");
+ m.setPrefix("Os");
+ m.setPluginName(p.getNsURI());
+ m.setName("OpenStackController");
+ m.setTitle("OpenStack Controller");
+ ControllerGenerator g = new ControllerGenerator(o,m);
+ EObject loc =LocationFactory.eINSTANCE.createOpenStackLocation();
+ g.addObject("loc",loc,m);
+ g.setEnableIRequestHandler(false);
+ //EObject gui = GuiFactory.eINSTANCE.createGuiClientApi();
+ //g.addObject("gui",gui,m);
+ //EObject e = OpenstackFactory.eINSTANCE.createVpnEnterprise();
+ //g.addApi("e",e,m);
+ //g.addFactory("org.openecomp.ncomp.sirius.servers.openstack.OsOpenstackFactory");
+ g.generate(dir);
+ g.generateAnt("./ant.xml",true,true);
+ g.generateScripts("src/main/server-gen/bin","openstack-controller");
+ String pName = p.getNsURI().replaceAll(p.getNsPrefix()+'$',"") + "servers." + p.getNsPrefix() +".logging";
+ YamlToJava.convert("src/main/resources/OpenStackAdaptor.yaml", dir + "/logging", pName);
+ YamlToJava.convert("src/main/sirius-gen/OpenStackController.yaml", dir + "/logging", pName);
+ String pName1 = p.getNsURI().replaceAll(p.getNsPrefix()+'$',"") + "servers." + p.getNsPrefix() +".loc.logging";
+ YamlToJava.convert("src/main/sirius-gen/OpenStackLocation.yaml", dir + "/loc/logging", pName1);
+
+ }
+
+
+}
diff --git a/ncomp-openstack-controller/src/main/java/org/openecomp/ncomp/openstack/controller/tools/OpenStackUtil.groovy b/ncomp-openstack-controller/src/main/java/org/openecomp/ncomp/openstack/controller/tools/OpenStackUtil.groovy new file mode 100644 index 0000000..55155fc --- /dev/null +++ b/ncomp-openstack-controller/src/main/java/org/openecomp/ncomp/openstack/controller/tools/OpenStackUtil.groovy @@ -0,0 +1,1028 @@ + +/*- + * ============LICENSE_START========================================== + * OPENECOMP - DCAE + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property. All rights reserved. + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + */ + +package org.openecomp.ncomp.openstack.controller.tools + +import org.openecomp.ncomp.sirius.manager.JavaHttpClient; +import org.openecomp.ncomp.sirius.manager.Jetty8Client; +import org.openecomp.ncomp.sirius.manager.ManagementServer; +import org.openecomp.ncomp.sirius.manager.Subject; +import org.openecomp.ncomp.sirius.manager.server.Response +import org.openecomp.ncomp.core.NamedEntity +import org.openecomp.ncomp.core.User +import org.openecomp.ncomp.openstack.* +import org.openecomp.ncomp.openstack.core.* +import org.openecomp.ncomp.openstack.location.* +import org.openecomp.ncomp.openstack.compute.* +import org.openecomp.ncomp.openstack.location.OpenStackLocation +import org.openecomp.ncomp.openstack.location.OpenStackProject +import org.openecomp.ncomp.openstack.neutron.CreateNetworkRequest; +import org.openecomp.ncomp.openstack.neutron.NeutronFactory; +import org.openecomp.ncomp.openstack.neutron.NeutronObject; +import org.openecomp.ncomp.openstack.neutron.NeutronPackage; +import org.openecomp.ncomp.openstack.neutron.NeutronRequest +import org.openecomp.ncomp.webservice.utils.FileUtils; + +import org.apache.log4j.Logger; +import org.eclipse.emf.ecore.EAnnotation; +import org.eclipse.emf.ecore.EAttribute +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EPackage +import org.eclipse.emf.ecore.EReference +import org.eclipse.emf.ecore.util.EcoreUtil +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.HttpExchange; +import org.eclipse.jetty.http.HttpHeaders; +import org.eclipse.jetty.io.Buffer; +import org.eclipse.jetty.io.BufferUtil; +import org.eclipse.jetty.io.ByteArrayBuffer +import org.json.JSONObject +import org.json.JSONArray + +import static org.openecomp.ncomp.utils.PropertyUtil.getPropertiesFromClasspath + + +class OpenStackUtil { + public static final Logger logger = Logger.getLogger(OpenStackUtil.class); + public static final Logger plogger = Logger.getLogger("org.openecomp.ncomp.openstack.OpenStackUtil.polling"); + Properties props + List<OpenStackControllerProject> projects = [] + ManagementServer server + OpenStackLocation loc // used for polling + OpenStackLocation realLocation // location in controller state. + boolean debug = false + int serverCreationTimeout + public long pollingFrequency = 300000 + + public OpenStackUtil(OpenStackLocation loc1, ManagementServer server1, String file = "openstack.properties") { + props = getPropertiesFromClasspath(file); + EPackage p1 = LocationPackage.eINSTANCE; + debug = Boolean.parseBoolean(props.getProperty("server.debug","false")); + serverCreationTimeout = Integer.parseInt(props.get("serverCreationTimeout","120")) + pollingFrequency = Integer.parseInt(props.get("pollingFrequency","300000")) + server = server1 + realLocation = loc1 + loc = EcoreUtil.copy(loc1) + loc.projects.each { p -> + projects += new OpenStackControllerProject(p) + } + System.err.println "OPENSTACK: debug=$debug pollingFrequency=$pollingFrequency" + logger.info("Found ${projects.size()} projects".toString()) + if (!projects.find { it.tenantName == "admin"}) { + logger.warn("Missing Admin Openstack project") + } + } + static main(args) { + // BROKEN WITH THE NEW SETUP. Need to create Location object + // ALWAYS USE GMT. + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + OpenStackUtil openstack = new OpenStackUtil() + switch ("T") { + case "T": + CreateNetworkRequest r = NeutronFactory.eINSTANCE.createCreateNetworkRequest() + r.name = "someone-test" + r.tenant_id = openstack.projects[0].tenantId + openstack.projects[0].create(r) + break + case "P": + openstack.poll() + println openstack.server.ecore2json(openstack.loc, 100, null, false).toString(2) + break + case "S": openstack.projects[0].createServer(); break + } + + } + public OpenStackLocation poll() { + if (loc.keystoneUrl == null) { + logger.warn("No keystoneUrl for $loc.name") + return + } + plogger.info "Starting Logging" + if (props.get("noPoll","no") == "yes") return null + loc.images.clear() + def oldFlavors = [] + loc.flavors.each { f -> oldFlavors += f } + loc.flavors.clear() + + if (projects.size() == 0) { + logger.warn("No project to poll") + return + } + + projects[0].updateGeneric(loc,"image") + try { + projects[0].updateGeneric(loc,"flavor") + } + catch (e) { + } + if (loc.flavors.size() == 0) { + logger.warn("Empty Flavor list, using old") + System.err.println("Empty Flavor list, using old") + oldFlavors.each { f -> loc.flavors.add(f) } + } + projects.each {OpenStackControllerProject p -> + p.poll() + } + realLocation.mergeLocation(loc) + server.save() +// plogger.debug("${server.ecore2json(loc, 100, null, false).toString(2)}".toString()) + plogger.info "Done Logging" + + return loc + } + static def object2json(o,boolean fix = false) { + switch (o) { + case JSONObject: return o + case EObject: return ManagementServer.ecore2json(o, 100, null, false) + case List: + def j = [] as JSONArray + o.each { j.put(object2json(it,fix)) } + return j + case Map: + def j = [:] as JSONObject + o.each { String k,v -> + if (v == null) return + if (!fix) {j.put(k,object2json(v)); return} + switch (k) { + case "addresses": + def a = [] as JSONArray + j.put(k,a) + v.each { k1, v1 -> + a.put(object2json([ name : k1, ips : v1],fix)) + } + break + case "metadata": + def a = [] as JSONArray + j.put(k,a) + v.each { k1, v1 -> + a.put(object2json([ key : k1, value :v1],fix)) + } + break + case ~/.*:.*/: + // eg OS-EXT-STS:vm_state + j.put(k.replace("-", "_").replace(":", "_"),object2json(v,fix)) +// String[] a = k.split(":") +// String nn = a[1] +// def j1 = [:] as JSONObject +// j1.put(nn,object2json(v,fix)) +// j.put(a[0].replace("-", "_").toLowerCase(),j1) + break + default: j.put(k,object2json(v,fix)) + } + } + return j + case boolean: case Boolean: + case int: case Integer: + case long: case Long: + case double: case Double: + case JSONObject.Null: + case null: + case String: return o; break + case GString: return o.toString(); break + default: logger.warn "Unable to convert: $o".toString() + } + } + def json2object (o) { + switch (o) { + case JSONObject: + def m = [:] + o.map.each { n,v -> m[n] = json2object(v) } + return m + case JSONArray: + def a = [] + o.myArrayList.each { a += json2object(it) } + return a + case boolean: case Boolean: + case int: case Integer: + case long: case Long: + case double: case Double: + case null: + case JSONObject.NULL: + case String: return o; break + case GString: return o.toString(); break + default: logger.warn "Unable to convert to object: $o ${o.getClass().name}".toString() + } + } + //{"flavor": {"vcpus": 1, "disk": 10, "name": "someone.test", "os-flavor-access:is_public": true, "rxtx_factor": 1, "OS-FLV-EXT-DATA:ephemeral": 33, "ram": 200, "id": 10001, "swap": 0}} + def x = [:] + def createFlavor(String projectName, VirtualMachineType vmType) { + OpenStackControllerProject p + p = projects.find {OpenStackControllerProject p1 -> p1.tenantName == projectName} + if (p == null) return "No project with name $projectName" + def fName = vmType.name + def i = null + switch (loc.version) { + case OpenStackVersion.FOLSOM: // old BSA version + def flavors = p.httpJsonTransaction([url : "${p.urls['nova']}/flavors"],false) + x.flavors = flavors + def existingId = null + synchronized (loc) { + i = loc.flavorId + 1 + flavors.flavors.each { ff -> + def j = Integer.parseInt(ff.id) + // if (debug) System.err.println "Existing Flavors: id=$ff.id name=$ff.name" + if (i <= j) i = j + 1 + if (fName == ff.name) existingId = ff.id + } + loc.flavorId = i + server.save() + } + break; + } + def req = [ + url : "${p.urls['nova']}/flavors", + method : "POST", + body : [ flavor : [ + vcpus: vmType.numberOfCores, + disk: vmType.rootDiskSizeGB, + name: fName, + "os-flavor-access:is_public": true, + rxtx_factor: 1, + "OS-FLV-EXT-DATA:ephemeral": vmType.diskSizeGB, + ram: vmType.memorySizeMB, + swap: 0] + ] + ] + if (i != null) req.body.flavor.identity = i + x.req = req + def res = p.httpJsonTransaction(req,false) + x.res = res + } + def createSecurityGroup(String projectName, VirtualMachineType vmType) { + OpenStackControllerProject p + p = projects.find {OpenStackControllerProject p1 -> p1.tenantName == projectName} + if (p == null) return "No project with name $projectName" + def gName = vmType.name + def req = [ + url : "${p.urls['nova']}/os-security-groups", + method : "POST", + body : [ security_group : [ name: gName, description : "Automatically created" ] ] + ] + x.req = req + def res = p.httpJsonTransaction(req,false) + // {"security_group_rule": {"from_port": 22, "ip_protocol": "tcp", "to_port": 22, "parent_group_id": 12, "cidr": "0.0.0.0/0", "group_id": null}} + vmType.incomingSecurityRules.each { SecurityRule r -> + def id = res.security_group.id + def req2 = [ + url : "${p.urls['nova']}/os-security-group-rules", + method : "POST", + body : [ security_group_rule : [ + from_port: r.portRangeStart, + to_port: r.portRangeEnd, + ip_protocol: r.ipProtocol.toString(), + cidr: r.prefix, + parent_group_id: id, + ] ] + ] + def res2 = p.httpJsonTransaction(req2,false) + } + x.res = res + } + def delete(String projectName, String type, String name) { + if (debug) System.err.println "DELETING $projectName $type $name" + OpenStackControllerProject p + p = projects.find {OpenStackControllerProject p1 -> p1.tenantName == projectName} + if (p == null) return "No project with name $projectName" + def types = "${type}s" + def idName = "id" + def oName = "name" + def api = "nova" + def dtypes = types + def nameAttr = loc.version == OpenStackVersion.FOLSOM ? "display_name" : "name" + switch (type) { + case "volume": oName = nameAttr; api = "cinder"; break + case "flavor": types = "$types/detail"; break + case "security_group": types = "os-security-groups"; dtypes = types; break + case "keypair": + p.httpJsonTransaction([url : "${p.urls[api]}/os-$types/$name", method:"DELETE"],false,true,true,false) + if (debug) System.err.println "$type name=$name deleted" + return + } + def l = p.httpJsonTransaction([url : "${p.urls[api]}/$types"],false) + if (debug) System.err.println "l=$l" + if (debug) System.err.println "DELETE LIST:" + l["${type}s"].each { if (debug) System.err.println it } + if (debug) System.err.println "type=$type types=$types oName=$oName name=$name idName=$idName" + def fl = l["${type}s"].findAll { it[oName] == name } + if (debug) System.err.println "DELETEING LIST: $fl" + if (fl.size() == null) return "No $type with name $name" + fl.each { f -> + p.httpJsonTransaction([url : "${p.urls[api]}/$dtypes/${f[idName]}", method:"DELETE"],false,true,true,false) + if (debug) System.err.println "$type name=$name id=${f[idName]} deleted" + } + } + + // {"volume": {"status": "creating", "availability_zone": "nova:lab2-bsa-02-bay04", + // "display_description": null, "snapshot_id": null, "user_id": null, "size": 2, + // "display_name": "someone.test", "imageRef": null, "attach_status": "detached", + // "volume_type": null, "project_id": null, "metadata": {}}} + def createVolume (OpenstackRequestNewServer req) { + OpenStackControllerProject p + p = projects.find {OpenStackControllerProject p1 -> p1.tenantName == req.projectName} + if (p == null) return "No project with name $projectName" + def reqV = [url : "${p.urls['cinder']}/volumes/detail"] + def resV = p.httpJsonTransaction(reqV,false) +// System.out.println("VVVVVVVVVVVVVVVVVV: ${reqV}") +// System.out.println("VVVVVVVVVVVVVVVVVV: ${resV}") + def nameAttr = loc.version == OpenStackVersion.FOLSOM ? "display_name" : "name" + def existingVol = resV.volumes.find { vol -> + ( vol["display_name"] ?: vol["name"] ) == req.name + } + if (existingVol != null) { + if (debug) System.err.println "EXISTING VOLUME: ${existingVol}" + switch (loc.version) { + case OpenStackVersion.FOLSOM: + if (existingVol.availability_zone != "nova:$req.hypervisor") + return [status:"error",message:"existing volume on wrong hypervisor: $existingVol.availability_zone"] + } + if ("$existingVol.size" != "$req.vmType.volumeSizeGB") + return [status:"error",message:"existing volume has wrong size: $existingVol.size"] + if (existingVol.status != "available") + return [status:"error",message:"existing volume is not available: $existingVol.status"] + return [status: "ok", volume: existingVol] + } + def req1 = [ + url : "${p.urls['cinder']}/volumes", + method : "POST", + body : [ volume : [ + display_name: req.name, + size: req.vmType.volumeSizeGB] + ] + ] + if (req.hypervisor != null) { + req1.body.volume.availability_zone = "nova:$req.hypervisor" + } + def res1 = p.httpJsonTransaction(req1,false,false) +// System.out.println("VVVVVVVVVVVVVVVVVV req1: ${req1}") +// System.out.println("VVVVVVVVVVVVVVVVVV res1: ${res1}") + def volume = res1.volume ?: null + // wait for the new volume to be available. Wait at most 10 seconds. + (1..10).each { + if (volume == null || volume.status == "available") return + sleep 1000 + res1 = p.httpJsonTransaction([url : "${p.urls['cinder']}/volumes/$volume.id"],false,false) +// System.out.println("VVVVVVVVVVVVVVVVVV res1 LOOP: ${res1}") + volume = res1.volume ?: null + } + if (volume == null) return [status:"error",message:res1] + if (volume.status != "available") return [status:"error",message:"new volume did not become available"] + return [status: "ok", volume: volume] + } + // {"server": {"name": "someone.test", "imageRef": "9a460998-6501-4008-9eed-a510cf9a13bc", + // "availability_zone": "nova:lab3-bsa-03-bay03", "key_name": "someone", "flavorRef": "2", + // "max_count": 1, "min_count": 1, "networks": [], + // "security_groups": [{"name": "default"}, {"name": "ssh"}]}} + def createServer (OpenstackRequestNewServer req) { + OpenStackControllerProject p + def loc = realLocation + p = projects.find {OpenStackControllerProject p1 -> p1.tenantName == req.projectName} + if (p == null) throw new RuntimeException( "No project with name $req.projectName" ) + if (req.vmType == null) throw new RuntimeException("Null VmType") + String flavorName = req.vmType.flavorName ?: req.vmType.name + def flavor = loc.flavors.find { it.name == flavorName } + if (flavor == null) { + System.err.println "flavors $loc.name: ${loc.flavors.collect {it.name}}" + throw new RuntimeException("No flavor with name '$flavorName'") + } + if (req.vmType.imageName == null) req.vmType.imageName = req.vmType.name + def image = loc.images.find { it.name == req.vmType.imageName } + if (image == null) throw new RuntimeException( "No image with name $req.vmType.imageName") + def keypair = p.project.keypairs.find { it.name == req.user } + if (req.user != null && keypair == null) throw new RuntimeException( "No key pair with name $req.user") + def req1 = [ + url : "${p.urls['nova']}/servers", + method : "POST", + body : [ server : [ + name: req.name, + imageRef: image.id, + key_name: req.user, + flavorRef: flavor.id, + max_count: 1, min_count: 1, networks: [], + security_groups: [[name: "default"]], + config_drive: true, + ], + ] + ] + if (! loc.supportsSecurityGroups) req1.body.server.remove('security_groups') + req.networks.each {network -> req1.body.server.networks += [uuid:network]} + req.ports.each {port -> req1.body.server.networks += [port:port]} + if (req.hypervisor != null) { + req1.body.server.availability_zone = "nova:$req.hypervisor" + } + if (req.user_data != null) { + req1.body.server.user_data = req.user_data + } + x["req"] = req1 + logger.info "create server request: ${object2json(req1).toString(2)}" + def server = p.httpJsonTransaction(req1,false) + logger.info "create server return: ${object2json(server).toString(2)}" + if (! server.server) { + throw new RuntimeException("create server failed: ${object2json(server).toString(2)}") + } + def vol + if (req.vmType.volumeSizeGB > 0) { + vol = createVolume(req) +// System.err.println "VOLUME= $req $vol " + if (vol.status != "ok") { + throw new RuntimeException("create volume failed: $vol.message") + } + } + String sid = server.server.id + // wait upto 2 minutes for status to become ACTIVE + def status = "??" + (1..serverCreationTimeout/5).each { + if (status == "ACTIVE") return + sleep 5000 + def x = p.httpJsonTransaction([url : "${p.urls['nova']}/servers/$sid"]) +// if (debug) System.err.println "Waiting status=$x.server.status" + status = x.server.status + } + logger.info "Done waiting status=$status" + if (status != "ACTIVE") { + throw new RuntimeException("create server failed to get ACTIVE: ${object2json(server).toString(2)}") + } +// if (debug) System.err.println object2json(server).toString(2) + if (req.vmType.volumeSizeGB > 0) { +// if (debug) System.err.println object2json(vol.volume).toString(2) + def attach = [ + url : "${p.urls['nova']}/servers/$sid/os-volume_attachments", + method : "POST", + body : [ volumeAttachment: [volumeId: vol.volume.id, device: "/dev/vdc"]] + ] + server["volume"] = vol +// if (debug) System.err.println "attach request: ${object2json(attach).toString(2)}" + def a = p.httpJsonTransaction(attach,false) +// if (debug) System.err.println object2json(a).toString(2) + server["volume_attach"] = a + } + if (req.vmType.incomingSecurityRules.size() > 0 && loc.supportsSecurityGroups) { + def addSecurityGroup = [ + url : "${p.urls['nova']}/servers/$sid/action", + method : "POST", + body : [ addSecurityGroup: [name: "$req.vmType.name"]] + ] + def res4 = p.httpJsonTransaction(addSecurityGroup,false,true,true,false) + } + if (req.vmType.needPublicIp) { + sleep 10000 + server["ip"] = addFloatingIp(req.projectName, sid, req.floatingIp) + } + x["res"] = server +// if (debug) System.err.println object2json(server).toString(2) + return server + } + def createKeypair (String projectName, User user) { + OpenStackControllerProject p + p = projects.find {OpenStackControllerProject p1 -> p1.tenantName == projectName} + if (p == null) return "No project with name $projectName" + def req1 = [ + url : "${p.urls['nova']}/os-keypairs", + method : "POST", + body : [ keypair : [ + name: user.name, + public_key: user.publicKey] + ] + ] + def k = p.httpJsonTransaction(req1,false) +// if (debug) System.err.println k + return k + } + def addFloatingIp(String projectName,sid,requestIp) { + OpenStackControllerProject p + p = projects.find {OpenStackControllerProject p1 -> p1.tenantName == projectName} + if (p == null) return "No project with name $projectName" + def res = p.httpJsonTransaction([url : "${p.urls['nova']}/os-floating-ips"],false) + def ip = null +// if (debug) System.err.println object2json(res).toString(2) + res.floating_ips.each { x -> + if (debug) System.err.println "AAAAAAAAAA ${object2json(x).toString(2)} ${x['instance_id']}" + if (requestIp != null && requestIp != "$x.ip") return + if ("${x['instance_id']}" == "null") ip = x.ip + } + if (requestIp != null && ip == null) { + throw new RuntimeException("Unable to find requested floating IP: $requestIp") + } + if (ip == null) { + res = p.httpJsonTransaction([method:"POST", url : "${p.urls['nova']}/os-floating-ips"],false) +// if (debug) System.err.println object2json(res).toString(2) + ip = res.floating_ip.ip + if (debug) System.err.println "Using new ip: $ip" + } else { + if (debug) System.err.println "Using old ip: $ip" + } + def req = [ + url : "${p.urls['nova']}/servers/$sid/action", + method : "POST", + body : [ addFloatingIp: [address: ip]] + ] +// if (debug) System.err.println object2json(req).toString(2) + p.httpJsonTransaction(req,false,true,true,false) + return ip + } + def action(req) { + switch (req) { + case OpenstackRequestDelete: delete(req.projectName,req.objectType, req.objectName); break + case OpenstackRequestKeyPair: createKeypair(req.projectName,req.user); break + case OpenstackRequestFlavor: createFlavor(req.projectName,req.vmType); break + case OpenstackRequestSecurityGroup: createSecurityGroup(req.projectName,req.vmType); break + case OpenstackRequestNewServer: + def r = createServer(req) + logger.info "createServer returns: $r" + break; + } + } + Response serverAction(OpenstackRequestServerAction req) { + OpenStackControllerProject p + p = projects.find {OpenStackControllerProject p1 -> p1.tenantName == req.projectName} + if (p == null) { + logger.warn "serverAction with null $req.projectName" + throw new RuntimeException("no Openstack project $req.projectName") + } + Server s = p.project.servers.find { it.name == req.name } + if (s == null) { + logger.warn "serverAction unable to find VM with name $req.name in $req.projectName" + throw new RuntimeException("unable to find VM with name $req.name in $req.projectName") + } + def url = "${p.urls['nova']}/servers/$s.ID/action" + def res + switch (req.action) { + case "stop": + case "start": + res = p.httpJsonTransaction([url:url,method:"POST",body:["os-$req.action":"null"]],false,true,true,false) + break; + case "pause": + case "unpause": + case "suspend": + case "resume": + case "lock": + case "unlock": + res = p.httpJsonTransaction([url:url,method:"POST",body:["$req.action":"null"]],false,true,true,false) + break; + case "reboot": + res = p.httpJsonTransaction([url:url,method:"POST",body:[reboot:[type:"SOFT"]]],false,true,true,false) + break; + case "hardReboot": + res = p.httpJsonTransaction([url:url,method:"POST",body:[reboot:[type:"HARD"]]],false,true,true,false) + break; + case "reset-state": + res = p.httpJsonTransaction([url:url,method:"POST",body:['os-resetState':[state:"error"]]],false,true,true,false) + break; + case "reset-state-active": + res = p.httpJsonTransaction([url:url,method:"POST",body:['os-resetState':[state:"active"]]],false,true,true,false) + break; + default: + logger.error "unknown nova command $req.action"; + return + } + if (res == null) { + logger.warn "ran nova command $req.action on $req.name succesfully" + return + } + logger.error "ran nova command $req.action on $req.name: $res" + } + + OpenStackControllerProject findProject(String name) { + return projects.find {OpenStackControllerProject p1 -> p1.tenantName == name} + } + + +class OpenStackControllerProject { + HttpClient httpClient + def tokens = null + String password + String username + String tenantName + String tenantId + String keystoneUrl + OpenStackProject project + def urls = [:] + public OpenStackControllerProject(OpenStackProject project1) { + project = project1 + tenantName = project.name + username = project.adminUser + password = props.get("${loc.name}.password.$username".toString()) + if (password == null) { + // BSA setup + password = props.get("project.${project.name}.password".toString()) + } + if (password == null) { + logger.warn("No password for $loc.name $project.name") + System.err.println "No password for $loc.name $project.name $username" + } + password = JavaHttpClient.decryptPassword(password) + tenantId = project.tenantId + keystoneUrl = loc.keystoneUrl +// if (debug) System.err.println "u=$username pw=$password tenantId=$tenantId" + // Remove the refs are supported. +// logger.info "${server.ecore2json(loc, 100, null, false).toString(2)}".toString() +// if (debug) System.err.println "${server.ecore2json(project, 100, null, false).toString(2)}" + httpClient = new HttpClient() + httpClient.start(); + updateTokens() + } + public void poll() { +// updateImages() +// updateGeneric(loc,"image") +// updateGeneric(loc,"flavor") + updateServers() + updateHypervisor() + try { updateSecurityGroups() } catch (e) { println "updateSecurityGroups failed: $e" } + updateVolumes() + updateKeypairs() + if (urls['neutron'] != null) { + updateGenericNeutron(project, "network") + updateGenericNeutron(project, "subnet") + updateGenericNeutron(project, "router") + updateGenericNeutron(project, "port") + updateGenericNeutron(project, "security_group") + updateGenericNeutron(project, "floatingip") + } + server.save() + } + /** + * Polls the Openstack Nova API for all the nova state (e.g, servers, images,..) + * for a project. + */ + def synchronized void updateTokens() { + if (keystoneUrl == null) { + logger.warn("No keystoneUrl for $loc.name") + return + } + if (password == null) { + logger.warn("No password for $loc.name") + return + } + def req = [ url : "$keystoneUrl/tokens", method : "POST", + body :[ auth : [passwordCredentials : [username: username, password: password], tenantId: tenantId]] + ] + + // RACKSPACE + if (project.apiKey != null) { + req.body.auth = ["RAX-KSKEY:apiKeyCredentials" : [username: username, apiKey: JavaHttpClient.decryptPassword(project.apiKey)]] + } + // {"auth": {"RAX-KSKEY:apiKeyCredentials": {"username": "ft123456", "apiKey": "dae41ba7484d4f8482"}}} + + tokens = httpJsonTransaction(req,,false,false,false) + if (debug) System.err.println object2json(tokens).toString(2) + if (! tokens.access) { + if (debug) System.err.println "Unabled to access tenant: $tenantName : ${object2json(tokens).toString(2)}" + logger.fatal "Unabled to access tenant: $tenantName : ${object2json(tokens).toString(2)}" + return; + } + tokens.access.serviceCatalog.each { it -> + def u = it.endpoints.get(0).publicURL + it.endpoints.each { x -> + if (x['region'] == project.region) + u = x.publicURL + } + urls[it.name] = u + if (debug) System.err.println "serviceCatalog $it.name -> ${urls[it.name]}" + } + // RACKSPACE + [ images :"cloudImages", + nova:"cloudServersOpenStack", + neutron: "cloudNetworks", + cinder: "cloudBlockStorage"]. each { n, v -> + if (urls[n] == null && urls[v] != null) { + System.err.println "Using $v service for $n" + if (n == "neutron" && urls[v].endsWith("/v2.0")) + urls[v] = urls[v].replace("/v2.0","") + urls[n] = urls[v] + } + if (urls[n] != null) { + System.err.println "No $n service" + } + } + } + def void updateImages() { + def req1 = [url : "${urls['nova']}/images"] + def res1 = httpJsonTransaction(req1) +// if (debug) System.err.println object2json(res1).toString(2) + loc.images.clear() + res1.images.each { s -> + def req2 = [url : s.links[0].href] + def res2 = httpJsonTransaction(req2) + logger.debug(object2json(res2).toString(2)) + createFromJson(server, new Subject(loc, "images"),object2json(res2.image,true)) ; + } + } + def void updateKeypairs() { + def req1 = [url : "${urls['nova']}/os-keypairs"] + def res1 = httpJsonTransaction(req1) + project.keypairs.clear() + res1.keypairs.each { s -> + createFromJson(server, new Subject(project, "keypairs"),object2json(s.keypair,true)) ; + } + } + def void updateGeneric(o,name) { + def req1 = [url : "${urls['nova']}/${name}s"] + def res1 = httpJsonTransaction(req1) +// if (debug) System.err.println object2json(res1).toString(2) + o["${name}s"].clear() + res1["${name}s"].each { s -> +// logger.info("getting ${s.links[0].href}") + def req2 = [url : s.links[0].href] + def res2 = httpJsonTransaction(req2) +// logger.debug( object2json(res2).toString(2)) +// if (debug) System.err.println "o=$o name=$name" + createFromJson(server, new Subject(o, "${name}s"),object2json(res2[name],true)) ; + } + } + def void updateGenericNeutron(o,name) { + def req1 = [url : "${urls['neutron']}/v2.0/${name.replace('_','-')}s"] + def res1 = httpJsonTransaction(req1) +// if (debug) System.err.println object2json(res1).toString(2) + o["${name}s"].clear() + res1["${name}s"].each { s -> + if (s.tenant_id != null && s.tenant_id != tenantId) return + JSONObject json = OpenStackUtil.object2json(s,true) +// if (debug) System.err.println json.toString(2) +// if (debug) System.err.println "o=$o id=$s.id" + if (s.name == null || s.name == "" || name == "security_group") json.put("name", s.id) + createFromJson(server, new Subject(o, "${name}s"),json) ; + } + } + def createFromJson(ManagementServer server,subject,JSONObject json) { + server.create(subject,json,false) + } + + def void updateHypervisor() { + if (tenantName != "admin") return + def req1 = [url : "${urls['nova']}/os-hypervisors/detail"] + def res1 = null; + try { res1 = httpJsonTransaction(req1) } catch (e) { + logger.error "Unable to get Hypervisor information: $e" + return + } +// if (debug) System.err.println object2json(res1).toString(2) + loc.hypervisors.clear() + res1.hypervisors.each { s -> + def json = new JSONObject(s.cpu_info) + s.cpu_info = json2object(json) +// if (debug) System.err.println s +// if (debug) System.err.println object2json(s,true) +// logger.info(object2json(s).toString(2)) + createFromJson(server, new Subject(loc, "hypervisors"),object2json(s,true)) + } + loc.hypervisors.each { it.name = it.service.host } + } + + def void updateSecurityGroups() { + def req1 = [url : "${urls['nova']}/os-security-groups"] + def res1 = httpJsonTransaction(req1) +// if (debug) System.err.println object2json(res1).toString(2) + project.groups.clear() + res1.security_groups.each { s -> +// logger.info(object2json(s).toString(2)) + createFromJson(server, new Subject(project, "groups"),object2json(s,true)) + } + } + + def void updateVolumes() { + if (urls['cinder'] == null) return + def req1 = [url : "${urls['cinder']}/volumes/detail"] + def res1 = httpJsonTransaction(req1) +// if (debug) System.err.println object2json(res1).toString(2) +// System.out.println("VVVVVVVVVVVVVVVVVV poll res1: ${res1}") + project.volumes.clear() + res1.volumes.each { s -> +// logger.info(object2json(s).toString(2)) + createFromJson(server, new Subject(project, "volumes"),object2json(s,true)) + } + if (loc.version == OpenStackVersion.FOLSOM ) + project.volumes.each { it.name = it.display_name } + project.volumes.each { + if (it.name == null) it.name = it.display_name + } + } + + def void updateFloatingIps() { + def req1 = [url : "${urls['nova']}/os-floating-ips"] + def res1 = httpJsonTransaction(req1) +// if (debug) System.err.println object2json(res1).toString(2) + project.ips.clear() + res1.floating_ips.each { s -> +// logger.info(object2json(s).toString(2)) + createFromJson(server, new Subject(project, "ips"),object2json(s,true)) + } + } + def void updateServers() { + def req1 = [url : "${urls['nova']}/servers" ] + def res1 = httpJsonTransaction(req1) + project.servers.clear() +// if (debug) System.err.println OpenStackUtil.object2json(res1).toString(2) + res1.servers.each { s -> + def req2 = [url : s.links[0].href ] + def res2 = httpJsonTransaction(req2) +// if (debug) System.err.println OpenStackUtil.object2json(res2).toString(2) +// return +// logger.debug(object2json(res2).toString(2)) + if (res2.server.image == "") res2.server.image = null + createFromJson(server, new Subject(project, "servers"),object2json(res2.server,true)) +// def req3 = [url : res2.server.image.links[0].href] +// def res3 = httpJsonTransaction(req3) +// logger.debug( object2json(res3).toString(2)) +// def req4 = [url : res3.choices[0].links[0].href] +// def res4 = httpJsonTransaction(req4) +// logger.debug( object2json(res4).toString(2)) + } + } + def NeutronObject create(NeutronRequest req) { + def ename = req.eClass().name + def cname = ename.substring(6,ename.length()-7) + def name = cname.toLowerCase() + switch (req) { + case CreateNetworkRequest: name = "network"; cname = "Network"; break + } + JSONObject j = new JSONObject() + // TODO look at annotations in ecore2json + JSONObject jj = ManagementServer.ecore2json(req, 100, null, false) + jj.remove('$class') + jj.remove('projectName') + req.eClass().EAllAttributes.each { EAttribute attr -> + EAnnotation anno = attr.getEAnnotation("http://openecomp.org/sirius/openstack"); + if (anno == null) return + String name1 = anno.details.get("name") + if (name1 != null && jj.has(attr.name)) { + def v = jj.get(attr.name) + jj.remove(attr.name) + jj.put(name1, v) + } + name1 = anno.details.get("removeEmptyList") + if (name1 == "true" && jj.has(attr.name)) { + def v = jj.get(attr.name) + switch (v) { + case JSONArray: + if (v.length() == 0) jj.remove(attr.name) + } + } + } + req.eClass().EAllReferences.each { EReference ref -> + EAnnotation anno = ref.getEAnnotation("http://openecomp.org/sirius/openstack"); + if (anno == null) return + String name1 = anno.details.get("name") + if (name1 != null && jj.has(ref.name)) { + def v = jj.get(ref.name) + jj.remove(ref.name) + jj.put(name1, v) + } + name1 = anno.details.get("removeEmptyList") + if (name1 == "true" && jj.has(ref.name)) { + def v = jj.get(ref.name) + switch (v) { + case JSONArray: + if (v.length() == 0) jj.remove(ref.name) + } + } + } + j.put(name, jj) + if (debug) System.err.println jj.toString(2) + def req1 = [url : "${urls['neutron']}/v2.0/${name.replace('_','-')}s", method:"POST", body:j] + if (debug) System.err.println req1 + def res1 = httpJsonTransaction(req1) + if (debug) System.err.println res1 + j = OpenStackUtil.object2json(res1[name],true) + if (debug) System.err.println j == null ? "NULL" : j.toString(2) + return server.json2ecore(NeutronPackage.eINSTANCE.getEClassifier(cname),j, false) + } + def void deleteNeutron(String type, String name) { + project["${type}s"].each { o -> + if (o.name != name) return + logger.warn "deleting $type $name $o.id" + def req1 = [url : "${urls['neutron']}/v2.0/${type.replace('_','-')}s/$o.id", method:"DELETE"] + if (debug) System.err.println req1 + def res1 = httpJsonTransaction(req1,false,true,true,false) + if (debug) System.err.println res1 + } + } + def httpJsonTransaction(m, boolean polling = true, boolean throwError = true, boolean addAuth = true, boolean expectResponse = true) { + def exchange = new Exchange() + if (debug) System.err.println "m=$m" + def url = m.url ?: "${urls[m.api]}/$m.uri" + if (loc.bypassIp) { + url = url.replaceFirst("http://.*:", "http://$loc.bypassIp:") + } + exchange.setURL(url); + if (debug) System.err.println "URL=$url" + exchange.setMethod(m.method ?: "GET"); + def headers = m.headers ?: [:] + headers['Content-type'] = 'application/json' + if (addAuth) { + headers['X-Auth-Token'] = tokens.access.token.id + headers['X-Auth-Project-Id'] = project.tenantId + } + headers.each { n,v -> + exchange.addRequestHeader(n, v); + if (debug) System.err.println "Header: $n: $v" + } + if (m.body) { + String json = object2json(m.body).toString() +// logger.info("REQUEST: ${object2json(m.body).toString(2)}") + if (debug) System.err.println "REQUEST BODY: $json" +// exchange.setRequestContentSource(new ByteArrayInputStream(json.bytes)) + exchange.setRequestContent(new ByteArrayBuffer(json.bytes)); + } +// if (debug) System.err.println "Sending request" + Date start = new Date() + httpClient.send(exchange) +// if (debug) System.err.println "Exchange sent" + int exchangeState = exchange.waitForDone(); + if (debug) System.err.println "Exchange done: $exchangeState" + if (debug) System.err.println "code=$exchange.code content=$exchange.content" + if (polling) plogger.info "content=$exchange.content" + else logger.info "content=$exchange.content" + def res = exchange.content.toString() + if (res == "" && ! expectResponse) return null + if (res == "") { + def duration = new Date().time - start.time + throw new RuntimeException("Openstack API returned NULL: $url duration=$duration") + } + if (res.startsWith("401 Unauthorize") || res.startsWith("Authentication required")) { + // keystone auth expired + logger.info("keystone auth expired, updating tokens and resending request") + updateTokens(); + return httpJsonTransaction(m, polling, throwError, addAuth) + } + if (res.startsWith("404 Not Found")) { + if (throwError) + throw new RuntimeException("Openstack API: 404 Not Found") + return null + } + JSONObject json = new JSONObject(res) + if (exchange.code < 200 || exchange.code >= 300) { + if (throwError && json.has("expection")) { + throw new RuntimeException("Openstack API: expection $json") + } + if (throwError && json.has("badRequest")) { + throw new RuntimeException("Openstack API: badRequest $json") + } + if (throwError && json.has("itemNotFound")) { + throw new RuntimeException("Openstack API: itemNotFound $json") + } + if (throwError && json.has("NeutronError")) { + throw new RuntimeException("Openstack API: NeutronError $json") + } + if (throwError) { + throw new RuntimeException("Openstack API: Error $json") + } + } + + if (debug) System.err.println json.toString(2) +// logger.info("RETURNED: ${json.toString(2)}") + return json2object(json) + } + public void associateFloatingIp(String ipId, String portId) { + def req1 = [url : "${urls['neutron']}/v2.0/floatingips/$ipId", method:"PUT", body:[floatingip:[port_id:portId]]] + if (debug) System.err.println req1 + def res1 = httpJsonTransaction(req1,false,true,true,false) + if (debug) System.err.println res1 +// return server.json2ecore(NeutronPackage.eINSTANCE.getEClassifier(cname),j, false) + } + + +} + +private class Exchange extends HttpExchange { + String version2; + int code; + String message; + String location; + StringBuffer content = new StringBuffer(); + + protected void onResponseHeader(Buffer name, Buffer value) { +// System.out.println("HEADER: " + name + " " + value); + if (name.toString().equals("Location")) + location = value.toString(); + } + + protected void onResponseStatus(Buffer httpVersion, int statusCode, Buffer statusMessage) { +// if (debug) System.err.println "v=$httpVersion code=$statusCode m=$statusMessage" + version2 = httpVersion.toString(); + code = statusCode; + message = statusMessage.toString(); + } + protected void onResponseContent(Buffer content) { + this.content.append(content.toString()); + } + +} +} + diff --git a/ncomp-openstack-controller/src/main/java/org/openecomp/ncomp/servers/openstack/OsOpenStackControllerProvider.java b/ncomp-openstack-controller/src/main/java/org/openecomp/ncomp/servers/openstack/OsOpenStackControllerProvider.java new file mode 100644 index 0000000..07941a9 --- /dev/null +++ b/ncomp-openstack-controller/src/main/java/org/openecomp/ncomp/servers/openstack/OsOpenStackControllerProvider.java @@ -0,0 +1,161 @@ + +/*- + * ============LICENSE_START========================================== + * OPENECOMP - DCAE + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property. All rights reserved. + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + */ + +package org.openecomp.ncomp.servers.openstack; + +import java.util.Date; +import java.util.HashMap; + +import org.apache.log4j.Logger; +import org.json.JSONObject; + +import org.openecomp.logger.EcompLogger; +import org.openecomp.ncomp.openstack.OpenStackController; +import org.openecomp.ncomp.openstack.controller.tools.OpenStackUtil; +import org.openecomp.ncomp.openstack.location.OpenStackLocation; +import org.openecomp.ncomp.servers.openstack.logging.OpenStackAdaptorMessageEnum; +import org.openecomp.ncomp.servers.openstack.logging.OpenStackAdaptorOperationEnum; +import org.openecomp.ncomp.sirius.manager.BasicAdaptorProvider; +import org.openecomp.ncomp.sirius.manager.ISiriusServer; +import org.openecomp.ncomp.sirius.manager.ManagementServer; +import org.openecomp.ncomp.sirius.manager.ManagementServerError; +import org.openecomp.ncomp.sirius.manager.ManagementServerUtils; +import org.openecomp.ncomp.sirius.manager.server.ServerPackage; + +public class OsOpenStackControllerProvider extends BasicAdaptorProvider { + public static final Logger logger = Logger.getLogger(OsOpenStackControllerProvider.class); + static final EcompLogger ecomplogger = EcompLogger.getEcompLogger(); + private HashMap<String, OpenStackUtil> utils = new HashMap<String, OpenStackUtil>(); + private HashMap<String, Thread> pollers = new HashMap<String, Thread>(); + private HashMap<String, Date> lastPoll = new HashMap<String, Date>(); + private OpenStackController o; + private OsOpenStackControllerClient parent = null; + protected long pollingFrequency; + + public OsOpenStackControllerProvider(ISiriusServer controller, OpenStackController o) { + super(controller, o); + this.o = o; + for (OpenStackLocation l : o.getLocations()) { + if (!l.isRemoteLocation()) { + startOpenstackPolling(l); + } + } + if (controller.getServer().getProps().containsKey("openstackParent.endpoint")) { + parent = new OsOpenStackControllerClient("location.properties", "openstackParent"); + } + } + + private synchronized void startOpenstackPolling(final OpenStackLocation l) { + Thread t = pollers.get(l.getName()); + if (t != null && t.isAlive()) { + return; + } + t = new Thread("openstackPoller " + l.getName()) { + @Override + public void run() { + ecomplogger.setOperation(OpenStackAdaptorOperationEnum.POLLING); + while (true) { + Date lastPoll2 = lastPoll.get(l.getName()); + if (lastPoll2 == null || lastPoll2.getTime() + pollingFrequency < new Date().getTime()) { + try { + ecomplogger.newRequestId(); + ecomplogger.recordAuditEventStart(); + openstackPolling(l); + } catch (Exception e) { + ecomplogger.warn(OpenStackAdaptorMessageEnum.POLLING_FAILED, ManagementServer.object2ref(l)); + ManagementServerUtils.printStackTrace(e); + } + finally { + ecomplogger.recordAuditEventEnd(); + } + } + try { + Thread.sleep(30000); + } catch (InterruptedException e1) { + } + } + }; + }; + t.setDaemon(true); + t.start(); + pollers.put(l.getName(), t); + } + + protected void openstackPolling(OpenStackLocation l) { + if (! l.getKeystoneUrl().startsWith("http")) { + logger.warn("openstackPolling ignored no valid keystone url: " + l.getName() + " " + l.getKeystoneUrl()); + return; + } + logger.info("openstackPolling: " + l.getName()); + OpenStackUtil util = getUtil(l.getName()); + lastPoll.put(l.getName(), new Date()); + OpenStackLocation poll = util.poll(); + poll.setName(l.getName()); + poll.setRemoteLocationName(l.getName()); + logger.info("polling done: " + poll); + if (poll != null) { + try { + uploadOpenstackConfiguration(null, poll); + } catch (ManagementServerError e) { + logger.warn("uploadOpenstackConfiguration: " + e.getJson().toString(2)); + } + } + + } + + public static void ecoreSetup() { + ServerPackage.eINSTANCE.getClass(); + } + + public void uploadOpenstackConfiguration(JSONObject cx, OpenStackLocation loc) { + if (parent != null) { + parent.uploadOpenstackConfiguration(cx, loc); + } + } + + public void start() { + for (OpenStackLocation l : o.getLocations()) { + if (!l.isRemoteLocation()) { + startOpenstackPolling(l); + } + } + } + + public synchronized OpenStackUtil getUtil(String name) { + OpenStackUtil util = utils.get(name); + if (util == null) { + for (OpenStackLocation l : o.getLocations()) { + if (l.isRemoteLocation()) { + break; + } + if (!l.getName().equals(name)) + continue; + util = new OpenStackUtil(l, controller.getServer(), controller.getServer().getProps() + .getProperty("openstack.propertyfile", "openstack.properties")); + utils.put(name, util); + pollingFrequency = util.pollingFrequency; + return (util); + } + } + return (util); + } + +} diff --git a/ncomp-openstack-controller/src/main/java/org/openecomp/ncomp/servers/openstack/loc/OsOpenStackLocationProvider.java b/ncomp-openstack-controller/src/main/java/org/openecomp/ncomp/servers/openstack/loc/OsOpenStackLocationProvider.java new file mode 100644 index 0000000..3652555 --- /dev/null +++ b/ncomp-openstack-controller/src/main/java/org/openecomp/ncomp/servers/openstack/loc/OsOpenStackLocationProvider.java @@ -0,0 +1,291 @@ + +/*- + * ============LICENSE_START========================================== + * OPENECOMP - DCAE + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property. All rights reserved. + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + */ + +package org.openecomp.ncomp.servers.openstack.loc; + +import org.apache.log4j.Logger; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.util.EcoreUtil; + +import org.openecomp.ncomp.core.User; +import org.openecomp.ncomp.openstack.OpenStackController; +import org.openecomp.ncomp.openstack.ceilometer.CeilometerAlarm; +import org.openecomp.ncomp.openstack.ceilometer.CeilometerSample; +import org.openecomp.ncomp.openstack.ceilometer.CreateAlarmRequest; +import org.openecomp.ncomp.openstack.ceilometer.SampleRequest; +import org.openecomp.ncomp.openstack.compute.ComputeFactory; +import org.openecomp.ncomp.openstack.compute.OpenstackRequestFlavor; +import org.openecomp.ncomp.openstack.compute.OpenstackRequestKeyPair; +import org.openecomp.ncomp.openstack.compute.OpenstackRequestNewServer; +import org.openecomp.ncomp.openstack.compute.OpenstackRequestSecurityGroup; +import org.openecomp.ncomp.openstack.compute.OpenstackRequestServerAction; +import org.openecomp.ncomp.openstack.controller.tools.OpenStackUtil; +import org.openecomp.ncomp.openstack.controller.tools.OpenStackUtil.OpenStackControllerProject; +import org.openecomp.ncomp.openstack.core.CoreFactory; +import org.openecomp.ncomp.openstack.core.OpenstackRequestDelete; +import org.openecomp.ncomp.openstack.core.VirtualMachineType; +import org.openecomp.ncomp.openstack.location.OpenStackLocation; +import org.openecomp.ncomp.openstack.neutron.CreateRouterRequest; +import org.openecomp.ncomp.openstack.neutron.CreateSubnetRequest; +import org.openecomp.ncomp.openstack.neutron.CreatePortRequest; +import org.openecomp.ncomp.openstack.neutron.Network; +import org.openecomp.ncomp.openstack.neutron.NeutronObject; +import org.openecomp.ncomp.openstack.neutron.NeutronRequest; +import org.openecomp.ncomp.openstack.neutron.Router; +import org.openecomp.ncomp.openstack.neutron.Subnet; +import org.openecomp.ncomp.openstack.neutron.Port; +import org.openecomp.ncomp.servers.openstack.OsOpenStackController; +import org.openecomp.ncomp.servers.openstack.OsOpenStackControllerProvider; +import org.openecomp.ncomp.sirius.manager.BasicAdaptorProvider; +import org.openecomp.ncomp.sirius.manager.ISiriusPlugin; +import org.openecomp.ncomp.sirius.manager.ISiriusServer; +import org.openecomp.ncomp.sirius.manager.ManagementServer; +import org.openecomp.ncomp.sirius.manager.Subject; +import org.openecomp.ncomp.sirius.manager.server.Response; +import org.openecomp.ncomp.sirius.manager.server.ServerPackage; + +public class OsOpenStackLocationProvider extends BasicAdaptorProvider implements ISiriusPlugin { + public static final Logger logger = Logger.getLogger(OsOpenStackLocationProvider.class); + OpenStackUtil util; + private OpenStackLocation o; + + public OsOpenStackLocationProvider(ISiriusServer controller, OpenStackLocation o) { + super(controller, o); + this.o = o; + } + + public Network createNetwork(org.openecomp.ncomp.openstack.neutron.CreateNetworkRequest request) { + return (Network) handleNeutronRequest(request); + } + + public void createServer(OpenstackRequestNewServer request) { + initUtil(); + util.createServer(request); + } + + public Subnet createSubnet(CreateSubnetRequest request) { + initUtil(); + return (Subnet) handleNeutronRequest(request); + } + + public Port createPort(CreatePortRequest request) { + initUtil(); + return (Port) handleNeutronRequest(request); + } + + public void poll() { + initUtil(); + // TODO implement poll + // o.poll(); + } + + @Override + public void start() { + // TODO Auto-generated method stub + + } + + private void initUtil() { + if (util == null) { + OsOpenStackController c = (OsOpenStackController) o.eContainer(); + util = c.controller.getUtil(o.getName()); + } + if (util == null) { + throw new RuntimeException("Unable to create Openstack Util"); + } + } + + private NeutronObject handleNeutronRequest(NeutronRequest request) { + initUtil(); + OpenStackControllerProject p = util.findProject(request.getProjectName()); + if (p == null) { + throw new RuntimeException("unable to find project: " + request.getProjectName()); + } + return p.create(request); + } + + public void deleteNetwork(String projectName, String name) { + initUtil(); + OpenStackControllerProject p = util.findProject(projectName); + if (p == null) { + logger.warn("unable to find project: " + projectName + " " + name); + return; + } + p.deleteNeutron("network", name); + } + + public void deleteSubnet(String projectName, String name) { + initUtil(); + OpenStackControllerProject p = util.findProject(projectName); + if (p == null) { + logger.warn("unable to find project: " + projectName); + return; + } + p.deleteNeutron("subnet", name); + } + + public void deleteServer(String projectName, String name) { + initUtil(); + util.delete(projectName, "server", name); + } + + public void associateFloatingIp(String projectName, String ipId, String portId) { + initUtil(); + OpenStackControllerProject p = util.findProject(projectName); + if (p == null) { + logger.warn("unable to find project: " + projectName); + return; + } + p.associateFloatingIp(ipId, portId); + } + + public CeilometerAlarm createAlarm(CreateAlarmRequest request) { + throw new UnsupportedOperationException(); + } + + public void deleteAlarm(String projectName, String name) { + throw new UnsupportedOperationException(); + } + + public EList<CeilometerSample> createAlarm(SampleRequest request) { + throw new UnsupportedOperationException(); + } + + public static void ecoreSetup() { + ServerPackage.eINSTANCE.getClass(); + } + + public void createKeyPair(OpenstackRequestKeyPair request) { + initUtil(); + util.createKeypair(request.getProjectName(), request.getUser()); + } + + public void delete(OpenstackRequestDelete request) { + initUtil(); + util.delete(request.getProjectName(), request.getObjectType(), request.getObjectName()); + } + + public void createFlavor(OpenstackRequestFlavor request) { + initUtil(); + util.createFlavor(request.getProjectName(), request.getVmType()); + } + + public void createSecurityGroup(OpenstackRequestSecurityGroup request) { + initUtil(); + util.createSecurityGroup(request.getProjectName(), request.getVmType()); + } + + public void serverAction(OpenstackRequestServerAction request) { + initUtil(); + util.serverAction(request); + } + + public void deployVmType(String vmTypeName, String projectName) { + OpenstackRequestSecurityGroup req2 = ComputeFactory.eINSTANCE.createOpenstackRequestSecurityGroup(); + req2.setProjectName(projectName); + req2.setVmType(EcoreUtil.copy(findVmType(vmTypeName))); + o.createSecurityGroup(req2); + if (o.isAllowCreateFlavor()) { + OpenstackRequestFlavor req = ComputeFactory.eINSTANCE.createOpenstackRequestFlavor(); + req.setProjectName(projectName); + req.setVmType(EcoreUtil.copy(findVmType(vmTypeName))); + o.createFlavor(req); + } + } + + private VirtualMachineType findVmType(String name) { + OpenStackController c = (OpenStackController) o.eContainer(); + for (VirtualMachineType v : c.getVmTypes()) { + if (v.getName().equals(name)) return v; + } + throw new RuntimeException("Not VmType with name: " + name); + } + + public void undeployVmType(String vmTypeName, String projectName) { + OpenstackRequestDelete req1 = CoreFactory.eINSTANCE.createOpenstackRequestDelete(); + req1.setProjectName(projectName); + req1.setObjectType("flavor"); + req1.setObjectName(vmTypeName); + o.delete(req1); + req1.setObjectType("security_group"); + o.delete(req1); + } + + public void deployUser(User user, String projectName) { + OpenstackRequestKeyPair req = ComputeFactory.eINSTANCE.createOpenstackRequestKeyPair(); + if (user == null) + throw new RuntimeException("Null user"); + req.setProjectName(projectName); + req.setUser(EcoreUtil.copy(user)); + o.createKeyPair(req); + } + + public void undeployUser(User user, String projectName) { + OpenstackRequestDelete req1 = CoreFactory.eINSTANCE.createOpenstackRequestDelete(); + if (user == null) + throw new RuntimeException("Null user"); + req1.setProjectName(projectName); + req1.setObjectType("keypair"); + req1.setObjectName(user.getName()); + o.delete(req1); + } + + @SuppressWarnings("unused") + private User findUser(String userPath) { + Subject s = controller.getServer().find(userPath); + if (s == null || s.o == null || ! (s instanceof User)) + throw new RuntimeException("Unable to find user: " + userPath); + return (User) s.o; + } + + public void mergeLocation(OpenStackLocation loc) { + ManagementServer.merge(o, loc, null, true, null); + } + + public void deletePort(String projectName, String name) { + initUtil(); + OpenStackControllerProject p = util.findProject(projectName); + if (p == null) { + logger.warn("unable to find project: " + projectName + " " + name); + return; + } + p.deleteNeutron("port", name); + + } + + public Router createRouter(CreateRouterRequest request) { + initUtil(); + return (Router) handleNeutronRequest(request); + } + + public void deleteRouter(String projectName, String name) { + initUtil(); + OpenStackControllerProject p = util.findProject(projectName); + if (p == null) { + logger.warn("unable to find project: " + projectName + " " + name); + return; + } + p.deleteNeutron("router", name); + + + } +} |