Browse Source

[DM] Changing the deployment implementation to openstack4j

 * Use openstack4j library instead of raw HTTP requests
 * Added latest openstack4j-3.0.3-SNAPSHOT to dependencies
 * Added re-authentication of openstack4j client
 * Minor code refactoring

Change-Id: I94d7e7d724a117ccfe63fc4aeaf73f1b0ef27870
Nikolay Mahotkin 2 years ago
parent
commit
05ae1e9b2f

+ 7
- 0
.gitignore View File

@@ -0,0 +1,7 @@
1
+*.classpath
2
+*.project
3
+*.iml
4
+*.settings
5
+.idea/
6
+work/
7
+target/

+ 12
- 2
deployment-manager/pom.xml View File

@@ -32,16 +32,26 @@
32 32
             <name>Alexey Khivin</name>
33 33
             <email>akhivin@gmail.com</email>
34 34
         </developer>
35
+        <developer>
36
+            <name>Nikolay Mahotkin</name>
37
+            <email>nmakhotkin@mirantis.com</email>
38
+        </developer>
35 39
     </developers>
36 40
 
37 41
     <properties>
38 42
         <java.level>8</java.level>
39 43
         <jenkins.version>2.23</jenkins.version>
40 44
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
41
-        <openstack4jversion>3.0.2</openstack4jversion>
45
+        <openstack4jversion>3.0.3-SNAPSHOT</openstack4jversion>
46
+        <openstack4jConnectorVersion>3.0.2</openstack4jConnectorVersion>
42 47
     </properties>
43 48
 
44 49
     <repositories>
50
+        <repository>
51
+            <id>st-snapshots</id>
52
+            <name>sonatype-snapshots</name>
53
+            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
54
+        </repository>
45 55
         <repository>
46 56
             <id>repo.jenkins-ci.org</id>
47 57
             <name>Jenkins Repository</name>
@@ -103,7 +113,7 @@
103 113
         <dependency>
104 114
             <groupId>org.pacesys.openstack4j.connectors</groupId>
105 115
             <artifactId>openstack4j-httpclient</artifactId>
106
-            <version>${openstack4jversion}</version>
116
+            <version>${openstack4jConnectorVersion}</version>
107 117
         </dependency>
108 118
 
109 119
         <dependency>

+ 65
- 238
deployment-manager/src/main/java/org/openstack/murano/jenkins_plugins/muranoci/deploy/MuranoHelper.java View File

@@ -1,32 +1,21 @@
1 1
 package org.openstack.murano.jenkins_plugins.muranoci.deploy;
2 2
 
3 3
 
4
-import org.apache.http.client.methods.CloseableHttpResponse;
5
-import org.json.simple.JSONArray;
6
-import org.json.simple.JSONObject;
7
-import org.json.simple.parser.JSONParser;
8
-import org.json.simple.parser.ParseException;
9 4
 import org.kohsuke.stapler.DataBoundConstructor;
5
+import org.openstack4j.api.Builders;
10 6
 import org.openstack4j.api.OSClient;
11 7
 import org.openstack4j.api.exceptions.AuthenticationException;
12
-import org.openstack4j.connectors.httpclient.HttpCommand;
13
-import org.openstack4j.core.transport.HttpMethod;
14
-import org.openstack4j.core.transport.HttpRequest;
8
+import org.openstack4j.model.murano.v1.domain.AppCatalogSession;
9
+import org.openstack4j.model.murano.v1.domain.Deployment;
10
+import org.openstack4j.model.murano.v1.domain.Environment;
15 11
 import org.openstack4j.openstack.OSFactory;
16 12
 
17
-import java.io.BufferedReader;
18
-import java.io.InputStreamReader;
19 13
 import java.time.Instant;
14
+import java.util.Date;
15
+import java.util.List;
20 16
 import java.util.concurrent.TimeoutException;
21
-import java.util.logging.Level;
22
-import java.util.logging.LogRecord;
23
-import java.util.logging.Logger;
24 17
 
25 18
 public class MuranoHelper {
26
-    public static final int MURANO_DEFAULT_PORT = 8082;
27
-
28
-    private final static Logger LOG = Logger.getLogger(MuranoHelper.class.getName());
29
-
30 19
     private OSClient.OSClientV2 os = null;
31 20
 
32 21
     /**
@@ -69,6 +58,10 @@ public class MuranoHelper {
69 58
     }
70 59
 
71 60
 
61
+    public boolean deployEnvAndWait(String envName, String objectModel) throws TimeoutException {
62
+        Environment env = deployNewFromObjectModel(envName, objectModel);
63
+        return waitDeploymentResult(env);
64
+    }
72 65
     /**
73 66
      *
74 67
      * @param name New environment name
@@ -76,29 +69,28 @@ public class MuranoHelper {
76 69
      * @return new environment id
77 70
      * @throws AuthenticationException in case credentials
78 71
      */
79
-    public String deployNewFromObjectModel(String name, String objectModel)
72
+    Environment deployNewFromObjectModel(String name, String objectModel)
80 73
             throws AuthenticationException {
81
-
82 74
         this.authenticate();
83 75
 
84
-        String token = getOSClient().getAccess().getToken().getId();
76
+        Environment env = checkIfDeploymentExists(name);
85 77
 
86
-        String envId = checkIfDeploymentExists(token, name);
87
-        if (envId == null) {
78
+        if (env == null) {
88 79
             // Create Env
89
-            envId = this.createEnvironment(token, name);
90
-
91
-            // Create Session
92
-            String sessionId = this.createEnvironmentSession(token, envId);
80
+            env = getOSClient().murano().environments().create(
81
+                    Builders.environment().name(name).build()
82
+            );
83
+        }
84
+        // Create Session
85
+        AppCatalogSession session = getOSClient().murano().sessions().configure(env.getId());
93 86
 
94
-            // Add App to Environment
95
-            addApplicationToEnvironment(token, envId, sessionId, objectModel);
87
+        // Add App to Environment
88
+        getOSClient().murano().services().create(env.getId(), session.getId(), objectModel);
96 89
 
97
-            // Deploy
98
-            deployEnvironment(token, envId, sessionId);
99
-        }
90
+        // Deploy
91
+        getOSClient().murano().sessions().deploy(env.getId(), session.getId());
100 92
 
101
-        return envId;
93
+        return env;
102 94
     }
103 95
 
104 96
 
@@ -106,234 +98,59 @@ public class MuranoHelper {
106 98
      * Loop around to see if the deployment is a success. This waits for about 10 secs 300 times hoping that
107 99
      * it finishes. This all depends on teh number of nodes and the speed of the boxes. But seems sufficient.
108 100
      *
109
-     * @param envId Environemnt Id
101
+     * @param env Environemnt instance
110 102
      * @return whether the deployment is a success
111 103
      * @throws TimeoutException if deployment process still in progress after deadline
112 104
      */
113
-    public boolean waitDeploymentResult(String envId) throws TimeoutException {
114
-        String token = getOSClient().getAccess().getToken().getId();
115
-
105
+    boolean waitDeploymentResult(Environment env) throws TimeoutException {
116 106
         boolean status = false;
107
+        boolean isTimedOut = false;
117 108
         Instant deadline = Instant.now().plusMillis(timeout);
118 109
 
119
-        while(true) {
120
-            try {
121
-                Thread.sleep(10000);
122
-                String payload = getResponseForJson(
123
-                        getMuranoEnpoint(),
124
-                        MURANO_DEFAULT_PORT,
125
-                        "/v1/environments/" + envId + "/deployments",
126
-                        HttpMethod.GET,
127
-                        token,
128
-                        null,
129
-                        null);
130
-                JSONParser parser = new JSONParser();
131
-                try {
132
-                    JSONObject deployments = (JSONObject) parser.parse(payload);
133
-                    JSONArray deploymentList = (JSONArray) deployments.get("deployments");
134
-                    JSONObject thisDeployment = (JSONObject) deploymentList.get(0);
135
-                    if ("success".equals(thisDeployment.get("state"))) {
136
-                        status = true;
137
-                        break;
138
-                    }
139
-                } catch (ParseException pe) {
140
-                }
141
-            } catch (Exception ex) {
142
-                status = false;
143
-                break;
144
-            }
110
+        Deployment deployment;
111
+
112
+        while(!isTimedOut) {
145 113
             if (Instant.now().isAfter(deadline)){
146
-                throw new TimeoutException("Environment was not ready in time.");
114
+                isTimedOut = true;
147 115
             }
148 116
 
149
-        }
150
-        return status;
151
-    }
117
+            deployment = getOSClient().murano().deployments().list(env.getId()).get(0);
118
+            String state = deployment.getState();
152 119
 
153
-    /**
154
-     * Return the Environment id if it exists
155
-     *
156
-     * @param token
157
-     * @param name
158
-     * @return
159
-     */
160
-    private String checkIfDeploymentExists(String token, String name) {
161
-        // TODO: remove string manipulation
162
-        String payload = getResponseForJson(
163
-                getMuranoEnpoint(),
164
-                MURANO_DEFAULT_PORT,
165
-                "/v1/environments",
166
-                HttpMethod.GET,
167
-                token,
168
-                null,
169
-                null);
170
-        String envId = null;
171
-        JSONParser parser = new JSONParser();
172
-        try{
173
-            Object obj = parser.parse(payload);
174
-            JSONObject response = (JSONObject)obj;
175
-            JSONArray environmentArray =  (JSONArray) response.get("environments");
176
-            for (Object env: environmentArray) {
177
-                JSONObject thisEnv = (JSONObject) env;
178
-                String envName = (String) thisEnv.get("name");
179
-                if (envName.equals(name)) {
180
-                    envId = (String) thisEnv.get("id");
181
-                    break;
182
-                }
120
+            if (!state.equals("running")) {
121
+                status = state.equals("success");
122
+                break;
123
+            }
124
+            try {
125
+                Thread.sleep(10000);
126
+            } catch (InterruptedException e) {
127
+                e.printStackTrace();
183 128
             }
184
-        }catch(ParseException pe){
185
-            LogRecord logRecord = new LogRecord(Level.WARNING, "Parse exception: position: " + pe.getPosition());
186
-            logRecord.setThrown(pe);
187
-            LOG.log(logRecord);
188
-        }
189
-        return envId;
190
-    }
191
-
192
-    /**
193
-     * Deploy the environment given the environment id and Session Token
194
-     */
195
-    private void deployEnvironment(String token, String envId, String sessionId) {
196
-        String response = getResponseForJson(
197
-                getMuranoEnpoint(),
198
-                MURANO_DEFAULT_PORT,
199
-                "/v1/environments/" + envId + "/sessions/" + sessionId + "/deploy",
200
-                HttpMethod.POST,
201
-                token,
202
-                null,
203
-                null);
204
-    }
205
-
206
-
207
-    public String getMuranoEnpoint() {
208
-        /*
209
-         * TODO: This is temporary decision. Murano URL should be obtained from Keystone
210
-         */
211
-        String string[] = this.serverUrl.split(":");
212
-
213
-        return string[0] + ":" + string[1];
214
-    }
215
-
216
-    /**
217
-     * Add the app(K8S) to the environment
218
-     * @param token
219
-     * @param envId
220
-     * @param sessionId
221
-     * @param jsonReq
222
-     */
223
-    private void addApplicationToEnvironment(String token, String envId, String sessionId, String jsonReq) {
224
-        String response = getResponseForJson(this.getMuranoEnpoint(),
225
-                MURANO_DEFAULT_PORT,
226
-                "/v1/environments/" + envId + "/services",
227
-                HttpMethod.POST,
228
-                token,
229
-                jsonReq,
230
-                sessionId);
231
-    }
232
-
233
-    private String createEnvironmentSession(String token, String envId) {
234
-        String payload = getResponseForJson(this.getMuranoEnpoint(),
235
-                MURANO_DEFAULT_PORT,
236
-                "/v1/environments/" + envId + "/configure",
237
-                HttpMethod.POST,
238
-                token,
239
-                null,
240
-                null);
241
-
242
-        String sessionId = "";
243
-        JSONParser parser = new JSONParser();
244
-        try{
245
-            Object obj = parser.parse(payload);
246
-            JSONObject response = (JSONObject)obj;
247
-            sessionId = (String)response.get("id");
248
-        }catch(ParseException pe){
249
-            System.out.println("position: " + pe.getPosition());
250
-            System.out.println(pe);
251 129
         }
252
-        return sessionId;
253
-    }
254 130
 
255
-    private String createEnvironment(String token, String envname) {
256
-        String reqPayload = "{\"name\":\"" + envname + "\"}";
257
-        String payload = getResponseForJson(
258
-                getMuranoEnpoint(),
259
-                MURANO_DEFAULT_PORT,
260
-                "/v1/environments",
261
-                HttpMethod.POST, token, reqPayload, null);
262
-
263
-        String envId = "";
264
-        JSONParser parser = new JSONParser();
265
-        try{
266
-            Object obj = parser.parse(payload);
267
-            JSONObject response = (JSONObject)obj;
268
-            envId = (String)response.get("id");
269
-        }catch(ParseException pe){
270
-            System.out.println("position: " + pe.getPosition());
271
-            System.out.println(pe);
131
+        if (isTimedOut) {
132
+            throw new TimeoutException("Timed out. Environment is not ready in time.");
272 133
         }
273 134
 
274
-        return envId;
135
+        return status;
275 136
     }
276 137
 
277 138
     /**
278
-     * Main helper method to call the Murano API and return the response. Accepts both GET and POST.
139
+     * Return the Environment if it exists else null
279 140
      *
280
-     * @param url Base URL to connect
281
-     * @param port Which port is murano listening on
282
-     * @param requestPath Path on Murano URL
283
-     * @param method GET or POST
284
-     * @param token Auth Token
285
-     * @param jsonPayload Payload for the message
286
-     * @param muranoSessionId Optional Session Id
287
-     * @return Response from the Call
141
+     * @param name Environment name
142
+     * @return Environment instance or null
288 143
      */
289
-    private  String getResponseForJson(String url,
290
-                                       int port,
291
-                                       String requestPath,
292
-                                       HttpMethod method,
293
-                                       String token,
294
-                                       String jsonPayload,
295
-                                       String muranoSessionId) {
296
-        HttpRequest request = HttpRequest.builder().method(method)
297
-                .endpoint(url + ":" + port)
298
-                .path(requestPath)
299
-                .header("X-Auth-Token", token)
300
-                .json(jsonPayload)
301
-                .build();
302
-        if (muranoSessionId != null) {
303
-            request.getHeaders().put("X-Configuration-Session", muranoSessionId);
304
-        }
305
-        if (jsonPayload != null) {
306
-            request = request.toBuilder().json(jsonPayload).build();
307
-        }
308
-
309
-        HttpCommand command = HttpCommand.create(request);
310
-        CloseableHttpResponse response = null;
311
-        try {
312
-            response = command.execute();
313
-        } catch(Exception ex) {
314
-            ex.printStackTrace();
315
-            return null;
316
-        }
317
-
318
-        StringBuffer jsonString = new StringBuffer();
319
-        try {
320
-            BufferedReader br = new BufferedReader(new InputStreamReader(
321
-                    response.getEntity().getContent()));
144
+    private Environment checkIfDeploymentExists(String name) {
145
+        return getEnvByName(name);
146
+    }
322 147
 
323
-            //Print the raw output of murano api from the server
324
-            String output;
148
+    private Environment getEnvByName(String name) {
149
+        List<? extends Environment> envs = getOSClient().murano().environments().list();
325 150
 
326
-            while ((output = br.readLine()) != null) {
327
-                jsonString.append(output + "\n");
328
-            }
329
-        } catch(Exception ex) {
330
-            return null;
331
-        }
332
-
333
-        return jsonString.toString();
151
+        return envs.stream().filter(e -> e.getName().equals(name)).findFirst().orElse(null);
334 152
     }
335 153
 
336
-
337 154
     /**
338 155
      * Authenticate to the Openstack instance given the credentials in constructor
339 156
      *
@@ -347,13 +164,23 @@ public class MuranoHelper {
347 164
                 .authenticate();
348 165
     }
349 166
 
167
+    private boolean isTokenExpiring() {
168
+        long oneMinute = 60000;
169
+        Date muniteInFuture = new Date(Date.from(Instant.now()).getTime() + oneMinute);
170
+
171
+        return os.getAccess().getToken().getExpires().before(muniteInFuture);
172
+    }
350 173
 
351 174
     /**
352 175
      * Helper object to return the OSClient
353 176
      * @return OSClient V2
354 177
      */
355
-    public OSClient.OSClientV2 getOSClient() {
356
-       return this.os;
178
+    private OSClient.OSClientV2 getOSClient() {
179
+        if (this.os == null || isTokenExpiring()) {
180
+            authenticate();
181
+        }
182
+
183
+        return this.os;
357 184
     }
358 185
 
359 186
     public void setTimeout(int timeout) {

+ 4
- 6
deployment-manager/src/main/java/org/openstack/murano/jenkins_plugins/muranoci/deploy/MuranoManagerBuildWrapper.java View File

@@ -81,11 +81,9 @@ public class MuranoManagerBuildWrapper extends BuildWrapper implements Serializa
81 81
 
82 82
             String name = generateEnvName();
83 83
 
84
-            String envId = helper.deployNewFromObjectModel(
85
-                    name, deployment.getObjectModel());
84
+            boolean result = helper.deployEnvAndWait(name, deployment.getObjectModel());
86 85
 
87
-            boolean result = helper.waitDeploymentResult(envId);
88
-            if (!result){
86
+            if (!result) {
89 87
                 build.setResult(Result.FAILURE);
90 88
             }
91 89
         } catch (Exception e) {
@@ -99,8 +97,8 @@ public class MuranoManagerBuildWrapper extends BuildWrapper implements Serializa
99 97
     private String generateEnvName() {
100 98
         return MURANO_ENV_NAME + new BigInteger(
101 99
                 32,
102
-                new SecureRandom())
103
-                .toString(16);
100
+                new SecureRandom()
101
+        ).toString(16);
104 102
     }
105 103
 
106 104
     private OpenstackCredentials getOpenstackCredentials(String credentialsId) {

+ 2
- 2
deployment-manager/src/main/java/org/openstack/murano/jenkins_plugins/muranoci/deploy/credentials/OpenstackCredentialsImpl.java View File

@@ -79,14 +79,14 @@ public class OpenstackCredentialsImpl extends BaseStandardCredentials implements
79 79
                                                @QueryParameter("password") final String password)
80 80
                 throws IOException, ServletException {
81 81
 
82
-            MuranoHelper client = new MuranoHelper(
82
+            MuranoHelper helper = new MuranoHelper(
83 83
                     identityServiceEndpoint,
84 84
                     username,
85 85
                     password,
86 86
                     tenant);
87 87
 
88 88
             try {
89
-                client.authenticate();
89
+                helper.authenticate();
90 90
             } catch (AuthenticationException ae) {
91 91
                 return FormValidation.error(
92 92
                         "Unable to connect to server. Please check credentials");

Loading…
Cancel
Save