11package org.zstack.testlib
22
3- import org.springframework.http.HttpHeaders
4- import org.springframework.http.HttpMethod
3+ import org.springframework.http.HttpEntity
54import org.springframework.http.HttpStatus
6- import org.springframework.http.MediaType
75import org.springframework.http.ResponseEntity
86import org.zstack.sdk.SdnControllerInventory
97import org.zstack.sdnController.h3cVcfc.H3cVcfcCommands
@@ -18,7 +16,6 @@ import org.zstack.sdnController.h3cVcfc.H3cVcfcCommands.GetH3cTenantsRsp
1816import org.zstack.sdnController.h3cVcfc.H3cVcfcCommands.H3cTenantStruct
1917import org.zstack.sdnController.h3cVcfc.H3cVcfcCommands.GetH3cTeamLederIpReply
2018import org.zstack.sdnController.h3cVcfc.H3cVcfcV2Commands
21- import org.springframework.http.HttpEntity
2219import org.zstack.sugonSdnController.controller.SugonSdnControllerConstant
2320import org.zstack.sugonSdnController.controller.api.ApiSerializer
2421import org.zstack.sugonSdnController.controller.api.TfCommands
@@ -28,10 +25,6 @@ import org.zstack.sugonSdnController.controller.api.types.Project
2825import org.zstack.sugonSdnController.controller.api.types.VirtualMachine
2926import org.zstack.sugonSdnController.controller.api.types.VirtualMachineInterface
3027import org.zstack.sugonSdnController.controller.api.types.VirtualNetwork
31- import org.zstack.utils.gson.JSONObjectUtil
32- import org.zstack.network.zns.ZnsSdnControllerConstant
33-
34- import javax.servlet.http.HttpServletRequest
3528
3629/**
3730 * Created by shixin.ruan on 2019/09/26.
@@ -296,178 +289,6 @@ class SdnControllerSpec extends Spec implements HasSession {
296289 ResponseEntity<String > response = new ResponseEntity<String > (json, HttpStatus . OK );
297290 return response. getBody()
298291 }
299-
300- // ===================== ZNS Simulators =====================
301-
302- // Helper: trigger ZNS async callback in a separate thread
303- def triggerZnsCallback = { HttpEntity<String > entity , EnvSpec spec , Object data ->
304- String jobUuid = entity. headers. getFirst(ZnsSdnControllerConstant . ZNS_HEADER_JOB_UUID )
305- String webhook = entity. headers. getFirst(ZnsSdnControllerConstant . ZNS_HEADER_WEBHOOK )
306- List<String > missingHeaders = []
307- if (! jobUuid) {
308- missingHeaders. add(ZnsSdnControllerConstant . ZNS_HEADER_JOB_UUID )
309- }
310- if (! webhook) {
311- missingHeaders. add(ZnsSdnControllerConstant . ZNS_HEADER_WEBHOOK )
312- }
313- if (! missingHeaders. isEmpty()) {
314- throw new IllegalStateException (" Missing required ZNS callback header(s): ${ missingHeaders.join(', ')} " )
315- }
316-
317- Thread . start {
318- Thread . sleep(100 )
319- def cmd = [taskUuid : jobUuid, success : true , status : ZnsSdnControllerConstant . ZNS_CALLBACK_STATUS_COMPLETED , data : data]
320- def headers = new HttpHeaders ()
321- headers. setContentType(MediaType . APPLICATION_JSON )
322- def body = JSONObjectUtil . toJsonString(cmd)
323- headers. set(" commandpath" , " /zns/callback" )
324- spec. restTemplate. exchange(webhook, HttpMethod . POST ,
325- new HttpEntity<String > (body, headers), String . class)
326- }
327- }
328-
329- // GET/DELETE /zns/api/v1/fabric/compute-managers/{uuid}
330- simulator(" /zns/api/v1/fabric/compute-managers/[^/]+" ) { HttpServletRequest req , HttpEntity<String > entity , EnvSpec spec ->
331- if (req. method == " DELETE" ) {
332- triggerZnsCallback(entity, spec, [:])
333- return [:]
334- }
335- return [success : true , data : [uuid : " cm-uuid-1" , name : " cm-1" , connectionStatus : " connected" ]]
336- }
337-
338- // GET /zns/api/v1/fabric/compute-collections
339- simulator(" /zns/api/v1/fabric/compute-collections" ) { HttpServletRequest req , HttpEntity<String > entity , EnvSpec spec ->
340- def c1 = spec. inventoryByName(" cluster-1" )
341- def c2 = spec. inventoryByName(" cluster-2" )
342- return [success : true , data : [
343- [uuid : c1?. uuid ?: " cc-1" , name : " cluster-1" , computeManagerId : " cm-uuid-1" ],
344- [uuid : c2?. uuid ?: " cc-2" , name : " cluster-2" , computeManagerId : " cm-uuid-1" ]
345- ], total : 2 ]
346- }
347-
348- // GET /zns/api/v1/fabric/discovered-nodes
349- simulator(" /zns/api/v1/fabric/discovered-nodes" ) { HttpServletRequest req , HttpEntity<String > entity , EnvSpec spec ->
350- def c1 = spec. inventoryByName(" cluster-1" )
351- return [success : true , data : [
352- [uuid : " dn-1" , name : " kvm-1" , managementIp : " 127.0.0.1" , clusterId : c1?. uuid ?: " cc-1" , transportNodeProfileId : " tnp-dpdk" ],
353- [uuid : " dn-2" , name : " kvm-2" , managementIp : " 127.0.0.2" , clusterId : c1?. uuid ?: " cc-1" , transportNodeProfileId : " tnp-dpdk" ]
354- ], total : 2 ]
355- }
356-
357- // GET /zns/api/v1/fabric/transport-zones
358- simulator(" /zns/api/v1/fabric/transport-zones" ) {
359- return [success : true , data : [
360- [uuid : " tz-1" , name : " tz-overlay" , type : " overlay" ]
361- ], total : 1 ]
362- }
363-
364- // GET /zns/api/v1/fabric/transport-node-profiles/{uuid}
365- simulator(" /zns/api/v1/fabric/transport-node-profiles/[^/]+" ) { HttpServletRequest req , HttpEntity<String > entity , EnvSpec spec ->
366- def uri = req. getRequestURI()
367- def profileUuid = uri. tokenize(" /" ). last()
368- if (profileUuid == " tnp-kernel" ) {
369- return [success : true , data : [uuid : " tnp-kernel" , name : " tnp-kernel" , hostSwitchProfiles : [" hsp-kernel" ]]]
370- }
371- return [success : true , data : [uuid : " tnp-dpdk" , name : " tnp-dpdk" , hostSwitchProfiles : [" hsp-dpdk" ]]]
372- }
373-
374- // GET /zns/api/v1/fabric/host-switch-profiles/{uuid}
375- simulator(" /zns/api/v1/fabric/host-switch-profiles/[^/]+" ) { HttpServletRequest req , HttpEntity<String > entity , EnvSpec spec ->
376- def uri = req. getRequestURI()
377- def hspUuid = uri. tokenize(" /" ). last()
378- if (hspUuid == " hsp-kernel" ) {
379- return [success : true , data : [uuid : " hsp-kernel" , name : " hsp-kernel" , type : " kernel" , switchType : " OVS" , transportZoneIds : [" tz-1" ]]]
380- }
381- return [success : true , data : [uuid : " hsp-dpdk" , name : " hsp-dpdk" , type : " dpdk" , switchType : " OVS" , transportZoneIds : [" tz-1" ]]]
382- }
383-
384- // /zns/api/v1/segments — GET(list) / POST(create) / DELETE(batch)
385- simulator(" /zns/api/v1/segments" ) { HttpServletRequest req , HttpEntity<String > entity , EnvSpec spec ->
386- if (req. method == " GET" ) {
387- return [success : true , data : [
388- [uuid : " zns-sg-1" , name : " sg-1" , transport_type : " overlay" , virtual_network_id : 100 ,
389- transport_zone_uuid : " tz-1" ,
390- cms : [cmsUuid : " cm-uuid-1" , ExternalIds : [:]],
391- ipams : [[ip_cidr : " 10.0.1.0/24" , gateway_ip : " 10.0.1.1" , prefix : 24 ,
392- ip_ranges : [[StartIp : " 10.0.1.10" , EndIp : " 10.0.1.100" ]]]]],
393- [uuid : " zns-sg-2" , name : " sg-2" , transport_type : " overlay" , virtual_network_id : 200 ,
394- transport_zone_uuid : " tz-1" ,
395- cms : [cmsUuid : " cm-uuid-1" , ExternalIds : [:]],
396- ipams : [[ip_cidr : " 10.0.2.0/24" , gateway_ip : " 10.0.2.1" , prefix : 24 ,
397- ip_ranges : [[StartIp : " 10.0.2.10" , EndIp : " 10.0.2.100" ]]]]]
398- ], total : 2 ]
399- }
400- // POST(create) or DELETE(batch) → async callback
401- def data = [uuid : " zns-sg-new" , name : " new-seg" , transport_type : " overlay" ]
402- triggerZnsCallback(entity, spec, data)
403- return [:]
404- }
405-
406- // /zns/api/v1/segments/{uuid} — GET(single) / PATCH(update)
407- simulator(" /zns/api/v1/segments/[^/]+" ) { HttpServletRequest req , HttpEntity<String > entity , EnvSpec spec ->
408- def uri = req. getRequestURI()
409- def segUuid = uri. tokenize(" /" ). last()
410- if (req. method == " GET" ) {
411- return [success : true , data : [uuid : segUuid, name : " seg-" + segUuid, transport_type : " overlay" ]]
412- }
413- // PATCH → async callback
414- def data = [uuid : segUuid, name : " seg-" + segUuid, transport_type : " overlay" ]
415- triggerZnsCallback(entity, spec, data)
416- return [:]
417- }
418-
419- // /zns/api/v1/segments/{uuid}/ports — GET(list) / POST(create) / DELETE(batch)
420- def portIpCounter = new java.util.concurrent.atomic.AtomicInteger (50 )
421- simulator(" /zns/api/v1/segments/[^/]+/ports" ) { HttpServletRequest req , HttpEntity<String > entity , EnvSpec spec ->
422- if (req. method == " GET" ) {
423- return [success : true , data : [], total : 0 ]
424- }
425- // POST(create) or DELETE(batch) → async callback
426- def body = entity. body ? JSONObjectUtil . toMap(entity. body) : [:]
427- def uri = req. getRequestURI()
428- def segParts = uri. split(" /segments/" )
429- def segmentUuid = segParts. length > 1 ? segParts[1 ]. split(" /ports" )[0 ] : " unknown"
430-
431- def data
432- if (req. method == " POST" ) {
433- def allocatedIp = body?. ip ?: (" 10.0.1." + portIpCounter. getAndIncrement())
434- data = [
435- uuid : " zns-port-" + UUID . randomUUID(). toString(). substring(0 , 8 ),
436- segment_uuid : segmentUuid,
437- mac : body?. mac ?: " 00:00:00:00:00:01" ,
438- ip : allocatedIp,
439- vm_uuid : body?. vm_uuid
440- ]
441- } else {
442- data = [:]
443- }
444- triggerZnsCallback(entity, spec, data)
445- return [:]
446- }
447-
448- // /zns/api/v1/segments/{uuid}/ports/{portUuid} — GET / PATCH
449- simulator(" /zns/api/v1/segments/[^/]+/ports/[^/]+" ) { HttpServletRequest req , HttpEntity<String > entity , EnvSpec spec ->
450- def uri = req. getRequestURI()
451- def portUuid = uri. tokenize(" /" ). last()
452- if (req. method == " GET" ) {
453- return [success : true , data : [uuid : portUuid, segment_uuid : " zns-sg-1" ]]
454- }
455- // PATCH → async callback
456- def data = [uuid : portUuid, segment_uuid : " zns-sg-1" ]
457- triggerZnsCallback(entity, spec, data)
458- return [:]
459- }
460-
461- // /zns/api/v1/segments/{uuid}/used-ips — GET
462- simulator(" /zns/api/v1/segments/[^/]+/used-ips" ) {
463- return [success : true , data : [], total : 0 ]
464- }
465-
466- // POST /zns/api/v1/fabric/compute-managers/{uuid}/sync-jobs
467- simulator(" /zns/api/v1/fabric/compute-managers/[^/]+/sync-jobs" ) { HttpServletRequest req , HttpEntity<String > entity , EnvSpec spec ->
468- triggerZnsCallback(entity, spec, [:])
469- return [:]
470- }
471292 }
472293 }
473294
0 commit comments