tag v0.155.0 Tagger: imagebuilder-bot <imagebuilder-bots+imagebuilder-bot@redhat.com> Changes with 0.155.0 ---------------- * Fedora 43: add shadow-utils when LockRoot is enabled, update cloud-init service name (osbuild/images#1618) * Author: Achilleas Koutsou, Reviewers: Gianluca Zuccarelli, Michael Vogt * Update osbuild dependency commit ID to latest (osbuild/images#1609) * Author: SchutzBot, Reviewers: Achilleas Koutsou, Simon de Vlieger, Tomáš Hozza * Update snapshots to 20250626 (osbuild/images#1623) * Author: SchutzBot, Reviewers: Achilleas Koutsou, Simon de Vlieger * distro/rhel9: xz compress azure-cvm image type [HMS-8587] (osbuild/images#1620) * Author: Achilleas Koutsou, Reviewers: Simon de Vlieger, Tomáš Hozza * distro/rhel: introduce new image type: Azure SAP Apps [HMS-8738] (osbuild/images#1612) * Author: Achilleas Koutsou, Reviewers: Simon de Vlieger, Tomáš Hozza * distro/rhel: move ansible-core to sap_extras_pkgset (osbuild/images#1624) * Author: Achilleas Koutsou, Reviewers: Brian C. Lane, Tomáš Hozza * github/create-tag: allow passing the version when run manually (osbuild/images#1621) * Author: Achilleas Koutsou, Reviewers: Lukáš Zapletal, Tomáš Hozza * rhel9: move image-config into pure YAML (HMS-8593) (osbuild/images#1616) * Author: Michael Vogt, Reviewers: Achilleas Koutsou, Simon de Vlieger * test: split manifest checksums into separate files (osbuild/images#1625) * Author: Achilleas Koutsou, Reviewers: Simon de Vlieger, Tomáš Hozza — Somewhere on the Internet, 2025-06-30 --- tag v0.156.0 Tagger: imagebuilder-bot <imagebuilder-bots+imagebuilder-bot@redhat.com> Changes with 0.156.0 ---------------- * Many: delete repositories for EOL distributions (HMS-7044) (osbuild/images#1607) * Author: Tomáš Hozza, Reviewers: Michael Vogt, Simon de Vlieger * RHSM/facts: add 'image-builder CLI' API type (osbuild/images#1640) * Author: Tomáš Hozza, Reviewers: Brian C. Lane, Simon de Vlieger * Update dependencies 2025-06-29 (osbuild/images#1628) * Author: SchutzBot, Reviewers: Simon de Vlieger, Tomáš Hozza * Update osbuild dependency commit ID to latest (osbuild/images#1627) * Author: SchutzBot, Reviewers: Simon de Vlieger, Tomáš Hozza * [RFC] image: drop `InstallWeakDeps` from image.DiskImage (osbuild/images#1642) * Author: Michael Vogt, Reviewers: Brian C. Lane, Simon de Vlieger, Tomáš Hozza * build(deps): bump the go-deps group across 1 directory with 3 updates (osbuild/images#1632) * Author: dependabot[bot], Reviewers: SchutzBot, Tomáš Hozza * distro/rhel10: xz compress azure-cvm image type (osbuild/images#1638) * Author: Achilleas Koutsou, Reviewers: Brian C. Lane, Simon de Vlieger * distro: cleanup/refactor distro/{defs,generic} (HMS-8744) (osbuild/images#1570) * Author: Michael Vogt, Reviewers: Simon de Vlieger, Tomáš Hozza * distro: remove some hardcoded values from generic/images.go (osbuild/images#1636) * Author: Michael Vogt, Reviewers: Simon de Vlieger, Tomáš Hozza * distro: small tweaks for the YAML based imagetypes (osbuild/images#1622) * Author: Michael Vogt, Reviewers: Brian C. Lane, Simon de Vlieger * fedora/wsl: packages and locale (osbuild/images#1635) * Author: Simon de Vlieger, Reviewers: Michael Vogt, Tomáš Hozza * image/many: make compression more generic (osbuild/images#1634) * Author: Simon de Vlieger, Reviewers: Brian C. Lane, Michael Vogt * manifest: handle content template name with spaces (osbuild/images#1641) * Author: Bryttanie, Reviewers: Brian C. Lane, Michael Vogt, Tomáš Hozza * many: implement gzip (osbuild/images#1633) * Author: Simon de Vlieger, Reviewers: Michael Vogt, Tomáš Hozza * rhel/azure: set GRUB_TERMINAL based on architecture [RHEL-91383] (osbuild/images#1626) * Author: Achilleas Koutsou, Reviewers: Simon de Vlieger, Tomáš Hozza — Somewhere on the Internet, 2025-07-07 ---
288 lines
7 KiB
Go
288 lines
7 KiB
Go
// © Broadcom. All Rights Reserved.
|
|
// The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package mo
|
|
|
|
import (
|
|
"context"
|
|
"reflect"
|
|
|
|
"github.com/vmware/govmomi/vim25/methods"
|
|
"github.com/vmware/govmomi/vim25/soap"
|
|
"github.com/vmware/govmomi/vim25/types"
|
|
)
|
|
|
|
func ignoreMissingProperty(ref types.ManagedObjectReference, p types.MissingProperty) bool {
|
|
switch ref.Type {
|
|
case "VirtualMachine":
|
|
switch p.Path {
|
|
case "environmentBrowser":
|
|
// See https://github.com/vmware/govmomi/pull/242
|
|
return true
|
|
case "alarmActionsEnabled":
|
|
// Seen with vApp child VM
|
|
return true
|
|
}
|
|
case "ResourcePool":
|
|
switch p.Path {
|
|
case "resourceConfigSpecDetailed":
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// ObjectContentToType loads an ObjectContent value into the value it
|
|
// represents. If the ObjectContent value has a non-empty 'MissingSet' field,
|
|
// it returns the first fault it finds there as error. If the 'MissingSet'
|
|
// field is empty, it returns a pointer to a reflect.Value. It handles contain
|
|
// nested properties, such as 'guest.ipAddress' or 'config.hardware'.
|
|
func ObjectContentToType(o types.ObjectContent, ptr ...bool) (any, error) {
|
|
// Expect no properties in the missing set
|
|
for _, p := range o.MissingSet {
|
|
if ignoreMissingProperty(o.Obj, p) {
|
|
continue
|
|
}
|
|
|
|
return nil, soap.WrapVimFault(p.Fault.Fault)
|
|
}
|
|
|
|
ti := typeInfoForType(o.Obj.Type)
|
|
v, err := ti.LoadFromObjectContent(o)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(ptr) == 1 && ptr[0] {
|
|
return v.Interface(), nil
|
|
}
|
|
return v.Elem().Interface(), nil
|
|
}
|
|
|
|
// ApplyPropertyChange converts the response of a call to WaitForUpdates
|
|
// and applies it to the given managed object.
|
|
func ApplyPropertyChange(obj Reference, changes []types.PropertyChange) {
|
|
t := typeInfoForType(obj.Reference().Type)
|
|
v := reflect.ValueOf(obj)
|
|
|
|
for _, p := range changes {
|
|
var field Field
|
|
if !field.FromString(p.Name) {
|
|
panic(p.Name + ": invalid property path")
|
|
}
|
|
|
|
rv, ok := t.props[field.Path]
|
|
if !ok {
|
|
panic(field.Path + ": property not found")
|
|
}
|
|
|
|
if field.Key == nil { // Key is only used for notifications
|
|
assignValue(v, rv, reflect.ValueOf(p.Val))
|
|
}
|
|
}
|
|
}
|
|
|
|
// LoadObjectContent converts the response of a call to
|
|
// RetrieveProperties{Ex} to one or more managed objects.
|
|
func LoadObjectContent(content []types.ObjectContent, dst any) error {
|
|
rt := reflect.TypeOf(dst)
|
|
if rt == nil || rt.Kind() != reflect.Ptr {
|
|
panic("need pointer")
|
|
}
|
|
|
|
rv := reflect.ValueOf(dst).Elem()
|
|
if !rv.CanSet() {
|
|
panic("cannot set dst")
|
|
}
|
|
|
|
isSlice := false
|
|
switch rt.Elem().Kind() {
|
|
case reflect.Struct:
|
|
case reflect.Slice:
|
|
isSlice = true
|
|
default:
|
|
panic("unexpected type")
|
|
}
|
|
|
|
if isSlice {
|
|
for _, p := range content {
|
|
v, err := ObjectContentToType(p)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
vt := reflect.TypeOf(v)
|
|
|
|
if !rv.Type().AssignableTo(vt) {
|
|
// For example: dst is []ManagedEntity, res is []HostSystem
|
|
if field, ok := vt.FieldByName(rt.Elem().Elem().Name()); ok && field.Anonymous {
|
|
rv.Set(reflect.Append(rv, reflect.ValueOf(v).FieldByIndex(field.Index)))
|
|
continue
|
|
}
|
|
}
|
|
|
|
rv.Set(reflect.Append(rv, reflect.ValueOf(v)))
|
|
}
|
|
} else {
|
|
switch len(content) {
|
|
case 0:
|
|
case 1:
|
|
v, err := ObjectContentToType(content[0])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
vt := reflect.TypeOf(v)
|
|
|
|
if !rv.Type().AssignableTo(vt) {
|
|
// For example: dst is ComputeResource, res is ClusterComputeResource
|
|
if field, ok := vt.FieldByName(rt.Elem().Name()); ok && field.Anonymous {
|
|
rv.Set(reflect.ValueOf(v).FieldByIndex(field.Index))
|
|
return nil
|
|
}
|
|
}
|
|
|
|
rv.Set(reflect.ValueOf(v))
|
|
default:
|
|
// If dst is not a slice, expect to receive 0 or 1 results
|
|
panic("more than 1 result")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// RetrievePropertiesEx wraps RetrievePropertiesEx and ContinueRetrievePropertiesEx to collect properties in batches.
|
|
func RetrievePropertiesEx(ctx context.Context, r soap.RoundTripper, req types.RetrievePropertiesEx) ([]types.ObjectContent, error) {
|
|
rx, err := methods.RetrievePropertiesEx(ctx, r, &req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if rx.Returnval == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
objects := rx.Returnval.Objects
|
|
token := rx.Returnval.Token
|
|
|
|
for token != "" {
|
|
cx, err := methods.ContinueRetrievePropertiesEx(ctx, r, &types.ContinueRetrievePropertiesEx{
|
|
This: req.This,
|
|
Token: token,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
token = cx.Returnval.Token
|
|
objects = append(objects, cx.Returnval.Objects...)
|
|
}
|
|
|
|
return objects, nil
|
|
}
|
|
|
|
// RetrievePropertiesForRequest calls the RetrieveProperties method with the
|
|
// specified request and decodes the response struct into the value pointed to
|
|
// by dst.
|
|
func RetrievePropertiesForRequest(ctx context.Context, r soap.RoundTripper, req types.RetrieveProperties, dst any) error {
|
|
objects, err := RetrievePropertiesEx(ctx, r, types.RetrievePropertiesEx{
|
|
This: req.This,
|
|
SpecSet: req.SpecSet,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return LoadObjectContent(objects, dst)
|
|
}
|
|
|
|
// RetrieveProperties retrieves the properties of the managed object specified
|
|
// as obj and decodes the response struct into the value pointed to by dst.
|
|
func RetrieveProperties(ctx context.Context, r soap.RoundTripper, pc, obj types.ManagedObjectReference, dst any) error {
|
|
req := types.RetrieveProperties{
|
|
This: pc,
|
|
SpecSet: []types.PropertyFilterSpec{
|
|
{
|
|
ObjectSet: []types.ObjectSpec{
|
|
{
|
|
Obj: obj,
|
|
Skip: types.NewBool(false),
|
|
},
|
|
},
|
|
PropSet: []types.PropertySpec{
|
|
{
|
|
All: types.NewBool(true),
|
|
Type: obj.Type,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
return RetrievePropertiesForRequest(ctx, r, req, dst)
|
|
}
|
|
|
|
var morType = reflect.TypeOf((*types.ManagedObjectReference)(nil)).Elem()
|
|
|
|
// References returns all non-nil moref field values in the given struct.
|
|
// Only Anonymous struct fields are followed by default. The optional follow
|
|
// param will follow any struct fields when true.
|
|
func References(s any, follow ...bool) []types.ManagedObjectReference {
|
|
var refs []types.ManagedObjectReference
|
|
rval := reflect.ValueOf(s)
|
|
rtype := rval.Type()
|
|
|
|
if rval.Kind() == reflect.Ptr {
|
|
rval = rval.Elem()
|
|
rtype = rval.Type()
|
|
}
|
|
|
|
for i := 0; i < rval.NumField(); i++ {
|
|
val := rval.Field(i)
|
|
finfo := rtype.Field(i)
|
|
|
|
if finfo.Anonymous {
|
|
refs = append(refs, References(val.Interface(), follow...)...)
|
|
continue
|
|
}
|
|
if finfo.Name == "Self" {
|
|
continue
|
|
}
|
|
|
|
ftype := val.Type()
|
|
|
|
if ftype.Kind() == reflect.Slice {
|
|
if ftype.Elem() == morType {
|
|
s := val.Interface().([]types.ManagedObjectReference)
|
|
for i := range s {
|
|
refs = append(refs, s[i])
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
|
|
if ftype.Kind() == reflect.Ptr {
|
|
if val.IsNil() {
|
|
continue
|
|
}
|
|
val = val.Elem()
|
|
ftype = val.Type()
|
|
}
|
|
|
|
if ftype == morType {
|
|
refs = append(refs, val.Interface().(types.ManagedObjectReference))
|
|
continue
|
|
}
|
|
|
|
if len(follow) != 0 && follow[0] {
|
|
if ftype.Kind() == reflect.Struct && val.CanSet() {
|
|
refs = append(refs, References(val.Interface(), follow...)...)
|
|
}
|
|
}
|
|
}
|
|
|
|
return refs
|
|
}
|