github.com/vmware/govmomi@v0.51.0/pbm/client.go (about) 1 // © Broadcom. All Rights Reserved. 2 // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 3 // SPDX-License-Identifier: Apache-2.0 4 5 package pbm 6 7 import ( 8 "context" 9 "fmt" 10 11 "github.com/vmware/govmomi/pbm/methods" 12 "github.com/vmware/govmomi/pbm/types" 13 "github.com/vmware/govmomi/vim25" 14 "github.com/vmware/govmomi/vim25/soap" 15 vim "github.com/vmware/govmomi/vim25/types" 16 ) 17 18 const ( 19 Namespace = "pbm" 20 Path = "/pbm" 21 ) 22 23 var ( 24 ServiceInstance = vim.ManagedObjectReference{ 25 Type: "PbmServiceInstance", 26 Value: "ServiceInstance", 27 } 28 ) 29 30 type Client struct { 31 *soap.Client 32 33 ServiceContent types.PbmServiceInstanceContent 34 35 RoundTripper soap.RoundTripper 36 } 37 38 func NewClient(ctx context.Context, c *vim25.Client) (*Client, error) { 39 sc := c.Client.NewServiceClient(Path, Namespace) 40 sc.Cookie = c.SessionCookie // vcSessionCookie soap.Header, value must be from vim25.Client 41 42 req := types.PbmRetrieveServiceContent{ 43 This: ServiceInstance, 44 } 45 46 res, err := methods.PbmRetrieveServiceContent(ctx, sc, &req) 47 if err != nil { 48 return nil, err 49 } 50 51 return &Client{sc, res.Returnval, sc}, nil 52 } 53 54 // RoundTrip dispatches to the RoundTripper field. 55 func (c *Client) RoundTrip(ctx context.Context, req, res soap.HasFault) error { 56 return c.RoundTripper.RoundTrip(ctx, req, res) 57 } 58 59 func (c *Client) QueryProfile(ctx context.Context, rtype types.PbmProfileResourceType, category string) ([]types.PbmProfileId, error) { 60 req := types.PbmQueryProfile{ 61 This: c.ServiceContent.ProfileManager, 62 ResourceType: rtype, 63 ProfileCategory: category, 64 } 65 66 res, err := methods.PbmQueryProfile(ctx, c, &req) 67 if err != nil { 68 return nil, err 69 } 70 71 return res.Returnval, nil 72 } 73 74 func (c *Client) RetrieveContent(ctx context.Context, ids []types.PbmProfileId) ([]types.BasePbmProfile, error) { 75 req := types.PbmRetrieveContent{ 76 This: c.ServiceContent.ProfileManager, 77 ProfileIds: ids, 78 } 79 80 res, err := methods.PbmRetrieveContent(ctx, c, &req) 81 if err != nil { 82 return nil, err 83 } 84 85 return res.Returnval, nil 86 } 87 88 type PlacementCompatibilityResult []types.PbmPlacementCompatibilityResult 89 90 func (c *Client) CheckRequirements(ctx context.Context, hubs []types.PbmPlacementHub, ref *types.PbmServerObjectRef, preq []types.BasePbmPlacementRequirement) (PlacementCompatibilityResult, error) { 91 req := types.PbmCheckRequirements{ 92 This: c.ServiceContent.PlacementSolver, 93 HubsToSearch: hubs, 94 PlacementSubjectRef: ref, 95 PlacementSubjectRequirement: preq, 96 } 97 98 res, err := methods.PbmCheckRequirements(ctx, c, &req) 99 if err != nil { 100 return nil, err 101 } 102 103 return res.Returnval, nil 104 } 105 106 func (l PlacementCompatibilityResult) CompatibleDatastores() []types.PbmPlacementHub { 107 var compatibleDatastores []types.PbmPlacementHub 108 109 for _, res := range l { 110 if len(res.Error) == 0 { 111 compatibleDatastores = append(compatibleDatastores, res.Hub) 112 } 113 } 114 return compatibleDatastores 115 } 116 117 func (l PlacementCompatibilityResult) NonCompatibleDatastores() []types.PbmPlacementHub { 118 var nonCompatibleDatastores []types.PbmPlacementHub 119 120 for _, res := range l { 121 if len(res.Error) > 0 { 122 nonCompatibleDatastores = append(nonCompatibleDatastores, res.Hub) 123 } 124 } 125 return nonCompatibleDatastores 126 } 127 128 func (c *Client) CreateProfile(ctx context.Context, capabilityProfileCreateSpec types.PbmCapabilityProfileCreateSpec) (*types.PbmProfileId, error) { 129 req := types.PbmCreate{ 130 This: c.ServiceContent.ProfileManager, 131 CreateSpec: capabilityProfileCreateSpec, 132 } 133 134 res, err := methods.PbmCreate(ctx, c, &req) 135 if err != nil { 136 return nil, err 137 } 138 139 return &res.Returnval, nil 140 } 141 142 func (c *Client) UpdateProfile(ctx context.Context, id types.PbmProfileId, updateSpec types.PbmCapabilityProfileUpdateSpec) error { 143 req := types.PbmUpdate{ 144 This: c.ServiceContent.ProfileManager, 145 ProfileId: id, 146 UpdateSpec: updateSpec, 147 } 148 149 _, err := methods.PbmUpdate(ctx, c, &req) 150 if err != nil { 151 return err 152 } 153 154 return nil 155 } 156 157 func (c *Client) DeleteProfile(ctx context.Context, ids []types.PbmProfileId) ([]types.PbmProfileOperationOutcome, error) { 158 req := types.PbmDelete{ 159 This: c.ServiceContent.ProfileManager, 160 ProfileId: ids, 161 } 162 163 res, err := methods.PbmDelete(ctx, c, &req) 164 if err != nil { 165 return nil, err 166 } 167 168 return res.Returnval, nil 169 } 170 171 func (c *Client) QueryAssociatedEntity(ctx context.Context, id types.PbmProfileId, entityType string) ([]types.PbmServerObjectRef, error) { 172 req := types.PbmQueryAssociatedEntity{ 173 This: c.ServiceContent.ProfileManager, 174 Profile: id, 175 EntityType: entityType, 176 } 177 178 res, err := methods.PbmQueryAssociatedEntity(ctx, c, &req) 179 if err != nil { 180 return nil, err 181 } 182 183 return res.Returnval, nil 184 } 185 186 func (c *Client) QueryAssociatedEntities(ctx context.Context, ids []types.PbmProfileId) ([]types.PbmQueryProfileResult, error) { 187 req := types.PbmQueryAssociatedEntities{ 188 This: c.ServiceContent.ProfileManager, 189 Profiles: ids, 190 } 191 192 res, err := methods.PbmQueryAssociatedEntities(ctx, c, &req) 193 if err != nil { 194 return nil, err 195 } 196 197 return res.Returnval, nil 198 } 199 200 func (c *Client) ProfileIDByName(ctx context.Context, profileName string) (string, error) { 201 resourceType := types.PbmProfileResourceType{ 202 ResourceType: string(types.PbmProfileResourceTypeEnumSTORAGE), 203 } 204 category := types.PbmProfileCategoryEnumREQUIREMENT 205 ids, err := c.QueryProfile(ctx, resourceType, string(category)) 206 if err != nil { 207 return "", err 208 } 209 210 profiles, err := c.RetrieveContent(ctx, ids) 211 if err != nil { 212 return "", err 213 } 214 215 for i := range profiles { 216 profile := profiles[i].GetPbmProfile() 217 if profile.Name == profileName { 218 return profile.ProfileId.UniqueId, nil 219 } 220 } 221 return "", fmt.Errorf("no pbm profile found with name: %q", profileName) 222 } 223 224 func (c *Client) FetchCapabilityMetadata(ctx context.Context, rtype *types.PbmProfileResourceType, vendorUuid string) ([]types.PbmCapabilityMetadataPerCategory, error) { 225 req := types.PbmFetchCapabilityMetadata{ 226 This: c.ServiceContent.ProfileManager, 227 ResourceType: rtype, 228 VendorUuid: vendorUuid, 229 } 230 231 res, err := methods.PbmFetchCapabilityMetadata(ctx, c, &req) 232 if err != nil { 233 return nil, err 234 } 235 236 return res.Returnval, nil 237 } 238 239 func (c *Client) FetchComplianceResult(ctx context.Context, entities []types.PbmServerObjectRef) ([]types.PbmComplianceResult, error) { 240 req := types.PbmFetchComplianceResult{ 241 This: c.ServiceContent.ComplianceManager, 242 Entities: entities, 243 } 244 245 res, err := methods.PbmFetchComplianceResult(ctx, c, &req) 246 if err != nil { 247 return nil, err 248 } 249 250 return res.Returnval, nil 251 } 252 253 // GetProfileNameByID gets storage profile name by ID 254 func (c *Client) GetProfileNameByID(ctx context.Context, profileID string) (string, error) { 255 resourceType := types.PbmProfileResourceType{ 256 ResourceType: string(types.PbmProfileResourceTypeEnumSTORAGE), 257 } 258 category := types.PbmProfileCategoryEnumREQUIREMENT 259 ids, err := c.QueryProfile(ctx, resourceType, string(category)) 260 if err != nil { 261 return "", err 262 } 263 264 profiles, err := c.RetrieveContent(ctx, ids) 265 if err != nil { 266 return "", err 267 } 268 269 for i := range profiles { 270 profile := profiles[i].GetPbmProfile() 271 if profile.ProfileId.UniqueId == profileID { 272 return profile.Name, nil 273 } 274 } 275 return "", fmt.Errorf("no pbm profile found with id: %q", profileID) 276 } 277 278 func (c *Client) QueryAssociatedProfile(ctx context.Context, entity types.PbmServerObjectRef) ([]types.PbmProfileId, error) { 279 req := types.PbmQueryAssociatedProfile{ 280 This: c.ServiceContent.ProfileManager, 281 Entity: entity, 282 } 283 284 res, err := methods.PbmQueryAssociatedProfile(ctx, c, &req) 285 if err != nil { 286 return nil, err 287 } 288 289 return res.Returnval, nil 290 } 291 292 func (c *Client) QueryAssociatedProfiles(ctx context.Context, entities []types.PbmServerObjectRef) ([]types.PbmQueryProfileResult, error) { 293 req := types.PbmQueryAssociatedProfiles{ 294 This: c.ServiceContent.ProfileManager, 295 Entities: entities, 296 } 297 298 res, err := methods.PbmQueryAssociatedProfiles(ctx, c, &req) 299 if err != nil { 300 return nil, err 301 } 302 303 return res.Returnval, nil 304 } 305 306 func (c *Client) QueryIOFiltersFromProfileId( 307 ctx context.Context, profileID string) ([]types.PbmProfileToIofilterMap, error) { 308 309 req := types.PbmQueryIOFiltersFromProfileId{ 310 This: c.ServiceContent.ProfileManager, 311 ProfileIds: []types.PbmProfileId{{UniqueId: profileID}}, 312 } 313 res, err := methods.PbmQueryIOFiltersFromProfileId(ctx, c, &req) 314 if err != nil { 315 return nil, err 316 } 317 return res.Returnval, nil 318 } 319 320 func (c *Client) SupportsEncryption( 321 ctx context.Context, profileID string) (bool, error) { 322 323 list, err := c.QueryIOFiltersFromProfileId(ctx, profileID) 324 if err != nil { 325 return false, err 326 } 327 for i := range list { 328 for j := range list[i].Iofilters { 329 f := list[i].Iofilters[j] 330 if f.FilterType == string(types.PbmIofilterInfoFilterTypeENCRYPTION) { 331 return true, nil 332 } 333 } 334 } 335 return false, nil 336 }