github.com/vmware/govmomi@v0.51.0/vapi/library/library.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 library 6 7 import ( 8 "context" 9 "fmt" 10 "net/http" 11 "net/url" 12 "time" 13 14 "github.com/vmware/govmomi/object" 15 "github.com/vmware/govmomi/vapi/internal" 16 "github.com/vmware/govmomi/vapi/rest" 17 ) 18 19 // StorageBacking defines a storage location where content in a library will be stored. 20 type StorageBacking struct { 21 DatastoreID string `json:"datastore_id,omitempty"` 22 Type string `json:"type,omitempty"` 23 StorageURI string `json:"storage_uri,omitempty"` 24 } 25 26 // Library provides methods to create, read, update, delete, and enumerate libraries. 27 type Library struct { 28 CreationTime *time.Time `json:"creation_time,omitempty"` 29 Description *string `json:"description,omitempty"` 30 ID string `json:"id,omitempty"` 31 LastModifiedTime *time.Time `json:"last_modified_time,omitempty"` 32 LastSyncTime *time.Time `json:"last_sync_time,omitempty"` 33 Name string `json:"name,omitempty"` 34 Storage []StorageBacking `json:"storage_backings,omitempty"` 35 Type string `json:"type,omitempty"` 36 Version string `json:"version,omitempty"` 37 Subscription *Subscription `json:"subscription_info,omitempty"` 38 Publication *Publication `json:"publish_info,omitempty"` 39 SecurityPolicyID string `json:"security_policy_id,omitempty"` 40 UnsetSecurityPolicyID bool `json:"unset_security_policy_id,omitempty"` 41 ServerGUID string `json:"server_guid,omitempty"` 42 StateInfo *StateInfo `json:"state_info,omitempty"` 43 } 44 45 // StateInfo provides the state info of a content library. 46 type StateInfo struct { 47 State string `json:"state"` 48 } 49 50 // Subscription info 51 type Subscription struct { 52 AuthenticationMethod string `json:"authentication_method"` 53 AutomaticSyncEnabled *bool `json:"automatic_sync_enabled,omitempty"` 54 OnDemand *bool `json:"on_demand,omitempty"` 55 Password string `json:"password,omitempty"` 56 SslThumbprint string `json:"ssl_thumbprint,omitempty"` 57 SubscriptionURL string `json:"subscription_url,omitempty"` 58 UserName string `json:"user_name,omitempty"` 59 } 60 61 // Publication info 62 type Publication struct { 63 AuthenticationMethod string `json:"authentication_method"` 64 UserName string `json:"user_name,omitempty"` 65 Password string `json:"password,omitempty"` 66 CurrentPassword string `json:"current_password,omitempty"` 67 PersistJSON *bool `json:"persist_json_enabled,omitempty"` 68 Published *bool `json:"published,omitempty"` 69 PublishURL string `json:"publish_url,omitempty"` 70 } 71 72 // SubscriberSummary as returned by ListSubscribers 73 type SubscriberSummary struct { 74 LibraryID string `json:"subscribed_library"` 75 LibraryName string `json:"subscribed_library_name"` 76 SubscriptionID string `json:"subscription"` 77 LibraryVcenterHostname string `json:"subscribed_library_vcenter_hostname,omitempty"` 78 } 79 80 // Placement information used to place a virtual machine template 81 type Placement struct { 82 ResourcePool string `json:"resource_pool,omitempty"` 83 Host string `json:"host,omitempty"` 84 Folder string `json:"folder,omitempty"` 85 Cluster string `json:"cluster,omitempty"` 86 Network string `json:"network,omitempty"` 87 } 88 89 // Vcenter contains information about the vCenter Server instance where a subscribed library associated with a subscription exists. 90 type Vcenter struct { 91 Hostname string `json:"hostname"` 92 Port int `json:"https_port,omitempty"` 93 ServerGUID string `json:"server_guid"` 94 } 95 96 // Subscriber contains the detailed info for a library subscriber. 97 type Subscriber struct { 98 LibraryID string `json:"subscribed_library"` 99 LibraryName string `json:"subscribed_library_name"` 100 LibraryLocation string `json:"subscribed_library_location"` 101 Placement *Placement `json:"subscribed_library_placement,omitempty"` 102 Vcenter *Vcenter `json:"subscribed_library_vcenter,omitempty"` 103 } 104 105 // SubscriberLibrary is the specification for a subscribed library to be associated with a subscription. 106 type SubscriberLibrary struct { 107 Target string `json:"target"` 108 LibraryID string `json:"subscribed_library,omitempty"` 109 Location string `json:"location"` 110 Vcenter *Vcenter `json:"vcenter,omitempty"` 111 Placement *Placement `json:"placement,omitempty"` 112 } 113 114 // Patch merges updates from the given src. 115 func (l *Library) Patch(src *Library) { 116 if src.Name != "" { 117 l.Name = src.Name 118 } 119 if src.Description != nil { 120 l.Description = src.Description 121 } 122 if src.Version != "" { 123 l.Version = src.Version 124 } 125 } 126 127 // Manager extends rest.Client, adding content library related methods. 128 type Manager struct { 129 *rest.Client 130 } 131 132 // NewManager creates a new Manager instance with the given client. 133 func NewManager(client *rest.Client) *Manager { 134 return &Manager{ 135 Client: client, 136 } 137 } 138 139 // Find is the search criteria for finding libraries. 140 type Find struct { 141 Name string `json:"name,omitempty"` 142 Type string `json:"type,omitempty"` 143 } 144 145 // FindLibrary returns one or more libraries that match the provided search 146 // criteria. 147 // 148 // The provided name is case-insensitive. 149 // 150 // Either the name or type of library may be set to empty values in order 151 // to search for all libraries, all libraries with a specific name, regardless 152 // of type, or all libraries of a specified type. 153 func (c *Manager) FindLibrary(ctx context.Context, search Find) ([]string, error) { 154 url := c.Resource(internal.LibraryPath).WithAction("find") 155 spec := struct { 156 Spec Find `json:"spec"` 157 }{search} 158 var res []string 159 return res, c.Do(ctx, url.Request(http.MethodPost, spec), &res) 160 } 161 162 // CreateLibrary creates a new library with the given Type, Name, 163 // Description, and CategoryID. 164 func (c *Manager) CreateLibrary(ctx context.Context, library Library) (string, error) { 165 spec := struct { 166 Library Library `json:"create_spec"` 167 }{library} 168 path := internal.LocalLibraryPath 169 if library.Type == "SUBSCRIBED" { 170 path = internal.SubscribedLibraryPath 171 sub := library.Subscription 172 u, err := url.Parse(sub.SubscriptionURL) 173 if err != nil { 174 return "", err 175 } 176 if u.Scheme == "https" && sub.SslThumbprint == "" { 177 thumbprint := c.Thumbprint(u.Host) 178 if thumbprint == "" { 179 t := c.DefaultTransport() 180 if t.TLSClientConfig.InsecureSkipVerify { 181 var info object.HostCertificateInfo 182 _ = info.FromURL(u, t.TLSClientConfig) 183 thumbprint = info.ThumbprintSHA1 184 } 185 sub.SslThumbprint = thumbprint 186 } 187 } 188 } 189 url := c.Resource(path) 190 var res string 191 return res, c.Do(ctx, url.Request(http.MethodPost, spec), &res) 192 } 193 194 // SyncLibrary syncs a subscribed library. 195 func (c *Manager) SyncLibrary(ctx context.Context, library *Library) error { 196 path := internal.SubscribedLibraryPath 197 url := c.Resource(path).WithID(library.ID).WithAction("sync") 198 return c.Do(ctx, url.Request(http.MethodPost), nil) 199 } 200 201 // PublishLibrary publishes the library to specified subscriptions. 202 // If no subscriptions are specified, then publishes the library to all subscriptions. 203 func (c *Manager) PublishLibrary(ctx context.Context, library *Library, subscriptions []string) error { 204 path := internal.LocalLibraryPath 205 var spec internal.SubscriptionDestinationSpec 206 for i := range subscriptions { 207 spec.Subscriptions = append(spec.Subscriptions, internal.SubscriptionDestination{ID: subscriptions[i]}) 208 } 209 url := c.Resource(path).WithID(library.ID).WithAction("publish") 210 return c.Do(ctx, url.Request(http.MethodPost, spec), nil) 211 } 212 213 // UpdateLibrary can update one or both of the tag Description and Name fields. 214 func (c *Manager) UpdateLibrary(ctx context.Context, l *Library) error { 215 spec := struct { 216 Library `json:"update_spec"` 217 }{ 218 Library{ 219 Name: l.Name, 220 Description: l.Description, 221 }, 222 } 223 url := c.Resource(internal.LibraryPath).WithID(l.ID) 224 return c.Do(ctx, url.Request(http.MethodPatch, spec), nil) 225 } 226 227 // DeleteLibrary deletes an existing library. 228 func (c *Manager) DeleteLibrary(ctx context.Context, library *Library) error { 229 path := internal.LocalLibraryPath 230 if library.Type == "SUBSCRIBED" { 231 path = internal.SubscribedLibraryPath 232 } 233 url := c.Resource(path).WithID(library.ID) 234 return c.Do(ctx, url.Request(http.MethodDelete), nil) 235 } 236 237 // ListLibraries returns a list of all content library IDs in the system. 238 func (c *Manager) ListLibraries(ctx context.Context) ([]string, error) { 239 url := c.Resource(internal.LibraryPath) 240 var res []string 241 return res, c.Do(ctx, url.Request(http.MethodGet), &res) 242 } 243 244 // GetLibraryByID returns information on a library for the given ID. 245 func (c *Manager) GetLibraryByID(ctx context.Context, id string) (*Library, error) { 246 url := c.Resource(internal.LibraryPath).WithID(id) 247 var res Library 248 return &res, c.Do(ctx, url.Request(http.MethodGet), &res) 249 } 250 251 // GetLibraryByName returns information on a library for the given name. 252 func (c *Manager) GetLibraryByName(ctx context.Context, name string) (*Library, error) { 253 // Lookup by name 254 libraries, err := c.GetLibraries(ctx) 255 if err != nil { 256 return nil, err 257 } 258 for i := range libraries { 259 if libraries[i].Name == name { 260 return &libraries[i], nil 261 } 262 } 263 return nil, fmt.Errorf("library name (%s) not found", name) 264 } 265 266 // GetLibraries returns a list of all content library details in the system. 267 func (c *Manager) GetLibraries(ctx context.Context) ([]Library, error) { 268 ids, err := c.ListLibraries(ctx) 269 if err != nil { 270 return nil, fmt.Errorf("get libraries failed for: %s", err) 271 } 272 273 var libraries []Library 274 for _, id := range ids { 275 library, err := c.GetLibraryByID(ctx, id) 276 if err != nil { 277 return nil, fmt.Errorf("get library %s failed for %s", id, err) 278 } 279 280 libraries = append(libraries, *library) 281 282 } 283 return libraries, nil 284 } 285 286 // ListSubscribers lists the subscriptions of the published library. 287 func (c *Manager) ListSubscribers(ctx context.Context, library *Library) ([]SubscriberSummary, error) { 288 url := c.Resource(internal.Subscriptions).WithParam("library", library.ID) 289 var res []SubscriberSummary 290 return res, c.Do(ctx, url.Request(http.MethodGet), &res) 291 } 292 293 // CreateSubscriber creates a subscription of the published library. 294 func (c *Manager) CreateSubscriber(ctx context.Context, library *Library, s SubscriberLibrary) (string, error) { 295 var spec struct { 296 Sub struct { 297 SubscriberLibrary SubscriberLibrary `json:"subscribed_library"` 298 } `json:"spec"` 299 } 300 spec.Sub.SubscriberLibrary = s 301 url := c.Resource(internal.Subscriptions).WithID(library.ID) 302 var res string 303 return res, c.Do(ctx, url.Request(http.MethodPost, &spec), &res) 304 } 305 306 // GetSubscriber returns information about the specified subscriber of the published library. 307 func (c *Manager) GetSubscriber(ctx context.Context, library *Library, subscriber string) (*Subscriber, error) { 308 id := internal.SubscriptionDestination{ID: subscriber} 309 url := c.Resource(internal.Subscriptions).WithID(library.ID).WithAction("get") 310 var res Subscriber 311 return &res, c.Do(ctx, url.Request(http.MethodPost, &id), &res) 312 } 313 314 // DeleteSubscriber deletes the specified subscription of the published library. 315 // The subscribed library associated with the subscription will not be deleted. 316 func (c *Manager) DeleteSubscriber(ctx context.Context, library *Library, subscriber string) error { 317 id := internal.SubscriptionDestination{ID: subscriber} 318 url := c.Resource(internal.Subscriptions).WithID(library.ID).WithAction("delete") 319 return c.Do(ctx, url.Request(http.MethodPost, &id), nil) 320 } 321 322 // EvictSubscribedLibrary evicts the cached content of an on-demand subscribed library. 323 // This operation allows the cached content of a subscribed library to be removed to free up storage capacity. 324 func (c *Manager) EvictSubscribedLibrary(ctx context.Context, library *Library) error { 325 path := internal.SubscribedLibraryPath 326 url := c.Resource(path).WithID(library.ID).WithAction("evict") 327 return c.Do(ctx, url.Request(http.MethodPost), nil) 328 }