github.com/vmware/govmomi@v0.43.0/vapi/cluster/simulator/simulator.go (about) 1 /* 2 Copyright (c) 2020 VMware, Inc. All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package simulator 18 19 import ( 20 "context" 21 "net/http" 22 "net/url" 23 "path" 24 25 "github.com/google/uuid" 26 27 "github.com/vmware/govmomi" 28 "github.com/vmware/govmomi/simulator" 29 "github.com/vmware/govmomi/vapi/rest" 30 vapi "github.com/vmware/govmomi/vapi/simulator" 31 "github.com/vmware/govmomi/vim25/types" 32 33 "github.com/vmware/govmomi/vapi/cluster" 34 "github.com/vmware/govmomi/vapi/cluster/internal" 35 ) 36 37 func init() { 38 simulator.RegisterEndpoint(func(s *simulator.Service, r *simulator.Registry) { 39 New(s.Listen).Register(s, r) 40 }) 41 } 42 43 type module struct { 44 cluster.ModuleSummary 45 members map[string]bool 46 } 47 48 // Handler implements the Cluster Modules API simulator 49 type Handler struct { 50 Modules map[string]module 51 URL *url.URL 52 } 53 54 // New creates a Handler instance 55 func New(u *url.URL) *Handler { 56 return &Handler{ 57 Modules: make(map[string]module), 58 URL: u, 59 } 60 } 61 62 // Register Cluster Modules API paths with the vapi simulator's http.ServeMux 63 func (h *Handler) Register(s *simulator.Service, r *simulator.Registry) { 64 if r.IsVPX() { 65 s.HandleFunc(rest.Path+internal.ModulesPath, h.modules) 66 s.HandleFunc(rest.Path+internal.ModulesPath+"/", h.modules) 67 s.HandleFunc(rest.Path+internal.ModulesVMPath+"/", h.modulesVM) 68 } 69 } 70 71 func (h *Handler) modules(w http.ResponseWriter, r *http.Request) { 72 switch r.Method { 73 case http.MethodGet: 74 var modules cluster.ModuleSummaryList 75 for _, s := range h.Modules { 76 modules.Summaries = append(modules.Summaries, s.ModuleSummary) 77 } 78 vapi.OK(w, modules) 79 case http.MethodPost: 80 var m internal.CreateModule 81 if vapi.Decode(r, w, &m) { 82 ref := types.ManagedObjectReference{Type: "ClusterComputeResource", Value: m.Spec.ID} 83 if simulator.Map.Get(ref) == nil { 84 vapi.BadRequest(w, "com.vmware.vapi.std.errors.invalid_argument") 85 return 86 } 87 88 id := uuid.New().String() 89 h.Modules[id] = module{ 90 cluster.ModuleSummary{ 91 Cluster: m.Spec.ID, 92 Module: id, 93 }, 94 make(map[string]bool), 95 } 96 vapi.OK(w, id) 97 } 98 case http.MethodDelete: 99 id := path.Base(r.URL.Path) 100 _, ok := h.Modules[id] 101 if !ok { 102 http.NotFound(w, r) 103 return 104 } 105 delete(h.Modules, id) 106 vapi.OK(w) 107 } 108 } 109 110 func (*Handler) action(r *http.Request) string { 111 return r.URL.Query().Get("action") 112 } 113 114 func (h *Handler) addMembers(members internal.ModuleMembers, m module) bool { 115 cluster := types.ManagedObjectReference{Type: "ClusterComputeResource", Value: m.Cluster} 116 c, err := govmomi.NewClient(context.Background(), h.URL, true) 117 if err != nil { 118 panic(err) 119 } 120 vms, err := internal.ClusterVM(c.Client, cluster) 121 if err != nil { 122 panic(err) 123 } 124 _ = c.Logout(context.Background()) 125 126 validVM := func(id string) bool { 127 for i := range vms { 128 if vms[i].Reference().Value == id { 129 return true 130 } 131 } 132 return false 133 } 134 135 for _, id := range members.VMs { 136 if m.members[id] { 137 return false 138 } 139 if !validVM(id) { 140 return false 141 } 142 m.members[id] = true 143 } 144 return true 145 } 146 147 func (h *Handler) removeMembers(members internal.ModuleMembers, m module) bool { 148 for _, id := range members.VMs { 149 if !m.members[id] { 150 return false 151 } 152 delete(m.members, id) 153 } 154 return true 155 } 156 157 func (h *Handler) modulesVM(w http.ResponseWriter, r *http.Request) { 158 p := path.Dir(r.URL.Path) 159 id := path.Base(p) 160 161 m, ok := h.Modules[id] 162 if !ok { 163 http.NotFound(w, r) 164 return 165 } 166 167 switch r.Method { 168 case http.MethodGet: 169 var members internal.ModuleMembers 170 for member := range m.members { 171 members.VMs = append(members.VMs, member) 172 } 173 vapi.OK(w, members) 174 case http.MethodPost: 175 action := h.addMembers 176 177 switch h.action(r) { 178 case "add": 179 case "remove": 180 action = h.removeMembers 181 default: 182 http.NotFound(w, r) 183 return 184 } 185 186 var status internal.Status 187 var members internal.ModuleMembers 188 if vapi.Decode(r, w, &members) { 189 status.Success = action(members, m) 190 vapi.OK(w, status) 191 } 192 } 193 }