vendor vsphere plugin
This commit is contained in:
parent
f6854f5528
commit
41c66d6935
|
@ -20,6 +20,10 @@ import (
|
|||
dockerpushpostprocessor "github.com/hashicorp/packer-plugin-docker/post-processor/docker-push"
|
||||
dockersavepostprocessor "github.com/hashicorp/packer-plugin-docker/post-processor/docker-save"
|
||||
dockertagpostprocessor "github.com/hashicorp/packer-plugin-docker/post-processor/docker-tag"
|
||||
vsphereclonebuilder "github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/clone"
|
||||
vsphereisobuilder "github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/iso"
|
||||
vspherepostprocessor "github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere"
|
||||
vspheretemplatepostprocessor "github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere-template"
|
||||
)
|
||||
|
||||
// VendoredDatasources are datasource components that were once bundled with the
|
||||
|
@ -38,6 +42,8 @@ var VendoredBuilders = map[string]packersdk.Builder{
|
|||
"amazon-ebssurrogate": new(amazonebssurrogatebuilder.Builder),
|
||||
"amazon-ebsvolume": new(amazonebsvolumebuilder.Builder),
|
||||
"amazon-instance": new(amazoninstancebuilder.Builder),
|
||||
"vsphere-clone": new(vsphereclonebuilder.Builder),
|
||||
"vsphere-iso": new(vsphereisobuilder.Builder),
|
||||
}
|
||||
|
||||
// VendoredProvisioners are provisioner components that were once bundled with the
|
||||
|
@ -47,12 +53,14 @@ var VendoredProvisioners = map[string]packersdk.Provisioner{}
|
|||
// VendoredPostProcessors are post-processor components that were once bundled with the
|
||||
// Packer core, but are now being imported from their counterpart plugin repos
|
||||
var VendoredPostProcessors = map[string]packersdk.PostProcessor{
|
||||
"docker-import": new(dockerimportpostprocessor.PostProcessor),
|
||||
"docker-push": new(dockerpushpostprocessor.PostProcessor),
|
||||
"docker-save": new(dockersavepostprocessor.PostProcessor),
|
||||
"docker-tag": new(dockertagpostprocessor.PostProcessor),
|
||||
"exoscale-import": new(exoscaleimportpostprocessor.PostProcessor),
|
||||
"amazon-import": new(anazibimportpostprocessor.PostProcessor),
|
||||
"docker-import": new(dockerimportpostprocessor.PostProcessor),
|
||||
"docker-push": new(dockerpushpostprocessor.PostProcessor),
|
||||
"docker-save": new(dockersavepostprocessor.PostProcessor),
|
||||
"docker-tag": new(dockertagpostprocessor.PostProcessor),
|
||||
"exoscale-import": new(exoscaleimportpostprocessor.PostProcessor),
|
||||
"amazon-import": new(anazibimportpostprocessor.PostProcessor),
|
||||
"vsphere": new(vspherepostprocessor.PostProcessor),
|
||||
"vsphere-template": new(vspheretemplatepostprocessor.PostProcessor),
|
||||
}
|
||||
|
||||
// Upon init lets load up any plugins that were vendored manually into the default
|
||||
|
|
4
go.mod
4
go.mod
|
@ -53,6 +53,7 @@ require (
|
|||
github.com/hashicorp/packer-plugin-amazon v0.0.1
|
||||
github.com/hashicorp/packer-plugin-docker v0.0.7
|
||||
github.com/hashicorp/packer-plugin-sdk v0.1.3-0.20210407132324-af39c7839daf
|
||||
github.com/hashicorp/packer-plugin-vsphere v0.0.0-20210409154313-881202ca3ffe
|
||||
github.com/hashicorp/vault/api v1.0.4
|
||||
github.com/hetznercloud/hcloud-go v1.15.1
|
||||
github.com/hyperonecom/h1-client-go v0.0.0-20191203060043-b46280e4c4a4
|
||||
|
@ -83,7 +84,8 @@ require (
|
|||
github.com/ucloud/ucloud-sdk-go v0.16.3
|
||||
github.com/ufilesdk-dev/ufile-gosdk v0.0.0-20190830075812-b4dbc4ef43a6
|
||||
github.com/ulikunitz/xz v0.5.6
|
||||
github.com/vmware/govmomi v0.23.1
|
||||
github.com/ulikunitz/xz v0.5.5
|
||||
github.com/vmware/govmomi v0.24.1
|
||||
github.com/xanzy/go-cloudstack v0.0.0-20190526095453-42f262b63ed0
|
||||
github.com/yandex-cloud/go-genproto v0.0.0-20200915125933-33de72a328bd
|
||||
github.com/yandex-cloud/go-sdk v0.0.0-20200921111412-ef15ded2014c
|
||||
|
|
8
go.sum
8
go.sum
|
@ -450,6 +450,8 @@ github.com/hashicorp/packer-plugin-sdk v0.1.1/go.mod h1:1d3nqB9LUsXMQaNUiL67Q+WY
|
|||
github.com/hashicorp/packer-plugin-sdk v0.1.2/go.mod h1:KRjczE1/c9NV5Re+PXt3myJsVTI/FxEHpZjRjOH0Fug=
|
||||
github.com/hashicorp/packer-plugin-sdk v0.1.3-0.20210407132324-af39c7839daf h1:0DBlIExTDefzbfkOl213QtgJsVJXWdgW/aIQIvYUMzs=
|
||||
github.com/hashicorp/packer-plugin-sdk v0.1.3-0.20210407132324-af39c7839daf/go.mod h1:xePpgQgQYv/bamiypx3hH9ukidxDdcN8q0R0wLi8IEQ=
|
||||
github.com/hashicorp/packer-plugin-vsphere v0.0.0-20210409154313-881202ca3ffe h1:qUU0ctLV5Pjq+RqxaKlVmKhE1BQtWZvqV4a05cF93PY=
|
||||
github.com/hashicorp/packer-plugin-vsphere v0.0.0-20210409154313-881202ca3ffe/go.mod h1:ZmA5O2CDiIOGW/hvHbhxNzq2hEXDYyUVj+knuoxyWu0=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hashicorp/serf v0.9.2 h1:yJoyfZXo4Pk2p/M/viW+YLibBFiIbKoP79gu7kDAFP0=
|
||||
github.com/hashicorp/serf v0.9.2/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
|
||||
|
@ -695,8 +697,9 @@ github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+
|
|||
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
|
||||
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
||||
github.com/vmware/govmomi v0.23.1 h1:vU09hxnNR/I7e+4zCJvW+5vHu5dO64Aoe2Lw7Yi/KRg=
|
||||
github.com/vmware/govmomi v0.23.1/go.mod h1:Y+Wq4lst78L85Ge/F8+ORXIWiKYqaro1vhAulACy9Lc=
|
||||
github.com/vmware/govmomi v0.24.1 h1:ecVvrxF28/5g738gLTiYgc62fpGfIPRKheQ1Dj1p35w=
|
||||
github.com/vmware/govmomi v0.24.1/go.mod h1:Y+Wq4lst78L85Ge/F8+ORXIWiKYqaro1vhAulACy9Lc=
|
||||
github.com/vmware/vmw-guestinfo v0.0.0-20170707015358-25eff159a728/go.mod h1:x9oS4Wk2s2u4tS29nEaDLdzvuHdB19CvSGJjPgkZJNk=
|
||||
github.com/xanzy/go-cloudstack v0.0.0-20190526095453-42f262b63ed0 h1:NJrcIkdzq0C3I8ypAZwFE9RHtGbfp+mJvqIcoFATZuk=
|
||||
github.com/xanzy/go-cloudstack v0.0.0-20190526095453-42f262b63ed0/go.mod h1:sBh287mCRwCz6zyXHMmw7sSZGPohVpnx+o+OY4M+i3A=
|
||||
|
@ -773,8 +776,9 @@ golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPI
|
|||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mobile v0.0.0-20191130191448-5c0e7e404af8/go.mod h1:p895TfNkDgPEmEQrNiOtIl3j98d/tGU95djDj7NfyjQ=
|
||||
golang.org/x/mobile v0.0.0-20201208152944-da85bec010a2 h1:3HADozU50HyrJ2jklLtr3xr0itFkz9u4LxCJhqKVdjI=
|
||||
golang.org/x/mobile v0.0.0-20201208152944-da85bec010a2/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
|
||||
golang.org/x/mobile v0.0.0-20210220033013-bdb1ca9a1e08 h1:h+GZ3ubjuWaQjGe8owMGcmMVCqs0xYJtRG5y2bpHaqU=
|
||||
golang.org/x/mobile v0.0.0-20210220033013-bdb1ca9a1e08/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
|
|
|
@ -0,0 +1,373 @@
|
|||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
175
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/clone/builder.go
generated
vendored
Normal file
175
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/clone/builder.go
generated
vendored
Normal file
|
@ -0,0 +1,175 @@
|
|||
package clone
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
type Builder struct {
|
||||
config Config
|
||||
runner multistep.Runner
|
||||
}
|
||||
|
||||
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
|
||||
|
||||
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
||||
warnings, errs := b.config.Prepare(raws...)
|
||||
if errs != nil {
|
||||
return nil, warnings, errs
|
||||
}
|
||||
|
||||
return nil, warnings, nil
|
||||
}
|
||||
|
||||
func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) {
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("debug", b.config.PackerDebug)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
||||
var steps []multistep.Step
|
||||
|
||||
steps = append(steps,
|
||||
&common.StepConnect{
|
||||
Config: &b.config.ConnectConfig,
|
||||
},
|
||||
&commonsteps.StepCreateCD{
|
||||
Files: b.config.CDConfig.CDFiles,
|
||||
Label: b.config.CDConfig.CDLabel,
|
||||
},
|
||||
&common.StepRemoteUpload{
|
||||
Datastore: b.config.Datastore,
|
||||
Host: b.config.Host,
|
||||
SetHostForDatastoreUploads: b.config.SetHostForDatastoreUploads,
|
||||
},
|
||||
&StepCloneVM{
|
||||
Config: &b.config.CloneConfig,
|
||||
Location: &b.config.LocationConfig,
|
||||
Force: b.config.PackerConfig.PackerForce,
|
||||
},
|
||||
&common.StepConfigureHardware{
|
||||
Config: &b.config.HardwareConfig,
|
||||
},
|
||||
&common.StepAddCDRom{
|
||||
Config: &b.config.CDRomConfig,
|
||||
},
|
||||
&common.StepConfigParams{
|
||||
Config: &b.config.ConfigParamsConfig,
|
||||
},
|
||||
)
|
||||
|
||||
if b.config.CustomizeConfig != nil {
|
||||
steps = append(steps, &StepCustomize{
|
||||
Config: b.config.CustomizeConfig,
|
||||
})
|
||||
}
|
||||
|
||||
if b.config.Comm.Type != "none" {
|
||||
steps = append(steps,
|
||||
&commonsteps.StepCreateFloppy{
|
||||
Files: b.config.FloppyFiles,
|
||||
Directories: b.config.FloppyDirectories,
|
||||
Label: b.config.FloppyLabel,
|
||||
},
|
||||
&common.StepAddFloppy{
|
||||
Config: &b.config.FloppyConfig,
|
||||
Datastore: b.config.Datastore,
|
||||
Host: b.config.Host,
|
||||
SetHostForDatastoreUploads: b.config.SetHostForDatastoreUploads,
|
||||
},
|
||||
&common.StepHTTPIPDiscover{
|
||||
HTTPIP: b.config.BootConfig.HTTPIP,
|
||||
Network: b.config.WaitIpConfig.GetIPNet(),
|
||||
},
|
||||
commonsteps.HTTPServerFromHTTPConfig(&b.config.HTTPConfig),
|
||||
&common.StepSshKeyPair{
|
||||
Debug: b.config.PackerDebug,
|
||||
DebugKeyPath: fmt.Sprintf("%s.pem", b.config.PackerBuildName),
|
||||
Comm: &b.config.Comm,
|
||||
},
|
||||
&common.StepRun{
|
||||
Config: &b.config.RunConfig,
|
||||
SetOrder: false,
|
||||
},
|
||||
&common.StepBootCommand{
|
||||
Config: &b.config.BootConfig,
|
||||
Ctx: b.config.ctx,
|
||||
VMName: b.config.VMName,
|
||||
},
|
||||
&common.StepWaitForIp{
|
||||
Config: &b.config.WaitIpConfig,
|
||||
},
|
||||
&communicator.StepConnect{
|
||||
Config: &b.config.Comm,
|
||||
Host: common.CommHost(b.config.Comm.Host()),
|
||||
SSHConfig: b.config.Comm.SSHConfigFunc(),
|
||||
},
|
||||
&commonsteps.StepProvision{},
|
||||
&common.StepShutdown{
|
||||
Config: &b.config.ShutdownConfig,
|
||||
},
|
||||
&common.StepRemoveFloppy{
|
||||
Datastore: b.config.Datastore,
|
||||
Host: b.config.Host,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
steps = append(steps,
|
||||
&common.StepRemoveCDRom{
|
||||
Config: &b.config.RemoveCDRomConfig,
|
||||
},
|
||||
&common.StepCreateSnapshot{
|
||||
CreateSnapshot: b.config.CreateSnapshot,
|
||||
},
|
||||
&common.StepConvertToTemplate{
|
||||
ConvertToTemplate: b.config.ConvertToTemplate,
|
||||
},
|
||||
)
|
||||
|
||||
if b.config.ContentLibraryDestinationConfig != nil {
|
||||
steps = append(steps, &common.StepImportToContentLibrary{
|
||||
ContentLibConfig: b.config.ContentLibraryDestinationConfig,
|
||||
})
|
||||
}
|
||||
|
||||
if b.config.Export != nil {
|
||||
steps = append(steps, &common.StepExport{
|
||||
Name: b.config.Export.Name,
|
||||
Force: b.config.Export.Force,
|
||||
Images: b.config.Export.Images,
|
||||
Manifest: b.config.Export.Manifest,
|
||||
OutputDir: b.config.Export.OutputDir.OutputDir,
|
||||
Options: b.config.Export.Options,
|
||||
})
|
||||
}
|
||||
|
||||
b.runner = commonsteps.NewRunnerWithPauseFn(steps, b.config.PackerConfig, ui, state)
|
||||
b.runner.Run(ctx, state)
|
||||
|
||||
if rawErr, ok := state.GetOk("error"); ok {
|
||||
return nil, rawErr.(error)
|
||||
}
|
||||
|
||||
if _, ok := state.GetOk("vm"); !ok {
|
||||
return nil, nil
|
||||
}
|
||||
artifact := &common.Artifact{
|
||||
Name: b.config.VMName,
|
||||
VM: state.Get("vm").(*driver.VirtualMachineDriver),
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
if b.config.Export != nil {
|
||||
artifact.Outconfig = &b.config.Export.OutputDir
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
}
|
104
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/clone/config.go
generated
vendored
Normal file
104
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/clone/config.go
generated
vendored
Normal file
|
@ -0,0 +1,104 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type Config
|
||||
|
||||
package clone
|
||||
|
||||
import (
|
||||
packerCommon "github.com/hashicorp/packer-plugin-sdk/common"
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
packerCommon.PackerConfig `mapstructure:",squash"`
|
||||
commonsteps.HTTPConfig `mapstructure:",squash"`
|
||||
commonsteps.CDConfig `mapstructure:",squash"`
|
||||
|
||||
common.ConnectConfig `mapstructure:",squash"`
|
||||
CloneConfig `mapstructure:",squash"`
|
||||
common.LocationConfig `mapstructure:",squash"`
|
||||
common.HardwareConfig `mapstructure:",squash"`
|
||||
common.ConfigParamsConfig `mapstructure:",squash"`
|
||||
|
||||
common.CDRomConfig `mapstructure:",squash"`
|
||||
common.RemoveCDRomConfig `mapstructure:",squash"`
|
||||
common.FloppyConfig `mapstructure:",squash"`
|
||||
common.RunConfig `mapstructure:",squash"`
|
||||
common.BootConfig `mapstructure:",squash"`
|
||||
common.WaitIpConfig `mapstructure:",squash"`
|
||||
Comm communicator.Config `mapstructure:",squash"`
|
||||
common.ShutdownConfig `mapstructure:",squash"`
|
||||
|
||||
// Create a snapshot when set to `true`, so the VM can be used as a base
|
||||
// for linked clones. Defaults to `false`.
|
||||
CreateSnapshot bool `mapstructure:"create_snapshot"`
|
||||
// Convert VM to a template. Defaults to `false`.
|
||||
ConvertToTemplate bool `mapstructure:"convert_to_template"`
|
||||
// Configuration for exporting VM to an ovf file.
|
||||
// The VM will not be exported if no [Export Configuration](#export-configuration) is specified.
|
||||
Export *common.ExportConfig `mapstructure:"export"`
|
||||
// Configuration for importing a VM template or OVF template to a Content Library.
|
||||
// The template will not be imported if no [Content Library Import Configuration](#content-library-import-configuration) is specified.
|
||||
// The import doesn't work if [convert_to_template](#convert_to_template) is set to true.
|
||||
ContentLibraryDestinationConfig *common.ContentLibraryDestinationConfig `mapstructure:"content_library_destination"`
|
||||
// Customize the cloned VM to configure host, network, or licensing settings. See the [customization options](#customization).
|
||||
CustomizeConfig *CustomizeConfig `mapstructure:"customize"`
|
||||
|
||||
ctx interpolate.Context
|
||||
}
|
||||
|
||||
func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
|
||||
err := config.Decode(c, &config.DecodeOpts{
|
||||
PluginType: common.BuilderId,
|
||||
Interpolate: true,
|
||||
InterpolateContext: &c.ctx,
|
||||
InterpolateFilter: &interpolate.RenderFilter{
|
||||
Exclude: []string{
|
||||
"boot_command",
|
||||
},
|
||||
},
|
||||
}, raws...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// warnings := make([]string, 0)
|
||||
errs := new(packersdk.MultiError)
|
||||
|
||||
errs = packersdk.MultiErrorAppend(errs, c.ConnectConfig.Prepare()...)
|
||||
errs = packersdk.MultiErrorAppend(errs, c.CloneConfig.Prepare()...)
|
||||
errs = packersdk.MultiErrorAppend(errs, c.LocationConfig.Prepare()...)
|
||||
errs = packersdk.MultiErrorAppend(errs, c.HardwareConfig.Prepare()...)
|
||||
errs = packersdk.MultiErrorAppend(errs, c.HTTPConfig.Prepare(&c.ctx)...)
|
||||
|
||||
errs = packersdk.MultiErrorAppend(errs, c.CDRomConfig.Prepare()...)
|
||||
errs = packersdk.MultiErrorAppend(errs, c.CDConfig.Prepare(&c.ctx)...)
|
||||
errs = packersdk.MultiErrorAppend(errs, c.BootConfig.Prepare(&c.ctx)...)
|
||||
errs = packersdk.MultiErrorAppend(errs, c.WaitIpConfig.Prepare()...)
|
||||
errs = packersdk.MultiErrorAppend(errs, c.Comm.Prepare(&c.ctx)...)
|
||||
|
||||
_, shutdownErrs := c.ShutdownConfig.Prepare(c.Comm)
|
||||
// shutdownWarnings, shutdownErrs := c.ShutdownConfig.Prepare(c.Comm)
|
||||
// warnings = append(warnings, shutdownWarnings...)
|
||||
errs = packersdk.MultiErrorAppend(errs, shutdownErrs...)
|
||||
|
||||
if c.Export != nil {
|
||||
errs = packersdk.MultiErrorAppend(errs, c.Export.Prepare(&c.ctx, &c.LocationConfig, &c.PackerConfig)...)
|
||||
}
|
||||
if c.ContentLibraryDestinationConfig != nil {
|
||||
errs = packersdk.MultiErrorAppend(errs, c.ContentLibraryDestinationConfig.Prepare(&c.LocationConfig)...)
|
||||
}
|
||||
if c.CustomizeConfig != nil {
|
||||
errs = packersdk.MultiErrorAppend(errs, c.CustomizeConfig.Prepare()...)
|
||||
}
|
||||
|
||||
if len(errs.Errors) > 0 {
|
||||
return nil, errs
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
282
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/clone/config.hcl2spec.go
generated
vendored
Normal file
282
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/clone/config.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,282 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type Config"; DO NOT EDIT.
|
||||
|
||||
package clone
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatConfig is an auto-generated flat version of Config.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatConfig struct {
|
||||
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"`
|
||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
|
||||
PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"`
|
||||
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
|
||||
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
|
||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
|
||||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"`
|
||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"`
|
||||
HTTPDir *string `mapstructure:"http_directory" cty:"http_directory" hcl:"http_directory"`
|
||||
HTTPContent map[string]string `mapstructure:"http_content" cty:"http_content" hcl:"http_content"`
|
||||
HTTPPortMin *int `mapstructure:"http_port_min" cty:"http_port_min" hcl:"http_port_min"`
|
||||
HTTPPortMax *int `mapstructure:"http_port_max" cty:"http_port_max" hcl:"http_port_max"`
|
||||
HTTPAddress *string `mapstructure:"http_bind_address" cty:"http_bind_address" hcl:"http_bind_address"`
|
||||
HTTPInterface *string `mapstructure:"http_interface" undocumented:"true" cty:"http_interface" hcl:"http_interface"`
|
||||
CDFiles []string `mapstructure:"cd_files" cty:"cd_files" hcl:"cd_files"`
|
||||
CDLabel *string `mapstructure:"cd_label" cty:"cd_label" hcl:"cd_label"`
|
||||
VCenterServer *string `mapstructure:"vcenter_server" cty:"vcenter_server" hcl:"vcenter_server"`
|
||||
Username *string `mapstructure:"username" cty:"username" hcl:"username"`
|
||||
Password *string `mapstructure:"password" cty:"password" hcl:"password"`
|
||||
InsecureConnection *bool `mapstructure:"insecure_connection" cty:"insecure_connection" hcl:"insecure_connection"`
|
||||
Datacenter *string `mapstructure:"datacenter" cty:"datacenter" hcl:"datacenter"`
|
||||
Template *string `mapstructure:"template" cty:"template" hcl:"template"`
|
||||
DiskSize *int64 `mapstructure:"disk_size" cty:"disk_size" hcl:"disk_size"`
|
||||
LinkedClone *bool `mapstructure:"linked_clone" cty:"linked_clone" hcl:"linked_clone"`
|
||||
Network *string `mapstructure:"network" cty:"network" hcl:"network"`
|
||||
MacAddress *string `mapstructure:"mac_address" cty:"mac_address" hcl:"mac_address"`
|
||||
Notes *string `mapstructure:"notes" cty:"notes" hcl:"notes"`
|
||||
VAppConfig *FlatvAppConfig `mapstructure:"vapp" cty:"vapp" hcl:"vapp"`
|
||||
DiskControllerType []string `mapstructure:"disk_controller_type" cty:"disk_controller_type" hcl:"disk_controller_type"`
|
||||
Storage []common.FlatDiskConfig `mapstructure:"storage" cty:"storage" hcl:"storage"`
|
||||
VMName *string `mapstructure:"vm_name" cty:"vm_name" hcl:"vm_name"`
|
||||
Folder *string `mapstructure:"folder" cty:"folder" hcl:"folder"`
|
||||
Cluster *string `mapstructure:"cluster" cty:"cluster" hcl:"cluster"`
|
||||
Host *string `mapstructure:"host" cty:"host" hcl:"host"`
|
||||
ResourcePool *string `mapstructure:"resource_pool" cty:"resource_pool" hcl:"resource_pool"`
|
||||
Datastore *string `mapstructure:"datastore" cty:"datastore" hcl:"datastore"`
|
||||
SetHostForDatastoreUploads *bool `mapstructure:"set_host_for_datastore_uploads" cty:"set_host_for_datastore_uploads" hcl:"set_host_for_datastore_uploads"`
|
||||
CPUs *int32 `mapstructure:"CPUs" cty:"CPUs" hcl:"CPUs"`
|
||||
CpuCores *int32 `mapstructure:"cpu_cores" cty:"cpu_cores" hcl:"cpu_cores"`
|
||||
CPUReservation *int64 `mapstructure:"CPU_reservation" cty:"CPU_reservation" hcl:"CPU_reservation"`
|
||||
CPULimit *int64 `mapstructure:"CPU_limit" cty:"CPU_limit" hcl:"CPU_limit"`
|
||||
CpuHotAddEnabled *bool `mapstructure:"CPU_hot_plug" cty:"CPU_hot_plug" hcl:"CPU_hot_plug"`
|
||||
RAM *int64 `mapstructure:"RAM" cty:"RAM" hcl:"RAM"`
|
||||
RAMReservation *int64 `mapstructure:"RAM_reservation" cty:"RAM_reservation" hcl:"RAM_reservation"`
|
||||
RAMReserveAll *bool `mapstructure:"RAM_reserve_all" cty:"RAM_reserve_all" hcl:"RAM_reserve_all"`
|
||||
MemoryHotAddEnabled *bool `mapstructure:"RAM_hot_plug" cty:"RAM_hot_plug" hcl:"RAM_hot_plug"`
|
||||
VideoRAM *int64 `mapstructure:"video_ram" cty:"video_ram" hcl:"video_ram"`
|
||||
VGPUProfile *string `mapstructure:"vgpu_profile" cty:"vgpu_profile" hcl:"vgpu_profile"`
|
||||
NestedHV *bool `mapstructure:"NestedHV" cty:"NestedHV" hcl:"NestedHV"`
|
||||
Firmware *string `mapstructure:"firmware" cty:"firmware" hcl:"firmware"`
|
||||
ForceBIOSSetup *bool `mapstructure:"force_bios_setup" cty:"force_bios_setup" hcl:"force_bios_setup"`
|
||||
ConfigParams map[string]string `mapstructure:"configuration_parameters" cty:"configuration_parameters" hcl:"configuration_parameters"`
|
||||
ToolsSyncTime *bool `mapstructure:"tools_sync_time" cty:"tools_sync_time" hcl:"tools_sync_time"`
|
||||
ToolsUpgradePolicy *bool `mapstructure:"tools_upgrade_policy" cty:"tools_upgrade_policy" hcl:"tools_upgrade_policy"`
|
||||
CdromType *string `mapstructure:"cdrom_type" cty:"cdrom_type" hcl:"cdrom_type"`
|
||||
ISOPaths []string `mapstructure:"iso_paths" cty:"iso_paths" hcl:"iso_paths"`
|
||||
RemoveCdrom *bool `mapstructure:"remove_cdrom" cty:"remove_cdrom" hcl:"remove_cdrom"`
|
||||
FloppyIMGPath *string `mapstructure:"floppy_img_path" cty:"floppy_img_path" hcl:"floppy_img_path"`
|
||||
FloppyFiles []string `mapstructure:"floppy_files" cty:"floppy_files" hcl:"floppy_files"`
|
||||
FloppyDirectories []string `mapstructure:"floppy_dirs" cty:"floppy_dirs" hcl:"floppy_dirs"`
|
||||
FloppyLabel *string `mapstructure:"floppy_label" cty:"floppy_label" hcl:"floppy_label"`
|
||||
BootOrder *string `mapstructure:"boot_order" cty:"boot_order" hcl:"boot_order"`
|
||||
BootGroupInterval *string `mapstructure:"boot_keygroup_interval" cty:"boot_keygroup_interval" hcl:"boot_keygroup_interval"`
|
||||
BootWait *string `mapstructure:"boot_wait" cty:"boot_wait" hcl:"boot_wait"`
|
||||
BootCommand []string `mapstructure:"boot_command" cty:"boot_command" hcl:"boot_command"`
|
||||
HTTPIP *string `mapstructure:"http_ip" cty:"http_ip" hcl:"http_ip"`
|
||||
WaitTimeout *string `mapstructure:"ip_wait_timeout" cty:"ip_wait_timeout" hcl:"ip_wait_timeout"`
|
||||
SettleTimeout *string `mapstructure:"ip_settle_timeout" cty:"ip_settle_timeout" hcl:"ip_settle_timeout"`
|
||||
WaitAddress *string `mapstructure:"ip_wait_address" cty:"ip_wait_address" hcl:"ip_wait_address"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator" hcl:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting" hcl:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host" hcl:"ssh_host"`
|
||||
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port" hcl:"ssh_port"`
|
||||
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username" hcl:"ssh_username"`
|
||||
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password" hcl:"ssh_password"`
|
||||
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" undocumented:"true" cty:"ssh_keypair_name" hcl:"ssh_keypair_name"`
|
||||
SSHTemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" undocumented:"true" cty:"temporary_key_pair_name" hcl:"temporary_key_pair_name"`
|
||||
SSHTemporaryKeyPairType *string `mapstructure:"temporary_key_pair_type" cty:"temporary_key_pair_type" hcl:"temporary_key_pair_type"`
|
||||
SSHTemporaryKeyPairBits *int `mapstructure:"temporary_key_pair_bits" cty:"temporary_key_pair_bits" hcl:"temporary_key_pair_bits"`
|
||||
SSHCiphers []string `mapstructure:"ssh_ciphers" cty:"ssh_ciphers" hcl:"ssh_ciphers"`
|
||||
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys" hcl:"ssh_clear_authorized_keys"`
|
||||
SSHKEXAlgos []string `mapstructure:"ssh_key_exchange_algorithms" cty:"ssh_key_exchange_algorithms" hcl:"ssh_key_exchange_algorithms"`
|
||||
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" undocumented:"true" cty:"ssh_private_key_file" hcl:"ssh_private_key_file"`
|
||||
SSHCertificateFile *string `mapstructure:"ssh_certificate_file" cty:"ssh_certificate_file" hcl:"ssh_certificate_file"`
|
||||
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty" hcl:"ssh_pty"`
|
||||
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout" hcl:"ssh_timeout"`
|
||||
SSHWaitTimeout *string `mapstructure:"ssh_wait_timeout" undocumented:"true" cty:"ssh_wait_timeout" hcl:"ssh_wait_timeout"`
|
||||
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" undocumented:"true" cty:"ssh_agent_auth" hcl:"ssh_agent_auth"`
|
||||
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding" hcl:"ssh_disable_agent_forwarding"`
|
||||
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts" hcl:"ssh_handshake_attempts"`
|
||||
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host" hcl:"ssh_bastion_host"`
|
||||
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port" hcl:"ssh_bastion_port"`
|
||||
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth" hcl:"ssh_bastion_agent_auth"`
|
||||
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username" hcl:"ssh_bastion_username"`
|
||||
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password" hcl:"ssh_bastion_password"`
|
||||
SSHBastionInteractive *bool `mapstructure:"ssh_bastion_interactive" cty:"ssh_bastion_interactive" hcl:"ssh_bastion_interactive"`
|
||||
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file" hcl:"ssh_bastion_private_key_file"`
|
||||
SSHBastionCertificateFile *string `mapstructure:"ssh_bastion_certificate_file" cty:"ssh_bastion_certificate_file" hcl:"ssh_bastion_certificate_file"`
|
||||
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method" hcl:"ssh_file_transfer_method"`
|
||||
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host" hcl:"ssh_proxy_host"`
|
||||
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port" hcl:"ssh_proxy_port"`
|
||||
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username" hcl:"ssh_proxy_username"`
|
||||
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password" hcl:"ssh_proxy_password"`
|
||||
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval" hcl:"ssh_keep_alive_interval"`
|
||||
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout" hcl:"ssh_read_write_timeout"`
|
||||
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels" hcl:"ssh_remote_tunnels"`
|
||||
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels" hcl:"ssh_local_tunnels"`
|
||||
SSHPublicKey []byte `mapstructure:"ssh_public_key" undocumented:"true" cty:"ssh_public_key" hcl:"ssh_public_key"`
|
||||
SSHPrivateKey []byte `mapstructure:"ssh_private_key" undocumented:"true" cty:"ssh_private_key" hcl:"ssh_private_key"`
|
||||
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username" hcl:"winrm_username"`
|
||||
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password" hcl:"winrm_password"`
|
||||
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host" hcl:"winrm_host"`
|
||||
WinRMNoProxy *bool `mapstructure:"winrm_no_proxy" cty:"winrm_no_proxy" hcl:"winrm_no_proxy"`
|
||||
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port" hcl:"winrm_port"`
|
||||
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout" hcl:"winrm_timeout"`
|
||||
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl" hcl:"winrm_use_ssl"`
|
||||
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure" hcl:"winrm_insecure"`
|
||||
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm" hcl:"winrm_use_ntlm"`
|
||||
Command *string `mapstructure:"shutdown_command" cty:"shutdown_command" hcl:"shutdown_command"`
|
||||
Timeout *string `mapstructure:"shutdown_timeout" cty:"shutdown_timeout" hcl:"shutdown_timeout"`
|
||||
DisableShutdown *bool `mapstructure:"disable_shutdown" cty:"disable_shutdown" hcl:"disable_shutdown"`
|
||||
CreateSnapshot *bool `mapstructure:"create_snapshot" cty:"create_snapshot" hcl:"create_snapshot"`
|
||||
ConvertToTemplate *bool `mapstructure:"convert_to_template" cty:"convert_to_template" hcl:"convert_to_template"`
|
||||
Export *common.FlatExportConfig `mapstructure:"export" cty:"export" hcl:"export"`
|
||||
ContentLibraryDestinationConfig *common.FlatContentLibraryDestinationConfig `mapstructure:"content_library_destination" cty:"content_library_destination" hcl:"content_library_destination"`
|
||||
CustomizeConfig *FlatCustomizeConfig `mapstructure:"customize" cty:"customize" hcl:"customize"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatConfig.
|
||||
// FlatConfig is an auto-generated flat version of Config.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a Config.
|
||||
// This spec is used by HCL to read the fields of Config.
|
||||
// The decoded values from this spec will then be applied to a FlatConfig.
|
||||
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
|
||||
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
|
||||
"packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false},
|
||||
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
|
||||
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
|
||||
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
|
||||
"packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"http_directory": &hcldec.AttrSpec{Name: "http_directory", Type: cty.String, Required: false},
|
||||
"http_content": &hcldec.AttrSpec{Name: "http_content", Type: cty.Map(cty.String), Required: false},
|
||||
"http_port_min": &hcldec.AttrSpec{Name: "http_port_min", Type: cty.Number, Required: false},
|
||||
"http_port_max": &hcldec.AttrSpec{Name: "http_port_max", Type: cty.Number, Required: false},
|
||||
"http_bind_address": &hcldec.AttrSpec{Name: "http_bind_address", Type: cty.String, Required: false},
|
||||
"http_interface": &hcldec.AttrSpec{Name: "http_interface", Type: cty.String, Required: false},
|
||||
"cd_files": &hcldec.AttrSpec{Name: "cd_files", Type: cty.List(cty.String), Required: false},
|
||||
"cd_label": &hcldec.AttrSpec{Name: "cd_label", Type: cty.String, Required: false},
|
||||
"vcenter_server": &hcldec.AttrSpec{Name: "vcenter_server", Type: cty.String, Required: false},
|
||||
"username": &hcldec.AttrSpec{Name: "username", Type: cty.String, Required: false},
|
||||
"password": &hcldec.AttrSpec{Name: "password", Type: cty.String, Required: false},
|
||||
"insecure_connection": &hcldec.AttrSpec{Name: "insecure_connection", Type: cty.Bool, Required: false},
|
||||
"datacenter": &hcldec.AttrSpec{Name: "datacenter", Type: cty.String, Required: false},
|
||||
"template": &hcldec.AttrSpec{Name: "template", Type: cty.String, Required: false},
|
||||
"disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, Required: false},
|
||||
"linked_clone": &hcldec.AttrSpec{Name: "linked_clone", Type: cty.Bool, Required: false},
|
||||
"network": &hcldec.AttrSpec{Name: "network", Type: cty.String, Required: false},
|
||||
"mac_address": &hcldec.AttrSpec{Name: "mac_address", Type: cty.String, Required: false},
|
||||
"notes": &hcldec.AttrSpec{Name: "notes", Type: cty.String, Required: false},
|
||||
"vapp": &hcldec.BlockSpec{TypeName: "vapp", Nested: hcldec.ObjectSpec((*FlatvAppConfig)(nil).HCL2Spec())},
|
||||
"disk_controller_type": &hcldec.AttrSpec{Name: "disk_controller_type", Type: cty.List(cty.String), Required: false},
|
||||
"storage": &hcldec.BlockListSpec{TypeName: "storage", Nested: hcldec.ObjectSpec((*common.FlatDiskConfig)(nil).HCL2Spec())},
|
||||
"vm_name": &hcldec.AttrSpec{Name: "vm_name", Type: cty.String, Required: false},
|
||||
"folder": &hcldec.AttrSpec{Name: "folder", Type: cty.String, Required: false},
|
||||
"cluster": &hcldec.AttrSpec{Name: "cluster", Type: cty.String, Required: false},
|
||||
"host": &hcldec.AttrSpec{Name: "host", Type: cty.String, Required: false},
|
||||
"resource_pool": &hcldec.AttrSpec{Name: "resource_pool", Type: cty.String, Required: false},
|
||||
"datastore": &hcldec.AttrSpec{Name: "datastore", Type: cty.String, Required: false},
|
||||
"set_host_for_datastore_uploads": &hcldec.AttrSpec{Name: "set_host_for_datastore_uploads", Type: cty.Bool, Required: false},
|
||||
"CPUs": &hcldec.AttrSpec{Name: "CPUs", Type: cty.Number, Required: false},
|
||||
"cpu_cores": &hcldec.AttrSpec{Name: "cpu_cores", Type: cty.Number, Required: false},
|
||||
"CPU_reservation": &hcldec.AttrSpec{Name: "CPU_reservation", Type: cty.Number, Required: false},
|
||||
"CPU_limit": &hcldec.AttrSpec{Name: "CPU_limit", Type: cty.Number, Required: false},
|
||||
"CPU_hot_plug": &hcldec.AttrSpec{Name: "CPU_hot_plug", Type: cty.Bool, Required: false},
|
||||
"RAM": &hcldec.AttrSpec{Name: "RAM", Type: cty.Number, Required: false},
|
||||
"RAM_reservation": &hcldec.AttrSpec{Name: "RAM_reservation", Type: cty.Number, Required: false},
|
||||
"RAM_reserve_all": &hcldec.AttrSpec{Name: "RAM_reserve_all", Type: cty.Bool, Required: false},
|
||||
"RAM_hot_plug": &hcldec.AttrSpec{Name: "RAM_hot_plug", Type: cty.Bool, Required: false},
|
||||
"video_ram": &hcldec.AttrSpec{Name: "video_ram", Type: cty.Number, Required: false},
|
||||
"vgpu_profile": &hcldec.AttrSpec{Name: "vgpu_profile", Type: cty.String, Required: false},
|
||||
"NestedHV": &hcldec.AttrSpec{Name: "NestedHV", Type: cty.Bool, Required: false},
|
||||
"firmware": &hcldec.AttrSpec{Name: "firmware", Type: cty.String, Required: false},
|
||||
"force_bios_setup": &hcldec.AttrSpec{Name: "force_bios_setup", Type: cty.Bool, Required: false},
|
||||
"configuration_parameters": &hcldec.AttrSpec{Name: "configuration_parameters", Type: cty.Map(cty.String), Required: false},
|
||||
"tools_sync_time": &hcldec.AttrSpec{Name: "tools_sync_time", Type: cty.Bool, Required: false},
|
||||
"tools_upgrade_policy": &hcldec.AttrSpec{Name: "tools_upgrade_policy", Type: cty.Bool, Required: false},
|
||||
"cdrom_type": &hcldec.AttrSpec{Name: "cdrom_type", Type: cty.String, Required: false},
|
||||
"iso_paths": &hcldec.AttrSpec{Name: "iso_paths", Type: cty.List(cty.String), Required: false},
|
||||
"remove_cdrom": &hcldec.AttrSpec{Name: "remove_cdrom", Type: cty.Bool, Required: false},
|
||||
"floppy_img_path": &hcldec.AttrSpec{Name: "floppy_img_path", Type: cty.String, Required: false},
|
||||
"floppy_files": &hcldec.AttrSpec{Name: "floppy_files", Type: cty.List(cty.String), Required: false},
|
||||
"floppy_dirs": &hcldec.AttrSpec{Name: "floppy_dirs", Type: cty.List(cty.String), Required: false},
|
||||
"floppy_label": &hcldec.AttrSpec{Name: "floppy_label", Type: cty.String, Required: false},
|
||||
"boot_order": &hcldec.AttrSpec{Name: "boot_order", Type: cty.String, Required: false},
|
||||
"boot_keygroup_interval": &hcldec.AttrSpec{Name: "boot_keygroup_interval", Type: cty.String, Required: false},
|
||||
"boot_wait": &hcldec.AttrSpec{Name: "boot_wait", Type: cty.String, Required: false},
|
||||
"boot_command": &hcldec.AttrSpec{Name: "boot_command", Type: cty.List(cty.String), Required: false},
|
||||
"http_ip": &hcldec.AttrSpec{Name: "http_ip", Type: cty.String, Required: false},
|
||||
"ip_wait_timeout": &hcldec.AttrSpec{Name: "ip_wait_timeout", Type: cty.String, Required: false},
|
||||
"ip_settle_timeout": &hcldec.AttrSpec{Name: "ip_settle_timeout", Type: cty.String, Required: false},
|
||||
"ip_wait_address": &hcldec.AttrSpec{Name: "ip_wait_address", Type: cty.String, Required: false},
|
||||
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
|
||||
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
|
||||
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},
|
||||
"ssh_port": &hcldec.AttrSpec{Name: "ssh_port", Type: cty.Number, Required: false},
|
||||
"ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
|
||||
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
|
||||
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
|
||||
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
|
||||
"temporary_key_pair_type": &hcldec.AttrSpec{Name: "temporary_key_pair_type", Type: cty.String, Required: false},
|
||||
"temporary_key_pair_bits": &hcldec.AttrSpec{Name: "temporary_key_pair_bits", Type: cty.Number, Required: false},
|
||||
"ssh_ciphers": &hcldec.AttrSpec{Name: "ssh_ciphers", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
|
||||
"ssh_key_exchange_algorithms": &hcldec.AttrSpec{Name: "ssh_key_exchange_algorithms", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_private_key_file": &hcldec.AttrSpec{Name: "ssh_private_key_file", Type: cty.String, Required: false},
|
||||
"ssh_certificate_file": &hcldec.AttrSpec{Name: "ssh_certificate_file", Type: cty.String, Required: false},
|
||||
"ssh_pty": &hcldec.AttrSpec{Name: "ssh_pty", Type: cty.Bool, Required: false},
|
||||
"ssh_timeout": &hcldec.AttrSpec{Name: "ssh_timeout", Type: cty.String, Required: false},
|
||||
"ssh_wait_timeout": &hcldec.AttrSpec{Name: "ssh_wait_timeout", Type: cty.String, Required: false},
|
||||
"ssh_agent_auth": &hcldec.AttrSpec{Name: "ssh_agent_auth", Type: cty.Bool, Required: false},
|
||||
"ssh_disable_agent_forwarding": &hcldec.AttrSpec{Name: "ssh_disable_agent_forwarding", Type: cty.Bool, Required: false},
|
||||
"ssh_handshake_attempts": &hcldec.AttrSpec{Name: "ssh_handshake_attempts", Type: cty.Number, Required: false},
|
||||
"ssh_bastion_host": &hcldec.AttrSpec{Name: "ssh_bastion_host", Type: cty.String, Required: false},
|
||||
"ssh_bastion_port": &hcldec.AttrSpec{Name: "ssh_bastion_port", Type: cty.Number, Required: false},
|
||||
"ssh_bastion_agent_auth": &hcldec.AttrSpec{Name: "ssh_bastion_agent_auth", Type: cty.Bool, Required: false},
|
||||
"ssh_bastion_username": &hcldec.AttrSpec{Name: "ssh_bastion_username", Type: cty.String, Required: false},
|
||||
"ssh_bastion_password": &hcldec.AttrSpec{Name: "ssh_bastion_password", Type: cty.String, Required: false},
|
||||
"ssh_bastion_interactive": &hcldec.AttrSpec{Name: "ssh_bastion_interactive", Type: cty.Bool, Required: false},
|
||||
"ssh_bastion_private_key_file": &hcldec.AttrSpec{Name: "ssh_bastion_private_key_file", Type: cty.String, Required: false},
|
||||
"ssh_bastion_certificate_file": &hcldec.AttrSpec{Name: "ssh_bastion_certificate_file", Type: cty.String, Required: false},
|
||||
"ssh_file_transfer_method": &hcldec.AttrSpec{Name: "ssh_file_transfer_method", Type: cty.String, Required: false},
|
||||
"ssh_proxy_host": &hcldec.AttrSpec{Name: "ssh_proxy_host", Type: cty.String, Required: false},
|
||||
"ssh_proxy_port": &hcldec.AttrSpec{Name: "ssh_proxy_port", Type: cty.Number, Required: false},
|
||||
"ssh_proxy_username": &hcldec.AttrSpec{Name: "ssh_proxy_username", Type: cty.String, Required: false},
|
||||
"ssh_proxy_password": &hcldec.AttrSpec{Name: "ssh_proxy_password", Type: cty.String, Required: false},
|
||||
"ssh_keep_alive_interval": &hcldec.AttrSpec{Name: "ssh_keep_alive_interval", Type: cty.String, Required: false},
|
||||
"ssh_read_write_timeout": &hcldec.AttrSpec{Name: "ssh_read_write_timeout", Type: cty.String, Required: false},
|
||||
"ssh_remote_tunnels": &hcldec.AttrSpec{Name: "ssh_remote_tunnels", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_local_tunnels": &hcldec.AttrSpec{Name: "ssh_local_tunnels", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_public_key": &hcldec.AttrSpec{Name: "ssh_public_key", Type: cty.List(cty.Number), Required: false},
|
||||
"ssh_private_key": &hcldec.AttrSpec{Name: "ssh_private_key", Type: cty.List(cty.Number), Required: false},
|
||||
"winrm_username": &hcldec.AttrSpec{Name: "winrm_username", Type: cty.String, Required: false},
|
||||
"winrm_password": &hcldec.AttrSpec{Name: "winrm_password", Type: cty.String, Required: false},
|
||||
"winrm_host": &hcldec.AttrSpec{Name: "winrm_host", Type: cty.String, Required: false},
|
||||
"winrm_no_proxy": &hcldec.AttrSpec{Name: "winrm_no_proxy", Type: cty.Bool, Required: false},
|
||||
"winrm_port": &hcldec.AttrSpec{Name: "winrm_port", Type: cty.Number, Required: false},
|
||||
"winrm_timeout": &hcldec.AttrSpec{Name: "winrm_timeout", Type: cty.String, Required: false},
|
||||
"winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false},
|
||||
"winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false},
|
||||
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
|
||||
"shutdown_command": &hcldec.AttrSpec{Name: "shutdown_command", Type: cty.String, Required: false},
|
||||
"shutdown_timeout": &hcldec.AttrSpec{Name: "shutdown_timeout", Type: cty.String, Required: false},
|
||||
"disable_shutdown": &hcldec.AttrSpec{Name: "disable_shutdown", Type: cty.Bool, Required: false},
|
||||
"create_snapshot": &hcldec.AttrSpec{Name: "create_snapshot", Type: cty.Bool, Required: false},
|
||||
"convert_to_template": &hcldec.AttrSpec{Name: "convert_to_template", Type: cty.Bool, Required: false},
|
||||
"export": &hcldec.BlockSpec{TypeName: "export", Nested: hcldec.ObjectSpec((*common.FlatExportConfig)(nil).HCL2Spec())},
|
||||
"content_library_destination": &hcldec.BlockSpec{TypeName: "content_library_destination", Nested: hcldec.ObjectSpec((*common.FlatContentLibraryDestinationConfig)(nil).HCL2Spec())},
|
||||
"customize": &hcldec.BlockSpec{TypeName: "customize", Nested: hcldec.ObjectSpec((*FlatCustomizeConfig)(nil).HCL2Spec())},
|
||||
}
|
||||
return s
|
||||
}
|
136
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/clone/step_clone.go
generated
vendored
Normal file
136
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/clone/step_clone.go
generated
vendored
Normal file
|
@ -0,0 +1,136 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type CloneConfig,vAppConfig
|
||||
|
||||
package clone
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
type vAppConfig struct {
|
||||
// Set values for the available vApp Properties to supply configuration parameters to a virtual machine cloned from
|
||||
// a template that came from an imported OVF or OVA file.
|
||||
//
|
||||
// -> **Note:** The only supported usage path for vApp properties is for existing user-configurable keys.
|
||||
// These generally come from an existing template that was created from an imported OVF or OVA file.
|
||||
// You cannot set values for vApp properties on virtual machines created from scratch,
|
||||
// virtual machines lacking a vApp configuration, or on property keys that do not exist.
|
||||
Properties map[string]string `mapstructure:"properties"`
|
||||
}
|
||||
|
||||
type CloneConfig struct {
|
||||
// Name of source VM. Path is optional.
|
||||
Template string `mapstructure:"template"`
|
||||
// The size of the disk in MB.
|
||||
DiskSize int64 `mapstructure:"disk_size"`
|
||||
// Create VM as a linked clone from latest snapshot. Defaults to `false`.
|
||||
LinkedClone bool `mapstructure:"linked_clone"`
|
||||
// Set the network in which the VM will be connected to. If no network is
|
||||
// specified, `host` must be specified to allow Packer to look for the
|
||||
// available network. If the network is inside a network folder in vCenter,
|
||||
// you need to provide the full path to the network.
|
||||
Network string `mapstructure:"network"`
|
||||
// Sets a custom Mac Address to the network adapter. If set, the [network](#network) must be also specified.
|
||||
MacAddress string `mapstructure:"mac_address"`
|
||||
// VM notes.
|
||||
Notes string `mapstructure:"notes"`
|
||||
// Set the vApp Options to a virtual machine.
|
||||
// See the [vApp Options Configuration](/docs/builders/vmware/vsphere-clone#vapp-options-configuration)
|
||||
// to know the available options and how to use it.
|
||||
VAppConfig vAppConfig `mapstructure:"vapp"`
|
||||
StorageConfig common.StorageConfig `mapstructure:",squash"`
|
||||
}
|
||||
|
||||
func (c *CloneConfig) Prepare() []error {
|
||||
var errs []error
|
||||
errs = append(errs, c.StorageConfig.Prepare()...)
|
||||
|
||||
if c.Template == "" {
|
||||
errs = append(errs, fmt.Errorf("'template' is required"))
|
||||
}
|
||||
|
||||
if c.LinkedClone == true && c.DiskSize != 0 {
|
||||
errs = append(errs, fmt.Errorf("'linked_clone' and 'disk_size' cannot be used together"))
|
||||
}
|
||||
|
||||
if c.MacAddress != "" && c.Network == "" {
|
||||
errs = append(errs, fmt.Errorf("'network' is required when 'mac_address' is specified"))
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
type StepCloneVM struct {
|
||||
Config *CloneConfig
|
||||
Location *common.LocationConfig
|
||||
Force bool
|
||||
}
|
||||
|
||||
func (s *StepCloneVM) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
d := state.Get("driver").(driver.Driver)
|
||||
vmPath := path.Join(s.Location.Folder, s.Location.VMName)
|
||||
|
||||
err := d.PreCleanVM(ui, vmPath, s.Force)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
ui.Say("Cloning VM...")
|
||||
template, err := d.FindVM(s.Config.Template)
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf("Error finding vm to clone: %s", err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
var disks []driver.Disk
|
||||
for _, disk := range s.Config.StorageConfig.Storage {
|
||||
disks = append(disks, driver.Disk{
|
||||
DiskSize: disk.DiskSize,
|
||||
DiskEagerlyScrub: disk.DiskEagerlyScrub,
|
||||
DiskThinProvisioned: disk.DiskThinProvisioned,
|
||||
ControllerIndex: disk.DiskControllerIndex,
|
||||
})
|
||||
}
|
||||
|
||||
vm, err := template.Clone(ctx, &driver.CloneConfig{
|
||||
Name: s.Location.VMName,
|
||||
Folder: s.Location.Folder,
|
||||
Cluster: s.Location.Cluster,
|
||||
Host: s.Location.Host,
|
||||
ResourcePool: s.Location.ResourcePool,
|
||||
Datastore: s.Location.Datastore,
|
||||
LinkedClone: s.Config.LinkedClone,
|
||||
Network: s.Config.Network,
|
||||
MacAddress: s.Config.MacAddress,
|
||||
Annotation: s.Config.Notes,
|
||||
VAppProperties: s.Config.VAppConfig.Properties,
|
||||
PrimaryDiskSize: s.Config.DiskSize,
|
||||
StorageConfig: driver.StorageConfig{
|
||||
DiskControllerType: s.Config.StorageConfig.DiskControllerType,
|
||||
Storage: disks,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
if vm == nil {
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
state.Put("vm", vm)
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepCloneVM) Cleanup(state multistep.StateBag) {
|
||||
common.CleanupVM(state)
|
||||
}
|
71
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/clone/step_clone.hcl2spec.go
generated
vendored
Normal file
71
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/clone/step_clone.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type CloneConfig,vAppConfig"; DO NOT EDIT.
|
||||
|
||||
package clone
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatCloneConfig is an auto-generated flat version of CloneConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatCloneConfig struct {
|
||||
Template *string `mapstructure:"template" cty:"template" hcl:"template"`
|
||||
DiskSize *int64 `mapstructure:"disk_size" cty:"disk_size" hcl:"disk_size"`
|
||||
LinkedClone *bool `mapstructure:"linked_clone" cty:"linked_clone" hcl:"linked_clone"`
|
||||
Network *string `mapstructure:"network" cty:"network" hcl:"network"`
|
||||
MacAddress *string `mapstructure:"mac_address" cty:"mac_address" hcl:"mac_address"`
|
||||
Notes *string `mapstructure:"notes" cty:"notes" hcl:"notes"`
|
||||
VAppConfig *FlatvAppConfig `mapstructure:"vapp" cty:"vapp" hcl:"vapp"`
|
||||
DiskControllerType []string `mapstructure:"disk_controller_type" cty:"disk_controller_type" hcl:"disk_controller_type"`
|
||||
Storage []common.FlatDiskConfig `mapstructure:"storage" cty:"storage" hcl:"storage"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatCloneConfig.
|
||||
// FlatCloneConfig is an auto-generated flat version of CloneConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*CloneConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatCloneConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a CloneConfig.
|
||||
// This spec is used by HCL to read the fields of CloneConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatCloneConfig.
|
||||
func (*FlatCloneConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"template": &hcldec.AttrSpec{Name: "template", Type: cty.String, Required: false},
|
||||
"disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, Required: false},
|
||||
"linked_clone": &hcldec.AttrSpec{Name: "linked_clone", Type: cty.Bool, Required: false},
|
||||
"network": &hcldec.AttrSpec{Name: "network", Type: cty.String, Required: false},
|
||||
"mac_address": &hcldec.AttrSpec{Name: "mac_address", Type: cty.String, Required: false},
|
||||
"notes": &hcldec.AttrSpec{Name: "notes", Type: cty.String, Required: false},
|
||||
"vapp": &hcldec.BlockSpec{TypeName: "vapp", Nested: hcldec.ObjectSpec((*FlatvAppConfig)(nil).HCL2Spec())},
|
||||
"disk_controller_type": &hcldec.AttrSpec{Name: "disk_controller_type", Type: cty.List(cty.String), Required: false},
|
||||
"storage": &hcldec.BlockListSpec{TypeName: "storage", Nested: hcldec.ObjectSpec((*common.FlatDiskConfig)(nil).HCL2Spec())},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// FlatvAppConfig is an auto-generated flat version of vAppConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatvAppConfig struct {
|
||||
Properties map[string]string `mapstructure:"properties" cty:"properties" hcl:"properties"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatvAppConfig.
|
||||
// FlatvAppConfig is an auto-generated flat version of vAppConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*vAppConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatvAppConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a vAppConfig.
|
||||
// This spec is used by HCL to read the fields of vAppConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatvAppConfig.
|
||||
func (*FlatvAppConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"properties": &hcldec.AttrSpec{Name: "properties", Type: cty.Map(cty.String), Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
276
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/clone/step_customize.go
generated
vendored
Normal file
276
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/clone/step_customize.go
generated
vendored
Normal file
|
@ -0,0 +1,276 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type CustomizeConfig,LinuxOptions,NetworkInterfaces,NetworkInterface,GlobalDnsSettings,GlobalRoutingSettings
|
||||
package clone
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
// A cloned virtual machine can be [customized](https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.vsphere.vm_admin.doc/GUID-58E346FF-83AE-42B8-BE58-253641D257BC.html)
|
||||
// to configure host, network, or licensing settings.
|
||||
//
|
||||
// To perform virtual machine customization as a part of the clone process, specify the customize block with the
|
||||
// respective customization options. Windows guests are customized using Sysprep, which will result in the machine SID being reset.
|
||||
// Before using customization, check that your source VM meets the [requirements](https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.vsphere.vm_admin.doc/GUID-E63B6FAA-8D35-428D-B40C-744769845906.html)
|
||||
// for guest OS customization on vSphere.
|
||||
// See the [customization example](#customization-example) for a usage synopsis.
|
||||
//
|
||||
// The settings for customize are as follows:
|
||||
type CustomizeConfig struct {
|
||||
// Settings to Linux guest OS customization. See [Linux customization settings](#linux-customization-settings).
|
||||
LinuxOptions *LinuxOptions `mapstructure:"linux_options"`
|
||||
// Supply your own sysprep.xml file to allow full control of the customization process out-of-band of vSphere.
|
||||
WindowsSysPrepFile string `mapstructure:"windows_sysprep_file"`
|
||||
// Configure network interfaces on a per-interface basis that should matched up to the network adapters present in the VM.
|
||||
// To use DHCP, declare an empty network_interface for each adapter being configured. This field is required.
|
||||
// See [Network interface settings](#network-interface-settings).
|
||||
NetworkInterfaces NetworkInterfaces `mapstructure:"network_interface"`
|
||||
GlobalRoutingSettings `mapstructure:",squash"`
|
||||
GlobalDnsSettings `mapstructure:",squash"`
|
||||
}
|
||||
|
||||
type LinuxOptions struct {
|
||||
// The domain name for this machine. This, along with [host_name](#host_name), make up the FQDN of this virtual machine.
|
||||
Domain string `mapstructure:"domain"`
|
||||
// The host name for this machine. This, along with [domain](#domain), make up the FQDN of this virtual machine.
|
||||
Hostname string `mapstructure:"host_name"`
|
||||
// Tells the operating system that the hardware clock is set to UTC. Default: true.
|
||||
HWClockUTC config.Trilean `mapstructure:"hw_clock_utc"`
|
||||
// Sets the time zone. The default is UTC.
|
||||
Timezone string `mapstructure:"time_zone"`
|
||||
}
|
||||
|
||||
type NetworkInterface struct {
|
||||
// Network interface-specific DNS server settings for Windows operating systems.
|
||||
// Ignored on Linux and possibly other operating systems - for those systems, please see the [global DNS settings](#global-dns-settings) section.
|
||||
DnsServerList []string `mapstructure:"dns_server_list"`
|
||||
// Network interface-specific DNS search domain for Windows operating systems.
|
||||
// Ignored on Linux and possibly other operating systems - for those systems, please see the [global DNS settings](#global-dns-settings) section.
|
||||
DnsDomain string `mapstructure:"dns_domain"`
|
||||
// The IPv4 address assigned to this network adapter. If left blank or not included, DHCP is used.
|
||||
Ipv4Address string `mapstructure:"ipv4_address"`
|
||||
// The IPv4 subnet mask, in bits (example: 24 for 255.255.255.0).
|
||||
Ipv4NetMask int `mapstructure:"ipv4_netmask"`
|
||||
// The IPv6 address assigned to this network adapter. If left blank or not included, auto-configuration is used.
|
||||
Ipv6Address string `mapstructure:"ipv6_address"`
|
||||
// The IPv6 subnet mask, in bits (example: 32).
|
||||
Ipv6NetMask int `mapstructure:"ipv6_netmask"`
|
||||
}
|
||||
|
||||
type NetworkInterfaces []NetworkInterface
|
||||
|
||||
// The settings here must match the IP/mask of at least one network_interface supplied to customization.
|
||||
type GlobalRoutingSettings struct {
|
||||
// The IPv4 default gateway when using network_interface customization on the virtual machine.
|
||||
Ipv4Gateway string `mapstructure:"ipv4_gateway"`
|
||||
// The IPv6 default gateway when using network_interface customization on the virtual machine.
|
||||
Ipv6Gateway string `mapstructure:"ipv6_gateway"`
|
||||
}
|
||||
|
||||
// The following settings configure DNS globally, generally for Linux systems. For Windows systems,
|
||||
// this is done per-interface, see [network interface](#network_interface) settings.
|
||||
type GlobalDnsSettings struct {
|
||||
// The list of DNS servers to configure on a virtual machine.
|
||||
DnsServerList []string `mapstructure:"dns_server_list"`
|
||||
// A list of DNS search domains to add to the DNS configuration on the virtual machine.
|
||||
DnsSuffixList []string `mapstructure:"dns_suffix_list"`
|
||||
}
|
||||
|
||||
type StepCustomize struct {
|
||||
Config *CustomizeConfig
|
||||
}
|
||||
|
||||
func (c *CustomizeConfig) Prepare() []error {
|
||||
var errs []error
|
||||
|
||||
if c.LinuxOptions == nil && c.WindowsSysPrepFile == "" {
|
||||
errs = append(errs, fmt.Errorf("customize is empty"))
|
||||
}
|
||||
if c.LinuxOptions != nil && c.WindowsSysPrepFile != "" {
|
||||
errs = append(errs, fmt.Errorf("`linux_options` and `windows_sysprep_text` both set - one must not be included if the other is specified"))
|
||||
}
|
||||
|
||||
if c.LinuxOptions != nil {
|
||||
if c.LinuxOptions.Hostname == "" {
|
||||
errs = append(errs, fmt.Errorf("linux options `host_name` is empty"))
|
||||
}
|
||||
if c.LinuxOptions.Domain == "" {
|
||||
errs = append(errs, fmt.Errorf("linux options `domain` is empty"))
|
||||
}
|
||||
|
||||
if c.LinuxOptions.HWClockUTC == config.TriUnset {
|
||||
c.LinuxOptions.HWClockUTC = config.TriTrue
|
||||
}
|
||||
if c.LinuxOptions.Timezone == "" {
|
||||
c.LinuxOptions.Timezone = "UTC"
|
||||
}
|
||||
}
|
||||
|
||||
if len(c.NetworkInterfaces) == 0 {
|
||||
errs = append(errs, fmt.Errorf("one or more `network_interface` must be provided"))
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
func (s *StepCustomize) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
|
||||
identity, err := s.identitySettings()
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
nicSettingsMap := s.nicSettingsMap()
|
||||
globalIpSettings := s.globalIpSettings()
|
||||
|
||||
spec := types.CustomizationSpec{
|
||||
Identity: identity,
|
||||
NicSettingMap: nicSettingsMap,
|
||||
GlobalIPSettings: globalIpSettings,
|
||||
}
|
||||
ui.Say("Customizing VM...")
|
||||
err = vm.Customize(spec)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepCustomize) identitySettings() (types.BaseCustomizationIdentitySettings, error) {
|
||||
if s.Config.LinuxOptions != nil {
|
||||
return &types.CustomizationLinuxPrep{
|
||||
HostName: &types.CustomizationFixedName{
|
||||
Name: s.Config.LinuxOptions.Hostname,
|
||||
},
|
||||
Domain: s.Config.LinuxOptions.Domain,
|
||||
TimeZone: s.Config.LinuxOptions.Timezone,
|
||||
HwClockUTC: s.Config.LinuxOptions.HWClockUTC.ToBoolPointer(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
if s.Config.WindowsSysPrepFile != "" {
|
||||
sysPrep, err := ioutil.ReadFile(s.Config.WindowsSysPrepFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error on reading %s: %s", s.Config.WindowsSysPrepFile, err)
|
||||
}
|
||||
return &types.CustomizationSysprepText{
|
||||
Value: string(sysPrep),
|
||||
}, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no customization identity found")
|
||||
}
|
||||
|
||||
func (s *StepCustomize) nicSettingsMap() []types.CustomizationAdapterMapping {
|
||||
result := make([]types.CustomizationAdapterMapping, len(s.Config.NetworkInterfaces))
|
||||
var ipv4gwFound, ipv6gwFound bool
|
||||
for i := range s.Config.NetworkInterfaces {
|
||||
var adapter types.CustomizationIPSettings
|
||||
adapter, ipv4gwFound, ipv6gwFound = s.ipSettings(i, !ipv4gwFound, !ipv6gwFound)
|
||||
obj := types.CustomizationAdapterMapping{
|
||||
Adapter: adapter,
|
||||
}
|
||||
result[i] = obj
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *StepCustomize) ipSettings(n int, ipv4gwAdd bool, ipv6gwAdd bool) (types.CustomizationIPSettings, bool, bool) {
|
||||
var v4gwFound, v6gwFound bool
|
||||
var obj types.CustomizationIPSettings
|
||||
|
||||
ipv4Address := s.Config.NetworkInterfaces[n].Ipv4Address
|
||||
if ipv4Address != "" {
|
||||
ipv4mask := s.Config.NetworkInterfaces[n].Ipv4NetMask
|
||||
ipv4Gateway := s.Config.Ipv4Gateway
|
||||
obj.Ip = &types.CustomizationFixedIp{
|
||||
IpAddress: ipv4Address,
|
||||
}
|
||||
obj.SubnetMask = v4CIDRMaskToDotted(ipv4mask)
|
||||
// Check for the gateway
|
||||
if ipv4gwAdd && ipv4Gateway != "" && matchGateway(ipv4Address, ipv4mask, ipv4Gateway) {
|
||||
obj.Gateway = []string{ipv4Gateway}
|
||||
v4gwFound = true
|
||||
}
|
||||
} else {
|
||||
obj.Ip = &types.CustomizationDhcpIpGenerator{}
|
||||
}
|
||||
|
||||
obj.DnsServerList = s.Config.NetworkInterfaces[n].DnsServerList
|
||||
obj.DnsDomain = s.Config.NetworkInterfaces[n].DnsDomain
|
||||
obj.IpV6Spec, v6gwFound = s.IPSettingsIPV6Address(n, ipv6gwAdd)
|
||||
|
||||
return obj, v4gwFound, v6gwFound
|
||||
}
|
||||
|
||||
func v4CIDRMaskToDotted(mask int) string {
|
||||
m := net.CIDRMask(mask, 32)
|
||||
a := int(m[0])
|
||||
b := int(m[1])
|
||||
c := int(m[2])
|
||||
d := int(m[3])
|
||||
return fmt.Sprintf("%d.%d.%d.%d", a, b, c, d)
|
||||
}
|
||||
|
||||
func (s *StepCustomize) IPSettingsIPV6Address(n int, gwAdd bool) (*types.CustomizationIPSettingsIpV6AddressSpec, bool) {
|
||||
addr := s.Config.NetworkInterfaces[n].Ipv6Address
|
||||
var gwFound bool
|
||||
if addr == "" {
|
||||
return nil, gwFound
|
||||
}
|
||||
mask := s.Config.NetworkInterfaces[n].Ipv6NetMask
|
||||
gw := s.Config.Ipv6Gateway
|
||||
obj := &types.CustomizationIPSettingsIpV6AddressSpec{
|
||||
Ip: []types.BaseCustomizationIpV6Generator{
|
||||
&types.CustomizationFixedIpV6{
|
||||
IpAddress: addr,
|
||||
SubnetMask: int32(mask),
|
||||
},
|
||||
},
|
||||
}
|
||||
if gwAdd && gw != "" && matchGateway(addr, mask, gw) {
|
||||
obj.Gateway = []string{gw}
|
||||
gwFound = true
|
||||
}
|
||||
return obj, gwFound
|
||||
}
|
||||
|
||||
// matchGateway take an IP, mask, and gateway, and checks to see if the gateway
|
||||
// is reachable from the IP address.
|
||||
func matchGateway(a string, m int, g string) bool {
|
||||
ip := net.ParseIP(a)
|
||||
gw := net.ParseIP(g)
|
||||
var mask net.IPMask
|
||||
if ip.To4() != nil {
|
||||
mask = net.CIDRMask(m, 32)
|
||||
} else {
|
||||
mask = net.CIDRMask(m, 128)
|
||||
}
|
||||
if ip.Mask(mask).Equal(gw.Mask(mask)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *StepCustomize) globalIpSettings() types.CustomizationGlobalIPSettings {
|
||||
return types.CustomizationGlobalIPSettings{
|
||||
DnsServerList: s.Config.DnsServerList,
|
||||
DnsSuffixList: s.Config.DnsSuffixList,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StepCustomize) Cleanup(_ multistep.StateBag) {}
|
155
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/clone/step_customize.hcl2spec.go
generated
vendored
Normal file
155
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/clone/step_customize.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,155 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type CustomizeConfig,LinuxOptions,NetworkInterfaces,NetworkInterface,GlobalDnsSettings,GlobalRoutingSettings"; DO NOT EDIT.
|
||||
|
||||
package clone
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatCustomizeConfig is an auto-generated flat version of CustomizeConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatCustomizeConfig struct {
|
||||
LinuxOptions *FlatLinuxOptions `mapstructure:"linux_options" cty:"linux_options" hcl:"linux_options"`
|
||||
WindowsSysPrepFile *string `mapstructure:"windows_sysprep_file" cty:"windows_sysprep_file" hcl:"windows_sysprep_file"`
|
||||
NetworkInterfaces []FlatNetworkInterface `mapstructure:"network_interface" cty:"network_interface" hcl:"network_interface"`
|
||||
Ipv4Gateway *string `mapstructure:"ipv4_gateway" cty:"ipv4_gateway" hcl:"ipv4_gateway"`
|
||||
Ipv6Gateway *string `mapstructure:"ipv6_gateway" cty:"ipv6_gateway" hcl:"ipv6_gateway"`
|
||||
DnsServerList []string `mapstructure:"dns_server_list" cty:"dns_server_list" hcl:"dns_server_list"`
|
||||
DnsSuffixList []string `mapstructure:"dns_suffix_list" cty:"dns_suffix_list" hcl:"dns_suffix_list"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatCustomizeConfig.
|
||||
// FlatCustomizeConfig is an auto-generated flat version of CustomizeConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*CustomizeConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatCustomizeConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a CustomizeConfig.
|
||||
// This spec is used by HCL to read the fields of CustomizeConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatCustomizeConfig.
|
||||
func (*FlatCustomizeConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"linux_options": &hcldec.BlockSpec{TypeName: "linux_options", Nested: hcldec.ObjectSpec((*FlatLinuxOptions)(nil).HCL2Spec())},
|
||||
"windows_sysprep_file": &hcldec.AttrSpec{Name: "windows_sysprep_file", Type: cty.String, Required: false},
|
||||
"network_interface": &hcldec.BlockListSpec{TypeName: "network_interface", Nested: hcldec.ObjectSpec((*FlatNetworkInterface)(nil).HCL2Spec())},
|
||||
"ipv4_gateway": &hcldec.AttrSpec{Name: "ipv4_gateway", Type: cty.String, Required: false},
|
||||
"ipv6_gateway": &hcldec.AttrSpec{Name: "ipv6_gateway", Type: cty.String, Required: false},
|
||||
"dns_server_list": &hcldec.AttrSpec{Name: "dns_server_list", Type: cty.List(cty.String), Required: false},
|
||||
"dns_suffix_list": &hcldec.AttrSpec{Name: "dns_suffix_list", Type: cty.List(cty.String), Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// FlatGlobalDnsSettings is an auto-generated flat version of GlobalDnsSettings.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatGlobalDnsSettings struct {
|
||||
DnsServerList []string `mapstructure:"dns_server_list" cty:"dns_server_list" hcl:"dns_server_list"`
|
||||
DnsSuffixList []string `mapstructure:"dns_suffix_list" cty:"dns_suffix_list" hcl:"dns_suffix_list"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatGlobalDnsSettings.
|
||||
// FlatGlobalDnsSettings is an auto-generated flat version of GlobalDnsSettings.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*GlobalDnsSettings) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatGlobalDnsSettings)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a GlobalDnsSettings.
|
||||
// This spec is used by HCL to read the fields of GlobalDnsSettings.
|
||||
// The decoded values from this spec will then be applied to a FlatGlobalDnsSettings.
|
||||
func (*FlatGlobalDnsSettings) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"dns_server_list": &hcldec.AttrSpec{Name: "dns_server_list", Type: cty.List(cty.String), Required: false},
|
||||
"dns_suffix_list": &hcldec.AttrSpec{Name: "dns_suffix_list", Type: cty.List(cty.String), Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// FlatGlobalRoutingSettings is an auto-generated flat version of GlobalRoutingSettings.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatGlobalRoutingSettings struct {
|
||||
Ipv4Gateway *string `mapstructure:"ipv4_gateway" cty:"ipv4_gateway" hcl:"ipv4_gateway"`
|
||||
Ipv6Gateway *string `mapstructure:"ipv6_gateway" cty:"ipv6_gateway" hcl:"ipv6_gateway"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatGlobalRoutingSettings.
|
||||
// FlatGlobalRoutingSettings is an auto-generated flat version of GlobalRoutingSettings.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*GlobalRoutingSettings) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatGlobalRoutingSettings)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a GlobalRoutingSettings.
|
||||
// This spec is used by HCL to read the fields of GlobalRoutingSettings.
|
||||
// The decoded values from this spec will then be applied to a FlatGlobalRoutingSettings.
|
||||
func (*FlatGlobalRoutingSettings) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"ipv4_gateway": &hcldec.AttrSpec{Name: "ipv4_gateway", Type: cty.String, Required: false},
|
||||
"ipv6_gateway": &hcldec.AttrSpec{Name: "ipv6_gateway", Type: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// FlatLinuxOptions is an auto-generated flat version of LinuxOptions.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatLinuxOptions struct {
|
||||
Domain *string `mapstructure:"domain" cty:"domain" hcl:"domain"`
|
||||
Hostname *string `mapstructure:"host_name" cty:"host_name" hcl:"host_name"`
|
||||
HWClockUTC *bool `mapstructure:"hw_clock_utc" cty:"hw_clock_utc" hcl:"hw_clock_utc"`
|
||||
Timezone *string `mapstructure:"time_zone" cty:"time_zone" hcl:"time_zone"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatLinuxOptions.
|
||||
// FlatLinuxOptions is an auto-generated flat version of LinuxOptions.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*LinuxOptions) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatLinuxOptions)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a LinuxOptions.
|
||||
// This spec is used by HCL to read the fields of LinuxOptions.
|
||||
// The decoded values from this spec will then be applied to a FlatLinuxOptions.
|
||||
func (*FlatLinuxOptions) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"domain": &hcldec.AttrSpec{Name: "domain", Type: cty.String, Required: false},
|
||||
"host_name": &hcldec.AttrSpec{Name: "host_name", Type: cty.String, Required: false},
|
||||
"hw_clock_utc": &hcldec.AttrSpec{Name: "hw_clock_utc", Type: cty.Bool, Required: false},
|
||||
"time_zone": &hcldec.AttrSpec{Name: "time_zone", Type: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// FlatNetworkInterface is an auto-generated flat version of NetworkInterface.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatNetworkInterface struct {
|
||||
DnsServerList []string `mapstructure:"dns_server_list" cty:"dns_server_list" hcl:"dns_server_list"`
|
||||
DnsDomain *string `mapstructure:"dns_domain" cty:"dns_domain" hcl:"dns_domain"`
|
||||
Ipv4Address *string `mapstructure:"ipv4_address" cty:"ipv4_address" hcl:"ipv4_address"`
|
||||
Ipv4NetMask *int `mapstructure:"ipv4_netmask" cty:"ipv4_netmask" hcl:"ipv4_netmask"`
|
||||
Ipv6Address *string `mapstructure:"ipv6_address" cty:"ipv6_address" hcl:"ipv6_address"`
|
||||
Ipv6NetMask *int `mapstructure:"ipv6_netmask" cty:"ipv6_netmask" hcl:"ipv6_netmask"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatNetworkInterface.
|
||||
// FlatNetworkInterface is an auto-generated flat version of NetworkInterface.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*NetworkInterface) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatNetworkInterface)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a NetworkInterface.
|
||||
// This spec is used by HCL to read the fields of NetworkInterface.
|
||||
// The decoded values from this spec will then be applied to a FlatNetworkInterface.
|
||||
func (*FlatNetworkInterface) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"dns_server_list": &hcldec.AttrSpec{Name: "dns_server_list", Type: cty.List(cty.String), Required: false},
|
||||
"dns_domain": &hcldec.AttrSpec{Name: "dns_domain", Type: cty.String, Required: false},
|
||||
"ipv4_address": &hcldec.AttrSpec{Name: "ipv4_address", Type: cty.String, Required: false},
|
||||
"ipv4_netmask": &hcldec.AttrSpec{Name: "ipv4_netmask", Type: cty.Number, Required: false},
|
||||
"ipv6_address": &hcldec.AttrSpec{Name: "ipv6_address", Type: cty.String, Required: false},
|
||||
"ipv6_netmask": &hcldec.AttrSpec{Name: "ipv6_netmask", Type: cty.Number, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
50
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/artifact.go
generated
vendored
Normal file
50
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/artifact.go
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
const BuilderId = "jetbrains.vsphere"
|
||||
|
||||
type Artifact struct {
|
||||
Outconfig *OutputConfig
|
||||
Name string
|
||||
VM *driver.VirtualMachineDriver
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (a *Artifact) BuilderId() string {
|
||||
return BuilderId
|
||||
}
|
||||
|
||||
func (a *Artifact) Files() []string {
|
||||
if a.Outconfig != nil {
|
||||
files, _ := a.Outconfig.ListFiles()
|
||||
return files
|
||||
}
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func (a *Artifact) Id() string {
|
||||
return a.Name
|
||||
}
|
||||
|
||||
func (a *Artifact) String() string {
|
||||
return a.Name
|
||||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
if a.Outconfig != nil {
|
||||
os.RemoveAll(a.Outconfig.OutputDir)
|
||||
}
|
||||
return a.VM.Destroy()
|
||||
}
|
30
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/cleanup_vm.go
generated
vendored
Normal file
30
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/cleanup_vm.go
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
func CleanupVM(state multistep.StateBag) {
|
||||
_, cancelled := state.GetOk(multistep.StateCancelled)
|
||||
_, halted := state.GetOk(multistep.StateHalted)
|
||||
_, destroy := state.GetOk("destroy_vm")
|
||||
if !cancelled && !halted && !destroy {
|
||||
return
|
||||
}
|
||||
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
|
||||
st := state.Get("vm")
|
||||
if st == nil {
|
||||
return
|
||||
}
|
||||
vm := st.(driver.VirtualMachine)
|
||||
|
||||
ui.Say("Destroying VM...")
|
||||
err := vm.Destroy()
|
||||
if err != nil {
|
||||
ui.Error(err.Error())
|
||||
}
|
||||
}
|
53
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/config_location.go
generated
vendored
Normal file
53
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/config_location.go
generated
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type LocationConfig
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type LocationConfig struct {
|
||||
// Name of the new VM to create.
|
||||
VMName string `mapstructure:"vm_name"`
|
||||
// VM folder to create the VM in.
|
||||
Folder string `mapstructure:"folder"`
|
||||
// ESXi cluster where target VM is created. See the
|
||||
// [Working With Clusters And Hosts](#working-with-clusters-and-hosts)
|
||||
// section above for more details.
|
||||
Cluster string `mapstructure:"cluster"`
|
||||
// ESXi host where target VM is created. A full path must be specified if
|
||||
// the host is in a folder. For example `folder/host`. See the
|
||||
// [Working With Clusters And Hosts](#working-with-clusters-and-hosts)
|
||||
// section above for more details.
|
||||
Host string `mapstructure:"host"`
|
||||
// VMWare resource pool. If not set, it will look for the root resource
|
||||
// pool of the `host` or `cluster`. If a root resource is not found, it
|
||||
// will then look for a default resource pool.
|
||||
ResourcePool string `mapstructure:"resource_pool"`
|
||||
// VMWare datastore. Required if `host` is a cluster, or if `host` has
|
||||
// multiple datastores.
|
||||
Datastore string `mapstructure:"datastore"`
|
||||
// Set this to true if packer should use the host for uploading files
|
||||
// to the datastore. Defaults to false.
|
||||
SetHostForDatastoreUploads bool `mapstructure:"set_host_for_datastore_uploads"`
|
||||
}
|
||||
|
||||
func (c *LocationConfig) Prepare() []error {
|
||||
var errs []error
|
||||
|
||||
if c.VMName == "" {
|
||||
errs = append(errs, fmt.Errorf("'vm_name' is required"))
|
||||
}
|
||||
if c.Cluster == "" && c.Host == "" {
|
||||
errs = append(errs, fmt.Errorf("'host' or 'cluster' is required"))
|
||||
}
|
||||
|
||||
// clean Folder path and remove leading slash as folders are relative within vsphere
|
||||
c.Folder = path.Clean(c.Folder)
|
||||
c.Folder = strings.TrimLeft(c.Folder, "/")
|
||||
|
||||
return errs
|
||||
}
|
43
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/config_location.hcl2spec.go
generated
vendored
Normal file
43
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/config_location.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type LocationConfig"; DO NOT EDIT.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatLocationConfig is an auto-generated flat version of LocationConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatLocationConfig struct {
|
||||
VMName *string `mapstructure:"vm_name" cty:"vm_name" hcl:"vm_name"`
|
||||
Folder *string `mapstructure:"folder" cty:"folder" hcl:"folder"`
|
||||
Cluster *string `mapstructure:"cluster" cty:"cluster" hcl:"cluster"`
|
||||
Host *string `mapstructure:"host" cty:"host" hcl:"host"`
|
||||
ResourcePool *string `mapstructure:"resource_pool" cty:"resource_pool" hcl:"resource_pool"`
|
||||
Datastore *string `mapstructure:"datastore" cty:"datastore" hcl:"datastore"`
|
||||
SetHostForDatastoreUploads *bool `mapstructure:"set_host_for_datastore_uploads" cty:"set_host_for_datastore_uploads" hcl:"set_host_for_datastore_uploads"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatLocationConfig.
|
||||
// FlatLocationConfig is an auto-generated flat version of LocationConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*LocationConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatLocationConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a LocationConfig.
|
||||
// This spec is used by HCL to read the fields of LocationConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatLocationConfig.
|
||||
func (*FlatLocationConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"vm_name": &hcldec.AttrSpec{Name: "vm_name", Type: cty.String, Required: false},
|
||||
"folder": &hcldec.AttrSpec{Name: "folder", Type: cty.String, Required: false},
|
||||
"cluster": &hcldec.AttrSpec{Name: "cluster", Type: cty.String, Required: false},
|
||||
"host": &hcldec.AttrSpec{Name: "host", Type: cty.String, Required: false},
|
||||
"resource_pool": &hcldec.AttrSpec{Name: "resource_pool", Type: cty.String, Required: false},
|
||||
"datastore": &hcldec.AttrSpec{Name: "datastore", Type: cty.String, Required: false},
|
||||
"set_host_for_datastore_uploads": &hcldec.AttrSpec{Name: "set_host_for_datastore_uploads", Type: cty.Bool, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
15
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/config_ssh.go
generated
vendored
Normal file
15
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/config_ssh.go
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func CommHost(host string) func(multistep.StateBag) (string, error) {
|
||||
return func(state multistep.StateBag) (string, error) {
|
||||
if host != "" {
|
||||
return host, nil
|
||||
} else {
|
||||
return state.Get("ip").(string), nil
|
||||
}
|
||||
}
|
||||
}
|
59
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/output_config.go
generated
vendored
Normal file
59
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/output_config.go
generated
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type OutputConfig
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/common"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
)
|
||||
|
||||
type OutputConfig struct {
|
||||
// This setting specifies the directory that
|
||||
// artifacts from the build, such as the virtual machine files and disks,
|
||||
// will be output to. The path to the directory may be relative or
|
||||
// absolute. If relative, the path is relative to the working directory
|
||||
// packer is executed from. This directory must not exist or, if
|
||||
// created, must be empty prior to running the builder. By default this is
|
||||
// "output-BUILDNAME" where "BUILDNAME" is the name of the build.
|
||||
OutputDir string `mapstructure:"output_directory" required:"false"`
|
||||
// The permissions to apply to the "output_directory", and to any parent
|
||||
// directories that get created for output_directory. By default this is
|
||||
// "0750". You should express the permission as quoted string with a
|
||||
// leading zero such as "0755" in JSON file, because JSON does not support
|
||||
// octal value. In Unix-like OS, the actual permission may differ from
|
||||
// this value because of umask.
|
||||
DirPerm os.FileMode `mapstructure:"directory_permission" required:"false"`
|
||||
}
|
||||
|
||||
func (c *OutputConfig) Prepare(ctx *interpolate.Context, pc *common.PackerConfig) []error {
|
||||
if c.OutputDir == "" {
|
||||
c.OutputDir = fmt.Sprintf("output-%s", pc.PackerBuildName)
|
||||
}
|
||||
if c.DirPerm == 0 {
|
||||
c.DirPerm = 0750
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stolen from output_dir_local.go in vmware builder.
|
||||
func (c *OutputConfig) ListFiles() ([]string, error) {
|
||||
files := make([]string, 0, 10)
|
||||
|
||||
visit := func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() {
|
||||
files = append(files, path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return files, filepath.Walk(c.OutputDir, visit)
|
||||
}
|
35
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/output_config.hcl2spec.go
generated
vendored
Normal file
35
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/output_config.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type OutputConfig"; DO NOT EDIT.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatOutputConfig is an auto-generated flat version of OutputConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatOutputConfig struct {
|
||||
OutputDir *string `mapstructure:"output_directory" required:"false" cty:"output_directory" hcl:"output_directory"`
|
||||
DirPerm *fs.FileMode `mapstructure:"directory_permission" required:"false" cty:"directory_permission" hcl:"directory_permission"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatOutputConfig.
|
||||
// FlatOutputConfig is an auto-generated flat version of OutputConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*OutputConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatOutputConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a OutputConfig.
|
||||
// This spec is used by HCL to read the fields of OutputConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatOutputConfig.
|
||||
func (*FlatOutputConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"output_directory": &hcldec.AttrSpec{Name: "output_directory", Type: cty.String, Required: false},
|
||||
"directory_permission": &hcldec.AttrSpec{Name: "directory_permission", Type: cty.Number, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
81
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_add_cdrom.go
generated
vendored
Normal file
81
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_add_cdrom.go
generated
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type CDRomConfig
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
type CDRomConfig struct {
|
||||
// Which controller to use. Example: `sata`. Defaults to `ide`.
|
||||
CdromType string `mapstructure:"cdrom_type"`
|
||||
// List of Datastore or Content Library paths to ISO files that will be mounted to the VM.
|
||||
// Here's an HCL2 example:
|
||||
// ```hcl
|
||||
// iso_paths = [
|
||||
// "[datastore1] ISO/ubuntu.iso",
|
||||
// "Packer Library Test/ubuntu-16.04.6-server-amd64/ubuntu-16.04.6-server-amd64.iso"
|
||||
// ]
|
||||
// ```
|
||||
ISOPaths []string `mapstructure:"iso_paths"`
|
||||
}
|
||||
|
||||
type StepAddCDRom struct {
|
||||
Config *CDRomConfig
|
||||
}
|
||||
|
||||
func (c *CDRomConfig) Prepare() []error {
|
||||
var errs []error
|
||||
|
||||
if c.CdromType != "" && c.CdromType != "ide" && c.CdromType != "sata" {
|
||||
errs = append(errs, fmt.Errorf("'cdrom_type' must be 'ide' or 'sata'"))
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
func (s *StepAddCDRom) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
vm := state.Get("vm").(driver.VirtualMachine)
|
||||
|
||||
if s.Config.CdromType == "sata" {
|
||||
if _, err := vm.FindSATAController(); err == driver.ErrNoSataController {
|
||||
ui.Say("Adding SATA controller...")
|
||||
if err := vm.AddSATAController(); err != nil {
|
||||
state.Put("error", fmt.Errorf("error adding SATA controller: %v", err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui.Say("Mounting ISO images...")
|
||||
if path, ok := state.GetOk("iso_remote_path"); ok {
|
||||
if err := vm.AddCdrom(s.Config.CdromType, path.(string)); err != nil {
|
||||
state.Put("error", fmt.Errorf("error mounting an image '%v': %v", path, err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
|
||||
// Add our custom CD, if it exists
|
||||
if cd_path, _ := state.Get("cd_path").(string); cd_path != "" {
|
||||
s.Config.ISOPaths = append(s.Config.ISOPaths, cd_path)
|
||||
}
|
||||
|
||||
if len(s.Config.ISOPaths) > 0 {
|
||||
for _, path := range s.Config.ISOPaths {
|
||||
if err := vm.AddCdrom(s.Config.CdromType, path); err != nil {
|
||||
state.Put("error", fmt.Errorf("error mounting an image '%v': %v", path, err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
}
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepAddCDRom) Cleanup(state multistep.StateBag) {}
|
33
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_add_cdrom.hcl2spec.go
generated
vendored
Normal file
33
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_add_cdrom.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type CDRomConfig"; DO NOT EDIT.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatCDRomConfig is an auto-generated flat version of CDRomConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatCDRomConfig struct {
|
||||
CdromType *string `mapstructure:"cdrom_type" cty:"cdrom_type" hcl:"cdrom_type"`
|
||||
ISOPaths []string `mapstructure:"iso_paths" cty:"iso_paths" hcl:"iso_paths"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatCDRomConfig.
|
||||
// FlatCDRomConfig is an auto-generated flat version of CDRomConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*CDRomConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatCDRomConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a CDRomConfig.
|
||||
// This spec is used by HCL to read the fields of CDRomConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatCDRomConfig.
|
||||
func (*FlatCDRomConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"cdrom_type": &hcldec.AttrSpec{Name: "cdrom_type", Type: cty.String, Required: false},
|
||||
"iso_paths": &hcldec.AttrSpec{Name: "iso_paths", Type: cty.List(cty.String), Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
111
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_add_floppy.go
generated
vendored
Normal file
111
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_add_floppy.go
generated
vendored
Normal file
|
@ -0,0 +1,111 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type FloppyConfig
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
type FloppyConfig struct {
|
||||
// Datastore path to a floppy image that will be mounted to the VM.
|
||||
// Example: `[datastore1] ISO/pvscsi-Windows8.flp`.
|
||||
FloppyIMGPath string `mapstructure:"floppy_img_path"`
|
||||
// List of local files to be mounted to the VM floppy drive. Can be used to
|
||||
// make Debian preseed or RHEL kickstart files available to the VM.
|
||||
FloppyFiles []string `mapstructure:"floppy_files"`
|
||||
// List of directories to copy files from.
|
||||
FloppyDirectories []string `mapstructure:"floppy_dirs"`
|
||||
// The label to use for the floppy disk that
|
||||
// is attached when the VM is booted. This is most useful for cloud-init,
|
||||
// Kickstart or other early initialization tools, which can benefit from labelled floppy disks.
|
||||
// By default, the floppy label will be 'packer'.
|
||||
FloppyLabel string `mapstructure:"floppy_label"`
|
||||
}
|
||||
|
||||
type StepAddFloppy struct {
|
||||
Config *FloppyConfig
|
||||
Datastore string
|
||||
Host string
|
||||
SetHostForDatastoreUploads bool
|
||||
}
|
||||
|
||||
func (s *StepAddFloppy) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
vm := state.Get("vm").(driver.VirtualMachine)
|
||||
d := state.Get("driver").(driver.Driver)
|
||||
|
||||
if floppyPath, ok := state.GetOk("floppy_path"); ok {
|
||||
ui.Say("Uploading created floppy image")
|
||||
|
||||
ds, err := d.FindDatastore(s.Datastore, s.Host)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
vmDir, err := vm.GetDir()
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
uploadPath := fmt.Sprintf("%v/packer-tmp-created-floppy.flp", vmDir)
|
||||
if err := ds.UploadFile(floppyPath.(string), uploadPath, s.Host, s.SetHostForDatastoreUploads); err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
state.Put("uploaded_floppy_path", uploadPath)
|
||||
|
||||
ui.Say("Adding generated Floppy...")
|
||||
floppyIMGPath := ds.ResolvePath(uploadPath)
|
||||
err = vm.AddFloppy(floppyIMGPath)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
|
||||
if s.Config.FloppyIMGPath != "" {
|
||||
ui.Say("Adding Floppy image...")
|
||||
err := vm.AddFloppy(s.Config.FloppyIMGPath)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepAddFloppy) Cleanup(state multistep.StateBag) {
|
||||
_, cancelled := state.GetOk(multistep.StateCancelled)
|
||||
_, halted := state.GetOk(multistep.StateHalted)
|
||||
if !cancelled && !halted {
|
||||
return
|
||||
}
|
||||
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
d := state.Get("driver").(driver.Driver)
|
||||
|
||||
if UploadedFloppyPath, ok := state.GetOk("uploaded_floppy_path"); ok {
|
||||
ui.Say("Deleting Floppy image ...")
|
||||
|
||||
ds, err := d.FindDatastore(s.Datastore, s.Host)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return
|
||||
}
|
||||
|
||||
err = ds.Delete(UploadedFloppyPath.(string))
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
}
|
37
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_add_floppy.hcl2spec.go
generated
vendored
Normal file
37
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_add_floppy.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type FloppyConfig"; DO NOT EDIT.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatFloppyConfig is an auto-generated flat version of FloppyConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatFloppyConfig struct {
|
||||
FloppyIMGPath *string `mapstructure:"floppy_img_path" cty:"floppy_img_path" hcl:"floppy_img_path"`
|
||||
FloppyFiles []string `mapstructure:"floppy_files" cty:"floppy_files" hcl:"floppy_files"`
|
||||
FloppyDirectories []string `mapstructure:"floppy_dirs" cty:"floppy_dirs" hcl:"floppy_dirs"`
|
||||
FloppyLabel *string `mapstructure:"floppy_label" cty:"floppy_label" hcl:"floppy_label"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatFloppyConfig.
|
||||
// FlatFloppyConfig is an auto-generated flat version of FloppyConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*FloppyConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatFloppyConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a FloppyConfig.
|
||||
// This spec is used by HCL to read the fields of FloppyConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatFloppyConfig.
|
||||
func (*FlatFloppyConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"floppy_img_path": &hcldec.AttrSpec{Name: "floppy_img_path", Type: cty.String, Required: false},
|
||||
"floppy_files": &hcldec.AttrSpec{Name: "floppy_files", Type: cty.List(cty.String), Required: false},
|
||||
"floppy_dirs": &hcldec.AttrSpec{Name: "floppy_dirs", Type: cty.List(cty.String), Required: false},
|
||||
"floppy_label": &hcldec.AttrSpec{Name: "floppy_label", Type: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
152
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_boot_command.go
generated
vendored
Normal file
152
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_boot_command.go
generated
vendored
Normal file
|
@ -0,0 +1,152 @@
|
|||
//go:generate struct-markdown
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/bootcommand"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
"golang.org/x/mobile/event/key"
|
||||
)
|
||||
|
||||
type BootConfig struct {
|
||||
bootcommand.BootConfig `mapstructure:",squash"`
|
||||
// The IP address to use for the HTTP server started to serve the `http_directory`.
|
||||
// If unset, Packer will automatically discover and assign an IP.
|
||||
HTTPIP string `mapstructure:"http_ip"`
|
||||
}
|
||||
|
||||
type bootCommandTemplateData struct {
|
||||
HTTPIP string
|
||||
HTTPPort int
|
||||
Name string
|
||||
}
|
||||
|
||||
func (c *BootConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
if c.BootWait == 0 {
|
||||
c.BootWait = 10 * time.Second
|
||||
}
|
||||
return c.BootConfig.Prepare(ctx)
|
||||
}
|
||||
|
||||
type StepBootCommand struct {
|
||||
Config *BootConfig
|
||||
VMName string
|
||||
Ctx interpolate.Context
|
||||
}
|
||||
|
||||
func (s *StepBootCommand) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
debug := state.Get("debug").(bool)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
if s.Config.BootCommand == nil {
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// Wait the for the vm to boot.
|
||||
if int64(s.Config.BootWait) > 0 {
|
||||
ui.Say(fmt.Sprintf("Waiting %s for boot...", s.Config.BootWait.String()))
|
||||
select {
|
||||
case <-time.After(s.Config.BootWait):
|
||||
break
|
||||
case <-ctx.Done():
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
|
||||
var pauseFn multistep.DebugPauseFn
|
||||
if debug {
|
||||
pauseFn = state.Get("pauseFn").(multistep.DebugPauseFn)
|
||||
}
|
||||
|
||||
port := state.Get("http_port").(int)
|
||||
if port > 0 {
|
||||
ip := state.Get("http_ip").(string)
|
||||
s.Ctx.Data = &bootCommandTemplateData{
|
||||
ip,
|
||||
port,
|
||||
s.VMName,
|
||||
}
|
||||
ui.Say(fmt.Sprintf("HTTP server is working at http://%v:%v/", ip, port))
|
||||
}
|
||||
|
||||
var keyAlt, keyCtrl, keyShift bool
|
||||
sendCodes := func(code key.Code, down bool) error {
|
||||
switch code {
|
||||
case key.CodeLeftAlt:
|
||||
keyAlt = down
|
||||
case key.CodeLeftControl:
|
||||
keyCtrl = down
|
||||
case key.CodeLeftShift:
|
||||
keyShift = down
|
||||
}
|
||||
|
||||
shift := down
|
||||
if keyShift {
|
||||
shift = keyShift
|
||||
}
|
||||
|
||||
_, err := vm.TypeOnKeyboard(driver.KeyInput{
|
||||
Scancode: code,
|
||||
Ctrl: keyCtrl,
|
||||
Alt: keyAlt,
|
||||
Shift: shift,
|
||||
})
|
||||
if err != nil {
|
||||
// retry once if error
|
||||
ui.Error(fmt.Errorf("error typing a boot command (code, down) `%d, %t`: %w", code, down, err).Error())
|
||||
ui.Say("trying key input again")
|
||||
time.Sleep(s.Config.BootGroupInterval)
|
||||
_, err = vm.TypeOnKeyboard(driver.KeyInput{
|
||||
Scancode: code,
|
||||
Ctrl: keyCtrl,
|
||||
Alt: keyAlt,
|
||||
Shift: shift,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error typing a boot command (code, down) `%d, %t`: %w", code, down, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
d := bootcommand.NewUSBDriver(sendCodes, s.Config.BootGroupInterval)
|
||||
|
||||
ui.Say("Typing boot command...")
|
||||
flatBootCommand := s.Config.FlatBootCommand()
|
||||
command, err := interpolate.Render(flatBootCommand, &s.Ctx)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error preparing boot command: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
seq, err := bootcommand.GenerateExpressionSequence(command)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error generating boot command: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if err := seq.Do(ctx, d); err != nil {
|
||||
err := fmt.Errorf("Error running boot command: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if pauseFn != nil {
|
||||
pauseFn(multistep.DebugLocationAfterRun, fmt.Sprintf("boot_command: %s", command), state)
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepBootCommand) Cleanup(_ multistep.StateBag) {}
|
65
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_config_params.go
generated
vendored
Normal file
65
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_config_params.go
generated
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type ConfigParamsConfig
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
type ConfigParamsConfig struct {
|
||||
// configuration_parameters is a direct passthrough to the VSphere API's
|
||||
// ConfigSpec: https://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.ConfigSpec.html
|
||||
ConfigParams map[string]string `mapstructure:"configuration_parameters"`
|
||||
|
||||
// Enables time synchronization with the host. Defaults to false.
|
||||
ToolsSyncTime bool `mapstructure:"tools_sync_time"`
|
||||
|
||||
// If sets to true, vSphere will automatically check and upgrade VMware Tools upon a system power cycle.
|
||||
// If not set, defaults to manual upgrade.
|
||||
ToolsUpgradePolicy bool `mapstructure:"tools_upgrade_policy"`
|
||||
}
|
||||
|
||||
type StepConfigParams struct {
|
||||
Config *ConfigParamsConfig
|
||||
}
|
||||
|
||||
func (s *StepConfigParams) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
configParams := make(map[string]string)
|
||||
|
||||
if s.Config.ConfigParams != nil {
|
||||
configParams = s.Config.ConfigParams
|
||||
}
|
||||
|
||||
var info *types.ToolsConfigInfo
|
||||
if s.Config.ToolsSyncTime || s.Config.ToolsUpgradePolicy {
|
||||
info = &types.ToolsConfigInfo{}
|
||||
|
||||
if s.Config.ToolsSyncTime {
|
||||
info.SyncTimeWithHost = &s.Config.ToolsSyncTime
|
||||
}
|
||||
|
||||
if s.Config.ToolsUpgradePolicy {
|
||||
info.ToolsUpgradePolicy = "UpgradeAtPowerCycle"
|
||||
}
|
||||
}
|
||||
|
||||
ui.Say("Adding configuration parameters...")
|
||||
if err := vm.AddConfigParams(configParams, info); err != nil {
|
||||
state.Put("error", fmt.Errorf("error adding configuration parameters: %v", err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepConfigParams) Cleanup(state multistep.StateBag) {}
|
35
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_config_params.hcl2spec.go
generated
vendored
Normal file
35
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_config_params.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type ConfigParamsConfig"; DO NOT EDIT.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatConfigParamsConfig is an auto-generated flat version of ConfigParamsConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatConfigParamsConfig struct {
|
||||
ConfigParams map[string]string `mapstructure:"configuration_parameters" cty:"configuration_parameters" hcl:"configuration_parameters"`
|
||||
ToolsSyncTime *bool `mapstructure:"tools_sync_time" cty:"tools_sync_time" hcl:"tools_sync_time"`
|
||||
ToolsUpgradePolicy *bool `mapstructure:"tools_upgrade_policy" cty:"tools_upgrade_policy" hcl:"tools_upgrade_policy"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatConfigParamsConfig.
|
||||
// FlatConfigParamsConfig is an auto-generated flat version of ConfigParamsConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*ConfigParamsConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatConfigParamsConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a ConfigParamsConfig.
|
||||
// This spec is used by HCL to read the fields of ConfigParamsConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatConfigParamsConfig.
|
||||
func (*FlatConfigParamsConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"configuration_parameters": &hcldec.AttrSpec{Name: "configuration_parameters", Type: cty.Map(cty.String), Required: false},
|
||||
"tools_sync_time": &hcldec.AttrSpec{Name: "tools_sync_time", Type: cty.Bool, Required: false},
|
||||
"tools_upgrade_policy": &hcldec.AttrSpec{Name: "tools_upgrade_policy", Type: cty.Bool, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
64
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_connect.go
generated
vendored
Normal file
64
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_connect.go
generated
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type ConnectConfig
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
type ConnectConfig struct {
|
||||
// vCenter server hostname.
|
||||
VCenterServer string `mapstructure:"vcenter_server"`
|
||||
// vSphere username.
|
||||
Username string `mapstructure:"username"`
|
||||
// vSphere password.
|
||||
Password string `mapstructure:"password"`
|
||||
// Do not validate vCenter server's TLS certificate. Defaults to `false`.
|
||||
InsecureConnection bool `mapstructure:"insecure_connection"`
|
||||
// VMware datacenter name. Required if there is more than one datacenter in vCenter.
|
||||
Datacenter string `mapstructure:"datacenter"`
|
||||
}
|
||||
|
||||
func (c *ConnectConfig) Prepare() []error {
|
||||
var errs []error
|
||||
|
||||
if c.VCenterServer == "" {
|
||||
errs = append(errs, fmt.Errorf("'vcenter_server' is required"))
|
||||
}
|
||||
if c.Username == "" {
|
||||
errs = append(errs, fmt.Errorf("'username' is required"))
|
||||
}
|
||||
if c.Password == "" {
|
||||
errs = append(errs, fmt.Errorf("'password' is required"))
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
type StepConnect struct {
|
||||
Config *ConnectConfig
|
||||
}
|
||||
|
||||
func (s *StepConnect) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
d, err := driver.NewDriver(&driver.ConnectConfig{
|
||||
VCenterServer: s.Config.VCenterServer,
|
||||
Username: s.Config.Username,
|
||||
Password: s.Config.Password,
|
||||
InsecureConnection: s.Config.InsecureConnection,
|
||||
Datacenter: s.Config.Datacenter,
|
||||
})
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
state.Put("driver", d)
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepConnect) Cleanup(multistep.StateBag) {}
|
39
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_connect.hcl2spec.go
generated
vendored
Normal file
39
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_connect.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type ConnectConfig"; DO NOT EDIT.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatConnectConfig is an auto-generated flat version of ConnectConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatConnectConfig struct {
|
||||
VCenterServer *string `mapstructure:"vcenter_server" cty:"vcenter_server" hcl:"vcenter_server"`
|
||||
Username *string `mapstructure:"username" cty:"username" hcl:"username"`
|
||||
Password *string `mapstructure:"password" cty:"password" hcl:"password"`
|
||||
InsecureConnection *bool `mapstructure:"insecure_connection" cty:"insecure_connection" hcl:"insecure_connection"`
|
||||
Datacenter *string `mapstructure:"datacenter" cty:"datacenter" hcl:"datacenter"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatConnectConfig.
|
||||
// FlatConnectConfig is an auto-generated flat version of ConnectConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*ConnectConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatConnectConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a ConnectConfig.
|
||||
// This spec is used by HCL to read the fields of ConnectConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatConnectConfig.
|
||||
func (*FlatConnectConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"vcenter_server": &hcldec.AttrSpec{Name: "vcenter_server", Type: cty.String, Required: false},
|
||||
"username": &hcldec.AttrSpec{Name: "username", Type: cty.String, Required: false},
|
||||
"password": &hcldec.AttrSpec{Name: "password", Type: cty.String, Required: false},
|
||||
"insecure_connection": &hcldec.AttrSpec{Name: "insecure_connection", Type: cty.Bool, Required: false},
|
||||
"datacenter": &hcldec.AttrSpec{Name: "datacenter", Type: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
68
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_download.go
generated
vendored
Normal file
68
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_download.go
generated
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
// Defining this interface ensures that we use the common step download, or the
|
||||
// mock created to test this wrapper
|
||||
type DownloadStep interface {
|
||||
Run(context.Context, multistep.StateBag) multistep.StepAction
|
||||
Cleanup(multistep.StateBag)
|
||||
UseSourceToFindCacheTarget(source string) (*url.URL, string, error)
|
||||
}
|
||||
|
||||
// VSphere has a specialized need -- before we waste time downloading an iso,
|
||||
// we need to check whether that iso already exists on the remote datastore.
|
||||
// if it does, we skip the download. This wrapping-step still uses the common
|
||||
// StepDownload but only if the image isn't already present on the datastore.
|
||||
type StepDownload struct {
|
||||
DownloadStep DownloadStep
|
||||
// These keys are VSphere-specific and used to check the remote datastore.
|
||||
Url []string
|
||||
ResultKey string
|
||||
Datastore string
|
||||
Host string
|
||||
}
|
||||
|
||||
func (s *StepDownload) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
driver := state.Get("driver").(driver.Driver)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
|
||||
// Check whether iso is present on remote datastore.
|
||||
ds, err := driver.FindDatastore(s.Datastore, s.Host)
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf("datastore doesn't exist: %v", err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
// loop over URLs to see if any are already present. If they are, store that
|
||||
// one instate and continue
|
||||
for _, source := range s.Url {
|
||||
_, targetPath, err := s.DownloadStep.UseSourceToFindCacheTarget(source)
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf("Error getting target path: %s", err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
_, remotePath, _, _ := GetRemoteDirectoryAndPath(targetPath, ds)
|
||||
|
||||
if exists := ds.FileExists(remotePath); exists {
|
||||
ui.Say(fmt.Sprintf("File %s already uploaded; continuing", targetPath))
|
||||
state.Put(s.ResultKey, targetPath)
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
}
|
||||
|
||||
// ISO is not present on datastore, so we need to download, then upload it.
|
||||
// Pass through to the common download step.
|
||||
return s.DownloadStep.Run(ctx, state)
|
||||
}
|
||||
|
||||
func (s *StepDownload) Cleanup(state multistep.StateBag) {
|
||||
}
|
338
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_export.go
generated
vendored
Normal file
338
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_export.go
generated
vendored
Normal file
|
@ -0,0 +1,338 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type ExportConfig
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/common"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vmware/govmomi/nfc"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
// You may optionally export an ovf from VSphere to the instance running Packer.
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// In JSON:
|
||||
// ```json
|
||||
// ...
|
||||
// "vm_name": "example-ubuntu",
|
||||
// ...
|
||||
// "export": {
|
||||
// "force": true,
|
||||
// "output_directory": "./output_vsphere"
|
||||
// },
|
||||
// ```
|
||||
// In HCL2:
|
||||
// ```hcl
|
||||
// # ...
|
||||
// vm_name = "example-ubuntu"
|
||||
// # ...
|
||||
// export {
|
||||
// force = true
|
||||
// output_directory = "./output_vsphere"
|
||||
// }
|
||||
// ```
|
||||
// The above configuration would create the following files:
|
||||
//
|
||||
// ```text
|
||||
// ./output_vsphere/example-ubuntu-disk-0.vmdk
|
||||
// ./output_vsphere/example-ubuntu.mf
|
||||
// ./output_vsphere/example-ubuntu.ovf
|
||||
// ```
|
||||
type ExportConfig struct {
|
||||
// name of the ovf. defaults to the name of the VM
|
||||
Name string `mapstructure:"name"`
|
||||
// overwrite ovf if it exists
|
||||
Force bool `mapstructure:"force"`
|
||||
// include iso and img image files that are attached to the VM
|
||||
Images bool `mapstructure:"images"`
|
||||
// generate manifest using sha1, sha256, sha512. Defaults to 'sha256'. Use 'none' for no manifest.
|
||||
Manifest string `mapstructure:"manifest"`
|
||||
// Directory on the computer running Packer to export files to
|
||||
OutputDir OutputConfig `mapstructure:",squash"`
|
||||
// Advanced ovf export options. Options can include:
|
||||
// * mac - MAC address is exported for all ethernet devices
|
||||
// * uuid - UUID is exported for all virtual machines
|
||||
// * extraconfig - all extra configuration options are exported for a virtual machine
|
||||
// * nodevicesubtypes - resource subtypes for CD/DVD drives, floppy drives, and serial and parallel ports are not exported
|
||||
//
|
||||
// For example, adding the following export config option would output the mac addresses for all Ethernet devices in the ovf file:
|
||||
//
|
||||
// In JSON:
|
||||
// ```json
|
||||
// ...
|
||||
// "export": {
|
||||
// "options": ["mac"]
|
||||
// },
|
||||
// ```
|
||||
// In HCL2:
|
||||
// ```hcl
|
||||
// ...
|
||||
// export {
|
||||
// options = ["mac"]
|
||||
// }
|
||||
// ```
|
||||
Options []string `mapstructure:"options"`
|
||||
}
|
||||
|
||||
var sha = map[string]func() hash.Hash{
|
||||
"none": nil,
|
||||
"sha1": sha1.New,
|
||||
"sha256": sha256.New,
|
||||
"sha512": sha512.New,
|
||||
}
|
||||
|
||||
func (c *ExportConfig) Prepare(ctx *interpolate.Context, lc *LocationConfig, pc *common.PackerConfig) []error {
|
||||
var errs *packersdk.MultiError
|
||||
|
||||
errs = packersdk.MultiErrorAppend(errs, c.OutputDir.Prepare(ctx, pc)...)
|
||||
|
||||
// manifest should default to sha256
|
||||
if c.Manifest == "" {
|
||||
c.Manifest = "sha256"
|
||||
}
|
||||
if _, ok := sha[c.Manifest]; !ok {
|
||||
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("unknown hash: %s. available options include available options being 'none', 'sha1', 'sha256', 'sha512'", c.Manifest))
|
||||
}
|
||||
|
||||
if c.Name == "" {
|
||||
c.Name = lc.VMName
|
||||
}
|
||||
target := getTarget(c.OutputDir.OutputDir, c.Name)
|
||||
if !c.Force {
|
||||
if _, err := os.Stat(target); err == nil {
|
||||
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("file already exists: %s", target))
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(c.OutputDir.OutputDir, c.OutputDir.DirPerm); err != nil {
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.Wrap(err, "unable to make directory for export"))
|
||||
}
|
||||
|
||||
if errs != nil && len(errs.Errors) > 0 {
|
||||
return errs.Errors
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getTarget(dir string, name string) string {
|
||||
return filepath.Join(dir, name+".ovf")
|
||||
}
|
||||
|
||||
type StepExport struct {
|
||||
Name string
|
||||
Force bool
|
||||
Images bool
|
||||
Manifest string
|
||||
OutputDir string
|
||||
Options []string
|
||||
mf bytes.Buffer
|
||||
}
|
||||
|
||||
func (s *StepExport) Cleanup(multistep.StateBag) {
|
||||
}
|
||||
|
||||
func (s *StepExport) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
ui.Message("Starting export...")
|
||||
lease, err := vm.Export()
|
||||
if err != nil {
|
||||
state.Put("error", errors.Wrap(err, "error exporting vm"))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
info, err := lease.Wait(ctx, nil)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
u := lease.StartUpdater(ctx, info)
|
||||
defer u.Done()
|
||||
|
||||
cdp := types.OvfCreateDescriptorParams{
|
||||
Name: s.Name,
|
||||
}
|
||||
|
||||
m := vm.NewOvfManager()
|
||||
if len(s.Options) > 0 {
|
||||
exportOptions, err := vm.GetOvfExportOptions(m)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
var unknown []string
|
||||
for _, option := range s.Options {
|
||||
found := false
|
||||
for _, exportOpt := range exportOptions {
|
||||
if exportOpt.Option == option {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
unknown = append(unknown, option)
|
||||
}
|
||||
cdp.ExportOption = append(cdp.ExportOption, option)
|
||||
}
|
||||
|
||||
// only printing error message because the unknown options are just ignored by vcenter
|
||||
if len(unknown) > 0 {
|
||||
ui.Error(fmt.Sprintf("unknown export options %s", strings.Join(unknown, ",")))
|
||||
}
|
||||
}
|
||||
|
||||
for _, i := range info.Items {
|
||||
if !s.include(&i) {
|
||||
continue
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(i.Path, s.Name) {
|
||||
i.Path = s.Name + "-" + i.Path
|
||||
}
|
||||
|
||||
file := i.File()
|
||||
|
||||
ui.Message("Downloading: " + file.Path)
|
||||
size, err := s.Download(ctx, lease, i)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
// Fix file size descriptor
|
||||
file.Size = size
|
||||
|
||||
ui.Message("Exporting file: " + file.Path)
|
||||
cdp.OvfFiles = append(cdp.OvfFiles, file)
|
||||
}
|
||||
|
||||
if err = lease.Complete(ctx); err != nil {
|
||||
state.Put("error", errors.Wrap(err, "unable to complete lease"))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
desc, err := vm.CreateDescriptor(m, cdp)
|
||||
if err != nil {
|
||||
state.Put("error", errors.Wrap(err, "unable to create descriptor"))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
target := getTarget(s.OutputDir, s.Name)
|
||||
file, err := os.Create(target)
|
||||
if err != nil {
|
||||
state.Put("error", errors.Wrap(err, "unable to create file: "+target))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
var w io.Writer = file
|
||||
h, ok := s.newHash()
|
||||
if ok {
|
||||
w = io.MultiWriter(file, h)
|
||||
}
|
||||
|
||||
ui.Message("Writing ovf...")
|
||||
_, err = io.WriteString(w, desc.OvfDescriptor)
|
||||
if err != nil {
|
||||
state.Put("error", errors.Wrap(err, "unable to write descriptor"))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if err = file.Close(); err != nil {
|
||||
state.Put("error", errors.Wrap(err, "unable to close descriptor"))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if s.Manifest == "none" {
|
||||
// manifest does not need to be created, return
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
ui.Message("Creating manifest...")
|
||||
s.addHash(filepath.Base(target), h)
|
||||
|
||||
file, err = os.Create(filepath.Join(s.OutputDir, s.Name+".mf"))
|
||||
if err != nil {
|
||||
state.Put("error", errors.Wrap(err, "unable to create manifest"))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
_, err = io.Copy(file, &s.mf)
|
||||
if err != nil {
|
||||
state.Put("error", errors.Wrap(err, "unable to write manifest"))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
err = file.Close()
|
||||
if err != nil {
|
||||
state.Put("error", errors.Wrap(err, "unable to close file"))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
ui.Message("Finished exporting...")
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepExport) include(item *nfc.FileItem) bool {
|
||||
if s.Images {
|
||||
return true
|
||||
}
|
||||
|
||||
return filepath.Ext(item.Path) == ".vmdk"
|
||||
}
|
||||
|
||||
func (s *StepExport) newHash() (hash.Hash, bool) {
|
||||
// check if function is nil to handle the 'none' case
|
||||
if h, ok := sha[s.Manifest]; ok && h != nil {
|
||||
return h(), true
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (s *StepExport) addHash(p string, h hash.Hash) {
|
||||
_, _ = fmt.Fprintf(&s.mf, "%s(%s)= %x\n", strings.ToUpper(s.Manifest), p, h.Sum(nil))
|
||||
}
|
||||
|
||||
func (s *StepExport) Download(ctx context.Context, lease *nfc.Lease, item nfc.FileItem) (int64, error) {
|
||||
path := filepath.Join(s.OutputDir, item.Path)
|
||||
opts := soap.Download{}
|
||||
|
||||
if h, ok := s.newHash(); ok {
|
||||
opts.Writer = h
|
||||
defer s.addHash(item.Path, h)
|
||||
}
|
||||
|
||||
err := lease.DownloadFile(ctx, path, item, opts)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
f, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return f.Size(), err
|
||||
}
|
45
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_export.hcl2spec.go
generated
vendored
Normal file
45
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_export.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type ExportConfig"; DO NOT EDIT.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatExportConfig is an auto-generated flat version of ExportConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatExportConfig struct {
|
||||
Name *string `mapstructure:"name" cty:"name" hcl:"name"`
|
||||
Force *bool `mapstructure:"force" cty:"force" hcl:"force"`
|
||||
Images *bool `mapstructure:"images" cty:"images" hcl:"images"`
|
||||
Manifest *string `mapstructure:"manifest" cty:"manifest" hcl:"manifest"`
|
||||
OutputDir *string `mapstructure:"output_directory" required:"false" cty:"output_directory" hcl:"output_directory"`
|
||||
DirPerm *fs.FileMode `mapstructure:"directory_permission" required:"false" cty:"directory_permission" hcl:"directory_permission"`
|
||||
Options []string `mapstructure:"options" cty:"options" hcl:"options"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatExportConfig.
|
||||
// FlatExportConfig is an auto-generated flat version of ExportConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*ExportConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatExportConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a ExportConfig.
|
||||
// This spec is used by HCL to read the fields of ExportConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatExportConfig.
|
||||
func (*FlatExportConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"name": &hcldec.AttrSpec{Name: "name", Type: cty.String, Required: false},
|
||||
"force": &hcldec.AttrSpec{Name: "force", Type: cty.Bool, Required: false},
|
||||
"images": &hcldec.AttrSpec{Name: "images", Type: cty.Bool, Required: false},
|
||||
"manifest": &hcldec.AttrSpec{Name: "manifest", Type: cty.String, Required: false},
|
||||
"output_directory": &hcldec.AttrSpec{Name: "output_directory", Type: cty.String, Required: false},
|
||||
"directory_permission": &hcldec.AttrSpec{Name: "directory_permission", Type: cty.Number, Required: false},
|
||||
"options": &hcldec.AttrSpec{Name: "options", Type: cty.List(cty.String), Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
98
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_hardware.go
generated
vendored
Normal file
98
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_hardware.go
generated
vendored
Normal file
|
@ -0,0 +1,98 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type HardwareConfig
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
type HardwareConfig struct {
|
||||
// Number of CPU cores.
|
||||
CPUs int32 `mapstructure:"CPUs"`
|
||||
// Number of CPU cores per socket.
|
||||
CpuCores int32 `mapstructure:"cpu_cores"`
|
||||
// Amount of reserved CPU resources in MHz.
|
||||
CPUReservation int64 `mapstructure:"CPU_reservation"`
|
||||
// Upper limit of available CPU resources in MHz.
|
||||
CPULimit int64 `mapstructure:"CPU_limit"`
|
||||
// Enable CPU hot plug setting for virtual machine. Defaults to `false`.
|
||||
CpuHotAddEnabled bool `mapstructure:"CPU_hot_plug"`
|
||||
// Amount of RAM in MB.
|
||||
RAM int64 `mapstructure:"RAM"`
|
||||
// Amount of reserved RAM in MB.
|
||||
RAMReservation int64 `mapstructure:"RAM_reservation"`
|
||||
// Reserve all available RAM. Defaults to `false`. Cannot be used together
|
||||
// with `RAM_reservation`.
|
||||
RAMReserveAll bool `mapstructure:"RAM_reserve_all"`
|
||||
// Enable RAM hot plug setting for virtual machine. Defaults to `false`.
|
||||
MemoryHotAddEnabled bool `mapstructure:"RAM_hot_plug"`
|
||||
// Amount of video memory in KB.
|
||||
VideoRAM int64 `mapstructure:"video_ram"`
|
||||
// vGPU profile for accelerated graphics. See [NVIDIA GRID vGPU documentation](https://docs.nvidia.com/grid/latest/grid-vgpu-user-guide/index.html#configure-vmware-vsphere-vm-with-vgpu)
|
||||
// for examples of profile names. Defaults to none.
|
||||
VGPUProfile string `mapstructure:"vgpu_profile"`
|
||||
// Enable nested hardware virtualization for VM. Defaults to `false`.
|
||||
NestedHV bool `mapstructure:"NestedHV"`
|
||||
// Set the Firmware for virtual machine. Supported values: `bios`, `efi` or `efi-secure`. Defaults to `bios`.
|
||||
Firmware string `mapstructure:"firmware"`
|
||||
// During the boot, force entry into the BIOS setup screen. Defaults to `false`.
|
||||
ForceBIOSSetup bool `mapstructure:"force_bios_setup"`
|
||||
}
|
||||
|
||||
func (c *HardwareConfig) Prepare() []error {
|
||||
var errs []error
|
||||
|
||||
if c.RAMReservation > 0 && c.RAMReserveAll != false {
|
||||
errs = append(errs, fmt.Errorf("'RAM_reservation' and 'RAM_reserve_all' cannot be used together"))
|
||||
}
|
||||
|
||||
if c.Firmware != "" && c.Firmware != "bios" && c.Firmware != "efi" && c.Firmware != "efi-secure" {
|
||||
errs = append(errs, fmt.Errorf("'firmware' must be '', 'bios', 'efi' or 'efi-secure'"))
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
type StepConfigureHardware struct {
|
||||
Config *HardwareConfig
|
||||
}
|
||||
|
||||
func (s *StepConfigureHardware) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
vm := state.Get("vm").(driver.VirtualMachine)
|
||||
|
||||
if *s.Config != (HardwareConfig{}) {
|
||||
ui.Say("Customizing hardware...")
|
||||
|
||||
err := vm.Configure(&driver.HardwareConfig{
|
||||
CPUs: s.Config.CPUs,
|
||||
CpuCores: s.Config.CpuCores,
|
||||
CPUReservation: s.Config.CPUReservation,
|
||||
CPULimit: s.Config.CPULimit,
|
||||
RAM: s.Config.RAM,
|
||||
RAMReservation: s.Config.RAMReservation,
|
||||
RAMReserveAll: s.Config.RAMReserveAll,
|
||||
NestedHV: s.Config.NestedHV,
|
||||
CpuHotAddEnabled: s.Config.CpuHotAddEnabled,
|
||||
MemoryHotAddEnabled: s.Config.MemoryHotAddEnabled,
|
||||
VideoRAM: s.Config.VideoRAM,
|
||||
VGPUProfile: s.Config.VGPUProfile,
|
||||
Firmware: s.Config.Firmware,
|
||||
ForceBIOSSetup: s.Config.ForceBIOSSetup,
|
||||
})
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepConfigureHardware) Cleanup(multistep.StateBag) {}
|
57
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_hardware.hcl2spec.go
generated
vendored
Normal file
57
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_hardware.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type HardwareConfig"; DO NOT EDIT.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatHardwareConfig is an auto-generated flat version of HardwareConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatHardwareConfig struct {
|
||||
CPUs *int32 `mapstructure:"CPUs" cty:"CPUs" hcl:"CPUs"`
|
||||
CpuCores *int32 `mapstructure:"cpu_cores" cty:"cpu_cores" hcl:"cpu_cores"`
|
||||
CPUReservation *int64 `mapstructure:"CPU_reservation" cty:"CPU_reservation" hcl:"CPU_reservation"`
|
||||
CPULimit *int64 `mapstructure:"CPU_limit" cty:"CPU_limit" hcl:"CPU_limit"`
|
||||
CpuHotAddEnabled *bool `mapstructure:"CPU_hot_plug" cty:"CPU_hot_plug" hcl:"CPU_hot_plug"`
|
||||
RAM *int64 `mapstructure:"RAM" cty:"RAM" hcl:"RAM"`
|
||||
RAMReservation *int64 `mapstructure:"RAM_reservation" cty:"RAM_reservation" hcl:"RAM_reservation"`
|
||||
RAMReserveAll *bool `mapstructure:"RAM_reserve_all" cty:"RAM_reserve_all" hcl:"RAM_reserve_all"`
|
||||
MemoryHotAddEnabled *bool `mapstructure:"RAM_hot_plug" cty:"RAM_hot_plug" hcl:"RAM_hot_plug"`
|
||||
VideoRAM *int64 `mapstructure:"video_ram" cty:"video_ram" hcl:"video_ram"`
|
||||
VGPUProfile *string `mapstructure:"vgpu_profile" cty:"vgpu_profile" hcl:"vgpu_profile"`
|
||||
NestedHV *bool `mapstructure:"NestedHV" cty:"NestedHV" hcl:"NestedHV"`
|
||||
Firmware *string `mapstructure:"firmware" cty:"firmware" hcl:"firmware"`
|
||||
ForceBIOSSetup *bool `mapstructure:"force_bios_setup" cty:"force_bios_setup" hcl:"force_bios_setup"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatHardwareConfig.
|
||||
// FlatHardwareConfig is an auto-generated flat version of HardwareConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*HardwareConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatHardwareConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a HardwareConfig.
|
||||
// This spec is used by HCL to read the fields of HardwareConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatHardwareConfig.
|
||||
func (*FlatHardwareConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"CPUs": &hcldec.AttrSpec{Name: "CPUs", Type: cty.Number, Required: false},
|
||||
"cpu_cores": &hcldec.AttrSpec{Name: "cpu_cores", Type: cty.Number, Required: false},
|
||||
"CPU_reservation": &hcldec.AttrSpec{Name: "CPU_reservation", Type: cty.Number, Required: false},
|
||||
"CPU_limit": &hcldec.AttrSpec{Name: "CPU_limit", Type: cty.Number, Required: false},
|
||||
"CPU_hot_plug": &hcldec.AttrSpec{Name: "CPU_hot_plug", Type: cty.Bool, Required: false},
|
||||
"RAM": &hcldec.AttrSpec{Name: "RAM", Type: cty.Number, Required: false},
|
||||
"RAM_reservation": &hcldec.AttrSpec{Name: "RAM_reservation", Type: cty.Number, Required: false},
|
||||
"RAM_reserve_all": &hcldec.AttrSpec{Name: "RAM_reserve_all", Type: cty.Bool, Required: false},
|
||||
"RAM_hot_plug": &hcldec.AttrSpec{Name: "RAM_hot_plug", Type: cty.Bool, Required: false},
|
||||
"video_ram": &hcldec.AttrSpec{Name: "video_ram", Type: cty.Number, Required: false},
|
||||
"vgpu_profile": &hcldec.AttrSpec{Name: "vgpu_profile", Type: cty.String, Required: false},
|
||||
"NestedHV": &hcldec.AttrSpec{Name: "NestedHV", Type: cty.Bool, Required: false},
|
||||
"firmware": &hcldec.AttrSpec{Name: "firmware", Type: cty.String, Required: false},
|
||||
"force_bios_setup": &hcldec.AttrSpec{Name: "force_bios_setup", Type: cty.Bool, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
68
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_http_ip_discover.go
generated
vendored
Normal file
68
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_http_ip_discover.go
generated
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
// Step to discover the http ip
|
||||
// which guests use to reach the vm host
|
||||
// To make sure the IP is set before boot command and http server steps
|
||||
type StepHTTPIPDiscover struct {
|
||||
HTTPIP string
|
||||
Network *net.IPNet
|
||||
}
|
||||
|
||||
func (s *StepHTTPIPDiscover) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ip, err := getHostIP(s.HTTPIP, s.Network)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
state.Put("http_ip", ip)
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepHTTPIPDiscover) Cleanup(state multistep.StateBag) {}
|
||||
|
||||
func getHostIP(s string, network *net.IPNet) (string, error) {
|
||||
if s != "" {
|
||||
if net.ParseIP(s) != nil {
|
||||
return s, nil
|
||||
} else {
|
||||
return "", fmt.Errorf("invalid IP address")
|
||||
}
|
||||
}
|
||||
|
||||
addrs, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// look for an IP that is contained in the ip_wait_address range
|
||||
if network != nil {
|
||||
for _, a := range addrs {
|
||||
ipnet, ok := a.(*net.IPNet)
|
||||
if ok && !ipnet.IP.IsLoopback() {
|
||||
if network.Contains(ipnet.IP) {
|
||||
return ipnet.IP.String(), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fallback to an ipv4 address if an IP is not found in the range
|
||||
for _, a := range addrs {
|
||||
ipnet, ok := a.(*net.IPNet)
|
||||
if ok && !ipnet.IP.IsLoopback() {
|
||||
if ipnet.IP.To4() != nil {
|
||||
return ipnet.IP.String(), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("IP not found")
|
||||
}
|
180
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_import_to_content_library.go
generated
vendored
Normal file
180
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_import_to_content_library.go
generated
vendored
Normal file
|
@ -0,0 +1,180 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type ContentLibraryDestinationConfig
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
"github.com/vmware/govmomi/vapi/vcenter"
|
||||
)
|
||||
|
||||
// With this configuration Packer creates a library item in a content library whose content is a VM template
|
||||
// or an OVF template created from the just built VM.
|
||||
// The template is stored in a existing or newly created library item.
|
||||
type ContentLibraryDestinationConfig struct {
|
||||
// Name of the library in which the new library item containing the template should be created/updated.
|
||||
// The Content Library should be of type Local to allow deploying virtual machines.
|
||||
Library string `mapstructure:"library"`
|
||||
// Name of the library item that will be created or updated.
|
||||
// For VM templates, the name of the item should be different from [vm_name](#vm_name) and
|
||||
// the default is [vm_name](#vm_name) + timestamp when not set. VM templates will be always imported to a new library item.
|
||||
// For OVF templates, the name defaults to [vm_name](#vm_name) when not set, and if an item with the same name already
|
||||
// exists it will be then updated with the new OVF template, otherwise a new item will be created.
|
||||
//
|
||||
// ~> **Note**: It's not possible to update existing library items with a new VM template. If updating an existing library
|
||||
// item is necessary, use an OVF template instead by setting the [ovf](#ovf) option as `true`.
|
||||
//
|
||||
Name string `mapstructure:"name"`
|
||||
// Description of the library item that will be created.
|
||||
// This option is not used when importing OVF templates.
|
||||
// Defaults to "Packer imported [vm_name](#vm_name) VM template".
|
||||
Description string `mapstructure:"description"`
|
||||
// Cluster onto which the virtual machine template should be placed.
|
||||
// If cluster and resource_pool are both specified, resource_pool must belong to cluster.
|
||||
// If cluster and host are both specified, host must be a member of cluster.
|
||||
// This option is not used when importing OVF templates.
|
||||
// Defaults to [cluster](#cluster).
|
||||
Cluster string `mapstructure:"cluster"`
|
||||
// Virtual machine folder into which the virtual machine template should be placed.
|
||||
// This option is not used when importing OVF templates.
|
||||
// Defaults to the same folder as the source virtual machine.
|
||||
Folder string `mapstructure:"folder"`
|
||||
// Host onto which the virtual machine template should be placed.
|
||||
// If host and resource_pool are both specified, resource_pool must belong to host.
|
||||
// If host and cluster are both specified, host must be a member of cluster.
|
||||
// This option is not used when importing OVF templates.
|
||||
// Defaults to [host](#host).
|
||||
Host string `mapstructure:"host"`
|
||||
// Resource pool into which the virtual machine template should be placed.
|
||||
// Defaults to [resource_pool](#resource_pool). if [resource_pool](#resource_pool) is also unset,
|
||||
// the system will attempt to choose a suitable resource pool for the virtual machine template.
|
||||
ResourcePool string `mapstructure:"resource_pool"`
|
||||
// The datastore for the virtual machine template's configuration and log files.
|
||||
// This option is not used when importing OVF templates.
|
||||
// Defaults to the storage backing associated with the library specified by library.
|
||||
Datastore string `mapstructure:"datastore"`
|
||||
// If set to true, the VM will be destroyed after deploying the template to the Content Library.
|
||||
// Defaults to `false`.
|
||||
Destroy bool `mapstructure:"destroy"`
|
||||
// When set to true, Packer will import and OVF template to the content library item. Defaults to `false`.
|
||||
Ovf bool `mapstructure:"ovf"`
|
||||
}
|
||||
|
||||
func (c *ContentLibraryDestinationConfig) Prepare(lc *LocationConfig) []error {
|
||||
var errs *packersdk.MultiError
|
||||
|
||||
if c.Library == "" {
|
||||
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("a library name must be provided"))
|
||||
}
|
||||
|
||||
if c.Ovf {
|
||||
if c.Name == "" {
|
||||
c.Name = lc.VMName
|
||||
}
|
||||
} else {
|
||||
if c.Name == lc.VMName {
|
||||
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("the content library destination name must be different from the VM name"))
|
||||
}
|
||||
|
||||
if c.Name == "" {
|
||||
// Add timestamp to the name to differentiate from the original VM
|
||||
// otherwise vSphere won't be able to create the template which will be imported
|
||||
name, err := interpolate.Render(lc.VMName+"{{timestamp}}", nil)
|
||||
if err != nil {
|
||||
errs = packersdk.MultiErrorAppend(errs,
|
||||
fmt.Errorf("unable to parse content library VM template name: %s", err))
|
||||
}
|
||||
c.Name = name
|
||||
}
|
||||
if c.Cluster == "" {
|
||||
c.Cluster = lc.Cluster
|
||||
}
|
||||
if c.Host == "" {
|
||||
c.Host = lc.Host
|
||||
}
|
||||
if c.ResourcePool == "" {
|
||||
c.ResourcePool = lc.ResourcePool
|
||||
}
|
||||
if c.Description == "" {
|
||||
c.Description = fmt.Sprintf("Packer imported %s VM template", lc.VMName)
|
||||
}
|
||||
}
|
||||
|
||||
if errs != nil && len(errs.Errors) > 0 {
|
||||
return errs.Errors
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type StepImportToContentLibrary struct {
|
||||
ContentLibConfig *ContentLibraryDestinationConfig
|
||||
}
|
||||
|
||||
func (s *StepImportToContentLibrary) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
var err error
|
||||
|
||||
if s.ContentLibConfig.Ovf {
|
||||
ui.Say(fmt.Sprintf("Importing VM OVF template %s to Content Library...", s.ContentLibConfig.Name))
|
||||
err = s.importOvfTemplate(vm)
|
||||
} else {
|
||||
ui.Say(fmt.Sprintf("Importing VM template %s to Content Library...", s.ContentLibConfig.Name))
|
||||
err = s.importVmTemplate(vm)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf("Failed to import template %s: %s", s.ContentLibConfig.Name, err.Error()))
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if s.ContentLibConfig.Destroy {
|
||||
state.Put("destroy_vm", s.ContentLibConfig.Destroy)
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepImportToContentLibrary) importOvfTemplate(vm *driver.VirtualMachineDriver) error {
|
||||
ovf := vcenter.OVF{
|
||||
Spec: vcenter.CreateSpec{
|
||||
Name: s.ContentLibConfig.Name,
|
||||
},
|
||||
Target: vcenter.LibraryTarget{
|
||||
LibraryID: s.ContentLibConfig.Library,
|
||||
},
|
||||
}
|
||||
return vm.ImportOvfToContentLibrary(ovf)
|
||||
}
|
||||
|
||||
func (s *StepImportToContentLibrary) importVmTemplate(vm *driver.VirtualMachineDriver) error {
|
||||
template := vcenter.Template{
|
||||
Name: s.ContentLibConfig.Name,
|
||||
Description: s.ContentLibConfig.Description,
|
||||
Library: s.ContentLibConfig.Library,
|
||||
Placement: &vcenter.Placement{
|
||||
Cluster: s.ContentLibConfig.Cluster,
|
||||
Folder: s.ContentLibConfig.Folder,
|
||||
Host: s.ContentLibConfig.Host,
|
||||
ResourcePool: s.ContentLibConfig.ResourcePool,
|
||||
},
|
||||
}
|
||||
|
||||
if s.ContentLibConfig.Datastore != "" {
|
||||
template.VMHomeStorage = &vcenter.DiskStorage{
|
||||
Datastore: s.ContentLibConfig.Datastore,
|
||||
}
|
||||
}
|
||||
|
||||
return vm.ImportToContentLibrary(template)
|
||||
}
|
||||
|
||||
func (s *StepImportToContentLibrary) Cleanup(multistep.StateBag) {
|
||||
}
|
49
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_import_to_content_library.hcl2spec.go
generated
vendored
Normal file
49
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_import_to_content_library.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type ContentLibraryDestinationConfig"; DO NOT EDIT.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatContentLibraryDestinationConfig is an auto-generated flat version of ContentLibraryDestinationConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatContentLibraryDestinationConfig struct {
|
||||
Library *string `mapstructure:"library" cty:"library" hcl:"library"`
|
||||
Name *string `mapstructure:"name" cty:"name" hcl:"name"`
|
||||
Description *string `mapstructure:"description" cty:"description" hcl:"description"`
|
||||
Cluster *string `mapstructure:"cluster" cty:"cluster" hcl:"cluster"`
|
||||
Folder *string `mapstructure:"folder" cty:"folder" hcl:"folder"`
|
||||
Host *string `mapstructure:"host" cty:"host" hcl:"host"`
|
||||
ResourcePool *string `mapstructure:"resource_pool" cty:"resource_pool" hcl:"resource_pool"`
|
||||
Datastore *string `mapstructure:"datastore" cty:"datastore" hcl:"datastore"`
|
||||
Destroy *bool `mapstructure:"destroy" cty:"destroy" hcl:"destroy"`
|
||||
Ovf *bool `mapstructure:"ovf" cty:"ovf" hcl:"ovf"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatContentLibraryDestinationConfig.
|
||||
// FlatContentLibraryDestinationConfig is an auto-generated flat version of ContentLibraryDestinationConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*ContentLibraryDestinationConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatContentLibraryDestinationConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a ContentLibraryDestinationConfig.
|
||||
// This spec is used by HCL to read the fields of ContentLibraryDestinationConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatContentLibraryDestinationConfig.
|
||||
func (*FlatContentLibraryDestinationConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"library": &hcldec.AttrSpec{Name: "library", Type: cty.String, Required: false},
|
||||
"name": &hcldec.AttrSpec{Name: "name", Type: cty.String, Required: false},
|
||||
"description": &hcldec.AttrSpec{Name: "description", Type: cty.String, Required: false},
|
||||
"cluster": &hcldec.AttrSpec{Name: "cluster", Type: cty.String, Required: false},
|
||||
"folder": &hcldec.AttrSpec{Name: "folder", Type: cty.String, Required: false},
|
||||
"host": &hcldec.AttrSpec{Name: "host", Type: cty.String, Required: false},
|
||||
"resource_pool": &hcldec.AttrSpec{Name: "resource_pool", Type: cty.String, Required: false},
|
||||
"datastore": &hcldec.AttrSpec{Name: "datastore", Type: cty.String, Required: false},
|
||||
"destroy": &hcldec.AttrSpec{Name: "destroy", Type: cty.Bool, Required: false},
|
||||
"ovf": &hcldec.AttrSpec{Name: "ovf", Type: cty.Bool, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
117
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_remote_upload.go
generated
vendored
Normal file
117
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_remote_upload.go
generated
vendored
Normal file
|
@ -0,0 +1,117 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
type StepRemoteUpload struct {
|
||||
Datastore string
|
||||
Host string
|
||||
SetHostForDatastoreUploads bool
|
||||
UploadedCustomCD bool
|
||||
}
|
||||
|
||||
func (s *StepRemoteUpload) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
d := state.Get("driver").(driver.Driver)
|
||||
|
||||
if path, ok := state.GetOk("iso_path"); ok {
|
||||
// user-supplied boot iso
|
||||
fullRemotePath, err := s.uploadFile(path.(string), d, ui)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
state.Put("iso_remote_path", fullRemotePath)
|
||||
}
|
||||
if cdPath, ok := state.GetOk("cd_path"); ok {
|
||||
// Packer-created cd_files disk
|
||||
fullRemotePath, err := s.uploadFile(cdPath.(string), d, ui)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
s.UploadedCustomCD = true
|
||||
state.Put("cd_path", fullRemotePath)
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func GetRemoteDirectoryAndPath(path string, ds driver.Datastore) (string, string, string, string) {
|
||||
filename := filepath.Base(path)
|
||||
remotePath := fmt.Sprintf("packer_cache/%s", filename)
|
||||
remoteDirectory := fmt.Sprintf("[%s] packer_cache/", ds.Name())
|
||||
fullRemotePath := fmt.Sprintf("%s/%s", remoteDirectory, filename)
|
||||
|
||||
return filename, remotePath, remoteDirectory, fullRemotePath
|
||||
|
||||
}
|
||||
func (s *StepRemoteUpload) uploadFile(path string, d driver.Driver, ui packersdk.Ui) (string, error) {
|
||||
ds, err := d.FindDatastore(s.Datastore, s.Host)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("datastore doesn't exist: %v", err)
|
||||
}
|
||||
|
||||
filename, remotePath, remoteDirectory, fullRemotePath := GetRemoteDirectoryAndPath(path, ds)
|
||||
|
||||
if exists := ds.FileExists(remotePath); exists == true {
|
||||
ui.Say(fmt.Sprintf("File %s already exists; skipping upload.", fullRemotePath))
|
||||
return fullRemotePath, nil
|
||||
}
|
||||
|
||||
ui.Say(fmt.Sprintf("Uploading %s to %s", filename, remotePath))
|
||||
|
||||
if exists := ds.DirExists(remotePath); exists == false {
|
||||
log.Printf("Remote directory doesn't exist; creating...")
|
||||
if err := ds.MakeDirectory(remoteDirectory); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
if err := ds.UploadFile(path, remotePath, s.Host, s.SetHostForDatastoreUploads); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fullRemotePath, nil
|
||||
}
|
||||
|
||||
func (s *StepRemoteUpload) Cleanup(state multistep.StateBag) {
|
||||
_, cancelled := state.GetOk(multistep.StateCancelled)
|
||||
_, halted := state.GetOk(multistep.StateHalted)
|
||||
if !cancelled && !halted {
|
||||
return
|
||||
}
|
||||
|
||||
if !s.UploadedCustomCD {
|
||||
return
|
||||
}
|
||||
|
||||
UploadedCDPath, ok := state.GetOk("cd_path")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
d := state.Get("driver").(*driver.VCenterDriver)
|
||||
ui.Say("Deleting cd_files image from remote datastore ...")
|
||||
|
||||
ds, err := d.FindDatastore(s.Datastore, s.Host)
|
||||
if err != nil {
|
||||
log.Printf("Error finding datastore to delete custom CD; please delete manually: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
err = ds.Delete(UploadedCDPath.(string))
|
||||
if err != nil {
|
||||
log.Printf("Error deleting custom CD from remote datastore; please delete manually: %s", err)
|
||||
return
|
||||
|
||||
}
|
||||
}
|
46
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_remove_cdrom.go
generated
vendored
Normal file
46
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_remove_cdrom.go
generated
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type RemoveCDRomConfig
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
type RemoveCDRomConfig struct {
|
||||
// Remove CD-ROM devices from template. Defaults to `false`.
|
||||
RemoveCdrom bool `mapstructure:"remove_cdrom"`
|
||||
}
|
||||
|
||||
type StepRemoveCDRom struct {
|
||||
Config *RemoveCDRomConfig
|
||||
}
|
||||
|
||||
func (s *StepRemoveCDRom) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
vm := state.Get("vm").(driver.VirtualMachine)
|
||||
|
||||
ui.Say("Eject CD-ROM drives...")
|
||||
err := vm.EjectCdroms()
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if s.Config.RemoveCdrom == true {
|
||||
ui.Say("Deleting CD-ROM drives...")
|
||||
err := vm.RemoveCdroms()
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepRemoveCDRom) Cleanup(state multistep.StateBag) {}
|
31
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_remove_cdrom.hcl2spec.go
generated
vendored
Normal file
31
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_remove_cdrom.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type RemoveCDRomConfig"; DO NOT EDIT.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatRemoveCDRomConfig is an auto-generated flat version of RemoveCDRomConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatRemoveCDRomConfig struct {
|
||||
RemoveCdrom *bool `mapstructure:"remove_cdrom" cty:"remove_cdrom" hcl:"remove_cdrom"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatRemoveCDRomConfig.
|
||||
// FlatRemoveCDRomConfig is an auto-generated flat version of RemoveCDRomConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*RemoveCDRomConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatRemoveCDRomConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a RemoveCDRomConfig.
|
||||
// This spec is used by HCL to read the fields of RemoveCDRomConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatRemoveCDRomConfig.
|
||||
func (*FlatRemoveCDRomConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"remove_cdrom": &hcldec.AttrSpec{Name: "remove_cdrom", Type: cty.Bool, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
49
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_remove_floppy.go
generated
vendored
Normal file
49
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_remove_floppy.go
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
type StepRemoveFloppy struct {
|
||||
Datastore string
|
||||
Host string
|
||||
}
|
||||
|
||||
func (s *StepRemoveFloppy) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
vm := state.Get("vm").(driver.VirtualMachine)
|
||||
d := state.Get("driver").(driver.Driver)
|
||||
|
||||
ui.Say("Deleting Floppy drives...")
|
||||
floppies, err := vm.FloppyDevices()
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
if err = vm.RemoveDevice(true, floppies...); err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if UploadedFloppyPath, ok := state.GetOk("uploaded_floppy_path"); ok {
|
||||
ui.Say("Deleting Floppy image...")
|
||||
ds, err := d.FindDatastore(s.Datastore, s.Host)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
if err := ds.Delete(UploadedFloppyPath.(string)); err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
state.Remove("uploaded_floppy_path")
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepRemoveFloppy) Cleanup(state multistep.StateBag) {}
|
80
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_run.go
generated
vendored
Normal file
80
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_run.go
generated
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type RunConfig
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
type RunConfig struct {
|
||||
// Priority of boot devices. Defaults to `disk,cdrom`
|
||||
BootOrder string `mapstructure:"boot_order"` // example: "floppy,cdrom,ethernet,disk"
|
||||
}
|
||||
|
||||
type StepRun struct {
|
||||
Config *RunConfig
|
||||
SetOrder bool
|
||||
}
|
||||
|
||||
func (s *StepRun) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
if s.Config.BootOrder != "" {
|
||||
ui.Say("Set boot order...")
|
||||
order := strings.Split(s.Config.BootOrder, ",")
|
||||
if err := vm.SetBootOrder(order); err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
} else {
|
||||
if s.SetOrder {
|
||||
ui.Say("Set boot order temporary...")
|
||||
if err := vm.SetBootOrder([]string{"disk", "cdrom"}); err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui.Say("Power on VM...")
|
||||
err := vm.PowerOn()
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepRun) Cleanup(state multistep.StateBag) {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
if s.Config.BootOrder == "" && s.SetOrder {
|
||||
ui.Say("Clear boot order...")
|
||||
if err := vm.SetBootOrder([]string{"-"}); err != nil {
|
||||
state.Put("error", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
_, cancelled := state.GetOk(multistep.StateCancelled)
|
||||
_, halted := state.GetOk(multistep.StateHalted)
|
||||
if !cancelled && !halted {
|
||||
return
|
||||
}
|
||||
|
||||
ui.Say("Power off VM...")
|
||||
|
||||
err := vm.PowerOff()
|
||||
if err != nil {
|
||||
ui.Error(err.Error())
|
||||
}
|
||||
}
|
31
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_run.hcl2spec.go
generated
vendored
Normal file
31
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_run.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type RunConfig"; DO NOT EDIT.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatRunConfig is an auto-generated flat version of RunConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatRunConfig struct {
|
||||
BootOrder *string `mapstructure:"boot_order" cty:"boot_order" hcl:"boot_order"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatRunConfig.
|
||||
// FlatRunConfig is an auto-generated flat version of RunConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*RunConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatRunConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a RunConfig.
|
||||
// This spec is used by HCL to read the fields of RunConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatRunConfig.
|
||||
func (*FlatRunConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"boot_order": &hcldec.AttrSpec{Name: "boot_order", Type: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
109
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_shutdown.go
generated
vendored
Normal file
109
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_shutdown.go
generated
vendored
Normal file
|
@ -0,0 +1,109 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type ShutdownConfig
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
type ShutdownConfig struct {
|
||||
// Specify a VM guest shutdown command. This command will be executed using
|
||||
// the `communicator`. Otherwise the VMware guest tools are used to gracefully
|
||||
// shutdown the VM guest.
|
||||
Command string `mapstructure:"shutdown_command"`
|
||||
// Amount of time to wait for graceful VM shutdown.
|
||||
// Defaults to 5m or five minutes.
|
||||
// This will likely need to be modified if the `communicator` is 'none'.
|
||||
Timeout time.Duration `mapstructure:"shutdown_timeout"`
|
||||
// Packer normally halts the virtual machine after all provisioners have
|
||||
// run when no `shutdown_command` is defined. If this is set to `true`, Packer
|
||||
// *will not* halt the virtual machine but will assume that you will send the stop
|
||||
// signal yourself through a preseed.cfg, a script or the final provisioner.
|
||||
// Packer will wait for a default of five minutes until the virtual machine is shutdown.
|
||||
// The timeout can be changed using `shutdown_timeout` option.
|
||||
DisableShutdown bool `mapstructure:"disable_shutdown"`
|
||||
}
|
||||
|
||||
func (c *ShutdownConfig) Prepare(comm communicator.Config) (warnings []string, errs []error) {
|
||||
|
||||
if c.Timeout == 0 {
|
||||
c.Timeout = 5 * time.Minute
|
||||
}
|
||||
|
||||
if comm.Type == "none" && c.Command != "" {
|
||||
warnings = append(warnings, "The parameter `shutdown_command` is ignored as it requires a `communicator`.")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type StepShutdown struct {
|
||||
Config *ShutdownConfig
|
||||
}
|
||||
|
||||
func (s *StepShutdown) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
if off, _ := vm.IsPoweredOff(); off {
|
||||
// Probably power off initiated by last provisioner, though disable_shutdown is not set
|
||||
ui.Say("VM is already powered off")
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
comm, _ := state.Get("communicator").(packersdk.Communicator)
|
||||
if comm == nil {
|
||||
|
||||
msg := fmt.Sprintf("Please shutdown virtual machine within %s.", s.Config.Timeout)
|
||||
ui.Message(msg)
|
||||
|
||||
} else if s.Config.DisableShutdown {
|
||||
ui.Say("Automatic shutdown disabled. Please shutdown virtual machine.")
|
||||
} else if s.Config.Command != "" {
|
||||
// Communicator is not needed unless shutdown_command is populated
|
||||
|
||||
ui.Say("Executing shutdown command...")
|
||||
log.Printf("Shutdown command: %s", s.Config.Command)
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd := &packersdk.RemoteCmd{
|
||||
Command: s.Config.Command,
|
||||
Stdout: &stdout,
|
||||
Stderr: &stderr,
|
||||
}
|
||||
err := comm.Start(ctx, cmd)
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf("Failed to send shutdown command: %s", err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
} else {
|
||||
ui.Say("Shutting down VM...")
|
||||
|
||||
err := vm.StartShutdown()
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf("Cannot shut down VM: %v", err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("Waiting max %s for shutdown to complete", s.Config.Timeout)
|
||||
err := vm.WaitForShutdown(ctx, s.Config.Timeout)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepShutdown) Cleanup(state multistep.StateBag) {}
|
35
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_shutdown.hcl2spec.go
generated
vendored
Normal file
35
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_shutdown.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type ShutdownConfig"; DO NOT EDIT.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatShutdownConfig is an auto-generated flat version of ShutdownConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatShutdownConfig struct {
|
||||
Command *string `mapstructure:"shutdown_command" cty:"shutdown_command" hcl:"shutdown_command"`
|
||||
Timeout *string `mapstructure:"shutdown_timeout" cty:"shutdown_timeout" hcl:"shutdown_timeout"`
|
||||
DisableShutdown *bool `mapstructure:"disable_shutdown" cty:"disable_shutdown" hcl:"disable_shutdown"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatShutdownConfig.
|
||||
// FlatShutdownConfig is an auto-generated flat version of ShutdownConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*ShutdownConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatShutdownConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a ShutdownConfig.
|
||||
// This spec is used by HCL to read the fields of ShutdownConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatShutdownConfig.
|
||||
func (*FlatShutdownConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"shutdown_command": &hcldec.AttrSpec{Name: "shutdown_command", Type: cty.String, Required: false},
|
||||
"shutdown_timeout": &hcldec.AttrSpec{Name: "shutdown_timeout", Type: cty.String, Required: false},
|
||||
"disable_shutdown": &hcldec.AttrSpec{Name: "disable_shutdown", Type: cty.Bool, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
32
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_snapshot.go
generated
vendored
Normal file
32
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_snapshot.go
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
type StepCreateSnapshot struct {
|
||||
CreateSnapshot bool
|
||||
}
|
||||
|
||||
func (s *StepCreateSnapshot) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
if s.CreateSnapshot {
|
||||
ui.Say("Creating snapshot...")
|
||||
|
||||
err := vm.CreateSnapshot("Created by Packer")
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepCreateSnapshot) Cleanup(state multistep.StateBag) {}
|
115
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_ssh_key_pair.go
generated
vendored
Normal file
115
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_ssh_key_pair.go
generated
vendored
Normal file
|
@ -0,0 +1,115 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator/ssh"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/uuid"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
// StepSshKeyPair executes the business logic for setting the SSH key pair in
|
||||
// the specified communicator.Config.
|
||||
type StepSshKeyPair struct {
|
||||
Debug bool
|
||||
DebugKeyPath string
|
||||
Comm *communicator.Config
|
||||
}
|
||||
|
||||
func (s *StepSshKeyPair) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
if s.Comm.Type != "ssh" || s.Comm.SSHPassword != "" {
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
|
||||
comment := fmt.Sprintf("packer_%s", uuid.TimeOrderedUUID())
|
||||
if s.Comm.SSHPrivateKeyFile != "" {
|
||||
ui.Say("Using existing SSH private key for the communicator...")
|
||||
privateKeyBytes, err := s.Comm.ReadSSHPrivateKeyFile()
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
kp, err := ssh.KeyPairFromPrivateKey(ssh.FromPrivateKeyConfig{
|
||||
RawPrivateKeyPemBlock: privateKeyBytes,
|
||||
Comment: comment,
|
||||
})
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
s.Comm.SSHPrivateKey = privateKeyBytes
|
||||
s.Comm.SSHKeyPairName = kp.Comment
|
||||
s.Comm.SSHTemporaryKeyPairName = kp.Comment
|
||||
s.Comm.SSHPublicKey = kp.PublicKeyAuthorizedKeysLine
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
if s.Comm.SSHAgentAuth {
|
||||
ui.Say("Using local SSH Agent to authenticate connections for the communicator...")
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
ui.Say("Creating ephemeral key pair for SSH communicator...")
|
||||
|
||||
if s.Comm.SSHTemporaryKeyPairName != "" {
|
||||
comment = s.Comm.SSHTemporaryKeyPairName
|
||||
}
|
||||
|
||||
kp, err := ssh.NewKeyPair(ssh.CreateKeyPairConfig{
|
||||
Comment: comment,
|
||||
Type: ssh.Rsa,
|
||||
})
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf("Error creating temporary keypair: %s", err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
s.Comm.SSHKeyPairName = kp.Comment
|
||||
s.Comm.SSHTemporaryKeyPairName = kp.Comment
|
||||
s.Comm.SSHPrivateKey = kp.PrivateKeyPemBlock
|
||||
s.Comm.SSHPublicKey = kp.PublicKeyAuthorizedKeysLine
|
||||
s.Comm.SSHClearAuthorizedKeys = true
|
||||
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
err = vm.AddPublicKeys(ctx, string(s.Comm.SSHPublicKey))
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf("error saving temporary keypair in the vm: %s", err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
ui.Say("Created ephemeral SSH key pair for communicator")
|
||||
|
||||
// If we're in debug mode, output the private key to the working
|
||||
// directory.
|
||||
if s.Debug {
|
||||
ui.Message(fmt.Sprintf("Saving communicator private key for debug purposes: %s", s.DebugKeyPath))
|
||||
// Write the key out
|
||||
if err := ioutil.WriteFile(s.DebugKeyPath, kp.PrivateKeyPemBlock, 0600); err != nil {
|
||||
state.Put("error", fmt.Errorf("Error saving debug key: %s", err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepSshKeyPair) Cleanup(state multistep.StateBag) {
|
||||
if s.Debug {
|
||||
if err := os.Remove(s.DebugKeyPath); err != nil {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
ui.Error(fmt.Sprintf(
|
||||
"Error removing debug key '%s': %s", s.DebugKeyPath, err))
|
||||
}
|
||||
}
|
||||
}
|
31
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_template.go
generated
vendored
Normal file
31
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_template.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
type StepConvertToTemplate struct {
|
||||
ConvertToTemplate bool
|
||||
}
|
||||
|
||||
func (s *StepConvertToTemplate) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
if s.ConvertToTemplate {
|
||||
ui.Say("Convert VM into template...")
|
||||
err := vm.ConvertToTemplate()
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepConvertToTemplate) Cleanup(state multistep.StateBag) {}
|
182
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_wait_for_ip.go
generated
vendored
Normal file
182
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_wait_for_ip.go
generated
vendored
Normal file
|
@ -0,0 +1,182 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type WaitIpConfig
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
type WaitIpConfig struct {
|
||||
// Amount of time to wait for VM's IP, similar to 'ssh_timeout'.
|
||||
// Defaults to 30m (30 minutes). See the Golang
|
||||
// [ParseDuration](https://golang.org/pkg/time/#ParseDuration) documentation
|
||||
// for full details.
|
||||
WaitTimeout time.Duration `mapstructure:"ip_wait_timeout"`
|
||||
// Amount of time to wait for VM's IP to settle down, sometimes VM may
|
||||
// report incorrect IP initially, then its recommended to set that
|
||||
// parameter to apx. 2 minutes. Examples 45s and 10m. Defaults to
|
||||
// 5s(5 seconds). See the Golang
|
||||
// [ParseDuration](https://golang.org/pkg/time/#ParseDuration) documentation
|
||||
// for full details.
|
||||
SettleTimeout time.Duration `mapstructure:"ip_settle_timeout"`
|
||||
// Set this to a CIDR address to cause the service to wait for an address that is contained in
|
||||
// this network range. Defaults to "0.0.0.0/0" for any ipv4 address. Examples include:
|
||||
//
|
||||
// * empty string ("") - remove all filters
|
||||
// * `0:0:0:0:0:0:0:0/0` - allow only ipv6 addresses
|
||||
// * `192.168.1.0/24` - only allow ipv4 addresses from 192.168.1.1 to 192.168.1.254
|
||||
WaitAddress *string `mapstructure:"ip_wait_address"`
|
||||
ipnet *net.IPNet
|
||||
|
||||
// WaitTimeout is a total timeout, so even if VM changes IP frequently and it doesn't settle down we will end waiting.
|
||||
}
|
||||
|
||||
type StepWaitForIp struct {
|
||||
Config *WaitIpConfig
|
||||
}
|
||||
|
||||
func (c *WaitIpConfig) Prepare() []error {
|
||||
var errs []error
|
||||
|
||||
if c.SettleTimeout == 0 {
|
||||
c.SettleTimeout = 5 * time.Second
|
||||
}
|
||||
if c.WaitTimeout == 0 {
|
||||
c.WaitTimeout = 30 * time.Minute
|
||||
}
|
||||
if c.WaitAddress == nil {
|
||||
addr := "0.0.0.0/0"
|
||||
c.WaitAddress = &addr
|
||||
}
|
||||
|
||||
if *c.WaitAddress != "" {
|
||||
var err error
|
||||
_, c.ipnet, err = net.ParseCIDR(*c.WaitAddress)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("unable to parse \"ip_wait_address\": %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
func (c *WaitIpConfig) GetIPNet() *net.IPNet {
|
||||
return c.ipnet
|
||||
}
|
||||
|
||||
func (s *StepWaitForIp) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
vm := state.Get("vm").(*driver.VirtualMachineDriver)
|
||||
|
||||
var ip string
|
||||
var err error
|
||||
|
||||
sub, cancel := context.WithCancel(ctx)
|
||||
waitDone := make(chan bool, 1)
|
||||
defer func() {
|
||||
cancel()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
ui.Say("Waiting for IP...")
|
||||
ip, err = doGetIp(vm, sub, s.Config)
|
||||
waitDone <- true
|
||||
}()
|
||||
|
||||
log.Printf("[INFO] Waiting for IP, up to total timeout: %s, settle timeout: %s", s.Config.WaitTimeout, s.Config.SettleTimeout)
|
||||
timeout := time.After(s.Config.WaitTimeout)
|
||||
for {
|
||||
select {
|
||||
case <-timeout:
|
||||
cancel()
|
||||
<-waitDone
|
||||
if ip != "" {
|
||||
state.Put("ip", ip)
|
||||
log.Printf("[WARN] API timeout waiting for IP but one IP was found. Using IP: %s", ip)
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
err := fmt.Errorf("Timeout waiting for IP.")
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
case <-ctx.Done():
|
||||
cancel()
|
||||
log.Println("[WARN] Interrupt detected, quitting waiting for IP.")
|
||||
return multistep.ActionHalt
|
||||
case <-waitDone:
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
state.Put("ip", ip)
|
||||
ui.Say(fmt.Sprintf("IP address: %v", ip))
|
||||
return multistep.ActionContinue
|
||||
case <-time.After(1 * time.Second):
|
||||
if _, ok := state.GetOk(multistep.StateCancelled); ok {
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func doGetIp(vm *driver.VirtualMachineDriver, ctx context.Context, c *WaitIpConfig) (string, error) {
|
||||
var prevIp = ""
|
||||
var stopTime time.Time
|
||||
var interval time.Duration
|
||||
if c.SettleTimeout.Seconds() >= 120 {
|
||||
interval = 30 * time.Second
|
||||
} else if c.SettleTimeout.Seconds() >= 60 {
|
||||
interval = 15 * time.Second
|
||||
} else if c.SettleTimeout.Seconds() >= 10 {
|
||||
interval = 5 * time.Second
|
||||
} else {
|
||||
interval = 1 * time.Second
|
||||
}
|
||||
loop:
|
||||
ip, err := vm.WaitForIP(ctx, c.ipnet)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Check for ctx cancellation to avoid printing any IP logs at the timeout
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ip, fmt.Errorf("IP wait cancelled.")
|
||||
default:
|
||||
}
|
||||
|
||||
if prevIp == "" || prevIp != ip {
|
||||
if prevIp == "" {
|
||||
log.Printf("VM IP aquired: %s", ip)
|
||||
} else {
|
||||
log.Printf("VM IP changed from %s to %s", prevIp, ip)
|
||||
}
|
||||
prevIp = ip
|
||||
stopTime = time.Now().Add(c.SettleTimeout)
|
||||
goto loop
|
||||
} else {
|
||||
log.Printf("VM IP is still the same: %s", prevIp)
|
||||
if time.Now().After(stopTime) {
|
||||
log.Printf("VM IP seems stable enough: %s", ip)
|
||||
return ip, nil
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return "", fmt.Errorf("IP wait cancelled")
|
||||
case <-time.After(interval):
|
||||
goto loop
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s *StepWaitForIp) Cleanup(state multistep.StateBag) {}
|
35
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_wait_for_ip.hcl2spec.go
generated
vendored
Normal file
35
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/step_wait_for_ip.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type WaitIpConfig"; DO NOT EDIT.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatWaitIpConfig is an auto-generated flat version of WaitIpConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatWaitIpConfig struct {
|
||||
WaitTimeout *string `mapstructure:"ip_wait_timeout" cty:"ip_wait_timeout" hcl:"ip_wait_timeout"`
|
||||
SettleTimeout *string `mapstructure:"ip_settle_timeout" cty:"ip_settle_timeout" hcl:"ip_settle_timeout"`
|
||||
WaitAddress *string `mapstructure:"ip_wait_address" cty:"ip_wait_address" hcl:"ip_wait_address"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatWaitIpConfig.
|
||||
// FlatWaitIpConfig is an auto-generated flat version of WaitIpConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*WaitIpConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatWaitIpConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a WaitIpConfig.
|
||||
// This spec is used by HCL to read the fields of WaitIpConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatWaitIpConfig.
|
||||
func (*FlatWaitIpConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"ip_wait_timeout": &hcldec.AttrSpec{Name: "ip_wait_timeout", Type: cty.String, Required: false},
|
||||
"ip_settle_timeout": &hcldec.AttrSpec{Name: "ip_settle_timeout", Type: cty.String, Required: false},
|
||||
"ip_wait_address": &hcldec.AttrSpec{Name: "ip_wait_address", Type: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
118
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/storage_config.go
generated
vendored
Normal file
118
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/storage_config.go
generated
vendored
Normal file
|
@ -0,0 +1,118 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type StorageConfig,DiskConfig
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Defines the disk storage for a VM.
|
||||
//
|
||||
// Example that will create a 15GB and a 20GB disk on the VM. The second disk will be thin provisioned:
|
||||
//
|
||||
// In JSON:
|
||||
// ```json
|
||||
// "storage": [
|
||||
// {
|
||||
// "disk_size": 15000
|
||||
// },
|
||||
// {
|
||||
// "disk_size": 20000,
|
||||
// "disk_thin_provisioned": true
|
||||
// }
|
||||
// ],
|
||||
// ```
|
||||
// In HCL2:
|
||||
// ```hcl
|
||||
// storage {
|
||||
// disk_size = 15000
|
||||
// }
|
||||
// storage {
|
||||
// disk_size = 20000
|
||||
// disk_thin_provisioned = true
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Example that creates 2 pvscsi controllers and adds 2 disks to each one:
|
||||
//
|
||||
// In JSON:
|
||||
// ```json
|
||||
// "disk_controller_type": ["pvscsi", "pvscsi"],
|
||||
// "storage": [
|
||||
// {
|
||||
// "disk_size": 15000,
|
||||
// "disk_controller_index": 0
|
||||
// },
|
||||
// {
|
||||
// "disk_size": 15000,
|
||||
// "disk_controller_index": 0
|
||||
// },
|
||||
// {
|
||||
// "disk_size": 15000,
|
||||
// "disk_controller_index": 1
|
||||
// },
|
||||
// {
|
||||
// "disk_size": 15000,
|
||||
// "disk_controller_index": 1
|
||||
// }
|
||||
// ],
|
||||
// ```
|
||||
//
|
||||
// In HCL2:
|
||||
// ```hcl
|
||||
// disk_controller_type = ["pvscsi", "pvscsi"]
|
||||
// storage {
|
||||
// disk_size = 15000,
|
||||
// disk_controller_index = 0
|
||||
// }
|
||||
// storage {
|
||||
// disk_size = 15000
|
||||
// disk_controller_index = 0
|
||||
// }
|
||||
// storage {
|
||||
// disk_size = 15000
|
||||
// disk_controller_index = 1
|
||||
// }
|
||||
// storage {
|
||||
// disk_size = 15000
|
||||
// disk_controller_index = 1
|
||||
// }
|
||||
// ```
|
||||
type DiskConfig struct {
|
||||
// The size of the disk in MB.
|
||||
DiskSize int64 `mapstructure:"disk_size" required:"true"`
|
||||
// Enable VMDK thin provisioning for VM. Defaults to `false`.
|
||||
DiskThinProvisioned bool `mapstructure:"disk_thin_provisioned"`
|
||||
// Enable VMDK eager scrubbing for VM. Defaults to `false`.
|
||||
DiskEagerlyScrub bool `mapstructure:"disk_eagerly_scrub"`
|
||||
// The assigned disk controller. Defaults to the first one (0)
|
||||
DiskControllerIndex int `mapstructure:"disk_controller_index"`
|
||||
}
|
||||
|
||||
type StorageConfig struct {
|
||||
// Set VM disk controller type. Example `lsilogic`, `pvscsi`, `nvme`, or `scsi`. Use a list to define additional controllers.
|
||||
// Defaults to `lsilogic`. See
|
||||
// [SCSI, SATA, and NVMe Storage Controller Conditions, Limitations, and Compatibility](https://docs.vmware.com/en/VMware-vSphere/7.0/com.vmware.vsphere.vm_admin.doc/GUID-5872D173-A076-42FE-8D0B-9DB0EB0E7362.html#GUID-5872D173-A076-42FE-8D0B-9DB0EB0E7362)
|
||||
// for additional details.
|
||||
DiskControllerType []string `mapstructure:"disk_controller_type"`
|
||||
// Configures a collection of one or more disks to be provisioned along with the VM. See the [Storage Configuration](#storage-configuration).
|
||||
Storage []DiskConfig `mapstructure:"storage"`
|
||||
}
|
||||
|
||||
func (c *StorageConfig) Prepare() []error {
|
||||
var errs []error
|
||||
|
||||
if len(c.Storage) > 0 {
|
||||
for i, storage := range c.Storage {
|
||||
if storage.DiskSize == 0 {
|
||||
errs = append(errs, fmt.Errorf("storage[%d].'disk_size' is required", i))
|
||||
}
|
||||
if storage.DiskControllerIndex >= len(c.DiskControllerType) {
|
||||
errs = append(errs, fmt.Errorf("storage[%d].'disk_controller_index' references an unknown disk controller", i))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
62
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/storage_config.hcl2spec.go
generated
vendored
Normal file
62
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common/storage_config.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type StorageConfig,DiskConfig"; DO NOT EDIT.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatDiskConfig is an auto-generated flat version of DiskConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatDiskConfig struct {
|
||||
DiskSize *int64 `mapstructure:"disk_size" required:"true" cty:"disk_size" hcl:"disk_size"`
|
||||
DiskThinProvisioned *bool `mapstructure:"disk_thin_provisioned" cty:"disk_thin_provisioned" hcl:"disk_thin_provisioned"`
|
||||
DiskEagerlyScrub *bool `mapstructure:"disk_eagerly_scrub" cty:"disk_eagerly_scrub" hcl:"disk_eagerly_scrub"`
|
||||
DiskControllerIndex *int `mapstructure:"disk_controller_index" cty:"disk_controller_index" hcl:"disk_controller_index"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatDiskConfig.
|
||||
// FlatDiskConfig is an auto-generated flat version of DiskConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*DiskConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatDiskConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a DiskConfig.
|
||||
// This spec is used by HCL to read the fields of DiskConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatDiskConfig.
|
||||
func (*FlatDiskConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, Required: false},
|
||||
"disk_thin_provisioned": &hcldec.AttrSpec{Name: "disk_thin_provisioned", Type: cty.Bool, Required: false},
|
||||
"disk_eagerly_scrub": &hcldec.AttrSpec{Name: "disk_eagerly_scrub", Type: cty.Bool, Required: false},
|
||||
"disk_controller_index": &hcldec.AttrSpec{Name: "disk_controller_index", Type: cty.Number, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// FlatStorageConfig is an auto-generated flat version of StorageConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatStorageConfig struct {
|
||||
DiskControllerType []string `mapstructure:"disk_controller_type" cty:"disk_controller_type" hcl:"disk_controller_type"`
|
||||
Storage []FlatDiskConfig `mapstructure:"storage" cty:"storage" hcl:"storage"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatStorageConfig.
|
||||
// FlatStorageConfig is an auto-generated flat version of StorageConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*StorageConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatStorageConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a StorageConfig.
|
||||
// This spec is used by HCL to read the fields of StorageConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatStorageConfig.
|
||||
func (*FlatStorageConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"disk_controller_type": &hcldec.AttrSpec{Name: "disk_controller_type", Type: cty.List(cty.String), Required: false},
|
||||
"storage": &hcldec.BlockListSpec{TypeName: "storage", Nested: hcldec.ObjectSpec((*FlatDiskConfig)(nil).HCL2Spec())},
|
||||
}
|
||||
return s
|
||||
}
|
19
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/cluster.go
generated
vendored
Normal file
19
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/cluster.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
package driver
|
||||
|
||||
import "github.com/vmware/govmomi/object"
|
||||
|
||||
type Cluster struct {
|
||||
driver *VCenterDriver
|
||||
cluster *object.ClusterComputeResource
|
||||
}
|
||||
|
||||
func (d *VCenterDriver) FindCluster(name string) (*Cluster, error) {
|
||||
c, err := d.finder.ClusterComputeResource(d.ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Cluster{
|
||||
cluster: c,
|
||||
driver: d,
|
||||
}, nil
|
||||
}
|
235
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/datastore.go
generated
vendored
Normal file
235
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/datastore.go
generated
vendored
Normal file
|
@ -0,0 +1,235 @@
|
|||
package driver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/property"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type Datastore interface {
|
||||
Info(params ...string) (*mo.Datastore, error)
|
||||
FileExists(path string) bool
|
||||
DirExists(path string) bool
|
||||
Name() string
|
||||
ResolvePath(path string) string
|
||||
UploadFile(src, dst, host string, setHost bool) error
|
||||
Delete(path string) error
|
||||
MakeDirectory(path string) error
|
||||
Reference() types.ManagedObjectReference
|
||||
}
|
||||
|
||||
type DatastoreDriver struct {
|
||||
ds *object.Datastore
|
||||
driver *VCenterDriver
|
||||
}
|
||||
|
||||
func (d *VCenterDriver) NewDatastore(ref *types.ManagedObjectReference) Datastore {
|
||||
return &DatastoreDriver{
|
||||
ds: object.NewDatastore(d.client.Client, *ref),
|
||||
driver: d,
|
||||
}
|
||||
}
|
||||
|
||||
// If name is an empty string, then resolve host's one
|
||||
func (d *VCenterDriver) FindDatastore(name string, host string) (Datastore, error) {
|
||||
if name == "" {
|
||||
h, err := d.FindHost(host)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error finding host for to get datastore: %s", err)
|
||||
}
|
||||
|
||||
i, err := h.Info("datastore")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error getting datastore info from host: %s", err)
|
||||
}
|
||||
|
||||
if len(i.Datastore) > 1 {
|
||||
return nil, fmt.Errorf("Host has multiple datastores. Specify it explicitly")
|
||||
}
|
||||
|
||||
ds := d.NewDatastore(&i.Datastore[0])
|
||||
inf, err := ds.Info("name")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error getting datastore name: %s", err)
|
||||
}
|
||||
name = inf.Name
|
||||
}
|
||||
|
||||
ds, err := d.finder.Datastore(d.ctx, name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error finding datastore with name %s: %s", name, err)
|
||||
}
|
||||
|
||||
return &DatastoreDriver{
|
||||
ds: ds,
|
||||
driver: d,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *VCenterDriver) GetDatastoreName(id string) (string, error) {
|
||||
obj := types.ManagedObjectReference{
|
||||
Type: "Datastore",
|
||||
Value: id,
|
||||
}
|
||||
pc := property.DefaultCollector(d.vimClient)
|
||||
var me mo.ManagedEntity
|
||||
|
||||
err := pc.RetrieveOne(d.ctx, obj, []string{"name"}, &me)
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
return me.Name, nil
|
||||
}
|
||||
|
||||
func (ds *DatastoreDriver) Info(params ...string) (*mo.Datastore, error) {
|
||||
var p []string
|
||||
if len(params) == 0 {
|
||||
p = []string{"*"}
|
||||
} else {
|
||||
p = params
|
||||
}
|
||||
var info mo.Datastore
|
||||
err := ds.ds.Properties(ds.driver.ctx, ds.ds.Reference(), p, &info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &info, nil
|
||||
}
|
||||
|
||||
func (ds *DatastoreDriver) DirExists(filepath string) bool {
|
||||
_, err := ds.ds.Stat(ds.driver.ctx, filepath)
|
||||
if _, ok := err.(object.DatastoreNoSuchDirectoryError); ok {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (ds *DatastoreDriver) FileExists(path string) bool {
|
||||
_, err := ds.ds.Stat(ds.driver.ctx, path)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func (ds *DatastoreDriver) Name() string {
|
||||
return ds.ds.Name()
|
||||
}
|
||||
|
||||
func (ds *DatastoreDriver) Reference() types.ManagedObjectReference {
|
||||
return ds.ds.Reference()
|
||||
}
|
||||
|
||||
func (ds *DatastoreDriver) ResolvePath(path string) string {
|
||||
return ds.ds.Path(path)
|
||||
}
|
||||
|
||||
// The file ID isn't available via the API, so we use DatastoreBrowser to search
|
||||
func (d *VCenterDriver) GetDatastoreFilePath(datastoreID, dir, filename string) (string, error) {
|
||||
ref := types.ManagedObjectReference{Type: "Datastore", Value: datastoreID}
|
||||
ds := object.NewDatastore(d.vimClient, ref)
|
||||
|
||||
b, err := ds.Browser(d.ctx)
|
||||
if err != nil {
|
||||
return filename, err
|
||||
}
|
||||
ext := path.Ext(filename)
|
||||
pat := strings.Replace(filename, ext, "*"+ext, 1)
|
||||
spec := types.HostDatastoreBrowserSearchSpec{
|
||||
MatchPattern: []string{pat},
|
||||
}
|
||||
|
||||
task, err := b.SearchDatastore(d.ctx, dir, &spec)
|
||||
if err != nil {
|
||||
return filename, err
|
||||
}
|
||||
|
||||
info, err := task.WaitForResult(d.ctx, nil)
|
||||
if err != nil {
|
||||
return filename, err
|
||||
}
|
||||
|
||||
res, ok := info.Result.(types.HostDatastoreBrowserSearchResults)
|
||||
if !ok {
|
||||
return filename, fmt.Errorf("search(%s) result type=%T", pat, info.Result)
|
||||
}
|
||||
|
||||
if len(res.File) != 1 {
|
||||
return filename, fmt.Errorf("search(%s) result files=%d", pat, len(res.File))
|
||||
}
|
||||
return res.File[0].GetFileInfo().Path, nil
|
||||
}
|
||||
|
||||
func (ds *DatastoreDriver) UploadFile(src, dst, host string, setHost bool) error {
|
||||
p := soap.DefaultUpload
|
||||
ctx := ds.driver.ctx
|
||||
|
||||
if setHost && host != "" {
|
||||
h, err := ds.driver.FindHost(host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctx = ds.ds.HostContext(ctx, h.host)
|
||||
}
|
||||
|
||||
return ds.ds.UploadFile(ctx, src, dst, &p)
|
||||
}
|
||||
|
||||
func (ds *DatastoreDriver) Delete(path string) error {
|
||||
dc, err := ds.driver.finder.Datacenter(ds.driver.ctx, ds.ds.DatacenterPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fm := ds.ds.NewFileManager(dc, false)
|
||||
return fm.Delete(ds.driver.ctx, path)
|
||||
}
|
||||
|
||||
func (ds *DatastoreDriver) MakeDirectory(path string) error {
|
||||
dc, err := ds.driver.finder.Datacenter(ds.driver.ctx, ds.ds.DatacenterPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fm := ds.ds.NewFileManager(dc, false)
|
||||
return fm.FileManager.MakeDirectory(ds.driver.ctx, path, dc, true)
|
||||
}
|
||||
|
||||
// Cuts out the datastore prefix
|
||||
// Example: "[datastore1] file.ext" --> "file.ext"
|
||||
func RemoveDatastorePrefix(path string) string {
|
||||
res := object.DatastorePath{}
|
||||
if hadPrefix := res.FromString(path); hadPrefix {
|
||||
return res.Path
|
||||
} else {
|
||||
return path
|
||||
}
|
||||
}
|
||||
|
||||
type DatastoreIsoPath struct {
|
||||
path string
|
||||
}
|
||||
|
||||
func (d *DatastoreIsoPath) Validate() bool {
|
||||
// Matches:
|
||||
// [datastore] /dir/subdir/file
|
||||
// [datastore] dir/subdir/file
|
||||
// [] /dir/subdir/file
|
||||
// [data-store] /dir/subdir/file
|
||||
// dir/subdir/file or dir/subdir/file
|
||||
matched, _ := regexp.MatchString(`^\s*(\[[^\[\]\/]*\])?\s*[^\[\]]+\s*$`, d.path)
|
||||
return matched
|
||||
}
|
||||
|
||||
func (d *DatastoreIsoPath) GetFilePath() string {
|
||||
filePath := d.path
|
||||
parts := strings.Split(d.path, "]")
|
||||
if len(parts) > 1 {
|
||||
// removes datastore name from path
|
||||
filePath = parts[1]
|
||||
filePath = strings.TrimSpace(filePath)
|
||||
}
|
||||
return filePath
|
||||
}
|
81
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/datastore_mock.go
generated
vendored
Normal file
81
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/datastore_mock.go
generated
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
package driver
|
||||
|
||||
import (
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type DatastoreMock struct {
|
||||
FileExistsCalled bool
|
||||
FileExistsReturn bool
|
||||
|
||||
DirExistsCalled bool
|
||||
DirExistsReturn bool
|
||||
|
||||
NameReturn string
|
||||
|
||||
MakeDirectoryCalled bool
|
||||
|
||||
ResolvePathCalled bool
|
||||
ResolvePathReturn string
|
||||
|
||||
DeleteCalled bool
|
||||
DeletePath string
|
||||
DeleteErr error
|
||||
|
||||
UploadFileCalled bool
|
||||
UploadFileSrc string
|
||||
UploadFileDst string
|
||||
UploadFileHost string
|
||||
UploadFileSetHost bool
|
||||
UploadFileErr error
|
||||
}
|
||||
|
||||
func (ds *DatastoreMock) Info(params ...string) (*mo.Datastore, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (ds *DatastoreMock) FileExists(path string) bool {
|
||||
ds.FileExistsCalled = true
|
||||
return ds.FileExistsReturn
|
||||
}
|
||||
|
||||
func (ds *DatastoreMock) DirExists(path string) bool {
|
||||
ds.DirExistsCalled = true
|
||||
return ds.DirExistsReturn
|
||||
}
|
||||
func (ds *DatastoreMock) Name() string {
|
||||
if ds.NameReturn == "" {
|
||||
return "datastore-mock"
|
||||
}
|
||||
return ds.NameReturn
|
||||
}
|
||||
|
||||
func (ds *DatastoreMock) Reference() types.ManagedObjectReference {
|
||||
return types.ManagedObjectReference{}
|
||||
}
|
||||
|
||||
func (ds *DatastoreMock) ResolvePath(path string) string {
|
||||
ds.ResolvePathCalled = true
|
||||
return ds.ResolvePathReturn
|
||||
}
|
||||
|
||||
func (ds *DatastoreMock) UploadFile(src, dst, host string, setHost bool) error {
|
||||
ds.UploadFileCalled = true
|
||||
ds.UploadFileSrc = src
|
||||
ds.UploadFileDst = dst
|
||||
ds.UploadFileHost = host
|
||||
ds.UploadFileSetHost = setHost
|
||||
return ds.UploadFileErr
|
||||
}
|
||||
|
||||
func (ds *DatastoreMock) Delete(path string) error {
|
||||
ds.DeleteCalled = true
|
||||
ds.DeletePath = path
|
||||
return ds.DeleteErr
|
||||
}
|
||||
|
||||
func (ds *DatastoreMock) MakeDirectory(path string) error {
|
||||
ds.MakeDirectoryCalled = true
|
||||
return nil
|
||||
}
|
85
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/disk.go
generated
vendored
Normal file
85
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/disk.go
generated
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
package driver
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type Disk struct {
|
||||
DiskSize int64
|
||||
DiskEagerlyScrub bool
|
||||
DiskThinProvisioned bool
|
||||
ControllerIndex int
|
||||
}
|
||||
|
||||
type StorageConfig struct {
|
||||
DiskControllerType []string // example: "scsi", "pvscsi", "nvme", "lsilogic"
|
||||
Storage []Disk
|
||||
}
|
||||
|
||||
func (c *StorageConfig) AddStorageDevices(existingDevices object.VirtualDeviceList) ([]types.BaseVirtualDeviceConfigSpec, error) {
|
||||
newDevices := object.VirtualDeviceList{}
|
||||
|
||||
// Create new controller based on existing devices list and add it to the new devices list
|
||||
// to confirm creation
|
||||
var controllers []types.BaseVirtualController
|
||||
for _, controllerType := range c.DiskControllerType {
|
||||
var device types.BaseVirtualDevice
|
||||
var err error
|
||||
if controllerType == "nvme" {
|
||||
device, err = existingDevices.CreateNVMEController()
|
||||
} else {
|
||||
device, err = existingDevices.CreateSCSIController(controllerType)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
existingDevices = append(existingDevices, device)
|
||||
newDevices = append(newDevices, device)
|
||||
controller, err := existingDevices.FindDiskController(existingDevices.Name(device))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
controllers = append(controllers, controller)
|
||||
}
|
||||
|
||||
for _, dc := range c.Storage {
|
||||
disk := &types.VirtualDisk{
|
||||
VirtualDevice: types.VirtualDevice{
|
||||
Key: existingDevices.NewKey(),
|
||||
Backing: &types.VirtualDiskFlatVer2BackingInfo{
|
||||
DiskMode: string(types.VirtualDiskModePersistent),
|
||||
ThinProvisioned: types.NewBool(dc.DiskThinProvisioned),
|
||||
EagerlyScrub: types.NewBool(dc.DiskEagerlyScrub),
|
||||
},
|
||||
},
|
||||
CapacityInKB: dc.DiskSize * 1024,
|
||||
}
|
||||
|
||||
existingDevices.AssignController(disk, controllers[dc.ControllerIndex])
|
||||
existingDevices = append(existingDevices, disk)
|
||||
newDevices = append(newDevices, disk)
|
||||
}
|
||||
|
||||
return newDevices.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd)
|
||||
}
|
||||
|
||||
func findDisk(devices object.VirtualDeviceList) (*types.VirtualDisk, error) {
|
||||
var disks []*types.VirtualDisk
|
||||
for _, device := range devices {
|
||||
switch d := device.(type) {
|
||||
case *types.VirtualDisk:
|
||||
disks = append(disks, d)
|
||||
}
|
||||
}
|
||||
|
||||
switch len(disks) {
|
||||
case 0:
|
||||
return nil, errors.New("VM has no disks")
|
||||
case 1:
|
||||
return disks[0], nil
|
||||
}
|
||||
return nil, errors.New("VM has multiple disks")
|
||||
}
|
129
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/driver.go
generated
vendored
Normal file
129
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/driver.go
generated
vendored
Normal file
|
@ -0,0 +1,129 @@
|
|||
package driver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/vmware/govmomi"
|
||||
"github.com/vmware/govmomi/find"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/session"
|
||||
"github.com/vmware/govmomi/vapi/library"
|
||||
"github.com/vmware/govmomi/vapi/rest"
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type Driver interface {
|
||||
NewVM(ref *types.ManagedObjectReference) VirtualMachine
|
||||
FindVM(name string) (VirtualMachine, error)
|
||||
FindCluster(name string) (*Cluster, error)
|
||||
PreCleanVM(ui packersdk.Ui, vmPath string, force bool) error
|
||||
CreateVM(config *CreateConfig) (VirtualMachine, error)
|
||||
|
||||
NewDatastore(ref *types.ManagedObjectReference) Datastore
|
||||
FindDatastore(name string, host string) (Datastore, error)
|
||||
GetDatastoreName(id string) (string, error)
|
||||
GetDatastoreFilePath(datastoreID, dir, filename string) (string, error)
|
||||
|
||||
NewFolder(ref *types.ManagedObjectReference) *Folder
|
||||
FindFolder(name string) (*Folder, error)
|
||||
NewHost(ref *types.ManagedObjectReference) *Host
|
||||
FindHost(name string) (*Host, error)
|
||||
NewNetwork(ref *types.ManagedObjectReference) *Network
|
||||
FindNetwork(name string) (*Network, error)
|
||||
FindNetworks(name string) ([]*Network, error)
|
||||
NewResourcePool(ref *types.ManagedObjectReference) *ResourcePool
|
||||
FindResourcePool(cluster string, host string, name string) (*ResourcePool, error)
|
||||
|
||||
FindContentLibraryByName(name string) (*Library, error)
|
||||
FindContentLibraryItem(libraryId string, name string) (*library.Item, error)
|
||||
FindContentLibraryFileDatastorePath(isoPath string) (string, error)
|
||||
}
|
||||
|
||||
type VCenterDriver struct {
|
||||
// context that controls the authenticated sessions used to run the VM commands
|
||||
ctx context.Context
|
||||
client *govmomi.Client
|
||||
vimClient *vim25.Client
|
||||
restClient *RestClient
|
||||
finder *find.Finder
|
||||
datacenter *object.Datacenter
|
||||
}
|
||||
|
||||
type ConnectConfig struct {
|
||||
VCenterServer string
|
||||
Username string
|
||||
Password string
|
||||
InsecureConnection bool
|
||||
Datacenter string
|
||||
}
|
||||
|
||||
func NewDriver(config *ConnectConfig) (Driver, error) {
|
||||
ctx := context.TODO()
|
||||
|
||||
vcenterUrl, err := url.Parse(fmt.Sprintf("https://%v/sdk", config.VCenterServer))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
credentials := url.UserPassword(config.Username, config.Password)
|
||||
vcenterUrl.User = credentials
|
||||
|
||||
soapClient := soap.NewClient(vcenterUrl, config.InsecureConnection)
|
||||
vimClient, err := vim25.NewClient(ctx, soapClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vimClient.RoundTripper = session.KeepAlive(vimClient.RoundTripper, 10*time.Minute)
|
||||
client := &govmomi.Client{
|
||||
Client: vimClient,
|
||||
SessionManager: session.NewManager(vimClient),
|
||||
}
|
||||
|
||||
err = client.SessionManager.Login(ctx, credentials)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
finder := find.NewFinder(client.Client, false)
|
||||
datacenter, err := finder.DatacenterOrDefault(ctx, config.Datacenter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
finder.SetDatacenter(datacenter)
|
||||
|
||||
d := &VCenterDriver{
|
||||
ctx: ctx,
|
||||
client: client,
|
||||
vimClient: vimClient,
|
||||
restClient: &RestClient{
|
||||
client: rest.NewClient(vimClient),
|
||||
credentials: credentials,
|
||||
},
|
||||
datacenter: datacenter,
|
||||
finder: finder,
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// The rest.Client requires vCenter.
|
||||
// RestClient is to modularize the rest.Client session and use it only when is necessary.
|
||||
// This will allow users without vCenter to use the other features that doesn't use the rest.Client.
|
||||
// To use the client login/logout must be done to create an authenticated session.
|
||||
type RestClient struct {
|
||||
client *rest.Client
|
||||
credentials *url.Userinfo
|
||||
}
|
||||
|
||||
func (r *RestClient) Login(ctx context.Context) error {
|
||||
return r.client.Login(ctx, r.credentials)
|
||||
}
|
||||
|
||||
func (r *RestClient) Logout(ctx context.Context) error {
|
||||
return r.client.Logout(ctx)
|
||||
}
|
119
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/driver_mock.go
generated
vendored
Normal file
119
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/driver_mock.go
generated
vendored
Normal file
|
@ -0,0 +1,119 @@
|
|||
package driver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/vmware/govmomi/vapi/library"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type DriverMock struct {
|
||||
FindDatastoreCalled bool
|
||||
DatastoreMock *DatastoreMock
|
||||
FindDatastoreName string
|
||||
FindDatastoreHost string
|
||||
FindDatastoreErr error
|
||||
|
||||
PreCleanShouldFail bool
|
||||
PreCleanVMCalled bool
|
||||
PreCleanForce bool
|
||||
PreCleanVMPath string
|
||||
|
||||
CreateVMShouldFail bool
|
||||
CreateVMCalled bool
|
||||
CreateConfig *CreateConfig
|
||||
VM VirtualMachine
|
||||
|
||||
FindVMCalled bool
|
||||
FindVMName string
|
||||
}
|
||||
|
||||
func NewDriverMock() *DriverMock {
|
||||
return new(DriverMock)
|
||||
}
|
||||
|
||||
func (d *DriverMock) FindDatastore(name string, host string) (Datastore, error) {
|
||||
d.FindDatastoreCalled = true
|
||||
if d.DatastoreMock == nil {
|
||||
d.DatastoreMock = new(DatastoreMock)
|
||||
}
|
||||
d.FindDatastoreName = name
|
||||
d.FindDatastoreHost = host
|
||||
return d.DatastoreMock, d.FindDatastoreErr
|
||||
}
|
||||
|
||||
func (d *DriverMock) NewVM(ref *types.ManagedObjectReference) VirtualMachine {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DriverMock) FindVM(name string) (VirtualMachine, error) {
|
||||
d.FindVMCalled = true
|
||||
if d.VM == nil {
|
||||
d.VM = new(VirtualMachineMock)
|
||||
}
|
||||
d.FindVMName = name
|
||||
return d.VM, d.FindDatastoreErr
|
||||
}
|
||||
|
||||
func (d *DriverMock) FindCluster(name string) (*Cluster, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (d *DriverMock) PreCleanVM(ui packersdk.Ui, vmPath string, force bool) error {
|
||||
d.PreCleanVMCalled = true
|
||||
if d.PreCleanShouldFail {
|
||||
return fmt.Errorf("pre clean failed")
|
||||
}
|
||||
d.PreCleanForce = true
|
||||
d.PreCleanVMPath = vmPath
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DriverMock) CreateVM(config *CreateConfig) (VirtualMachine, error) {
|
||||
d.CreateVMCalled = true
|
||||
if d.CreateVMShouldFail {
|
||||
return nil, fmt.Errorf("create vm failed")
|
||||
}
|
||||
d.CreateConfig = config
|
||||
d.VM = new(VirtualMachineDriver)
|
||||
return d.VM, nil
|
||||
}
|
||||
|
||||
func (d *DriverMock) NewDatastore(ref *types.ManagedObjectReference) Datastore { return nil }
|
||||
|
||||
func (d *DriverMock) GetDatastoreName(id string) (string, error) { return "", nil }
|
||||
|
||||
func (d *DriverMock) GetDatastoreFilePath(datastoreID, dir, filename string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (d *DriverMock) NewFolder(ref *types.ManagedObjectReference) *Folder { return nil }
|
||||
|
||||
func (d *DriverMock) FindFolder(name string) (*Folder, error) { return nil, nil }
|
||||
|
||||
func (d *DriverMock) NewHost(ref *types.ManagedObjectReference) *Host { return nil }
|
||||
|
||||
func (d *DriverMock) FindHost(name string) (*Host, error) { return nil, nil }
|
||||
|
||||
func (d *DriverMock) NewNetwork(ref *types.ManagedObjectReference) *Network { return nil }
|
||||
|
||||
func (d *DriverMock) FindNetwork(name string) (*Network, error) { return nil, nil }
|
||||
|
||||
func (d *DriverMock) FindNetworks(name string) ([]*Network, error) { return nil, nil }
|
||||
|
||||
func (d *DriverMock) NewResourcePool(ref *types.ManagedObjectReference) *ResourcePool { return nil }
|
||||
|
||||
func (d *DriverMock) FindResourcePool(cluster string, host string, name string) (*ResourcePool, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (d *DriverMock) FindContentLibraryByName(name string) (*Library, error) { return nil, nil }
|
||||
|
||||
func (d *DriverMock) FindContentLibraryItem(libraryId string, name string) (*library.Item, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (d *DriverMock) FindContentLibraryFileDatastorePath(isoPath string) (string, error) {
|
||||
return "", nil
|
||||
}
|
93
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/folder.go
generated
vendored
Normal file
93
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/folder.go
generated
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
package driver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/find"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type Folder struct {
|
||||
driver *VCenterDriver
|
||||
folder *object.Folder
|
||||
}
|
||||
|
||||
func (d *VCenterDriver) NewFolder(ref *types.ManagedObjectReference) *Folder {
|
||||
return &Folder{
|
||||
folder: object.NewFolder(d.client.Client, *ref),
|
||||
driver: d,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *VCenterDriver) FindFolder(name string) (*Folder, error) {
|
||||
if name != "" {
|
||||
// create folders if they don't exist
|
||||
parent := ""
|
||||
parentFolder, err := d.finder.Folder(d.ctx, path.Join(d.datacenter.InventoryPath, "vm"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
folders := strings.Split(name, "/")
|
||||
for _, folder := range folders {
|
||||
parent = path.Join(parent, folder)
|
||||
f, err := d.finder.Folder(d.ctx, path.Join(d.datacenter.InventoryPath, "vm", parent))
|
||||
if _, ok := err.(*find.NotFoundError); ok {
|
||||
f, err = parentFolder.CreateFolder(d.ctx, folder)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parentFolder = f
|
||||
}
|
||||
}
|
||||
|
||||
f, err := d.finder.Folder(d.ctx, path.Join(d.datacenter.InventoryPath, "vm", name))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Folder{
|
||||
folder: f,
|
||||
driver: d,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (f *Folder) Info(params ...string) (*mo.Folder, error) {
|
||||
var p []string
|
||||
if len(params) == 0 {
|
||||
p = []string{"*"}
|
||||
} else {
|
||||
p = params
|
||||
}
|
||||
var info mo.Folder
|
||||
err := f.folder.Properties(f.driver.ctx, f.folder.Reference(), p, &info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &info, nil
|
||||
}
|
||||
|
||||
func (f *Folder) Path() (string, error) {
|
||||
info, err := f.Info("name", "parent")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if info.Parent.Type == "Datacenter" {
|
||||
return "", nil
|
||||
} else {
|
||||
parent := f.driver.NewFolder(info.Parent)
|
||||
path, err := parent.Path()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if path == "" {
|
||||
return info.Name, nil
|
||||
} else {
|
||||
return fmt.Sprintf("%v/%v", path, info.Name), nil
|
||||
}
|
||||
}
|
||||
}
|
45
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/host.go
generated
vendored
Normal file
45
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/host.go
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
package driver
|
||||
|
||||
import (
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type Host struct {
|
||||
driver *VCenterDriver
|
||||
host *object.HostSystem
|
||||
}
|
||||
|
||||
func (d *VCenterDriver) NewHost(ref *types.ManagedObjectReference) *Host {
|
||||
return &Host{
|
||||
host: object.NewHostSystem(d.client.Client, *ref),
|
||||
driver: d,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *VCenterDriver) FindHost(name string) (*Host, error) {
|
||||
h, err := d.finder.HostSystem(d.ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Host{
|
||||
host: h,
|
||||
driver: d,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *Host) Info(params ...string) (*mo.HostSystem, error) {
|
||||
var p []string
|
||||
if len(params) == 0 {
|
||||
p = []string{"*"}
|
||||
} else {
|
||||
p = params
|
||||
}
|
||||
var info mo.HostSystem
|
||||
err := h.host.Properties(h.driver.ctx, h.host.Reference(), p, &info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &info, nil
|
||||
}
|
113
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/library.go
generated
vendored
Normal file
113
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/library.go
generated
vendored
Normal file
|
@ -0,0 +1,113 @@
|
|||
package driver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/vapi/library"
|
||||
)
|
||||
|
||||
type Library struct {
|
||||
driver *VCenterDriver
|
||||
library *library.Library
|
||||
}
|
||||
|
||||
func (d *VCenterDriver) FindContentLibraryByName(name string) (*Library, error) {
|
||||
lm := library.NewManager(d.restClient.client)
|
||||
l, err := lm.GetLibraryByName(d.ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Library{
|
||||
library: l,
|
||||
driver: d,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *VCenterDriver) FindContentLibraryItem(libraryId string, name string) (*library.Item, error) {
|
||||
lm := library.NewManager(d.restClient.client)
|
||||
items, err := lm.GetLibraryItems(d.ctx, libraryId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, item := range items {
|
||||
if item.Name == name {
|
||||
return &item, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("Item %s not found", name)
|
||||
}
|
||||
|
||||
func (d *VCenterDriver) FindContentLibraryFileDatastorePath(isoPath string) (string, error) {
|
||||
log.Printf("Check if ISO path is a Content Library path")
|
||||
err := d.restClient.Login(d.ctx)
|
||||
if err != nil {
|
||||
log.Printf("vCenter client not available. ISO path not identified as a Content Library path")
|
||||
return isoPath, err
|
||||
}
|
||||
|
||||
libraryFilePath := &LibraryFilePath{path: isoPath}
|
||||
err = libraryFilePath.Validate()
|
||||
if err != nil {
|
||||
log.Printf("ISO path not identified as a Content Library path")
|
||||
return isoPath, err
|
||||
}
|
||||
libraryName := libraryFilePath.GetLibraryName()
|
||||
itemName := libraryFilePath.GetLibraryItemName()
|
||||
isoFile := libraryFilePath.GetFileName()
|
||||
|
||||
lib, err := d.FindContentLibraryByName(libraryName)
|
||||
if err != nil {
|
||||
log.Printf("ISO path not identified as a Content Library path")
|
||||
return isoPath, err
|
||||
}
|
||||
log.Printf("ISO path identified as a Content Library path")
|
||||
log.Printf("Finding the equivalent datastore path for the Content Library ISO file path")
|
||||
libItem, err := d.FindContentLibraryItem(lib.library.ID, itemName)
|
||||
if err != nil {
|
||||
log.Printf("[WARN] Couldn't find item %s: %s", itemName, err.Error())
|
||||
return isoPath, err
|
||||
}
|
||||
datastoreName, err := d.GetDatastoreName(lib.library.Storage[0].DatastoreID)
|
||||
if err != nil {
|
||||
log.Printf("[WARN] Couldn't find datastore name for library %s", libraryName)
|
||||
return isoPath, err
|
||||
}
|
||||
libItemDir := fmt.Sprintf("[%s] contentlib-%s/%s", datastoreName, lib.library.ID, libItem.ID)
|
||||
|
||||
isoFilePath, err := d.GetDatastoreFilePath(lib.library.Storage[0].DatastoreID, libItemDir, isoFile)
|
||||
if err != nil {
|
||||
log.Printf("[WARN] Couldn't find datastore ID path for %s", isoFile)
|
||||
return isoPath, err
|
||||
}
|
||||
|
||||
_ = d.restClient.Logout(d.ctx)
|
||||
return path.Join(libItemDir, isoFilePath), nil
|
||||
}
|
||||
|
||||
type LibraryFilePath struct {
|
||||
path string
|
||||
}
|
||||
|
||||
func (l *LibraryFilePath) Validate() error {
|
||||
l.path = strings.TrimLeft(l.path, "/")
|
||||
parts := strings.Split(l.path, "/")
|
||||
if len(parts) != 3 {
|
||||
return fmt.Errorf("Not a valid Content Library File path. The path must contain the nanmes for the library, item and file.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *LibraryFilePath) GetLibraryName() string {
|
||||
return strings.Split(l.path, "/")[0]
|
||||
}
|
||||
|
||||
func (l *LibraryFilePath) GetLibraryItemName() string {
|
||||
return strings.Split(l.path, "/")[1]
|
||||
}
|
||||
|
||||
func (l *LibraryFilePath) GetFileName() string {
|
||||
return strings.Split(l.path, "/")[2]
|
||||
}
|
77
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/network.go
generated
vendored
Normal file
77
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/network.go
generated
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
package driver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type Network struct {
|
||||
driver *VCenterDriver
|
||||
network object.NetworkReference
|
||||
}
|
||||
|
||||
func (d *VCenterDriver) NewNetwork(ref *types.ManagedObjectReference) *Network {
|
||||
return &Network{
|
||||
network: object.NewNetwork(d.client.Client, *ref),
|
||||
driver: d,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *VCenterDriver) FindNetwork(name string) (*Network, error) {
|
||||
n, err := d.finder.Network(d.ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Network{
|
||||
network: n,
|
||||
driver: d,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *VCenterDriver) FindNetworks(name string) ([]*Network, error) {
|
||||
ns, err := d.finder.NetworkList(d.ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var networks []*Network
|
||||
for _, n := range ns {
|
||||
networks = append(networks, &Network{
|
||||
network: n,
|
||||
driver: d,
|
||||
})
|
||||
}
|
||||
return networks, nil
|
||||
}
|
||||
|
||||
func (n *Network) Info(params ...string) (*mo.Network, error) {
|
||||
var p []string
|
||||
if len(params) == 0 {
|
||||
p = []string{"*"}
|
||||
} else {
|
||||
p = params
|
||||
}
|
||||
var info mo.Network
|
||||
|
||||
network, ok := n.network.(*object.Network)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected %t network object type", n.network)
|
||||
}
|
||||
|
||||
err := network.Properties(n.driver.ctx, network.Reference(), p, &info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &info, nil
|
||||
}
|
||||
|
||||
type MultipleNetworkFoundError struct {
|
||||
path string
|
||||
append string
|
||||
}
|
||||
|
||||
func (e *MultipleNetworkFoundError) Error() string {
|
||||
return fmt.Sprintf("path '%s' resolves to multiple networks. %s", e.path, e.append)
|
||||
}
|
91
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/resource_pool.go
generated
vendored
Normal file
91
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/resource_pool.go
generated
vendored
Normal file
|
@ -0,0 +1,91 @@
|
|||
package driver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/vmware/govmomi/find"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type ResourcePool struct {
|
||||
pool *object.ResourcePool
|
||||
driver *VCenterDriver
|
||||
}
|
||||
|
||||
func (d *VCenterDriver) NewResourcePool(ref *types.ManagedObjectReference) *ResourcePool {
|
||||
return &ResourcePool{
|
||||
pool: object.NewResourcePool(d.client.Client, *ref),
|
||||
driver: d,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *VCenterDriver) FindResourcePool(cluster string, host string, name string) (*ResourcePool, error) {
|
||||
var res string
|
||||
if cluster != "" {
|
||||
res = cluster
|
||||
} else {
|
||||
res = host
|
||||
}
|
||||
|
||||
resourcePath := fmt.Sprintf("%v/Resources/%v", res, name)
|
||||
p, err := d.finder.ResourcePool(d.ctx, resourcePath)
|
||||
if err != nil {
|
||||
log.Printf("[WARN] %s not found. Looking for default resource pool.", resourcePath)
|
||||
dp, dperr := d.finder.DefaultResourcePool(d.ctx)
|
||||
if _, ok := dperr.(*find.NotFoundError); ok {
|
||||
// VirtualApp extends ResourcePool, so it should support VirtualApp types.
|
||||
vapp, verr := d.finder.VirtualApp(d.ctx, name)
|
||||
if verr != nil {
|
||||
return nil, err
|
||||
}
|
||||
dp = vapp.ResourcePool
|
||||
} else if dperr != nil {
|
||||
return nil, err
|
||||
}
|
||||
p = dp
|
||||
}
|
||||
|
||||
return &ResourcePool{
|
||||
pool: p,
|
||||
driver: d,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *ResourcePool) Info(params ...string) (*mo.ResourcePool, error) {
|
||||
var params2 []string
|
||||
if len(params) == 0 {
|
||||
params2 = []string{"*"}
|
||||
} else {
|
||||
params2 = params
|
||||
}
|
||||
var info mo.ResourcePool
|
||||
err := p.pool.Properties(p.driver.ctx, p.pool.Reference(), params2, &info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &info, nil
|
||||
}
|
||||
|
||||
func (p *ResourcePool) Path() (string, error) {
|
||||
poolInfo, err := p.Info("name", "parent")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if poolInfo.Parent.Type == "ComputeResource" {
|
||||
return "", nil
|
||||
} else {
|
||||
parent := p.driver.NewResourcePool(poolInfo.Parent)
|
||||
parentPath, err := parent.Path()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if parentPath == "" {
|
||||
return poolInfo.Name, nil
|
||||
} else {
|
||||
return fmt.Sprintf("%v/%v", parentPath, poolInfo.Name), nil
|
||||
}
|
||||
}
|
||||
}
|
1102
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/vm.go
generated
vendored
Normal file
1102
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/vm.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
89
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/vm_cdrom.go
generated
vendored
Normal file
89
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/vm_cdrom.go
generated
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
package driver
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNoSataController = errors.New("no available SATA controller")
|
||||
)
|
||||
|
||||
func (vm *VirtualMachineDriver) AddSATAController() error {
|
||||
sata := &types.VirtualAHCIController{}
|
||||
return vm.addDevice(sata)
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineDriver) FindSATAController() (*types.VirtualAHCIController, error) {
|
||||
l, err := vm.Devices()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := l.PickController((*types.VirtualAHCIController)(nil))
|
||||
if c == nil {
|
||||
return nil, ErrNoSataController
|
||||
}
|
||||
|
||||
return c.(*types.VirtualAHCIController), nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineDriver) CreateCdrom(c *types.VirtualController) (*types.VirtualCdrom, error) {
|
||||
l, err := vm.Devices()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
device := &types.VirtualCdrom{}
|
||||
|
||||
l.AssignController(device, c)
|
||||
|
||||
device.Backing = &types.VirtualCdromAtapiBackingInfo{
|
||||
VirtualDeviceDeviceBackingInfo: types.VirtualDeviceDeviceBackingInfo{},
|
||||
}
|
||||
|
||||
device.Connectable = &types.VirtualDeviceConnectInfo{
|
||||
AllowGuestControl: true,
|
||||
Connected: true,
|
||||
StartConnected: true,
|
||||
}
|
||||
|
||||
return device, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineDriver) RemoveCdroms() error {
|
||||
devices, err := vm.Devices()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cdroms := devices.SelectByType((*types.VirtualCdrom)(nil))
|
||||
if err = vm.RemoveDevice(true, cdroms...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sata := devices.SelectByType((*types.VirtualAHCIController)(nil))
|
||||
if err = vm.RemoveDevice(true, sata...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineDriver) EjectCdroms() error {
|
||||
devices, err := vm.Devices()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cdroms := devices.SelectByType((*types.VirtualCdrom)(nil))
|
||||
for _, cd := range cdroms {
|
||||
c := cd.(*types.VirtualCdrom)
|
||||
c.Backing = &types.VirtualCdromRemotePassthroughBackingInfo{}
|
||||
c.Connectable = &types.VirtualDeviceConnectInfo{}
|
||||
err := vm.vm.EditDevice(vm.driver.ctx, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
39
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/vm_keyboard.go
generated
vendored
Normal file
39
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/vm_keyboard.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
package driver
|
||||
|
||||
import (
|
||||
"github.com/vmware/govmomi/vim25/methods"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/mobile/event/key"
|
||||
)
|
||||
|
||||
type KeyInput struct {
|
||||
Scancode key.Code
|
||||
Alt bool
|
||||
Ctrl bool
|
||||
Shift bool
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineDriver) TypeOnKeyboard(input KeyInput) (int32, error) {
|
||||
var spec types.UsbScanCodeSpec
|
||||
|
||||
spec.KeyEvents = append(spec.KeyEvents, types.UsbScanCodeSpecKeyEvent{
|
||||
UsbHidCode: int32(input.Scancode)<<16 | 7,
|
||||
Modifiers: &types.UsbScanCodeSpecModifierType{
|
||||
LeftControl: &input.Ctrl,
|
||||
LeftAlt: &input.Alt,
|
||||
LeftShift: &input.Shift,
|
||||
},
|
||||
})
|
||||
|
||||
req := &types.PutUsbScanCodes{
|
||||
This: vm.vm.Reference(),
|
||||
Spec: spec,
|
||||
}
|
||||
|
||||
resp, err := methods.PutUsbScanCodes(vm.driver.ctx, vm.driver.client.RoundTripper, req)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return resp.Returnval, nil
|
||||
}
|
235
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/vm_mock.go
generated
vendored
Normal file
235
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver/vm_mock.go
generated
vendored
Normal file
|
@ -0,0 +1,235 @@
|
|||
package driver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/vmware/govmomi/nfc"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/ovf"
|
||||
"github.com/vmware/govmomi/vapi/vcenter"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type VirtualMachineMock struct {
|
||||
DestroyError error
|
||||
DestroyCalled bool
|
||||
|
||||
ConfigureError error
|
||||
ConfigureCalled bool
|
||||
ConfigureHardwareConfig *HardwareConfig
|
||||
|
||||
FindSATAControllerCalled bool
|
||||
FindSATAControllerErr error
|
||||
|
||||
AddSATAControllerCalled bool
|
||||
AddSATAControllerErr error
|
||||
|
||||
AddCdromCalled bool
|
||||
AddCdromCalledTimes int
|
||||
AddCdromErr error
|
||||
AddCdromTypes []string
|
||||
AddCdromPaths []string
|
||||
|
||||
GetDirCalled bool
|
||||
GetDirResponse string
|
||||
GetDirErr error
|
||||
|
||||
AddFloppyCalled bool
|
||||
AddFloppyImagePath string
|
||||
AddFloppyErr error
|
||||
|
||||
FloppyDevicesErr error
|
||||
FloppyDevicesReturn object.VirtualDeviceList
|
||||
FloppyDevicesCalled bool
|
||||
|
||||
RemoveDeviceErr error
|
||||
RemoveDeviceCalled bool
|
||||
RemoveDeviceKeepFiles bool
|
||||
RemoveDeviceDevices []types.BaseVirtualDevice
|
||||
|
||||
EjectCdromsCalled bool
|
||||
EjectCdromsErr error
|
||||
|
||||
RemoveCdromsCalled bool
|
||||
RemoveCdromsErr error
|
||||
CloneCalled bool
|
||||
CloneConfig *CloneConfig
|
||||
CloneError error
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) Info(params ...string) (*mo.VirtualMachine, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) Devices() (object.VirtualDeviceList, error) {
|
||||
return object.VirtualDeviceList{}, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) FloppyDevices() (object.VirtualDeviceList, error) {
|
||||
vm.FloppyDevicesCalled = true
|
||||
return vm.FloppyDevicesReturn, vm.FloppyDevicesErr
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) Clone(ctx context.Context, config *CloneConfig) (VirtualMachine, error) {
|
||||
vm.CloneCalled = true
|
||||
vm.CloneConfig = config
|
||||
return vm, vm.CloneError
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) updateVAppConfig(ctx context.Context, newProps map[string]string) (*types.VmConfigSpec, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) AddPublicKeys(ctx context.Context, publicKeys string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) Properties(ctx context.Context) (*mo.VirtualMachine, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) Destroy() error {
|
||||
vm.DestroyCalled = true
|
||||
if vm.DestroyError != nil {
|
||||
return vm.DestroyError
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) Configure(config *HardwareConfig) error {
|
||||
vm.ConfigureCalled = true
|
||||
vm.ConfigureHardwareConfig = config
|
||||
if vm.ConfigureError != nil {
|
||||
return vm.ConfigureError
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) Customize(spec types.CustomizationSpec) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) ResizeDisk(diskSize int64) ([]types.BaseVirtualDeviceConfigSpec, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) PowerOn() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) WaitForIP(ctx context.Context, ipNet *net.IPNet) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) PowerOff() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) IsPoweredOff() (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) StartShutdown() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) WaitForShutdown(ctx context.Context, timeout time.Duration) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) CreateSnapshot(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) ConvertToTemplate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) ImportOvfToContentLibrary(ovf vcenter.OVF) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) ImportToContentLibrary(template vcenter.Template) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) GetDir() (string, error) {
|
||||
vm.GetDirCalled = true
|
||||
return vm.GetDirResponse, vm.GetDirErr
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) AddCdrom(cdromType string, isoPath string) error {
|
||||
vm.AddCdromCalledTimes++
|
||||
vm.AddCdromCalled = true
|
||||
vm.AddCdromTypes = append(vm.AddCdromTypes, cdromType)
|
||||
vm.AddCdromPaths = append(vm.AddCdromPaths, isoPath)
|
||||
return vm.AddCdromErr
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) AddFloppy(imgPath string) error {
|
||||
vm.AddFloppyCalled = true
|
||||
vm.AddFloppyImagePath = imgPath
|
||||
return vm.AddFloppyErr
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) SetBootOrder(order []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) RemoveDevice(keepFiles bool, device ...types.BaseVirtualDevice) error {
|
||||
vm.RemoveDeviceCalled = true
|
||||
vm.RemoveDeviceKeepFiles = keepFiles
|
||||
vm.RemoveDeviceDevices = device
|
||||
return vm.RemoveDeviceErr
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) addDevice(device types.BaseVirtualDevice) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) AddConfigParams(params map[string]string, info *types.ToolsConfigInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) Export() (*nfc.Lease, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) CreateDescriptor(m *ovf.Manager, cdp types.OvfCreateDescriptorParams) (*types.OvfCreateDescriptorResult, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) NewOvfManager() *ovf.Manager {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) GetOvfExportOptions(m *ovf.Manager) ([]types.OvfOptionInfo, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) AddSATAController() error {
|
||||
vm.AddSATAControllerCalled = true
|
||||
return vm.AddSATAControllerErr
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) FindSATAController() (*types.VirtualAHCIController, error) {
|
||||
vm.FindSATAControllerCalled = true
|
||||
return nil, vm.FindSATAControllerErr
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) CreateCdrom(c *types.VirtualController) (*types.VirtualCdrom, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) RemoveCdroms() error {
|
||||
vm.RemoveCdromsCalled = true
|
||||
return vm.RemoveCdromsErr
|
||||
}
|
||||
|
||||
func (vm *VirtualMachineMock) EjectCdroms() error {
|
||||
vm.EjectCdromsCalled = true
|
||||
return vm.EjectCdromsErr
|
||||
}
|
179
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/iso/builder.go
generated
vendored
Normal file
179
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/iso/builder.go
generated
vendored
Normal file
|
@ -0,0 +1,179 @@
|
|||
package iso
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
type Builder struct {
|
||||
config Config
|
||||
runner multistep.Runner
|
||||
}
|
||||
|
||||
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
|
||||
|
||||
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
||||
warnings, errs := b.config.Prepare(raws...)
|
||||
if errs != nil {
|
||||
return nil, warnings, errs
|
||||
}
|
||||
|
||||
return nil, warnings, nil
|
||||
}
|
||||
|
||||
func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) {
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("debug", b.config.PackerDebug)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
||||
var steps []multistep.Step
|
||||
|
||||
steps = append(steps,
|
||||
&common.StepConnect{
|
||||
Config: &b.config.ConnectConfig,
|
||||
},
|
||||
&common.StepDownload{
|
||||
DownloadStep: &commonsteps.StepDownload{
|
||||
Checksum: b.config.ISOChecksum,
|
||||
Description: "ISO",
|
||||
Extension: b.config.TargetExtension,
|
||||
ResultKey: "iso_path",
|
||||
TargetPath: b.config.TargetPath,
|
||||
Url: b.config.ISOUrls,
|
||||
},
|
||||
Url: b.config.ISOUrls,
|
||||
ResultKey: "iso_path",
|
||||
Datastore: b.config.Datastore,
|
||||
Host: b.config.Host,
|
||||
},
|
||||
&commonsteps.StepCreateCD{
|
||||
Files: b.config.CDConfig.CDFiles,
|
||||
Label: b.config.CDConfig.CDLabel,
|
||||
},
|
||||
&common.StepRemoteUpload{
|
||||
Datastore: b.config.Datastore,
|
||||
Host: b.config.Host,
|
||||
SetHostForDatastoreUploads: b.config.SetHostForDatastoreUploads,
|
||||
},
|
||||
&StepCreateVM{
|
||||
Config: &b.config.CreateConfig,
|
||||
Location: &b.config.LocationConfig,
|
||||
Force: b.config.PackerConfig.PackerForce,
|
||||
},
|
||||
&common.StepConfigureHardware{
|
||||
Config: &b.config.HardwareConfig,
|
||||
},
|
||||
&common.StepAddCDRom{
|
||||
Config: &b.config.CDRomConfig,
|
||||
},
|
||||
&common.StepConfigParams{
|
||||
Config: &b.config.ConfigParamsConfig,
|
||||
},
|
||||
&commonsteps.StepCreateFloppy{
|
||||
Files: b.config.FloppyFiles,
|
||||
Directories: b.config.FloppyDirectories,
|
||||
Label: b.config.FloppyLabel,
|
||||
},
|
||||
&common.StepAddFloppy{
|
||||
Config: &b.config.FloppyConfig,
|
||||
Datastore: b.config.Datastore,
|
||||
Host: b.config.Host,
|
||||
SetHostForDatastoreUploads: b.config.SetHostForDatastoreUploads,
|
||||
},
|
||||
&common.StepHTTPIPDiscover{
|
||||
HTTPIP: b.config.BootConfig.HTTPIP,
|
||||
Network: b.config.WaitIpConfig.GetIPNet(),
|
||||
},
|
||||
commonsteps.HTTPServerFromHTTPConfig(&b.config.HTTPConfig),
|
||||
&common.StepRun{
|
||||
Config: &b.config.RunConfig,
|
||||
SetOrder: true,
|
||||
},
|
||||
&common.StepBootCommand{
|
||||
Config: &b.config.BootConfig,
|
||||
Ctx: b.config.ctx,
|
||||
VMName: b.config.VMName,
|
||||
},
|
||||
)
|
||||
|
||||
if b.config.Comm.Type != "none" {
|
||||
steps = append(steps,
|
||||
&common.StepWaitForIp{
|
||||
Config: &b.config.WaitIpConfig,
|
||||
},
|
||||
&communicator.StepConnect{
|
||||
Config: &b.config.Comm,
|
||||
Host: common.CommHost(b.config.Comm.Host()),
|
||||
SSHConfig: b.config.Comm.SSHConfigFunc(),
|
||||
},
|
||||
&commonsteps.StepProvision{},
|
||||
)
|
||||
}
|
||||
|
||||
steps = append(steps,
|
||||
&common.StepShutdown{
|
||||
Config: &b.config.ShutdownConfig,
|
||||
},
|
||||
&common.StepRemoveFloppy{
|
||||
Datastore: b.config.Datastore,
|
||||
Host: b.config.Host,
|
||||
},
|
||||
&common.StepRemoveCDRom{
|
||||
Config: &b.config.RemoveCDRomConfig,
|
||||
},
|
||||
&common.StepCreateSnapshot{
|
||||
CreateSnapshot: b.config.CreateSnapshot,
|
||||
},
|
||||
&common.StepConvertToTemplate{
|
||||
ConvertToTemplate: b.config.ConvertToTemplate,
|
||||
},
|
||||
)
|
||||
|
||||
if b.config.ContentLibraryDestinationConfig != nil {
|
||||
steps = append(steps, &common.StepImportToContentLibrary{
|
||||
ContentLibConfig: b.config.ContentLibraryDestinationConfig,
|
||||
})
|
||||
}
|
||||
|
||||
if b.config.Export != nil {
|
||||
steps = append(steps, &common.StepExport{
|
||||
Name: b.config.Export.Name,
|
||||
Force: b.config.Export.Force,
|
||||
Images: b.config.Export.Images,
|
||||
Manifest: b.config.Export.Manifest,
|
||||
OutputDir: b.config.Export.OutputDir.OutputDir,
|
||||
Options: b.config.Export.Options,
|
||||
})
|
||||
}
|
||||
|
||||
b.runner = commonsteps.NewRunnerWithPauseFn(steps, b.config.PackerConfig, ui, state)
|
||||
b.runner.Run(ctx, state)
|
||||
|
||||
if rawErr, ok := state.GetOk("error"); ok {
|
||||
return nil, rawErr.(error)
|
||||
}
|
||||
|
||||
if _, ok := state.GetOk("vm"); !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
artifact := &common.Artifact{
|
||||
Name: b.config.VMName,
|
||||
VM: state.Get("vm").(*driver.VirtualMachineDriver),
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
if b.config.Export != nil {
|
||||
artifact.Outconfig = &b.config.Export.OutputDir
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
}
|
107
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/iso/config.go
generated
vendored
Normal file
107
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/iso/config.go
generated
vendored
Normal file
|
@ -0,0 +1,107 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type Config
|
||||
|
||||
package iso
|
||||
|
||||
import (
|
||||
packerCommon "github.com/hashicorp/packer-plugin-sdk/common"
|
||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
packerCommon.PackerConfig `mapstructure:",squash"`
|
||||
commonsteps.HTTPConfig `mapstructure:",squash"`
|
||||
commonsteps.CDConfig `mapstructure:",squash"`
|
||||
|
||||
common.ConnectConfig `mapstructure:",squash"`
|
||||
CreateConfig `mapstructure:",squash"`
|
||||
common.LocationConfig `mapstructure:",squash"`
|
||||
common.HardwareConfig `mapstructure:",squash"`
|
||||
common.ConfigParamsConfig `mapstructure:",squash"`
|
||||
|
||||
commonsteps.ISOConfig `mapstructure:",squash"`
|
||||
|
||||
common.CDRomConfig `mapstructure:",squash"`
|
||||
common.RemoveCDRomConfig `mapstructure:",squash"`
|
||||
common.FloppyConfig `mapstructure:",squash"`
|
||||
common.RunConfig `mapstructure:",squash"`
|
||||
common.BootConfig `mapstructure:",squash"`
|
||||
common.WaitIpConfig `mapstructure:",squash"`
|
||||
Comm communicator.Config `mapstructure:",squash"`
|
||||
|
||||
common.ShutdownConfig `mapstructure:",squash"`
|
||||
|
||||
// Create a snapshot when set to `true`, so the VM can be used as a base
|
||||
// for linked clones. Defaults to `false`.
|
||||
CreateSnapshot bool `mapstructure:"create_snapshot"`
|
||||
// Convert VM to a template. Defaults to `false`.
|
||||
ConvertToTemplate bool `mapstructure:"convert_to_template"`
|
||||
// Configuration for exporting VM to an ovf file.
|
||||
// The VM will not be exported if no [Export Configuration](#export-configuration) is specified.
|
||||
Export *common.ExportConfig `mapstructure:"export"`
|
||||
// Configuration for importing the VM template to a Content Library.
|
||||
// The VM template will not be imported if no [Content Library Import Configuration](#content-library-import-configuration) is specified.
|
||||
// The import doesn't work if [convert_to_template](#convert_to_template) is set to true.
|
||||
ContentLibraryDestinationConfig *common.ContentLibraryDestinationConfig `mapstructure:"content_library_destination"`
|
||||
|
||||
ctx interpolate.Context
|
||||
}
|
||||
|
||||
func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
|
||||
err := config.Decode(c, &config.DecodeOpts{
|
||||
PluginType: common.BuilderId,
|
||||
Interpolate: true,
|
||||
InterpolateContext: &c.ctx,
|
||||
InterpolateFilter: &interpolate.RenderFilter{
|
||||
Exclude: []string{
|
||||
"boot_command",
|
||||
},
|
||||
},
|
||||
}, raws...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
warnings := make([]string, 0)
|
||||
errs := new(packersdk.MultiError)
|
||||
|
||||
if c.ISOUrls != nil || c.RawSingleISOUrl != "" {
|
||||
isoWarnings, isoErrs := c.ISOConfig.Prepare(&c.ctx)
|
||||
warnings = append(warnings, isoWarnings...)
|
||||
errs = packersdk.MultiErrorAppend(errs, isoErrs...)
|
||||
}
|
||||
|
||||
errs = packersdk.MultiErrorAppend(errs, c.ConnectConfig.Prepare()...)
|
||||
errs = packersdk.MultiErrorAppend(errs, c.CreateConfig.Prepare()...)
|
||||
errs = packersdk.MultiErrorAppend(errs, c.LocationConfig.Prepare()...)
|
||||
errs = packersdk.MultiErrorAppend(errs, c.HardwareConfig.Prepare()...)
|
||||
errs = packersdk.MultiErrorAppend(errs, c.HTTPConfig.Prepare(&c.ctx)...)
|
||||
|
||||
errs = packersdk.MultiErrorAppend(errs, c.CDRomConfig.Prepare()...)
|
||||
errs = packersdk.MultiErrorAppend(errs, c.CDConfig.Prepare(&c.ctx)...)
|
||||
errs = packersdk.MultiErrorAppend(errs, c.BootConfig.Prepare(&c.ctx)...)
|
||||
errs = packersdk.MultiErrorAppend(errs, c.WaitIpConfig.Prepare()...)
|
||||
errs = packersdk.MultiErrorAppend(errs, c.Comm.Prepare(&c.ctx)...)
|
||||
|
||||
shutdownWarnings, shutdownErrs := c.ShutdownConfig.Prepare(c.Comm)
|
||||
warnings = append(warnings, shutdownWarnings...)
|
||||
errs = packersdk.MultiErrorAppend(errs, shutdownErrs...)
|
||||
|
||||
if c.Export != nil {
|
||||
errs = packersdk.MultiErrorAppend(errs, c.Export.Prepare(&c.ctx, &c.LocationConfig, &c.PackerConfig)...)
|
||||
}
|
||||
if c.ContentLibraryDestinationConfig != nil {
|
||||
errs = packersdk.MultiErrorAppend(errs, c.ContentLibraryDestinationConfig.Prepare(&c.LocationConfig)...)
|
||||
}
|
||||
|
||||
if len(errs.Errors) > 0 {
|
||||
return warnings, errs
|
||||
}
|
||||
|
||||
return warnings, nil
|
||||
}
|
286
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/iso/config.hcl2spec.go
generated
vendored
Normal file
286
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/iso/config.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,286 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type Config"; DO NOT EDIT.
|
||||
|
||||
package iso
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatConfig is an auto-generated flat version of Config.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatConfig struct {
|
||||
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"`
|
||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
|
||||
PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"`
|
||||
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
|
||||
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
|
||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
|
||||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"`
|
||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"`
|
||||
HTTPDir *string `mapstructure:"http_directory" cty:"http_directory" hcl:"http_directory"`
|
||||
HTTPContent map[string]string `mapstructure:"http_content" cty:"http_content" hcl:"http_content"`
|
||||
HTTPPortMin *int `mapstructure:"http_port_min" cty:"http_port_min" hcl:"http_port_min"`
|
||||
HTTPPortMax *int `mapstructure:"http_port_max" cty:"http_port_max" hcl:"http_port_max"`
|
||||
HTTPAddress *string `mapstructure:"http_bind_address" cty:"http_bind_address" hcl:"http_bind_address"`
|
||||
HTTPInterface *string `mapstructure:"http_interface" undocumented:"true" cty:"http_interface" hcl:"http_interface"`
|
||||
CDFiles []string `mapstructure:"cd_files" cty:"cd_files" hcl:"cd_files"`
|
||||
CDLabel *string `mapstructure:"cd_label" cty:"cd_label" hcl:"cd_label"`
|
||||
VCenterServer *string `mapstructure:"vcenter_server" cty:"vcenter_server" hcl:"vcenter_server"`
|
||||
Username *string `mapstructure:"username" cty:"username" hcl:"username"`
|
||||
Password *string `mapstructure:"password" cty:"password" hcl:"password"`
|
||||
InsecureConnection *bool `mapstructure:"insecure_connection" cty:"insecure_connection" hcl:"insecure_connection"`
|
||||
Datacenter *string `mapstructure:"datacenter" cty:"datacenter" hcl:"datacenter"`
|
||||
Version *uint `mapstructure:"vm_version" cty:"vm_version" hcl:"vm_version"`
|
||||
GuestOSType *string `mapstructure:"guest_os_type" cty:"guest_os_type" hcl:"guest_os_type"`
|
||||
DiskControllerType []string `mapstructure:"disk_controller_type" cty:"disk_controller_type" hcl:"disk_controller_type"`
|
||||
Storage []common.FlatDiskConfig `mapstructure:"storage" cty:"storage" hcl:"storage"`
|
||||
NICs []FlatNIC `mapstructure:"network_adapters" cty:"network_adapters" hcl:"network_adapters"`
|
||||
USBController []string `mapstructure:"usb_controller" cty:"usb_controller" hcl:"usb_controller"`
|
||||
Notes *string `mapstructure:"notes" cty:"notes" hcl:"notes"`
|
||||
VMName *string `mapstructure:"vm_name" cty:"vm_name" hcl:"vm_name"`
|
||||
Folder *string `mapstructure:"folder" cty:"folder" hcl:"folder"`
|
||||
Cluster *string `mapstructure:"cluster" cty:"cluster" hcl:"cluster"`
|
||||
Host *string `mapstructure:"host" cty:"host" hcl:"host"`
|
||||
ResourcePool *string `mapstructure:"resource_pool" cty:"resource_pool" hcl:"resource_pool"`
|
||||
Datastore *string `mapstructure:"datastore" cty:"datastore" hcl:"datastore"`
|
||||
SetHostForDatastoreUploads *bool `mapstructure:"set_host_for_datastore_uploads" cty:"set_host_for_datastore_uploads" hcl:"set_host_for_datastore_uploads"`
|
||||
CPUs *int32 `mapstructure:"CPUs" cty:"CPUs" hcl:"CPUs"`
|
||||
CpuCores *int32 `mapstructure:"cpu_cores" cty:"cpu_cores" hcl:"cpu_cores"`
|
||||
CPUReservation *int64 `mapstructure:"CPU_reservation" cty:"CPU_reservation" hcl:"CPU_reservation"`
|
||||
CPULimit *int64 `mapstructure:"CPU_limit" cty:"CPU_limit" hcl:"CPU_limit"`
|
||||
CpuHotAddEnabled *bool `mapstructure:"CPU_hot_plug" cty:"CPU_hot_plug" hcl:"CPU_hot_plug"`
|
||||
RAM *int64 `mapstructure:"RAM" cty:"RAM" hcl:"RAM"`
|
||||
RAMReservation *int64 `mapstructure:"RAM_reservation" cty:"RAM_reservation" hcl:"RAM_reservation"`
|
||||
RAMReserveAll *bool `mapstructure:"RAM_reserve_all" cty:"RAM_reserve_all" hcl:"RAM_reserve_all"`
|
||||
MemoryHotAddEnabled *bool `mapstructure:"RAM_hot_plug" cty:"RAM_hot_plug" hcl:"RAM_hot_plug"`
|
||||
VideoRAM *int64 `mapstructure:"video_ram" cty:"video_ram" hcl:"video_ram"`
|
||||
VGPUProfile *string `mapstructure:"vgpu_profile" cty:"vgpu_profile" hcl:"vgpu_profile"`
|
||||
NestedHV *bool `mapstructure:"NestedHV" cty:"NestedHV" hcl:"NestedHV"`
|
||||
Firmware *string `mapstructure:"firmware" cty:"firmware" hcl:"firmware"`
|
||||
ForceBIOSSetup *bool `mapstructure:"force_bios_setup" cty:"force_bios_setup" hcl:"force_bios_setup"`
|
||||
ConfigParams map[string]string `mapstructure:"configuration_parameters" cty:"configuration_parameters" hcl:"configuration_parameters"`
|
||||
ToolsSyncTime *bool `mapstructure:"tools_sync_time" cty:"tools_sync_time" hcl:"tools_sync_time"`
|
||||
ToolsUpgradePolicy *bool `mapstructure:"tools_upgrade_policy" cty:"tools_upgrade_policy" hcl:"tools_upgrade_policy"`
|
||||
ISOChecksum *string `mapstructure:"iso_checksum" required:"true" cty:"iso_checksum" hcl:"iso_checksum"`
|
||||
RawSingleISOUrl *string `mapstructure:"iso_url" required:"true" cty:"iso_url" hcl:"iso_url"`
|
||||
ISOUrls []string `mapstructure:"iso_urls" cty:"iso_urls" hcl:"iso_urls"`
|
||||
TargetPath *string `mapstructure:"iso_target_path" cty:"iso_target_path" hcl:"iso_target_path"`
|
||||
TargetExtension *string `mapstructure:"iso_target_extension" cty:"iso_target_extension" hcl:"iso_target_extension"`
|
||||
CdromType *string `mapstructure:"cdrom_type" cty:"cdrom_type" hcl:"cdrom_type"`
|
||||
ISOPaths []string `mapstructure:"iso_paths" cty:"iso_paths" hcl:"iso_paths"`
|
||||
RemoveCdrom *bool `mapstructure:"remove_cdrom" cty:"remove_cdrom" hcl:"remove_cdrom"`
|
||||
FloppyIMGPath *string `mapstructure:"floppy_img_path" cty:"floppy_img_path" hcl:"floppy_img_path"`
|
||||
FloppyFiles []string `mapstructure:"floppy_files" cty:"floppy_files" hcl:"floppy_files"`
|
||||
FloppyDirectories []string `mapstructure:"floppy_dirs" cty:"floppy_dirs" hcl:"floppy_dirs"`
|
||||
FloppyLabel *string `mapstructure:"floppy_label" cty:"floppy_label" hcl:"floppy_label"`
|
||||
BootOrder *string `mapstructure:"boot_order" cty:"boot_order" hcl:"boot_order"`
|
||||
BootGroupInterval *string `mapstructure:"boot_keygroup_interval" cty:"boot_keygroup_interval" hcl:"boot_keygroup_interval"`
|
||||
BootWait *string `mapstructure:"boot_wait" cty:"boot_wait" hcl:"boot_wait"`
|
||||
BootCommand []string `mapstructure:"boot_command" cty:"boot_command" hcl:"boot_command"`
|
||||
HTTPIP *string `mapstructure:"http_ip" cty:"http_ip" hcl:"http_ip"`
|
||||
WaitTimeout *string `mapstructure:"ip_wait_timeout" cty:"ip_wait_timeout" hcl:"ip_wait_timeout"`
|
||||
SettleTimeout *string `mapstructure:"ip_settle_timeout" cty:"ip_settle_timeout" hcl:"ip_settle_timeout"`
|
||||
WaitAddress *string `mapstructure:"ip_wait_address" cty:"ip_wait_address" hcl:"ip_wait_address"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator" hcl:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting" hcl:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host" hcl:"ssh_host"`
|
||||
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port" hcl:"ssh_port"`
|
||||
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username" hcl:"ssh_username"`
|
||||
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password" hcl:"ssh_password"`
|
||||
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" undocumented:"true" cty:"ssh_keypair_name" hcl:"ssh_keypair_name"`
|
||||
SSHTemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" undocumented:"true" cty:"temporary_key_pair_name" hcl:"temporary_key_pair_name"`
|
||||
SSHTemporaryKeyPairType *string `mapstructure:"temporary_key_pair_type" cty:"temporary_key_pair_type" hcl:"temporary_key_pair_type"`
|
||||
SSHTemporaryKeyPairBits *int `mapstructure:"temporary_key_pair_bits" cty:"temporary_key_pair_bits" hcl:"temporary_key_pair_bits"`
|
||||
SSHCiphers []string `mapstructure:"ssh_ciphers" cty:"ssh_ciphers" hcl:"ssh_ciphers"`
|
||||
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys" hcl:"ssh_clear_authorized_keys"`
|
||||
SSHKEXAlgos []string `mapstructure:"ssh_key_exchange_algorithms" cty:"ssh_key_exchange_algorithms" hcl:"ssh_key_exchange_algorithms"`
|
||||
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" undocumented:"true" cty:"ssh_private_key_file" hcl:"ssh_private_key_file"`
|
||||
SSHCertificateFile *string `mapstructure:"ssh_certificate_file" cty:"ssh_certificate_file" hcl:"ssh_certificate_file"`
|
||||
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty" hcl:"ssh_pty"`
|
||||
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout" hcl:"ssh_timeout"`
|
||||
SSHWaitTimeout *string `mapstructure:"ssh_wait_timeout" undocumented:"true" cty:"ssh_wait_timeout" hcl:"ssh_wait_timeout"`
|
||||
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" undocumented:"true" cty:"ssh_agent_auth" hcl:"ssh_agent_auth"`
|
||||
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding" hcl:"ssh_disable_agent_forwarding"`
|
||||
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts" hcl:"ssh_handshake_attempts"`
|
||||
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host" hcl:"ssh_bastion_host"`
|
||||
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port" hcl:"ssh_bastion_port"`
|
||||
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth" hcl:"ssh_bastion_agent_auth"`
|
||||
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username" hcl:"ssh_bastion_username"`
|
||||
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password" hcl:"ssh_bastion_password"`
|
||||
SSHBastionInteractive *bool `mapstructure:"ssh_bastion_interactive" cty:"ssh_bastion_interactive" hcl:"ssh_bastion_interactive"`
|
||||
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file" hcl:"ssh_bastion_private_key_file"`
|
||||
SSHBastionCertificateFile *string `mapstructure:"ssh_bastion_certificate_file" cty:"ssh_bastion_certificate_file" hcl:"ssh_bastion_certificate_file"`
|
||||
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method" hcl:"ssh_file_transfer_method"`
|
||||
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host" hcl:"ssh_proxy_host"`
|
||||
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port" hcl:"ssh_proxy_port"`
|
||||
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username" hcl:"ssh_proxy_username"`
|
||||
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password" hcl:"ssh_proxy_password"`
|
||||
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval" hcl:"ssh_keep_alive_interval"`
|
||||
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout" hcl:"ssh_read_write_timeout"`
|
||||
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels" hcl:"ssh_remote_tunnels"`
|
||||
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels" hcl:"ssh_local_tunnels"`
|
||||
SSHPublicKey []byte `mapstructure:"ssh_public_key" undocumented:"true" cty:"ssh_public_key" hcl:"ssh_public_key"`
|
||||
SSHPrivateKey []byte `mapstructure:"ssh_private_key" undocumented:"true" cty:"ssh_private_key" hcl:"ssh_private_key"`
|
||||
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username" hcl:"winrm_username"`
|
||||
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password" hcl:"winrm_password"`
|
||||
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host" hcl:"winrm_host"`
|
||||
WinRMNoProxy *bool `mapstructure:"winrm_no_proxy" cty:"winrm_no_proxy" hcl:"winrm_no_proxy"`
|
||||
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port" hcl:"winrm_port"`
|
||||
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout" hcl:"winrm_timeout"`
|
||||
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl" hcl:"winrm_use_ssl"`
|
||||
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure" hcl:"winrm_insecure"`
|
||||
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm" hcl:"winrm_use_ntlm"`
|
||||
Command *string `mapstructure:"shutdown_command" cty:"shutdown_command" hcl:"shutdown_command"`
|
||||
Timeout *string `mapstructure:"shutdown_timeout" cty:"shutdown_timeout" hcl:"shutdown_timeout"`
|
||||
DisableShutdown *bool `mapstructure:"disable_shutdown" cty:"disable_shutdown" hcl:"disable_shutdown"`
|
||||
CreateSnapshot *bool `mapstructure:"create_snapshot" cty:"create_snapshot" hcl:"create_snapshot"`
|
||||
ConvertToTemplate *bool `mapstructure:"convert_to_template" cty:"convert_to_template" hcl:"convert_to_template"`
|
||||
Export *common.FlatExportConfig `mapstructure:"export" cty:"export" hcl:"export"`
|
||||
ContentLibraryDestinationConfig *common.FlatContentLibraryDestinationConfig `mapstructure:"content_library_destination" cty:"content_library_destination" hcl:"content_library_destination"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatConfig.
|
||||
// FlatConfig is an auto-generated flat version of Config.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a Config.
|
||||
// This spec is used by HCL to read the fields of Config.
|
||||
// The decoded values from this spec will then be applied to a FlatConfig.
|
||||
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
|
||||
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
|
||||
"packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false},
|
||||
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
|
||||
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
|
||||
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
|
||||
"packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"http_directory": &hcldec.AttrSpec{Name: "http_directory", Type: cty.String, Required: false},
|
||||
"http_content": &hcldec.AttrSpec{Name: "http_content", Type: cty.Map(cty.String), Required: false},
|
||||
"http_port_min": &hcldec.AttrSpec{Name: "http_port_min", Type: cty.Number, Required: false},
|
||||
"http_port_max": &hcldec.AttrSpec{Name: "http_port_max", Type: cty.Number, Required: false},
|
||||
"http_bind_address": &hcldec.AttrSpec{Name: "http_bind_address", Type: cty.String, Required: false},
|
||||
"http_interface": &hcldec.AttrSpec{Name: "http_interface", Type: cty.String, Required: false},
|
||||
"cd_files": &hcldec.AttrSpec{Name: "cd_files", Type: cty.List(cty.String), Required: false},
|
||||
"cd_label": &hcldec.AttrSpec{Name: "cd_label", Type: cty.String, Required: false},
|
||||
"vcenter_server": &hcldec.AttrSpec{Name: "vcenter_server", Type: cty.String, Required: false},
|
||||
"username": &hcldec.AttrSpec{Name: "username", Type: cty.String, Required: false},
|
||||
"password": &hcldec.AttrSpec{Name: "password", Type: cty.String, Required: false},
|
||||
"insecure_connection": &hcldec.AttrSpec{Name: "insecure_connection", Type: cty.Bool, Required: false},
|
||||
"datacenter": &hcldec.AttrSpec{Name: "datacenter", Type: cty.String, Required: false},
|
||||
"vm_version": &hcldec.AttrSpec{Name: "vm_version", Type: cty.Number, Required: false},
|
||||
"guest_os_type": &hcldec.AttrSpec{Name: "guest_os_type", Type: cty.String, Required: false},
|
||||
"disk_controller_type": &hcldec.AttrSpec{Name: "disk_controller_type", Type: cty.List(cty.String), Required: false},
|
||||
"storage": &hcldec.BlockListSpec{TypeName: "storage", Nested: hcldec.ObjectSpec((*common.FlatDiskConfig)(nil).HCL2Spec())},
|
||||
"network_adapters": &hcldec.BlockListSpec{TypeName: "network_adapters", Nested: hcldec.ObjectSpec((*FlatNIC)(nil).HCL2Spec())},
|
||||
"usb_controller": &hcldec.AttrSpec{Name: "usb_controller", Type: cty.List(cty.String), Required: false},
|
||||
"notes": &hcldec.AttrSpec{Name: "notes", Type: cty.String, Required: false},
|
||||
"vm_name": &hcldec.AttrSpec{Name: "vm_name", Type: cty.String, Required: false},
|
||||
"folder": &hcldec.AttrSpec{Name: "folder", Type: cty.String, Required: false},
|
||||
"cluster": &hcldec.AttrSpec{Name: "cluster", Type: cty.String, Required: false},
|
||||
"host": &hcldec.AttrSpec{Name: "host", Type: cty.String, Required: false},
|
||||
"resource_pool": &hcldec.AttrSpec{Name: "resource_pool", Type: cty.String, Required: false},
|
||||
"datastore": &hcldec.AttrSpec{Name: "datastore", Type: cty.String, Required: false},
|
||||
"set_host_for_datastore_uploads": &hcldec.AttrSpec{Name: "set_host_for_datastore_uploads", Type: cty.Bool, Required: false},
|
||||
"CPUs": &hcldec.AttrSpec{Name: "CPUs", Type: cty.Number, Required: false},
|
||||
"cpu_cores": &hcldec.AttrSpec{Name: "cpu_cores", Type: cty.Number, Required: false},
|
||||
"CPU_reservation": &hcldec.AttrSpec{Name: "CPU_reservation", Type: cty.Number, Required: false},
|
||||
"CPU_limit": &hcldec.AttrSpec{Name: "CPU_limit", Type: cty.Number, Required: false},
|
||||
"CPU_hot_plug": &hcldec.AttrSpec{Name: "CPU_hot_plug", Type: cty.Bool, Required: false},
|
||||
"RAM": &hcldec.AttrSpec{Name: "RAM", Type: cty.Number, Required: false},
|
||||
"RAM_reservation": &hcldec.AttrSpec{Name: "RAM_reservation", Type: cty.Number, Required: false},
|
||||
"RAM_reserve_all": &hcldec.AttrSpec{Name: "RAM_reserve_all", Type: cty.Bool, Required: false},
|
||||
"RAM_hot_plug": &hcldec.AttrSpec{Name: "RAM_hot_plug", Type: cty.Bool, Required: false},
|
||||
"video_ram": &hcldec.AttrSpec{Name: "video_ram", Type: cty.Number, Required: false},
|
||||
"vgpu_profile": &hcldec.AttrSpec{Name: "vgpu_profile", Type: cty.String, Required: false},
|
||||
"NestedHV": &hcldec.AttrSpec{Name: "NestedHV", Type: cty.Bool, Required: false},
|
||||
"firmware": &hcldec.AttrSpec{Name: "firmware", Type: cty.String, Required: false},
|
||||
"force_bios_setup": &hcldec.AttrSpec{Name: "force_bios_setup", Type: cty.Bool, Required: false},
|
||||
"configuration_parameters": &hcldec.AttrSpec{Name: "configuration_parameters", Type: cty.Map(cty.String), Required: false},
|
||||
"tools_sync_time": &hcldec.AttrSpec{Name: "tools_sync_time", Type: cty.Bool, Required: false},
|
||||
"tools_upgrade_policy": &hcldec.AttrSpec{Name: "tools_upgrade_policy", Type: cty.Bool, Required: false},
|
||||
"iso_checksum": &hcldec.AttrSpec{Name: "iso_checksum", Type: cty.String, Required: false},
|
||||
"iso_url": &hcldec.AttrSpec{Name: "iso_url", Type: cty.String, Required: false},
|
||||
"iso_urls": &hcldec.AttrSpec{Name: "iso_urls", Type: cty.List(cty.String), Required: false},
|
||||
"iso_target_path": &hcldec.AttrSpec{Name: "iso_target_path", Type: cty.String, Required: false},
|
||||
"iso_target_extension": &hcldec.AttrSpec{Name: "iso_target_extension", Type: cty.String, Required: false},
|
||||
"cdrom_type": &hcldec.AttrSpec{Name: "cdrom_type", Type: cty.String, Required: false},
|
||||
"iso_paths": &hcldec.AttrSpec{Name: "iso_paths", Type: cty.List(cty.String), Required: false},
|
||||
"remove_cdrom": &hcldec.AttrSpec{Name: "remove_cdrom", Type: cty.Bool, Required: false},
|
||||
"floppy_img_path": &hcldec.AttrSpec{Name: "floppy_img_path", Type: cty.String, Required: false},
|
||||
"floppy_files": &hcldec.AttrSpec{Name: "floppy_files", Type: cty.List(cty.String), Required: false},
|
||||
"floppy_dirs": &hcldec.AttrSpec{Name: "floppy_dirs", Type: cty.List(cty.String), Required: false},
|
||||
"floppy_label": &hcldec.AttrSpec{Name: "floppy_label", Type: cty.String, Required: false},
|
||||
"boot_order": &hcldec.AttrSpec{Name: "boot_order", Type: cty.String, Required: false},
|
||||
"boot_keygroup_interval": &hcldec.AttrSpec{Name: "boot_keygroup_interval", Type: cty.String, Required: false},
|
||||
"boot_wait": &hcldec.AttrSpec{Name: "boot_wait", Type: cty.String, Required: false},
|
||||
"boot_command": &hcldec.AttrSpec{Name: "boot_command", Type: cty.List(cty.String), Required: false},
|
||||
"http_ip": &hcldec.AttrSpec{Name: "http_ip", Type: cty.String, Required: false},
|
||||
"ip_wait_timeout": &hcldec.AttrSpec{Name: "ip_wait_timeout", Type: cty.String, Required: false},
|
||||
"ip_settle_timeout": &hcldec.AttrSpec{Name: "ip_settle_timeout", Type: cty.String, Required: false},
|
||||
"ip_wait_address": &hcldec.AttrSpec{Name: "ip_wait_address", Type: cty.String, Required: false},
|
||||
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
|
||||
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
|
||||
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},
|
||||
"ssh_port": &hcldec.AttrSpec{Name: "ssh_port", Type: cty.Number, Required: false},
|
||||
"ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
|
||||
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
|
||||
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
|
||||
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
|
||||
"temporary_key_pair_type": &hcldec.AttrSpec{Name: "temporary_key_pair_type", Type: cty.String, Required: false},
|
||||
"temporary_key_pair_bits": &hcldec.AttrSpec{Name: "temporary_key_pair_bits", Type: cty.Number, Required: false},
|
||||
"ssh_ciphers": &hcldec.AttrSpec{Name: "ssh_ciphers", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
|
||||
"ssh_key_exchange_algorithms": &hcldec.AttrSpec{Name: "ssh_key_exchange_algorithms", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_private_key_file": &hcldec.AttrSpec{Name: "ssh_private_key_file", Type: cty.String, Required: false},
|
||||
"ssh_certificate_file": &hcldec.AttrSpec{Name: "ssh_certificate_file", Type: cty.String, Required: false},
|
||||
"ssh_pty": &hcldec.AttrSpec{Name: "ssh_pty", Type: cty.Bool, Required: false},
|
||||
"ssh_timeout": &hcldec.AttrSpec{Name: "ssh_timeout", Type: cty.String, Required: false},
|
||||
"ssh_wait_timeout": &hcldec.AttrSpec{Name: "ssh_wait_timeout", Type: cty.String, Required: false},
|
||||
"ssh_agent_auth": &hcldec.AttrSpec{Name: "ssh_agent_auth", Type: cty.Bool, Required: false},
|
||||
"ssh_disable_agent_forwarding": &hcldec.AttrSpec{Name: "ssh_disable_agent_forwarding", Type: cty.Bool, Required: false},
|
||||
"ssh_handshake_attempts": &hcldec.AttrSpec{Name: "ssh_handshake_attempts", Type: cty.Number, Required: false},
|
||||
"ssh_bastion_host": &hcldec.AttrSpec{Name: "ssh_bastion_host", Type: cty.String, Required: false},
|
||||
"ssh_bastion_port": &hcldec.AttrSpec{Name: "ssh_bastion_port", Type: cty.Number, Required: false},
|
||||
"ssh_bastion_agent_auth": &hcldec.AttrSpec{Name: "ssh_bastion_agent_auth", Type: cty.Bool, Required: false},
|
||||
"ssh_bastion_username": &hcldec.AttrSpec{Name: "ssh_bastion_username", Type: cty.String, Required: false},
|
||||
"ssh_bastion_password": &hcldec.AttrSpec{Name: "ssh_bastion_password", Type: cty.String, Required: false},
|
||||
"ssh_bastion_interactive": &hcldec.AttrSpec{Name: "ssh_bastion_interactive", Type: cty.Bool, Required: false},
|
||||
"ssh_bastion_private_key_file": &hcldec.AttrSpec{Name: "ssh_bastion_private_key_file", Type: cty.String, Required: false},
|
||||
"ssh_bastion_certificate_file": &hcldec.AttrSpec{Name: "ssh_bastion_certificate_file", Type: cty.String, Required: false},
|
||||
"ssh_file_transfer_method": &hcldec.AttrSpec{Name: "ssh_file_transfer_method", Type: cty.String, Required: false},
|
||||
"ssh_proxy_host": &hcldec.AttrSpec{Name: "ssh_proxy_host", Type: cty.String, Required: false},
|
||||
"ssh_proxy_port": &hcldec.AttrSpec{Name: "ssh_proxy_port", Type: cty.Number, Required: false},
|
||||
"ssh_proxy_username": &hcldec.AttrSpec{Name: "ssh_proxy_username", Type: cty.String, Required: false},
|
||||
"ssh_proxy_password": &hcldec.AttrSpec{Name: "ssh_proxy_password", Type: cty.String, Required: false},
|
||||
"ssh_keep_alive_interval": &hcldec.AttrSpec{Name: "ssh_keep_alive_interval", Type: cty.String, Required: false},
|
||||
"ssh_read_write_timeout": &hcldec.AttrSpec{Name: "ssh_read_write_timeout", Type: cty.String, Required: false},
|
||||
"ssh_remote_tunnels": &hcldec.AttrSpec{Name: "ssh_remote_tunnels", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_local_tunnels": &hcldec.AttrSpec{Name: "ssh_local_tunnels", Type: cty.List(cty.String), Required: false},
|
||||
"ssh_public_key": &hcldec.AttrSpec{Name: "ssh_public_key", Type: cty.List(cty.Number), Required: false},
|
||||
"ssh_private_key": &hcldec.AttrSpec{Name: "ssh_private_key", Type: cty.List(cty.Number), Required: false},
|
||||
"winrm_username": &hcldec.AttrSpec{Name: "winrm_username", Type: cty.String, Required: false},
|
||||
"winrm_password": &hcldec.AttrSpec{Name: "winrm_password", Type: cty.String, Required: false},
|
||||
"winrm_host": &hcldec.AttrSpec{Name: "winrm_host", Type: cty.String, Required: false},
|
||||
"winrm_no_proxy": &hcldec.AttrSpec{Name: "winrm_no_proxy", Type: cty.Bool, Required: false},
|
||||
"winrm_port": &hcldec.AttrSpec{Name: "winrm_port", Type: cty.Number, Required: false},
|
||||
"winrm_timeout": &hcldec.AttrSpec{Name: "winrm_timeout", Type: cty.String, Required: false},
|
||||
"winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false},
|
||||
"winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false},
|
||||
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
|
||||
"shutdown_command": &hcldec.AttrSpec{Name: "shutdown_command", Type: cty.String, Required: false},
|
||||
"shutdown_timeout": &hcldec.AttrSpec{Name: "shutdown_timeout", Type: cty.String, Required: false},
|
||||
"disable_shutdown": &hcldec.AttrSpec{Name: "disable_shutdown", Type: cty.Bool, Required: false},
|
||||
"create_snapshot": &hcldec.AttrSpec{Name: "create_snapshot", Type: cty.Bool, Required: false},
|
||||
"convert_to_template": &hcldec.AttrSpec{Name: "convert_to_template", Type: cty.Bool, Required: false},
|
||||
"export": &hcldec.BlockSpec{TypeName: "export", Nested: hcldec.ObjectSpec((*common.FlatExportConfig)(nil).HCL2Spec())},
|
||||
"content_library_destination": &hcldec.BlockSpec{TypeName: "content_library_destination", Nested: hcldec.ObjectSpec((*common.FlatContentLibraryDestinationConfig)(nil).HCL2Spec())},
|
||||
}
|
||||
return s
|
||||
}
|
188
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/iso/step_create.go
generated
vendored
Normal file
188
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/iso/step_create.go
generated
vendored
Normal file
|
@ -0,0 +1,188 @@
|
|||
//go:generate struct-markdown
|
||||
//go:generate mapstructure-to-hcl2 -type NIC,CreateConfig
|
||||
|
||||
package iso
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
// Defines a Network Adapter
|
||||
//
|
||||
// Example that creates two network adapters:
|
||||
//
|
||||
// In JSON:
|
||||
// ```json
|
||||
// "network_adapters": [
|
||||
// {
|
||||
// "network": "VM Network",
|
||||
// "network_card": "vmxnet3"
|
||||
// },
|
||||
// {
|
||||
// "network": "OtherNetwork",
|
||||
// "network_card": "vmxnet3"
|
||||
// }
|
||||
// ],
|
||||
// ```
|
||||
// In HCL2:
|
||||
// ```hcl
|
||||
// network_adapters {
|
||||
// network = "VM Network"
|
||||
// network_card = "vmxnet3"
|
||||
// }
|
||||
// network_adapters {
|
||||
// network = "OtherNetwork"
|
||||
// network_card = "vmxnet3"
|
||||
// }
|
||||
// ```
|
||||
type NIC struct {
|
||||
// Set the network in which the VM will be connected to. If no network is
|
||||
// specified, `host` must be specified to allow Packer to look for the
|
||||
// available network. If the network is inside a network folder in vCenter,
|
||||
// you need to provide the full path to the network.
|
||||
Network string `mapstructure:"network"`
|
||||
// Set VM network card type. Example `vmxnet3`.
|
||||
NetworkCard string `mapstructure:"network_card" required:"true"`
|
||||
// Set network card MAC address
|
||||
MacAddress string `mapstructure:"mac_address"`
|
||||
// Enable DirectPath I/O passthrough
|
||||
Passthrough *bool `mapstructure:"passthrough"`
|
||||
}
|
||||
|
||||
type CreateConfig struct {
|
||||
// Set VM hardware version. Defaults to the most current VM hardware
|
||||
// version supported by vCenter. See
|
||||
// [VMWare article 1003746](https://kb.vmware.com/s/article/1003746) for
|
||||
// the full list of supported VM hardware versions.
|
||||
Version uint `mapstructure:"vm_version"`
|
||||
// Set VM OS type. Defaults to `otherGuest`. See [
|
||||
// here](https://code.vmware.com/apis/358/vsphere/doc/vim.vm.GuestOsDescriptor.GuestOsIdentifier.html)
|
||||
// for a full list of possible values.
|
||||
GuestOSType string `mapstructure:"guest_os_type"`
|
||||
StorageConfig common.StorageConfig `mapstructure:",squash"`
|
||||
// Network adapters
|
||||
NICs []NIC `mapstructure:"network_adapters"`
|
||||
// Create USB controllers for the virtual machine. "usb" for a usb 2.0 controller. "xhci" for a usb 3.0 controller. There can only be at most one of each.
|
||||
USBController []string `mapstructure:"usb_controller"`
|
||||
// VM notes.
|
||||
Notes string `mapstructure:"notes"`
|
||||
}
|
||||
|
||||
func (c *CreateConfig) Prepare() []error {
|
||||
var errs []error
|
||||
|
||||
if len(c.StorageConfig.DiskControllerType) == 0 {
|
||||
c.StorageConfig.DiskControllerType = append(c.StorageConfig.DiskControllerType, "")
|
||||
}
|
||||
|
||||
// there should be at least one
|
||||
if len(c.StorageConfig.Storage) == 0 {
|
||||
errs = append(errs, fmt.Errorf("no storage devices have been defined"))
|
||||
}
|
||||
errs = append(errs, c.StorageConfig.Prepare()...)
|
||||
|
||||
if c.GuestOSType == "" {
|
||||
c.GuestOSType = "otherGuest"
|
||||
}
|
||||
|
||||
usbCount := 0
|
||||
xhciCount := 0
|
||||
|
||||
for i, s := range c.USBController {
|
||||
switch s {
|
||||
// 1 and true for backwards compatibility
|
||||
case "usb", "1", "true":
|
||||
usbCount++
|
||||
case "xhci":
|
||||
xhciCount++
|
||||
// 0 and false for backwards compatibility
|
||||
case "false", "0":
|
||||
continue
|
||||
default:
|
||||
errs = append(errs, fmt.Errorf("usb_controller[%d] references an unknown usb controller", i))
|
||||
}
|
||||
}
|
||||
if usbCount > 1 || xhciCount > 1 {
|
||||
errs = append(errs, fmt.Errorf("there can only be one usb controller and one xhci controller"))
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
type StepCreateVM struct {
|
||||
Config *CreateConfig
|
||||
Location *common.LocationConfig
|
||||
Force bool
|
||||
}
|
||||
|
||||
func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
d := state.Get("driver").(driver.Driver)
|
||||
vmPath := path.Join(s.Location.Folder, s.Location.VMName)
|
||||
|
||||
err := d.PreCleanVM(ui, vmPath, s.Force)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
ui.Say("Creating VM...")
|
||||
|
||||
// add network/network card an the first nic for backwards compatibility in the type is defined
|
||||
var networkCards []driver.NIC
|
||||
for _, nic := range s.Config.NICs {
|
||||
networkCards = append(networkCards, driver.NIC{
|
||||
Network: nic.Network,
|
||||
NetworkCard: nic.NetworkCard,
|
||||
MacAddress: nic.MacAddress,
|
||||
Passthrough: nic.Passthrough,
|
||||
})
|
||||
}
|
||||
|
||||
// add disk as the first drive for backwards compatibility if the type is defined
|
||||
var disks []driver.Disk
|
||||
for _, disk := range s.Config.StorageConfig.Storage {
|
||||
disks = append(disks, driver.Disk{
|
||||
DiskSize: disk.DiskSize,
|
||||
DiskEagerlyScrub: disk.DiskEagerlyScrub,
|
||||
DiskThinProvisioned: disk.DiskThinProvisioned,
|
||||
ControllerIndex: disk.DiskControllerIndex,
|
||||
})
|
||||
}
|
||||
|
||||
vm, err := d.CreateVM(&driver.CreateConfig{
|
||||
StorageConfig: driver.StorageConfig{
|
||||
DiskControllerType: s.Config.StorageConfig.DiskControllerType,
|
||||
Storage: disks,
|
||||
},
|
||||
Annotation: s.Config.Notes,
|
||||
Name: s.Location.VMName,
|
||||
Folder: s.Location.Folder,
|
||||
Cluster: s.Location.Cluster,
|
||||
Host: s.Location.Host,
|
||||
ResourcePool: s.Location.ResourcePool,
|
||||
Datastore: s.Location.Datastore,
|
||||
GuestOS: s.Config.GuestOSType,
|
||||
NICs: networkCards,
|
||||
USBController: s.Config.USBController,
|
||||
Version: s.Config.Version,
|
||||
})
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf("error creating vm: %v", err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
state.Put("vm", vm)
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepCreateVM) Cleanup(state multistep.StateBag) {
|
||||
common.CleanupVM(state)
|
||||
}
|
73
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/iso/step_create.hcl2spec.go
generated
vendored
Normal file
73
vendor/github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/iso/step_create.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type NIC,CreateConfig"; DO NOT EDIT.
|
||||
|
||||
package iso
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatCreateConfig is an auto-generated flat version of CreateConfig.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatCreateConfig struct {
|
||||
Version *uint `mapstructure:"vm_version" cty:"vm_version" hcl:"vm_version"`
|
||||
GuestOSType *string `mapstructure:"guest_os_type" cty:"guest_os_type" hcl:"guest_os_type"`
|
||||
DiskControllerType []string `mapstructure:"disk_controller_type" cty:"disk_controller_type" hcl:"disk_controller_type"`
|
||||
Storage []common.FlatDiskConfig `mapstructure:"storage" cty:"storage" hcl:"storage"`
|
||||
NICs []FlatNIC `mapstructure:"network_adapters" cty:"network_adapters" hcl:"network_adapters"`
|
||||
USBController []string `mapstructure:"usb_controller" cty:"usb_controller" hcl:"usb_controller"`
|
||||
Notes *string `mapstructure:"notes" cty:"notes" hcl:"notes"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatCreateConfig.
|
||||
// FlatCreateConfig is an auto-generated flat version of CreateConfig.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*CreateConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatCreateConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a CreateConfig.
|
||||
// This spec is used by HCL to read the fields of CreateConfig.
|
||||
// The decoded values from this spec will then be applied to a FlatCreateConfig.
|
||||
func (*FlatCreateConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"vm_version": &hcldec.AttrSpec{Name: "vm_version", Type: cty.Number, Required: false},
|
||||
"guest_os_type": &hcldec.AttrSpec{Name: "guest_os_type", Type: cty.String, Required: false},
|
||||
"disk_controller_type": &hcldec.AttrSpec{Name: "disk_controller_type", Type: cty.List(cty.String), Required: false},
|
||||
"storage": &hcldec.BlockListSpec{TypeName: "storage", Nested: hcldec.ObjectSpec((*common.FlatDiskConfig)(nil).HCL2Spec())},
|
||||
"network_adapters": &hcldec.BlockListSpec{TypeName: "network_adapters", Nested: hcldec.ObjectSpec((*FlatNIC)(nil).HCL2Spec())},
|
||||
"usb_controller": &hcldec.AttrSpec{Name: "usb_controller", Type: cty.List(cty.String), Required: false},
|
||||
"notes": &hcldec.AttrSpec{Name: "notes", Type: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// FlatNIC is an auto-generated flat version of NIC.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatNIC struct {
|
||||
Network *string `mapstructure:"network" cty:"network" hcl:"network"`
|
||||
NetworkCard *string `mapstructure:"network_card" required:"true" cty:"network_card" hcl:"network_card"`
|
||||
MacAddress *string `mapstructure:"mac_address" cty:"mac_address" hcl:"mac_address"`
|
||||
Passthrough *bool `mapstructure:"passthrough" cty:"passthrough" hcl:"passthrough"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatNIC.
|
||||
// FlatNIC is an auto-generated flat version of NIC.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*NIC) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatNIC)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a NIC.
|
||||
// This spec is used by HCL to read the fields of NIC.
|
||||
// The decoded values from this spec will then be applied to a FlatNIC.
|
||||
func (*FlatNIC) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"network": &hcldec.AttrSpec{Name: "network", Type: cty.String, Required: false},
|
||||
"network_card": &hcldec.AttrSpec{Name: "network_card", Type: cty.String, Required: false},
|
||||
"mac_address": &hcldec.AttrSpec{Name: "mac_address", Type: cty.String, Required: false},
|
||||
"passthrough": &hcldec.AttrSpec{Name: "passthrough", Type: cty.Bool, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
160
vendor/github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere-template/post-processor.go
generated
vendored
Normal file
160
vendor/github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere-template/post-processor.go
generated
vendored
Normal file
|
@ -0,0 +1,160 @@
|
|||
//go:generate mapstructure-to-hcl2 -type Config
|
||||
|
||||
package vsphere_template
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/hashicorp/packer-plugin-sdk/common"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
vsphere "github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/common"
|
||||
vspherepost "github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere"
|
||||
"github.com/vmware/govmomi"
|
||||
)
|
||||
|
||||
const (
|
||||
// BuilderId for the local artifacts
|
||||
BuilderIdESX = "mitchellh.vmware-esx"
|
||||
|
||||
ArtifactConfFormat = "artifact.conf.format"
|
||||
ArtifactConfKeepRegistered = "artifact.conf.keep_registered"
|
||||
ArtifactConfSkipExport = "artifact.conf.skip_export"
|
||||
)
|
||||
|
||||
var builtins = map[string]string{
|
||||
vspherepost.BuilderId: "vmware",
|
||||
BuilderIdESX: "vmware",
|
||||
vsphere.BuilderId: "vsphere",
|
||||
"packer.post-processor.artifice": "artifice",
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
common.PackerConfig `mapstructure:",squash"`
|
||||
Host string `mapstructure:"host"`
|
||||
Insecure bool `mapstructure:"insecure"`
|
||||
Username string `mapstructure:"username"`
|
||||
Password string `mapstructure:"password"`
|
||||
Datacenter string `mapstructure:"datacenter"`
|
||||
Folder string `mapstructure:"folder"`
|
||||
SnapshotEnable bool `mapstructure:"snapshot_enable"`
|
||||
SnapshotName string `mapstructure:"snapshot_name"`
|
||||
SnapshotDescription string `mapstructure:"snapshot_description"`
|
||||
ReregisterVM config.Trilean `mapstructure:"reregister_vm"`
|
||||
|
||||
ctx interpolate.Context
|
||||
}
|
||||
|
||||
type PostProcessor struct {
|
||||
config Config
|
||||
url *url.URL
|
||||
}
|
||||
|
||||
func (p *PostProcessor) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
|
||||
|
||||
func (p *PostProcessor) Configure(raws ...interface{}) error {
|
||||
err := config.Decode(&p.config, &config.DecodeOpts{
|
||||
PluginType: vsphere.BuilderId,
|
||||
Interpolate: true,
|
||||
InterpolateContext: &p.config.ctx,
|
||||
InterpolateFilter: &interpolate.RenderFilter{
|
||||
Exclude: []string{},
|
||||
},
|
||||
}, raws...)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
errs := new(packersdk.MultiError)
|
||||
vc := map[string]*string{
|
||||
"host": &p.config.Host,
|
||||
"username": &p.config.Username,
|
||||
"password": &p.config.Password,
|
||||
}
|
||||
|
||||
for key, ptr := range vc {
|
||||
if *ptr == "" {
|
||||
errs = packersdk.MultiErrorAppend(
|
||||
errs, fmt.Errorf("%s must be set", key))
|
||||
}
|
||||
}
|
||||
|
||||
if p.config.Folder != "" && !strings.HasPrefix(p.config.Folder, "/") {
|
||||
errs = packersdk.MultiErrorAppend(
|
||||
errs, fmt.Errorf("Folder must be bound to the root"))
|
||||
}
|
||||
|
||||
sdk, err := url.Parse(fmt.Sprintf("https://%v/sdk", p.config.Host))
|
||||
if err != nil {
|
||||
errs = packersdk.MultiErrorAppend(
|
||||
errs, fmt.Errorf("Error invalid vSphere sdk endpoint: %s", err))
|
||||
return errs
|
||||
}
|
||||
|
||||
sdk.User = url.UserPassword(p.config.Username, p.config.Password)
|
||||
p.url = sdk
|
||||
|
||||
if len(errs.Errors) > 0 {
|
||||
return errs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PostProcessor) PostProcess(ctx context.Context, ui packersdk.Ui, artifact packersdk.Artifact) (packersdk.Artifact, bool, bool, error) {
|
||||
if _, ok := builtins[artifact.BuilderId()]; !ok {
|
||||
return nil, false, false, fmt.Errorf("The Packer vSphere Template post-processor "+
|
||||
"can only take an artifact from the VMware-iso builder, built on "+
|
||||
"ESXi (i.e. remote) or an artifact from the vSphere post-processor. "+
|
||||
"Artifact type %s does not fit this requirement", artifact.BuilderId())
|
||||
}
|
||||
|
||||
f := artifact.State(ArtifactConfFormat)
|
||||
k := artifact.State(ArtifactConfKeepRegistered)
|
||||
s := artifact.State(ArtifactConfSkipExport)
|
||||
|
||||
if f != "" && k != "true" && s == "false" {
|
||||
return nil, false, false, errors.New("To use this post-processor with exporting behavior you need set keep_registered as true")
|
||||
}
|
||||
|
||||
// In some occasions the VM state is powered on and if we immediately try to mark as template
|
||||
// (after the ESXi creates it) it will fail. If vSphere is given a few seconds this behavior doesn't reappear.
|
||||
ui.Message("Waiting 10s for VMware vSphere to start")
|
||||
time.Sleep(10 * time.Second)
|
||||
c, err := govmomi.NewClient(context.Background(), p.url, p.config.Insecure)
|
||||
if err != nil {
|
||||
return nil, false, false, fmt.Errorf("Error connecting to vSphere: %s", err)
|
||||
}
|
||||
|
||||
defer c.Logout(context.Background())
|
||||
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("ui", ui)
|
||||
state.Put("client", c)
|
||||
|
||||
steps := []multistep.Step{
|
||||
&stepChooseDatacenter{
|
||||
Datacenter: p.config.Datacenter,
|
||||
},
|
||||
&stepCreateFolder{
|
||||
Folder: p.config.Folder,
|
||||
},
|
||||
NewStepCreateSnapshot(artifact, p),
|
||||
NewStepMarkAsTemplate(artifact, p),
|
||||
}
|
||||
runner := commonsteps.NewRunnerWithPauseFn(steps, p.config.PackerConfig, ui, state)
|
||||
runner.Run(ctx, state)
|
||||
if rawErr, ok := state.GetOk("error"); ok {
|
||||
return nil, false, false, rawErr.(error)
|
||||
}
|
||||
return artifact, true, true, nil
|
||||
}
|
65
vendor/github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere-template/post-processor.hcl2spec.go
generated
vendored
Normal file
65
vendor/github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere-template/post-processor.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type Config"; DO NOT EDIT.
|
||||
|
||||
package vsphere_template
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatConfig is an auto-generated flat version of Config.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatConfig struct {
|
||||
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"`
|
||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
|
||||
PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"`
|
||||
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
|
||||
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
|
||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
|
||||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"`
|
||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"`
|
||||
Host *string `mapstructure:"host" cty:"host" hcl:"host"`
|
||||
Insecure *bool `mapstructure:"insecure" cty:"insecure" hcl:"insecure"`
|
||||
Username *string `mapstructure:"username" cty:"username" hcl:"username"`
|
||||
Password *string `mapstructure:"password" cty:"password" hcl:"password"`
|
||||
Datacenter *string `mapstructure:"datacenter" cty:"datacenter" hcl:"datacenter"`
|
||||
Folder *string `mapstructure:"folder" cty:"folder" hcl:"folder"`
|
||||
SnapshotEnable *bool `mapstructure:"snapshot_enable" cty:"snapshot_enable" hcl:"snapshot_enable"`
|
||||
SnapshotName *string `mapstructure:"snapshot_name" cty:"snapshot_name" hcl:"snapshot_name"`
|
||||
SnapshotDescription *string `mapstructure:"snapshot_description" cty:"snapshot_description" hcl:"snapshot_description"`
|
||||
ReregisterVM *bool `mapstructure:"reregister_vm" cty:"reregister_vm" hcl:"reregister_vm"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatConfig.
|
||||
// FlatConfig is an auto-generated flat version of Config.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a Config.
|
||||
// This spec is used by HCL to read the fields of Config.
|
||||
// The decoded values from this spec will then be applied to a FlatConfig.
|
||||
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
|
||||
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
|
||||
"packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false},
|
||||
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
|
||||
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
|
||||
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
|
||||
"packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"host": &hcldec.AttrSpec{Name: "host", Type: cty.String, Required: false},
|
||||
"insecure": &hcldec.AttrSpec{Name: "insecure", Type: cty.Bool, Required: false},
|
||||
"username": &hcldec.AttrSpec{Name: "username", Type: cty.String, Required: false},
|
||||
"password": &hcldec.AttrSpec{Name: "password", Type: cty.String, Required: false},
|
||||
"datacenter": &hcldec.AttrSpec{Name: "datacenter", Type: cty.String, Required: false},
|
||||
"folder": &hcldec.AttrSpec{Name: "folder", Type: cty.String, Required: false},
|
||||
"snapshot_enable": &hcldec.AttrSpec{Name: "snapshot_enable", Type: cty.Bool, Required: false},
|
||||
"snapshot_name": &hcldec.AttrSpec{Name: "snapshot_name", Type: cty.String, Required: false},
|
||||
"snapshot_description": &hcldec.AttrSpec{Name: "snapshot_description", Type: cty.String, Required: false},
|
||||
"reregister_vm": &hcldec.AttrSpec{Name: "reregister_vm", Type: cty.Bool, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
35
vendor/github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere-template/step_choose_datacenter.go
generated
vendored
Normal file
35
vendor/github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere-template/step_choose_datacenter.go
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
package vsphere_template
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/vmware/govmomi"
|
||||
"github.com/vmware/govmomi/find"
|
||||
)
|
||||
|
||||
type stepChooseDatacenter struct {
|
||||
Datacenter string
|
||||
}
|
||||
|
||||
func (s *stepChooseDatacenter) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
cli := state.Get("client").(*govmomi.Client)
|
||||
finder := find.NewFinder(cli.Client, false)
|
||||
|
||||
ui.Message("Choosing datacenter...")
|
||||
|
||||
dc, err := finder.DatacenterOrDefault(context.Background(), s.Datacenter)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
state.Put("dcPath", dc.InventoryPath)
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *stepChooseDatacenter) Cleanup(multistep.StateBag) {}
|
86
vendor/github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere-template/step_create_folder.go
generated
vendored
Normal file
86
vendor/github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere-template/step_create_folder.go
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
package vsphere_template
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/vmware/govmomi"
|
||||
"github.com/vmware/govmomi/object"
|
||||
)
|
||||
|
||||
type stepCreateFolder struct {
|
||||
Folder string
|
||||
}
|
||||
|
||||
func (s *stepCreateFolder) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
cli := state.Get("client").(*govmomi.Client)
|
||||
dcPath := state.Get("dcPath").(string)
|
||||
|
||||
ui.Message("Creating or checking destination folders...")
|
||||
|
||||
base := path.Join(dcPath, "vm")
|
||||
fullPath := path.Join(base, s.Folder)
|
||||
si := object.NewSearchIndex(cli.Client)
|
||||
|
||||
var folders []string
|
||||
var err error
|
||||
var ref object.Reference
|
||||
|
||||
// We iterate over the path starting with full path
|
||||
// If we don't find it, we save the folder name and continue with the previous path
|
||||
// The iteration ends when we find an existing path otherwise it throws error
|
||||
for {
|
||||
ref, err = si.FindByInventoryPath(context.Background(), fullPath)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if ref == nil {
|
||||
dir, folder := path.Split(fullPath)
|
||||
fullPath = path.Clean(dir)
|
||||
|
||||
if fullPath == dcPath {
|
||||
err = fmt.Errorf("vSphere base path %s not found", base)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
folders = append(folders, folder)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if root, ok := ref.(*object.Folder); ok {
|
||||
for i := len(folders) - 1; i >= 0; i-- {
|
||||
ui.Message(fmt.Sprintf("Creating folder: %v", folders[i]))
|
||||
|
||||
root, err = root.CreateFolder(context.Background(), folders[i])
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
fullPath = path.Join(fullPath, folders[i])
|
||||
}
|
||||
root.SetInventoryPath(fullPath)
|
||||
state.Put("folder", root)
|
||||
} else {
|
||||
err = fmt.Errorf("folder not found: '%v'", ref)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *stepCreateFolder) Cleanup(multistep.StateBag) {}
|
76
vendor/github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere-template/step_create_snapshot.go
generated
vendored
Normal file
76
vendor/github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere-template/step_create_snapshot.go
generated
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
package vsphere_template
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere"
|
||||
"github.com/vmware/govmomi"
|
||||
)
|
||||
|
||||
type stepCreateSnapshot struct {
|
||||
VMName string
|
||||
RemoteFolder string
|
||||
SnapshotName string
|
||||
SnapshotDescription string
|
||||
SnapshotEnable bool
|
||||
}
|
||||
|
||||
func NewStepCreateSnapshot(artifact packersdk.Artifact, p *PostProcessor) *stepCreateSnapshot {
|
||||
remoteFolder := "Discovered virtual machine"
|
||||
vmname := artifact.Id()
|
||||
|
||||
if artifact.BuilderId() == vsphere.BuilderId {
|
||||
id := strings.Split(artifact.Id(), "::")
|
||||
remoteFolder = id[1]
|
||||
vmname = id[2]
|
||||
}
|
||||
|
||||
return &stepCreateSnapshot{
|
||||
VMName: vmname,
|
||||
RemoteFolder: remoteFolder,
|
||||
SnapshotEnable: p.config.SnapshotEnable,
|
||||
SnapshotName: p.config.SnapshotName,
|
||||
SnapshotDescription: p.config.SnapshotDescription,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stepCreateSnapshot) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
cli := state.Get("client").(*govmomi.Client)
|
||||
dcPath := state.Get("dcPath").(string)
|
||||
|
||||
if !s.SnapshotEnable {
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
ui.Message("Creating a Snapshot...")
|
||||
|
||||
vm, err := findRuntimeVM(cli, dcPath, s.VMName, s.RemoteFolder)
|
||||
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
task, err := vm.CreateSnapshot(context.Background(), s.SnapshotName, s.SnapshotDescription, false, false)
|
||||
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if err = task.Wait(context.Background()); err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *stepCreateSnapshot) Cleanup(multistep.StateBag) {}
|
186
vendor/github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere-template/step_mark_as_template.go
generated
vendored
Normal file
186
vendor/github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere-template/step_mark_as_template.go
generated
vendored
Normal file
|
@ -0,0 +1,186 @@
|
|||
package vsphere_template
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere"
|
||||
"github.com/vmware/govmomi"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type stepMarkAsTemplate struct {
|
||||
VMName string
|
||||
RemoteFolder string
|
||||
ReregisterVM config.Trilean
|
||||
}
|
||||
|
||||
func NewStepMarkAsTemplate(artifact packersdk.Artifact, p *PostProcessor) *stepMarkAsTemplate {
|
||||
remoteFolder := "Discovered virtual machine"
|
||||
vmname := artifact.Id()
|
||||
|
||||
if artifact.BuilderId() == vsphere.BuilderId {
|
||||
id := strings.Split(artifact.Id(), "::")
|
||||
remoteFolder = id[1]
|
||||
vmname = id[2]
|
||||
}
|
||||
|
||||
return &stepMarkAsTemplate{
|
||||
VMName: vmname,
|
||||
RemoteFolder: remoteFolder,
|
||||
ReregisterVM: p.config.ReregisterVM,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stepMarkAsTemplate) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
cli := state.Get("client").(*govmomi.Client)
|
||||
folder := state.Get("folder").(*object.Folder)
|
||||
dcPath := state.Get("dcPath").(string)
|
||||
|
||||
vm, err := findRuntimeVM(cli, dcPath, s.VMName, s.RemoteFolder)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
// Use a simple "MarkAsTemplate" method unless `reregister_vm` is true
|
||||
if s.ReregisterVM.False() {
|
||||
ui.Message("Marking as a template...")
|
||||
|
||||
if err := vm.MarkAsTemplate(context.Background()); err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error("vm.MarkAsTemplate:" + err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
ui.Message("Re-register VM as a template...")
|
||||
|
||||
dsPath, err := datastorePath(vm)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error("datastorePath:" + err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
host, err := vm.HostSystem(context.Background())
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error("vm.HostSystem:" + err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if err := vm.Unregister(context.Background()); err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error("vm.Unregister:" + err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if err := unregisterPreviousVM(cli, folder, s.VMName); err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error("unregisterPreviousVM:" + err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
task, err := folder.RegisterVM(context.Background(), dsPath.String(), s.VMName, true, nil, host)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error("RegisterVM:" + err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if err = task.Wait(context.Background()); err != nil {
|
||||
state.Put("error", err)
|
||||
ui.Error("task.Wait:" + err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func datastorePath(vm *object.VirtualMachine) (*object.DatastorePath, error) {
|
||||
devices, err := vm.Device(context.Background())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
disk := ""
|
||||
for _, device := range devices {
|
||||
if d, ok := device.(*types.VirtualDisk); ok {
|
||||
if b, ok := d.Backing.(types.BaseVirtualDeviceFileBackingInfo); ok {
|
||||
disk = b.GetVirtualDeviceFileBackingInfo().FileName
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if disk == "" {
|
||||
return nil, fmt.Errorf("disk not found in '%v'", vm.Name())
|
||||
}
|
||||
|
||||
re := regexp.MustCompile("\\[(.*?)\\]")
|
||||
|
||||
datastore := re.FindStringSubmatch(disk)[1]
|
||||
vmxPath := path.Join("/", path.Dir(strings.Split(disk, " ")[1]), vm.Name()+".vmx")
|
||||
|
||||
return &object.DatastorePath{
|
||||
Datastore: datastore,
|
||||
Path: vmxPath,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func findRuntimeVM(cli *govmomi.Client, dcPath, name, remoteFolder string) (*object.VirtualMachine, error) {
|
||||
si := object.NewSearchIndex(cli.Client)
|
||||
fullPath := path.Join(dcPath, "vm", remoteFolder, name)
|
||||
|
||||
ref, err := si.FindByInventoryPath(context.Background(), fullPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if ref == nil {
|
||||
return nil, fmt.Errorf("VM at path %s not found", fullPath)
|
||||
}
|
||||
|
||||
vm := ref.(*object.VirtualMachine)
|
||||
if vm.InventoryPath == "" {
|
||||
vm.SetInventoryPath(fullPath)
|
||||
}
|
||||
|
||||
return vm, nil
|
||||
}
|
||||
|
||||
// If in the target folder a virtual machine or template already exists
|
||||
// it will be removed to maintain consistency
|
||||
func unregisterPreviousVM(cli *govmomi.Client, folder *object.Folder, name string) error {
|
||||
si := object.NewSearchIndex(cli.Client)
|
||||
fullPath := path.Join(folder.InventoryPath, name)
|
||||
|
||||
ref, err := si.FindByInventoryPath(context.Background(), fullPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ref != nil {
|
||||
if vm, ok := ref.(*object.VirtualMachine); ok {
|
||||
return vm.Unregister(context.Background())
|
||||
} else {
|
||||
return fmt.Errorf("an object name '%v' already exists", name)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stepMarkAsTemplate) Cleanup(multistep.StateBag) {}
|
47
vendor/github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere/artifact.go
generated
vendored
Normal file
47
vendor/github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere/artifact.go
generated
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
package vsphere
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const BuilderId = "packer.post-processor.vsphere"
|
||||
|
||||
type Artifact struct {
|
||||
files []string
|
||||
datastore string
|
||||
vmfolder string
|
||||
vmname string
|
||||
}
|
||||
|
||||
func NewArtifact(datastore, vmfolder, vmname string, files []string) *Artifact {
|
||||
return &Artifact{
|
||||
files: files,
|
||||
datastore: datastore,
|
||||
vmfolder: vmfolder,
|
||||
vmname: vmname,
|
||||
}
|
||||
}
|
||||
|
||||
func (*Artifact) BuilderId() string {
|
||||
return BuilderId
|
||||
}
|
||||
|
||||
func (a *Artifact) Files() []string {
|
||||
return a.files
|
||||
}
|
||||
|
||||
func (a *Artifact) Id() string {
|
||||
return fmt.Sprintf("%s::%s::%s", a.datastore, a.vmfolder, a.vmname)
|
||||
}
|
||||
|
||||
func (a *Artifact) String() string {
|
||||
return fmt.Sprintf("VM: %s Folder: %s Datastore: %s", a.vmname, a.vmfolder, a.datastore)
|
||||
}
|
||||
|
||||
func (*Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
return nil
|
||||
}
|
280
vendor/github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere/post-processor.go
generated
vendored
Normal file
280
vendor/github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere/post-processor.go
generated
vendored
Normal file
|
@ -0,0 +1,280 @@
|
|||
//go:generate mapstructure-to-hcl2 -type Config
|
||||
|
||||
package vsphere
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/hashicorp/packer-plugin-sdk/common"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
shelllocal "github.com/hashicorp/packer-plugin-sdk/shell-local"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
||||
)
|
||||
|
||||
var ovftool string = "ovftool"
|
||||
|
||||
var (
|
||||
// Regular expression to validate RFC1035 hostnames from full fqdn or simple hostname.
|
||||
// For example "packer-esxi1". Requires proper DNS setup and/or correct DNS search domain setting.
|
||||
hostnameRegex = regexp.MustCompile(`^[[:alnum:]][[:alnum:]\-]{0,61}[[:alnum:]]|[[:alpha:]]$`)
|
||||
|
||||
// Simple regular expression to validate IPv4 values.
|
||||
// For example "192.168.1.1".
|
||||
ipv4Regex = regexp.MustCompile(`^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`)
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
common.PackerConfig `mapstructure:",squash"`
|
||||
|
||||
Cluster string `mapstructure:"cluster"`
|
||||
Datacenter string `mapstructure:"datacenter"`
|
||||
Datastore string `mapstructure:"datastore"`
|
||||
DiskMode string `mapstructure:"disk_mode"`
|
||||
Host string `mapstructure:"host"`
|
||||
ESXiHost string `mapstructure:"esxi_host"`
|
||||
Insecure bool `mapstructure:"insecure"`
|
||||
Options []string `mapstructure:"options"`
|
||||
Overwrite bool `mapstructure:"overwrite"`
|
||||
Password string `mapstructure:"password"`
|
||||
ResourcePool string `mapstructure:"resource_pool"`
|
||||
Username string `mapstructure:"username"`
|
||||
VMFolder string `mapstructure:"vm_folder"`
|
||||
VMName string `mapstructure:"vm_name"`
|
||||
VMNetwork string `mapstructure:"vm_network"`
|
||||
|
||||
ctx interpolate.Context
|
||||
}
|
||||
|
||||
type PostProcessor struct {
|
||||
config Config
|
||||
}
|
||||
|
||||
func (p *PostProcessor) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
|
||||
|
||||
func (p *PostProcessor) Configure(raws ...interface{}) error {
|
||||
err := config.Decode(&p.config, &config.DecodeOpts{
|
||||
PluginType: BuilderId,
|
||||
Interpolate: true,
|
||||
InterpolateContext: &p.config.ctx,
|
||||
InterpolateFilter: &interpolate.RenderFilter{
|
||||
Exclude: []string{},
|
||||
},
|
||||
}, raws...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Defaults
|
||||
if p.config.DiskMode == "" {
|
||||
p.config.DiskMode = "thick"
|
||||
}
|
||||
|
||||
// Accumulate any errors
|
||||
errs := new(packersdk.MultiError)
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
ovftool = "ovftool.exe"
|
||||
}
|
||||
|
||||
if _, err := exec.LookPath(ovftool); err != nil {
|
||||
errs = packersdk.MultiErrorAppend(
|
||||
errs, fmt.Errorf("ovftool not found: %s", err))
|
||||
}
|
||||
|
||||
// First define all our templatable parameters that are _required_
|
||||
templates := map[string]*string{
|
||||
"cluster": &p.config.Cluster,
|
||||
"datacenter": &p.config.Datacenter,
|
||||
"diskmode": &p.config.DiskMode,
|
||||
"host": &p.config.Host,
|
||||
"password": &p.config.Password,
|
||||
"username": &p.config.Username,
|
||||
"vm_name": &p.config.VMName,
|
||||
}
|
||||
for key, ptr := range templates {
|
||||
if *ptr == "" {
|
||||
errs = packersdk.MultiErrorAppend(
|
||||
errs, fmt.Errorf("%s must be set", key))
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs.Errors) > 0 {
|
||||
return errs
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PostProcessor) generateURI() (*url.URL, error) {
|
||||
// use net/url lib to encode and escape url elements
|
||||
ovftool_uri := fmt.Sprintf("vi://%s/%s/host/%s",
|
||||
p.config.Host,
|
||||
p.config.Datacenter,
|
||||
p.config.Cluster)
|
||||
|
||||
if p.config.ResourcePool != "" {
|
||||
ovftool_uri += "/Resources/" + p.config.ResourcePool
|
||||
}
|
||||
|
||||
u, err := url.Parse(ovftool_uri)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Couldn't generate uri for ovftool: %s", err)
|
||||
}
|
||||
u.User = url.UserPassword(p.config.Username, p.config.Password)
|
||||
|
||||
if p.config.ESXiHost != "" {
|
||||
q := u.Query()
|
||||
if ipv4Regex.MatchString(p.config.ESXiHost) {
|
||||
q.Add("ip", p.config.ESXiHost)
|
||||
} else if hostnameRegex.MatchString(p.config.ESXiHost) {
|
||||
q.Add("dns", p.config.ESXiHost)
|
||||
}
|
||||
u.RawQuery = q.Encode()
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func getEncodedPassword(u *url.URL) (string, bool) {
|
||||
// filter password from all logging
|
||||
password, passwordSet := u.User.Password()
|
||||
if passwordSet && password != "" {
|
||||
encodedPassword := strings.Split(u.User.String(), ":")[1]
|
||||
return encodedPassword, true
|
||||
}
|
||||
return password, false
|
||||
}
|
||||
|
||||
func (p *PostProcessor) PostProcess(ctx context.Context, ui packersdk.Ui, artifact packersdk.Artifact) (packersdk.Artifact, bool, bool, error) {
|
||||
source := ""
|
||||
for _, path := range artifact.Files() {
|
||||
if strings.HasSuffix(path, ".vmx") || strings.HasSuffix(path, ".ovf") || strings.HasSuffix(path, ".ova") {
|
||||
source = path
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if source == "" {
|
||||
return nil, false, false, fmt.Errorf("VMX, OVF or OVA file not found")
|
||||
}
|
||||
|
||||
ovftool_uri, err := p.generateURI()
|
||||
if err != nil {
|
||||
return nil, false, false, err
|
||||
}
|
||||
encodedPassword, isSet := getEncodedPassword(ovftool_uri)
|
||||
if isSet {
|
||||
packersdk.LogSecretFilter.Set(encodedPassword)
|
||||
}
|
||||
|
||||
args, err := p.BuildArgs(source, ovftool_uri.String())
|
||||
if err != nil {
|
||||
ui.Message(fmt.Sprintf("Failed: %s\n", err))
|
||||
}
|
||||
|
||||
ui.Message(fmt.Sprintf("Uploading %s to vSphere", source))
|
||||
|
||||
log.Printf("Starting ovftool with parameters: %s", strings.Join(args, " "))
|
||||
|
||||
ui.Message("Validating Username and Password with dry-run")
|
||||
err = p.ValidateOvfTool(args, ovftool)
|
||||
if err != nil {
|
||||
return nil, false, false, err
|
||||
}
|
||||
|
||||
// Validation has passed, so run for real.
|
||||
ui.Message("Calling OVFtool to upload vm")
|
||||
commandAndArgs := []string{ovftool}
|
||||
commandAndArgs = append(commandAndArgs, args...)
|
||||
comm := &shelllocal.Communicator{
|
||||
ExecuteCommand: commandAndArgs,
|
||||
}
|
||||
flattenedCmd := strings.Join(commandAndArgs, " ")
|
||||
cmd := &packersdk.RemoteCmd{Command: flattenedCmd}
|
||||
log.Printf("[INFO] (vsphere): starting ovftool command: %s", flattenedCmd)
|
||||
err = cmd.RunWithUi(ctx, comm, ui)
|
||||
if err != nil || cmd.ExitStatus() != 0 {
|
||||
return nil, false, false, fmt.Errorf(
|
||||
"Error uploading virtual machine: Please see output above for more information.")
|
||||
}
|
||||
|
||||
artifact = NewArtifact(p.config.Datastore, p.config.VMFolder, p.config.VMName, artifact.Files())
|
||||
|
||||
return artifact, false, false, nil
|
||||
}
|
||||
|
||||
func (p *PostProcessor) ValidateOvfTool(args []string, ofvtool string) error {
|
||||
args = append([]string{"--verifyOnly"}, args...)
|
||||
var out bytes.Buffer
|
||||
cmdCtx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
||||
defer cancel()
|
||||
cmd := exec.CommandContext(cmdCtx, ovftool, args...)
|
||||
cmd.Stdout = &out
|
||||
|
||||
// Need to manually close stdin or else the ofvtool call will hang
|
||||
// forever in a situation where the user has provided an invalid
|
||||
// password or username
|
||||
stdin, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer stdin.Close()
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
outString := out.String()
|
||||
if strings.Contains(outString, "Enter login information for") {
|
||||
err = fmt.Errorf("Error performing OVFtool dry run; the username " +
|
||||
"or password you provided to ovftool is likely invalid.")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PostProcessor) BuildArgs(source, ovftool_uri string) ([]string, error) {
|
||||
args := []string{
|
||||
"--acceptAllEulas",
|
||||
fmt.Sprintf(`--name=%s`, p.config.VMName),
|
||||
fmt.Sprintf(`--datastore=%s`, p.config.Datastore),
|
||||
}
|
||||
|
||||
if p.config.Insecure {
|
||||
args = append(args, fmt.Sprintf(`--noSSLVerify=%t`, p.config.Insecure))
|
||||
}
|
||||
|
||||
if p.config.DiskMode != "" {
|
||||
args = append(args, fmt.Sprintf(`--diskMode=%s`, p.config.DiskMode))
|
||||
}
|
||||
|
||||
if p.config.VMFolder != "" {
|
||||
args = append(args, fmt.Sprintf(`--vmFolder=%s`, p.config.VMFolder))
|
||||
}
|
||||
|
||||
if p.config.VMNetwork != "" {
|
||||
args = append(args, fmt.Sprintf(`--network=%s`, p.config.VMNetwork))
|
||||
}
|
||||
|
||||
if p.config.Overwrite == true {
|
||||
args = append(args, "--overwrite")
|
||||
}
|
||||
|
||||
if len(p.config.Options) > 0 {
|
||||
args = append(args, p.config.Options...)
|
||||
}
|
||||
|
||||
args = append(args, source)
|
||||
args = append(args, ovftool_uri)
|
||||
|
||||
return args, nil
|
||||
}
|
75
vendor/github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere/post-processor.hcl2spec.go
generated
vendored
Normal file
75
vendor/github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere/post-processor.hcl2spec.go
generated
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
// Code generated by "mapstructure-to-hcl2 -type Config"; DO NOT EDIT.
|
||||
|
||||
package vsphere
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// FlatConfig is an auto-generated flat version of Config.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatConfig struct {
|
||||
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"`
|
||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
|
||||
PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"`
|
||||
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
|
||||
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
|
||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
|
||||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"`
|
||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"`
|
||||
Cluster *string `mapstructure:"cluster" cty:"cluster" hcl:"cluster"`
|
||||
Datacenter *string `mapstructure:"datacenter" cty:"datacenter" hcl:"datacenter"`
|
||||
Datastore *string `mapstructure:"datastore" cty:"datastore" hcl:"datastore"`
|
||||
DiskMode *string `mapstructure:"disk_mode" cty:"disk_mode" hcl:"disk_mode"`
|
||||
Host *string `mapstructure:"host" cty:"host" hcl:"host"`
|
||||
ESXiHost *string `mapstructure:"esxi_host" cty:"esxi_host" hcl:"esxi_host"`
|
||||
Insecure *bool `mapstructure:"insecure" cty:"insecure" hcl:"insecure"`
|
||||
Options []string `mapstructure:"options" cty:"options" hcl:"options"`
|
||||
Overwrite *bool `mapstructure:"overwrite" cty:"overwrite" hcl:"overwrite"`
|
||||
Password *string `mapstructure:"password" cty:"password" hcl:"password"`
|
||||
ResourcePool *string `mapstructure:"resource_pool" cty:"resource_pool" hcl:"resource_pool"`
|
||||
Username *string `mapstructure:"username" cty:"username" hcl:"username"`
|
||||
VMFolder *string `mapstructure:"vm_folder" cty:"vm_folder" hcl:"vm_folder"`
|
||||
VMName *string `mapstructure:"vm_name" cty:"vm_name" hcl:"vm_name"`
|
||||
VMNetwork *string `mapstructure:"vm_network" cty:"vm_network" hcl:"vm_network"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatConfig.
|
||||
// FlatConfig is an auto-generated flat version of Config.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatConfig)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a Config.
|
||||
// This spec is used by HCL to read the fields of Config.
|
||||
// The decoded values from this spec will then be applied to a FlatConfig.
|
||||
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
|
||||
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
|
||||
"packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false},
|
||||
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
|
||||
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
|
||||
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
|
||||
"packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||
"cluster": &hcldec.AttrSpec{Name: "cluster", Type: cty.String, Required: false},
|
||||
"datacenter": &hcldec.AttrSpec{Name: "datacenter", Type: cty.String, Required: false},
|
||||
"datastore": &hcldec.AttrSpec{Name: "datastore", Type: cty.String, Required: false},
|
||||
"disk_mode": &hcldec.AttrSpec{Name: "disk_mode", Type: cty.String, Required: false},
|
||||
"host": &hcldec.AttrSpec{Name: "host", Type: cty.String, Required: false},
|
||||
"esxi_host": &hcldec.AttrSpec{Name: "esxi_host", Type: cty.String, Required: false},
|
||||
"insecure": &hcldec.AttrSpec{Name: "insecure", Type: cty.Bool, Required: false},
|
||||
"options": &hcldec.AttrSpec{Name: "options", Type: cty.List(cty.String), Required: false},
|
||||
"overwrite": &hcldec.AttrSpec{Name: "overwrite", Type: cty.Bool, Required: false},
|
||||
"password": &hcldec.AttrSpec{Name: "password", Type: cty.String, Required: false},
|
||||
"resource_pool": &hcldec.AttrSpec{Name: "resource_pool", Type: cty.String, Required: false},
|
||||
"username": &hcldec.AttrSpec{Name: "username", Type: cty.String, Required: false},
|
||||
"vm_folder": &hcldec.AttrSpec{Name: "vm_folder", Type: cty.String, Required: false},
|
||||
"vm_name": &hcldec.AttrSpec{Name: "vm_name", Type: cty.String, Required: false},
|
||||
"vm_network": &hcldec.AttrSpec{Name: "vm_network", Type: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
|
@ -11,6 +11,7 @@ builds:
|
|||
- amd64
|
||||
- 386
|
||||
- arm64
|
||||
- mips64le
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
main: ./govc/main.go
|
||||
|
@ -27,6 +28,7 @@ builds:
|
|||
- amd64
|
||||
- 386
|
||||
- arm64
|
||||
- mips64le
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
main: ./vcsim/main.go
|
||||
|
|
|
@ -33,3 +33,6 @@ Uwe Bessle <Uwe.Bessle@iteratec.de> Uwe Bessle <uwe.bessle@web.de>
|
|||
Vadim Egorov <vegorov@vmware.com> <egorovv@gmail.com>
|
||||
Zach Tucker <ztucker@vmware.com> <jzt@users.noreply.github.com>
|
||||
Zee Yang <zeey@vmware.com> <zee.yang@gmail.com>
|
||||
Ian Eyberg <ian@deferpanic.com> <ian@opuler.com>
|
||||
Parveen Chahal <parkuma@microsoft.com> <mail.chahal@gmail.com>
|
||||
Yun Zhou <yunz@vmware.com> <41678287+gh05tn0va@users.noreply.github.com>
|
||||
|
|
|
@ -12,7 +12,7 @@ services: false
|
|||
|
||||
# Set the version of Go.
|
||||
language: go
|
||||
go: 1.14
|
||||
go: 1.15
|
||||
|
||||
# Always set the project's Go import path to ensure that forked
|
||||
# builds get cloned to the correct location.
|
||||
|
@ -44,23 +44,14 @@ jobs:
|
|||
install: true
|
||||
script: make install
|
||||
|
||||
- <<: *build-stage
|
||||
env: GOOS=linux GOARCH=386
|
||||
|
||||
- <<: *build-stage
|
||||
env: GOOS=darwin GOARCH=amd64
|
||||
- <<: *build-stage
|
||||
env: GOOS=darwin GOARCH=386
|
||||
|
||||
- <<: *build-stage
|
||||
env: GOOS=freebsd GOARCH=amd64
|
||||
- <<: *build-stage
|
||||
env: GOOS=freebsd GOARCH=386
|
||||
|
||||
- <<: *build-stage
|
||||
env: GOOS=windows GOARCH=amd64
|
||||
- <<: *build-stage
|
||||
env: GOOS=windows GOARCH=386
|
||||
|
||||
# The test stage executes the test target.
|
||||
- stage: test
|
||||
|
|
|
@ -1,5 +1,19 @@
|
|||
# changelog
|
||||
|
||||
### 0.24.0 (2020-12-20)
|
||||
|
||||
* Update generated API bindings to vSphere 7.0U1 release
|
||||
|
||||
* Add vSAN 7.0 API bindings
|
||||
|
||||
* Add AuthorizationManager.HasUserPrivilegeOnEntities wrapper
|
||||
|
||||
* Add sms generated types and methods
|
||||
|
||||
* Add ExtendDisk and InflateDisk wrappers to vlsm.ObjectManager
|
||||
|
||||
* Add vSAN Performance Data Collection API
|
||||
|
||||
### 0.23.0 (2020-06-11)
|
||||
|
||||
* Finder: support DistributedVirtualSwitch traversal
|
||||
|
|
|
@ -8,9 +8,9 @@ abrarshivani <abrarshivani@users.noreply.github.com>
|
|||
Adam Shannon <adamkshannon@gmail.com>
|
||||
Al Biheiri <abiheiri@apple.com>
|
||||
Alessandro Cortiana <alessandro.cortiana@gmail.com>
|
||||
Alex <puzo2002@gmail.com>
|
||||
Alex Bozhenko <alexbozhenko@fb.com>
|
||||
Alex Ellis (VMware) <alexellis2@gmail.com>
|
||||
Alex <puzo2002@gmail.com>
|
||||
Alvaro Miranda <kikitux@gmail.com>
|
||||
Amanda H. L. de Andrade <amanda.andrade@serpro.gov.br>
|
||||
Amit Bathla <abathla@.vmware.com>
|
||||
|
@ -31,27 +31,30 @@ Austin Parker <aparker@apprenda.com>
|
|||
Balu Dontu <bdontu@vmware.com>
|
||||
bastienbc <bastien.barbe.creuly@gmail.com>
|
||||
Ben Corrie <bcorrie@vmware.com>
|
||||
Ben Vickers <bvickers@pivotal.io>
|
||||
Benjamin Davini <davinib@vmware.com>
|
||||
Benjamin Peterson <benjamin@python.org>
|
||||
Bhavya Choudhary <bhavyac@vmware.com>
|
||||
Bob Killen <killen.bob@gmail.com>
|
||||
Brad Fitzpatrick <bradfitz@golang.org>
|
||||
brian57860 <brian57860@users.noreply.github.com>
|
||||
Bruce Downs <bruceadowns@gmail.com>
|
||||
Cédric Blomart <cblomart@gmail.com>
|
||||
Cheng Cheng <chengch@vmware.com>
|
||||
Chethan Venkatesh <chethanv@vmware.com>
|
||||
Chris Marchesi <chrism@vancluevertech.com>
|
||||
Christian Höltje <docwhat@gerf.org>
|
||||
Clint Greenwood <cgreenwood@vmware.com>
|
||||
CuiHaozhi <cuihaozhi@chinacloud.com.cn>
|
||||
Daniel Mueller <deso@posteo.net>
|
||||
Cédric Blomart <cblomart@gmail.com>
|
||||
Dan Ilan <danilan@google.com>
|
||||
Daniel Mueller <deso@posteo.net>
|
||||
Danny Lockard <danny.lockard@banno.com>
|
||||
Dave Gress <gressd@vmware.com>
|
||||
Dave Smith-Uchida <dsmithuchida@vmware.com>
|
||||
Dave Tucker <dave@dtucker.co.uk>
|
||||
Davide Agnello <dagnello@hp.com>
|
||||
David Gress <gressd@vmware.com>
|
||||
David Stark <dave@davidstark.name>
|
||||
Davide Agnello <dagnello@hp.com>
|
||||
Davinder Kumar <davinderk@vmware.com>
|
||||
demarey <christophe.demarey@inria.fr>
|
||||
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
|
||||
|
@ -82,6 +85,7 @@ Hasan Mahmood <mahmoodh@vmware.com>
|
|||
Henrik Hodne <henrik@travis-ci.com>
|
||||
hkumar <hkumar@vmware.com>
|
||||
hui luo <luoh@vmware.com>
|
||||
Ian Eyberg <ian@deferpanic.com>
|
||||
Isaac Rodman <isaac@eyz.us>
|
||||
Ivan Mikushin <imikushin@vmware.com>
|
||||
Ivan Porto Carrero <icarrero@vmware.com>
|
||||
|
@ -91,16 +95,18 @@ Jeremy Canady <jcanady@jackhenry.com>
|
|||
jeremy-clerc <jeremy@clerc.io>
|
||||
Jiatong Wang <wjiatong@vmware.com>
|
||||
jingyizPensando <jingyiz@pensando.io>
|
||||
João Pereira <joaodrp@gmail.com>
|
||||
Jonas Ausevicius <jonas.ausevicius@virtustream.com>
|
||||
Jorge Sevilla <jorge.sevilla@rstor.io>
|
||||
João Pereira <joaodrp@gmail.com>
|
||||
kayrus <kay.diam@gmail.com>
|
||||
Kevin George <georgek@vmware.com>
|
||||
Leslie Wang <qiwa@pensando.io>
|
||||
leslie-qiwa <leslie.qiwa@gmail.com>
|
||||
Lintong Jiang <lintongj@vmware.com>
|
||||
Liping Xue <lipingx@vmware.com>
|
||||
Louie Jiang <jiangl@vmware.com>
|
||||
Luther Monson <luther.monson@gmail.com>
|
||||
Madanagopal Arunachalam <marunachalam@vmware.com>
|
||||
maplain <fangyuanl@vmware.com>
|
||||
Marc Carmier <mcarmier@gmail.com>
|
||||
Marcus Tan <marcus.tan@rubrik.com>
|
||||
|
@ -109,15 +115,17 @@ Marin Atanasov Nikolov <mnikolov@vmware.com>
|
|||
Mario Trangoni <mjtrangoni@gmail.com>
|
||||
Mark Peek <markpeek@vmware.com>
|
||||
Matt Clay <matt@mystile.com>
|
||||
Matthew Cosgrove <matthew.cosgrove@dell.com>
|
||||
Matt Moore <mattmoor@vmware.com>
|
||||
Matt Moriarity <matt@mattmoriarity.com>
|
||||
Matthew Cosgrove <matthew.cosgrove@dell.com>
|
||||
Mevan Samaratunga <mevansam@gmail.com>
|
||||
Michael Gasch <mgasch@vmware.com>
|
||||
Michal Jankowski <mjankowski@vmware.com>
|
||||
mingwei <mingwei@smartx.com>
|
||||
Nicolas Lamirault <nicolas.lamirault@gmail.com>
|
||||
Omar Kohl <omarkohl@gmail.com>
|
||||
Parham Alvani <parham.alvani@gmail.com>
|
||||
Parveen Chahal <parkuma@microsoft.com>
|
||||
Pierre Gronlier <pierre.gronlier@corp.ovh.com>
|
||||
Pieter Noordhuis <pnoordhuis@vmware.com>
|
||||
prydin <prydin@vmware.com>
|
||||
|
@ -125,11 +133,12 @@ rHermes <teodor_spaeren@riseup.net>
|
|||
Rowan Jacobs <rojacobs@pivotal.io>
|
||||
rsikdar <rsikdar@berkeley.edu>
|
||||
runner.mei <runner.mei@gmail.com>
|
||||
Sandeep Pissay Srinivasa Rao <ssrinivas@vmware.com>
|
||||
S.Çağlar Onur <conur@vmware.com>
|
||||
Sandeep Pissay Srinivasa Rao <ssrinivas@vmware.com>
|
||||
Sergey Ignatov <sergey.ignatov@jetbrains.com>
|
||||
serokles <timbo.alexander@gmail.com>
|
||||
Shalini Bhaskara <sbhaskara@vmware.com>
|
||||
Shaozhen Ding <dsz0111@gmail.com>
|
||||
Shawn Neal <sneal@sneal.net>
|
||||
shylasrinivas <sshyla@vmware.com>
|
||||
sky-joker <sky.jokerxx@gmail.com>
|
||||
|
@ -157,12 +166,17 @@ Waldek Maleska <w.maleska@gmail.com>
|
|||
William Lam <info.virtuallyghetto@gmail.com>
|
||||
Witold Krecicki <wpk@culm.net>
|
||||
xing-yang <xingyang105@gmail.com>
|
||||
yangxi <yangxi@vmware.com>
|
||||
Yang Yang <yangy@vmware.com>
|
||||
yangxi <yangxi@vmware.com>
|
||||
Yann Hodique <yhodique@google.com>
|
||||
Yash Nitin Desai <desaiy@vmware.com>
|
||||
Yassine TIJANI <ytijani@vmware.com>
|
||||
yiyingy <yiyingy@vmware.com>
|
||||
ykakarap <yuva2811@gmail.com>
|
||||
Yogesh Sobale <6104071+ysobale@users.noreply.github.com>
|
||||
Yun Zhou <yunz@vmware.com>
|
||||
Yuya Kusakabe <yuya.kusakabe@gmail.com>
|
||||
Zacharias Taubert <zacharias.taubert@gmail.com>
|
||||
Zach Tucker <ztucker@vmware.com>
|
||||
Zacharias Taubert <zacharias.taubert@gmail.com>
|
||||
Zee Yang <zeey@vmware.com>
|
||||
zyuxin <zyuxin@vmware.com>
|
||||
|
|
|
@ -89,6 +89,8 @@ Refer to the [CHANGELOG](CHANGELOG.md) for version to version changes.
|
|||
|
||||
* [OPS](https://github.com/nanovms/ops)
|
||||
|
||||
* [VMware Event Broker Appliance](https://github.com/vmware-samples/vcenter-event-broker-appliance/tree/development/vmware-event-router)
|
||||
|
||||
## Related projects
|
||||
|
||||
* [rbvmomi](https://github.com/vmware/rbvmomi)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (c) 2014-2017 VMware, Inc. All Rights Reserved.
|
||||
Copyright (c) 2014-2020 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -22,6 +22,7 @@ import (
|
|||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/internal"
|
||||
"github.com/vmware/govmomi/list"
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/property"
|
||||
|
@ -67,6 +68,18 @@ func (f *Finder) SetDatacenter(dc *object.Datacenter) *Finder {
|
|||
return f
|
||||
}
|
||||
|
||||
// InventoryPath composes the given object's inventory path.
|
||||
// There is no vSphere property or method that provides an inventory path directly.
|
||||
// This method uses the ManagedEntity.Parent field to determine the ancestry tree of the object and
|
||||
// the ManagedEntity.Name field for each ancestor to compose the path.
|
||||
func InventoryPath(ctx context.Context, client *vim25.Client, obj types.ManagedObjectReference) (string, error) {
|
||||
entities, err := mo.Ancestors(ctx, client, client.ServiceContent.PropertyCollector, obj)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return internal.InventoryPath(entities), nil
|
||||
}
|
||||
|
||||
// findRoot makes it possible to use "find" mode with a different root path.
|
||||
// Example: ResourcePoolList("/dc1/host/cluster1/...")
|
||||
func (f *Finder) findRoot(ctx context.Context, root *list.Element, parts []string) bool {
|
||||
|
@ -103,8 +116,8 @@ func (f *Finder) find(ctx context.Context, arg string, s *spec) ([]list.Element,
|
|||
isPath := strings.Contains(arg, "/")
|
||||
|
||||
root := list.Element{
|
||||
Path: "/",
|
||||
Object: object.NewRootFolder(f.client),
|
||||
Path: "/",
|
||||
}
|
||||
|
||||
parts := list.ToParts(arg)
|
||||
|
@ -119,19 +132,10 @@ func (f *Finder) find(ctx context.Context, arg string, s *spec) ([]list.Element,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
mes, err := mo.Ancestors(ctx, f.client, f.client.ServiceContent.PropertyCollector, pivot.Reference())
|
||||
root.Path, err = InventoryPath(ctx, f.client, pivot.Reference())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, me := range mes {
|
||||
// Skip root entity in building inventory path.
|
||||
if me.Parent == nil {
|
||||
continue
|
||||
}
|
||||
root.Path = path.Join(root.Path, me.Name)
|
||||
}
|
||||
|
||||
root.Object = pivot
|
||||
parts = parts[1:]
|
||||
}
|
||||
|
@ -281,8 +285,7 @@ func (f *Finder) managedObjectList(ctx context.Context, path string, tl bool, in
|
|||
return f.find(ctx, path, s)
|
||||
}
|
||||
|
||||
// Element returns an Element for the given ManagedObjectReference
|
||||
// This method is only useful for looking up the InventoryPath of a ManagedObjectReference.
|
||||
// Element is deprecated, use InventoryPath() instead.
|
||||
func (f *Finder) Element(ctx context.Context, ref types.ManagedObjectReference) (*list.Element, error) {
|
||||
rl := func(_ context.Context) (object.Reference, error) {
|
||||
return ref, nil
|
||||
|
@ -311,7 +314,7 @@ func (f *Finder) Element(ctx context.Context, ref types.ManagedObjectReference)
|
|||
// ObjectReference converts the given ManagedObjectReference to a type from the object package via object.NewReference
|
||||
// with the object.Common.InventoryPath field set.
|
||||
func (f *Finder) ObjectReference(ctx context.Context, ref types.ManagedObjectReference) (object.Reference, error) {
|
||||
e, err := f.Element(ctx, ref)
|
||||
path, err := InventoryPath(ctx, f.client, ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -322,7 +325,7 @@ func (f *Finder) ObjectReference(ctx context.Context, ref types.ManagedObjectRef
|
|||
SetInventoryPath(string)
|
||||
}
|
||||
|
||||
r.(common).SetInventoryPath(e.Path)
|
||||
r.(common).SetInventoryPath(path)
|
||||
|
||||
if f.dc != nil {
|
||||
if ds, ok := r.(*object.Datastore); ok {
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
Copyright (c) 2020 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"path"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
)
|
||||
|
||||
// InventoryPath composed of entities by Name
|
||||
func InventoryPath(entities []mo.ManagedEntity) string {
|
||||
val := "/"
|
||||
|
||||
for _, entity := range entities {
|
||||
// Skip root folder in building inventory path.
|
||||
if entity.Parent == nil {
|
||||
continue
|
||||
}
|
||||
val = path.Join(val, entity.Name)
|
||||
}
|
||||
|
||||
return val
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
)
|
||||
|
||||
type RetrieveDynamicTypeManagerBody struct {
|
||||
Req *RetrieveDynamicTypeManagerRequest `xml:"urn:vim25 RetrieveDynamicTypeManager"`
|
||||
Res *RetrieveDynamicTypeManagerResponse `xml:"urn:vim25 RetrieveDynamicTypeManagerResponse"`
|
||||
Fault_ *soap.Fault
|
||||
}
|
||||
|
||||
func (b *RetrieveDynamicTypeManagerBody) Fault() *soap.Fault { return b.Fault_ }
|
||||
|
||||
func RetrieveDynamicTypeManager(ctx context.Context, r soap.RoundTripper, req *RetrieveDynamicTypeManagerRequest) (*RetrieveDynamicTypeManagerResponse, error) {
|
||||
var reqBody, resBody RetrieveDynamicTypeManagerBody
|
||||
|
||||
reqBody.Req = req
|
||||
|
||||
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resBody.Res, nil
|
||||
}
|
||||
|
||||
type RetrieveManagedMethodExecuterBody struct {
|
||||
Req *RetrieveManagedMethodExecuterRequest `xml:"urn:vim25 RetrieveManagedMethodExecuter"`
|
||||
Res *RetrieveManagedMethodExecuterResponse `xml:"urn:vim25 RetrieveManagedMethodExecuterResponse"`
|
||||
Fault_ *soap.Fault
|
||||
}
|
||||
|
||||
func (b *RetrieveManagedMethodExecuterBody) Fault() *soap.Fault { return b.Fault_ }
|
||||
|
||||
func RetrieveManagedMethodExecuter(ctx context.Context, r soap.RoundTripper, req *RetrieveManagedMethodExecuterRequest) (*RetrieveManagedMethodExecuterResponse, error) {
|
||||
var reqBody, resBody RetrieveManagedMethodExecuterBody
|
||||
|
||||
reqBody.Req = req
|
||||
|
||||
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resBody.Res, nil
|
||||
}
|
||||
|
||||
type DynamicTypeMgrQueryMoInstancesBody struct {
|
||||
Req *DynamicTypeMgrQueryMoInstancesRequest `xml:"urn:vim25 DynamicTypeMgrQueryMoInstances"`
|
||||
Res *DynamicTypeMgrQueryMoInstancesResponse `xml:"urn:vim25 DynamicTypeMgrQueryMoInstancesResponse"`
|
||||
Fault_ *soap.Fault
|
||||
}
|
||||
|
||||
func (b *DynamicTypeMgrQueryMoInstancesBody) Fault() *soap.Fault { return b.Fault_ }
|
||||
|
||||
func DynamicTypeMgrQueryMoInstances(ctx context.Context, r soap.RoundTripper, req *DynamicTypeMgrQueryMoInstancesRequest) (*DynamicTypeMgrQueryMoInstancesResponse, error) {
|
||||
var reqBody, resBody DynamicTypeMgrQueryMoInstancesBody
|
||||
|
||||
reqBody.Req = req
|
||||
|
||||
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resBody.Res, nil
|
||||
}
|
||||
|
||||
type DynamicTypeMgrQueryTypeInfoBody struct {
|
||||
Req *DynamicTypeMgrQueryTypeInfoRequest `xml:"urn:vim25 DynamicTypeMgrQueryTypeInfo"`
|
||||
Res *DynamicTypeMgrQueryTypeInfoResponse `xml:"urn:vim25 DynamicTypeMgrQueryTypeInfoResponse"`
|
||||
Fault_ *soap.Fault
|
||||
}
|
||||
|
||||
func (b *DynamicTypeMgrQueryTypeInfoBody) Fault() *soap.Fault { return b.Fault_ }
|
||||
|
||||
func DynamicTypeMgrQueryTypeInfo(ctx context.Context, r soap.RoundTripper, req *DynamicTypeMgrQueryTypeInfoRequest) (*DynamicTypeMgrQueryTypeInfoResponse, error) {
|
||||
var reqBody, resBody DynamicTypeMgrQueryTypeInfoBody
|
||||
|
||||
reqBody.Req = req
|
||||
|
||||
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resBody.Res, nil
|
||||
}
|
||||
|
||||
type ExecuteSoapBody struct {
|
||||
Req *ExecuteSoapRequest `xml:"urn:vim25 ExecuteSoap"`
|
||||
Res *ExecuteSoapResponse `xml:"urn:vim25 ExecuteSoapResponse"`
|
||||
Fault_ *soap.Fault
|
||||
}
|
||||
|
||||
func (b *ExecuteSoapBody) Fault() *soap.Fault { return b.Fault_ }
|
||||
|
||||
func ExecuteSoap(ctx context.Context, r soap.RoundTripper, req *ExecuteSoapRequest) (*ExecuteSoapResponse, error) {
|
||||
var reqBody, resBody ExecuteSoapBody
|
||||
|
||||
reqBody.Req = req
|
||||
|
||||
if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resBody.Res, nil
|
||||
}
|
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
Copyright (c) 2014 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type DynamicTypeMgrQueryMoInstancesRequest struct {
|
||||
This types.ManagedObjectReference `xml:"_this"`
|
||||
FilterSpec BaseDynamicTypeMgrFilterSpec `xml:"filterSpec,omitempty,typeattr"`
|
||||
}
|
||||
|
||||
type DynamicTypeMgrQueryMoInstancesResponse struct {
|
||||
Returnval []DynamicTypeMgrMoInstance `xml:"urn:vim25 returnval"`
|
||||
}
|
||||
|
||||
type DynamicTypeEnumTypeInfo struct {
|
||||
types.DynamicData
|
||||
|
||||
Name string `xml:"name"`
|
||||
WsdlName string `xml:"wsdlName"`
|
||||
Version string `xml:"version"`
|
||||
Value []string `xml:"value,omitempty"`
|
||||
Annotation []DynamicTypeMgrAnnotation `xml:"annotation,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("DynamicTypeEnumTypeInfo", reflect.TypeOf((*DynamicTypeEnumTypeInfo)(nil)).Elem())
|
||||
}
|
||||
|
||||
type DynamicTypeMgrAllTypeInfoRequest struct {
|
||||
types.DynamicData
|
||||
|
||||
ManagedTypeInfo []DynamicTypeMgrManagedTypeInfo `xml:"managedTypeInfo,omitempty"`
|
||||
EnumTypeInfo []DynamicTypeEnumTypeInfo `xml:"enumTypeInfo,omitempty"`
|
||||
DataTypeInfo []DynamicTypeMgrDataTypeInfo `xml:"dataTypeInfo,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("DynamicTypeMgrAllTypeInfo", reflect.TypeOf((*DynamicTypeMgrAllTypeInfoRequest)(nil)).Elem())
|
||||
}
|
||||
|
||||
type DynamicTypeMgrAnnotation struct {
|
||||
types.DynamicData
|
||||
|
||||
Name string `xml:"name"`
|
||||
Parameter []string `xml:"parameter,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("DynamicTypeMgrAnnotation", reflect.TypeOf((*DynamicTypeMgrAnnotation)(nil)).Elem())
|
||||
}
|
||||
|
||||
type DynamicTypeMgrDataTypeInfo struct {
|
||||
types.DynamicData
|
||||
|
||||
Name string `xml:"name"`
|
||||
WsdlName string `xml:"wsdlName"`
|
||||
Version string `xml:"version"`
|
||||
Base []string `xml:"base,omitempty"`
|
||||
Property []DynamicTypeMgrPropertyTypeInfo `xml:"property,omitempty"`
|
||||
Annotation []DynamicTypeMgrAnnotation `xml:"annotation,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("DynamicTypeMgrDataTypeInfo", reflect.TypeOf((*DynamicTypeMgrDataTypeInfo)(nil)).Elem())
|
||||
}
|
||||
|
||||
func (b *DynamicTypeMgrFilterSpec) GetDynamicTypeMgrFilterSpec() *DynamicTypeMgrFilterSpec { return b }
|
||||
|
||||
type BaseDynamicTypeMgrFilterSpec interface {
|
||||
GetDynamicTypeMgrFilterSpec() *DynamicTypeMgrFilterSpec
|
||||
}
|
||||
|
||||
type DynamicTypeMgrFilterSpec struct {
|
||||
types.DynamicData
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("DynamicTypeMgrFilterSpec", reflect.TypeOf((*DynamicTypeMgrFilterSpec)(nil)).Elem())
|
||||
}
|
||||
|
||||
type DynamicTypeMgrManagedTypeInfo struct {
|
||||
types.DynamicData
|
||||
|
||||
Name string `xml:"name"`
|
||||
WsdlName string `xml:"wsdlName"`
|
||||
Version string `xml:"version"`
|
||||
Base []string `xml:"base,omitempty"`
|
||||
Property []DynamicTypeMgrPropertyTypeInfo `xml:"property,omitempty"`
|
||||
Method []DynamicTypeMgrMethodTypeInfo `xml:"method,omitempty"`
|
||||
Annotation []DynamicTypeMgrAnnotation `xml:"annotation,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("DynamicTypeMgrManagedTypeInfo", reflect.TypeOf((*DynamicTypeMgrManagedTypeInfo)(nil)).Elem())
|
||||
}
|
||||
|
||||
type DynamicTypeMgrMethodTypeInfo struct {
|
||||
types.DynamicData
|
||||
|
||||
Name string `xml:"name"`
|
||||
WsdlName string `xml:"wsdlName"`
|
||||
Version string `xml:"version"`
|
||||
ParamTypeInfo []DynamicTypeMgrParamTypeInfo `xml:"paramTypeInfo,omitempty"`
|
||||
ReturnTypeInfo *DynamicTypeMgrParamTypeInfo `xml:"returnTypeInfo,omitempty"`
|
||||
Fault []string `xml:"fault,omitempty"`
|
||||
PrivId string `xml:"privId,omitempty"`
|
||||
Annotation []DynamicTypeMgrAnnotation `xml:"annotation,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("DynamicTypeMgrMethodTypeInfo", reflect.TypeOf((*DynamicTypeMgrMethodTypeInfo)(nil)).Elem())
|
||||
}
|
||||
|
||||
type DynamicTypeMgrMoFilterSpec struct {
|
||||
DynamicTypeMgrFilterSpec
|
||||
|
||||
Id string `xml:"id,omitempty"`
|
||||
TypeSubstr string `xml:"typeSubstr,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("DynamicTypeMgrMoFilterSpec", reflect.TypeOf((*DynamicTypeMgrMoFilterSpec)(nil)).Elem())
|
||||
}
|
||||
|
||||
type DynamicTypeMgrMoInstance struct {
|
||||
types.DynamicData
|
||||
|
||||
Id string `xml:"id"`
|
||||
MoType string `xml:"moType"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("DynamicTypeMgrMoInstance", reflect.TypeOf((*DynamicTypeMgrMoInstance)(nil)).Elem())
|
||||
}
|
||||
|
||||
type DynamicTypeMgrParamTypeInfo struct {
|
||||
types.DynamicData
|
||||
|
||||
Name string `xml:"name"`
|
||||
Version string `xml:"version"`
|
||||
Type string `xml:"type"`
|
||||
PrivId string `xml:"privId,omitempty"`
|
||||
Annotation []DynamicTypeMgrAnnotation `xml:"annotation,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("DynamicTypeMgrParamTypeInfo", reflect.TypeOf((*DynamicTypeMgrParamTypeInfo)(nil)).Elem())
|
||||
}
|
||||
|
||||
type DynamicTypeMgrPropertyTypeInfo struct {
|
||||
types.DynamicData
|
||||
|
||||
Name string `xml:"name"`
|
||||
Version string `xml:"version"`
|
||||
Type string `xml:"type"`
|
||||
PrivId string `xml:"privId,omitempty"`
|
||||
MsgIdFormat string `xml:"msgIdFormat,omitempty"`
|
||||
Annotation []DynamicTypeMgrAnnotation `xml:"annotation,omitempty"`
|
||||
}
|
||||
|
||||
type DynamicTypeMgrQueryTypeInfoRequest struct {
|
||||
This types.ManagedObjectReference `xml:"_this"`
|
||||
FilterSpec BaseDynamicTypeMgrFilterSpec `xml:"filterSpec,omitempty,typeattr"`
|
||||
}
|
||||
|
||||
type DynamicTypeMgrQueryTypeInfoResponse struct {
|
||||
Returnval DynamicTypeMgrAllTypeInfoRequest `xml:"urn:vim25 returnval"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("DynamicTypeMgrPropertyTypeInfo", reflect.TypeOf((*DynamicTypeMgrPropertyTypeInfo)(nil)).Elem())
|
||||
}
|
||||
|
||||
type DynamicTypeMgrTypeFilterSpec struct {
|
||||
DynamicTypeMgrFilterSpec
|
||||
|
||||
TypeSubstr string `xml:"typeSubstr,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("DynamicTypeMgrTypeFilterSpec", reflect.TypeOf((*DynamicTypeMgrTypeFilterSpec)(nil)).Elem())
|
||||
}
|
||||
|
||||
type ReflectManagedMethodExecuterSoapArgument struct {
|
||||
types.DynamicData
|
||||
|
||||
Name string `xml:"name"`
|
||||
Val string `xml:"val"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("ReflectManagedMethodExecuterSoapArgument", reflect.TypeOf((*ReflectManagedMethodExecuterSoapArgument)(nil)).Elem())
|
||||
}
|
||||
|
||||
type ReflectManagedMethodExecuterSoapFault struct {
|
||||
types.DynamicData
|
||||
|
||||
FaultMsg string `xml:"faultMsg"`
|
||||
FaultDetail string `xml:"faultDetail,omitempty"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("ReflectManagedMethodExecuterSoapFault", reflect.TypeOf((*ReflectManagedMethodExecuterSoapFault)(nil)).Elem())
|
||||
}
|
||||
|
||||
type ReflectManagedMethodExecuterSoapResult struct {
|
||||
types.DynamicData
|
||||
|
||||
Response string `xml:"response,omitempty"`
|
||||
Fault *ReflectManagedMethodExecuterSoapFault `xml:"fault,omitempty"`
|
||||
}
|
||||
|
||||
type RetrieveDynamicTypeManagerRequest struct {
|
||||
This types.ManagedObjectReference `xml:"_this"`
|
||||
}
|
||||
|
||||
type RetrieveDynamicTypeManagerResponse struct {
|
||||
Returnval *InternalDynamicTypeManager `xml:"urn:vim25 returnval"`
|
||||
}
|
||||
|
||||
type RetrieveManagedMethodExecuterRequest struct {
|
||||
This types.ManagedObjectReference `xml:"_this"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
types.Add("RetrieveManagedMethodExecuter", reflect.TypeOf((*RetrieveManagedMethodExecuterRequest)(nil)).Elem())
|
||||
}
|
||||
|
||||
type RetrieveManagedMethodExecuterResponse struct {
|
||||
Returnval *ReflectManagedMethodExecuter `xml:"urn:vim25 returnval"`
|
||||
}
|
||||
|
||||
type InternalDynamicTypeManager struct {
|
||||
types.ManagedObjectReference
|
||||
}
|
||||
|
||||
type ReflectManagedMethodExecuter struct {
|
||||
types.ManagedObjectReference
|
||||
}
|
||||
|
||||
type ExecuteSoapRequest struct {
|
||||
This types.ManagedObjectReference `xml:"_this"`
|
||||
Moid string `xml:"moid"`
|
||||
Version string `xml:"version"`
|
||||
Method string `xml:"method"`
|
||||
Argument []ReflectManagedMethodExecuterSoapArgument `xml:"argument,omitempty"`
|
||||
}
|
||||
|
||||
type ExecuteSoapResponse struct {
|
||||
Returnval *ReflectManagedMethodExecuterSoapResult `xml:"urn:vim25 returnval"`
|
||||
}
|
|
@ -172,3 +172,50 @@ func (m AuthorizationManager) UpdateRole(ctx context.Context, id int32, name str
|
|||
_, err := methods.UpdateAuthorizationRole(ctx, m.Client(), &req)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m AuthorizationManager) HasUserPrivilegeOnEntities(ctx context.Context, entities []types.ManagedObjectReference, userName string, privID []string) ([]types.EntityPrivilege, error) {
|
||||
req := types.HasUserPrivilegeOnEntities{
|
||||
This: m.Reference(),
|
||||
Entities: entities,
|
||||
UserName: userName,
|
||||
PrivId: privID,
|
||||
}
|
||||
|
||||
res, err := methods.HasUserPrivilegeOnEntities(ctx, m.Client(), &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res.Returnval, nil
|
||||
}
|
||||
|
||||
func (m AuthorizationManager) HasPrivilegeOnEntity(ctx context.Context, entity types.ManagedObjectReference, sessionID string, privID []string) ([]bool, error) {
|
||||
req := types.HasPrivilegeOnEntity{
|
||||
This: m.Reference(),
|
||||
Entity: entity,
|
||||
SessionId: sessionID,
|
||||
PrivId: privID,
|
||||
}
|
||||
|
||||
res, err := methods.HasPrivilegeOnEntity(ctx, m.Client(), &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res.Returnval, nil
|
||||
}
|
||||
|
||||
func (m AuthorizationManager) FetchUserPrivilegeOnEntities(ctx context.Context, entities []types.ManagedObjectReference, userName string) ([]types.UserPrivilegeResult, error) {
|
||||
req := types.FetchUserPrivilegeOnEntities{
|
||||
This: m.Reference(),
|
||||
Entities: entities,
|
||||
UserName: userName,
|
||||
}
|
||||
|
||||
res, err := methods.FetchUserPrivilegeOnEntities(ctx, m.Client(), &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res.Returnval, nil
|
||||
}
|
||||
|
|
|
@ -103,3 +103,19 @@ func (p VirtualApp) Suspend(ctx context.Context) (*Task, error) {
|
|||
|
||||
return NewTask(p.c, res.Returnval), nil
|
||||
}
|
||||
|
||||
func (p VirtualApp) Clone(ctx context.Context, name string, target types.ManagedObjectReference, spec types.VAppCloneSpec) (*Task, error) {
|
||||
req := types.CloneVApp_Task{
|
||||
This: p.Reference(),
|
||||
Name: name,
|
||||
Target: target,
|
||||
Spec: spec,
|
||||
}
|
||||
|
||||
res, err := methods.CloneVApp_Task(ctx, p.c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewTask(p.c, res.Returnval), nil
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package object
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
|
@ -67,7 +68,7 @@ func EthernetCardTypes() VirtualDeviceList {
|
|||
&types.VirtualSriovEthernetCard{},
|
||||
}).Select(func(device types.BaseVirtualDevice) bool {
|
||||
c := device.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard()
|
||||
c.GetVirtualDevice().Key = -1
|
||||
c.GetVirtualDevice().Key = int32(rand.Uint32()) * -1
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
@ -134,6 +135,9 @@ func (l VirtualDeviceList) SelectByBackingInfo(backing types.BaseVirtualDeviceBa
|
|||
b := backing.(*types.VirtualEthernetCardDistributedVirtualPortBackingInfo)
|
||||
return a.Port.SwitchUuid == b.Port.SwitchUuid &&
|
||||
a.Port.PortgroupKey == b.Port.PortgroupKey
|
||||
case *types.VirtualEthernetCardOpaqueNetworkBackingInfo:
|
||||
b := backing.(*types.VirtualEthernetCardOpaqueNetworkBackingInfo)
|
||||
return a.OpaqueNetworkId == b.OpaqueNetworkId
|
||||
case *types.VirtualDiskFlatVer2BackingInfo:
|
||||
b := backing.(*types.VirtualDiskFlatVer2BackingInfo)
|
||||
if a.Parent != nil && b.Parent != nil {
|
||||
|
@ -433,7 +437,7 @@ func (l VirtualDeviceList) AssignController(device types.BaseVirtualDevice, c ty
|
|||
d.UnitNumber = new(int32)
|
||||
*d.UnitNumber = l.newUnitNumber(c)
|
||||
if d.Key == 0 {
|
||||
d.Key = -1
|
||||
d.Key = int32(rand.Uint32()) * -1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (c) 2015-2017 VMware, Inc. All Rights Reserved.
|
||||
Copyright (c) 2015-2021 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -40,6 +40,34 @@ type VirtualMachine struct {
|
|||
Common
|
||||
}
|
||||
|
||||
// extractDiskLayoutFiles is a helper function used to extract file keys for
|
||||
// all disk files attached to the virtual machine at the current point of
|
||||
// running.
|
||||
func extractDiskLayoutFiles(diskLayoutList []types.VirtualMachineFileLayoutExDiskLayout) []int {
|
||||
var result []int
|
||||
|
||||
for _, layoutExDisk := range diskLayoutList {
|
||||
for _, link := range layoutExDisk.Chain {
|
||||
for i := range link.FileKey { // diskDescriptor, diskExtent pairs
|
||||
result = append(result, int(link.FileKey[i]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// removeKey is a helper function for removing a specific file key from a list
|
||||
// of keys associated with disks attached to a virtual machine.
|
||||
func removeKey(l *[]int, key int) {
|
||||
for i, k := range *l {
|
||||
if k == key {
|
||||
*l = append((*l)[:i], (*l)[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewVirtualMachine(c *vim25.Client, ref types.ManagedObjectReference) *VirtualMachine {
|
||||
return &VirtualMachine{
|
||||
Common: NewCommon(c, ref),
|
||||
|
@ -181,6 +209,20 @@ func (v VirtualMachine) Clone(ctx context.Context, folder *Folder, name string,
|
|||
return NewTask(v.c, res.Returnval), nil
|
||||
}
|
||||
|
||||
func (v VirtualMachine) InstantClone(ctx context.Context, config types.VirtualMachineInstantCloneSpec) (*Task, error) {
|
||||
req := types.InstantClone_Task{
|
||||
This: v.Reference(),
|
||||
Spec: config,
|
||||
}
|
||||
|
||||
res, err := methods.InstantClone_Task(ctx, v.c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewTask(v.c, res.Returnval), nil
|
||||
}
|
||||
|
||||
func (v VirtualMachine) Customize(ctx context.Context, spec types.CustomizationSpec) (*Task, error) {
|
||||
req := types.CustomizeVM_Task{
|
||||
This: v.Reference(),
|
||||
|
@ -469,6 +511,41 @@ func (v VirtualMachine) RemoveDevice(ctx context.Context, keepFiles bool, device
|
|||
return v.configureDevice(ctx, types.VirtualDeviceConfigSpecOperationRemove, fop, device...)
|
||||
}
|
||||
|
||||
// AttachDisk attaches the given disk to the VirtualMachine
|
||||
func (v VirtualMachine) AttachDisk(ctx context.Context, id string, datastore *Datastore, controllerKey int32, unitNumber int32) error {
|
||||
req := types.AttachDisk_Task{
|
||||
This: v.Reference(),
|
||||
DiskId: types.ID{Id: id},
|
||||
Datastore: datastore.Reference(),
|
||||
ControllerKey: controllerKey,
|
||||
UnitNumber: &unitNumber,
|
||||
}
|
||||
|
||||
res, err := methods.AttachDisk_Task(ctx, v.c, &req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
task := NewTask(v.c, res.Returnval)
|
||||
return task.Wait(ctx)
|
||||
}
|
||||
|
||||
// DetachDisk detaches the given disk from the VirtualMachine
|
||||
func (v VirtualMachine) DetachDisk(ctx context.Context, id string) error {
|
||||
req := types.DetachDisk_Task{
|
||||
This: v.Reference(),
|
||||
DiskId: types.ID{Id: id},
|
||||
}
|
||||
|
||||
res, err := methods.DetachDisk_Task(ctx, v.c, &req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
task := NewTask(v.c, res.Returnval)
|
||||
return task.Wait(ctx)
|
||||
}
|
||||
|
||||
// BootOptions returns the VirtualMachine's config.bootOptions property.
|
||||
func (v VirtualMachine) BootOptions(ctx context.Context) (*types.VirtualMachineBootOptions, error) {
|
||||
var o mo.VirtualMachine
|
||||
|
@ -579,6 +656,63 @@ func (m snapshotMap) add(parent string, tree []types.VirtualMachineSnapshotTree)
|
|||
}
|
||||
}
|
||||
|
||||
// SnapshotSize calculates the size of a given snapshot in bytes. If the
|
||||
// snapshot is current, disk files not associated with any parent snapshot are
|
||||
// included in size calculations. This allows for measuring and including the
|
||||
// growth from the last fixed snapshot to the present state.
|
||||
func SnapshotSize(info types.ManagedObjectReference, parent *types.ManagedObjectReference, vmlayout *types.VirtualMachineFileLayoutEx, isCurrent bool) int {
|
||||
var fileKeyList []int
|
||||
var parentFiles []int
|
||||
var allSnapshotFiles []int
|
||||
|
||||
diskFiles := extractDiskLayoutFiles(vmlayout.Disk)
|
||||
|
||||
for _, layout := range vmlayout.Snapshot {
|
||||
diskLayout := extractDiskLayoutFiles(layout.Disk)
|
||||
allSnapshotFiles = append(allSnapshotFiles, diskLayout...)
|
||||
|
||||
if layout.Key.Value == info.Value {
|
||||
fileKeyList = append(fileKeyList, int(layout.DataKey)) // The .vmsn file
|
||||
fileKeyList = append(fileKeyList, diskLayout...) // The .vmdk files
|
||||
} else if parent != nil && layout.Key.Value == parent.Value {
|
||||
parentFiles = append(parentFiles, diskLayout...)
|
||||
}
|
||||
}
|
||||
|
||||
for _, parentFile := range parentFiles {
|
||||
removeKey(&fileKeyList, parentFile)
|
||||
}
|
||||
|
||||
for _, file := range allSnapshotFiles {
|
||||
removeKey(&diskFiles, file)
|
||||
}
|
||||
|
||||
fileKeyMap := make(map[int]types.VirtualMachineFileLayoutExFileInfo)
|
||||
for _, file := range vmlayout.File {
|
||||
fileKeyMap[int(file.Key)] = file
|
||||
}
|
||||
|
||||
size := 0
|
||||
|
||||
for _, fileKey := range fileKeyList {
|
||||
file := fileKeyMap[fileKey]
|
||||
if parent != nil ||
|
||||
(file.Type != string(types.VirtualMachineFileLayoutExFileTypeDiskDescriptor) &&
|
||||
file.Type != string(types.VirtualMachineFileLayoutExFileTypeDiskExtent)) {
|
||||
size += int(file.Size)
|
||||
}
|
||||
}
|
||||
|
||||
if isCurrent {
|
||||
for _, diskFile := range diskFiles {
|
||||
file := fileKeyMap[diskFile]
|
||||
size += int(file.Size)
|
||||
}
|
||||
}
|
||||
|
||||
return size
|
||||
}
|
||||
|
||||
// FindSnapshot supports snapshot lookup by name, where name can be:
|
||||
// 1) snapshot ManagedObjectReference.Value (unique)
|
||||
// 2) snapshot name (may not be unique)
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package ovf
|
||||
|
||||
import (
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
/*
|
||||
Source: http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2.24.0/CIM_VirtualSystemSettingData.xsd
|
||||
*/
|
||||
|
||||
type CIMVirtualSystemSettingData struct {
|
||||
ElementName string `xml:"ElementName"`
|
||||
InstanceID string `xml:"InstanceID"`
|
||||
|
||||
AutomaticRecoveryAction *uint8 `xml:"AutomaticRecoveryAction"`
|
||||
AutomaticShutdownAction *uint8 `xml:"AutomaticShutdownAction"`
|
||||
AutomaticStartupAction *uint8 `xml:"AutomaticStartupAction"`
|
||||
AutomaticStartupActionDelay *string `xml:"AutomaticStartupActionDelay>Interval"`
|
||||
AutomaticStartupActionSequenceNumber *uint16 `xml:"AutomaticStartupActionSequenceNumber"`
|
||||
Caption *string `xml:"Caption"`
|
||||
ConfigurationDataRoot *string `xml:"ConfigurationDataRoot"`
|
||||
ConfigurationFile *string `xml:"ConfigurationFile"`
|
||||
ConfigurationID *string `xml:"ConfigurationID"`
|
||||
CreationTime *string `xml:"CreationTime"`
|
||||
Description *string `xml:"Description"`
|
||||
LogDataRoot *string `xml:"LogDataRoot"`
|
||||
Notes []string `xml:"Notes"`
|
||||
RecoveryFile *string `xml:"RecoveryFile"`
|
||||
SnapshotDataRoot *string `xml:"SnapshotDataRoot"`
|
||||
SuspendDataRoot *string `xml:"SuspendDataRoot"`
|
||||
SwapFileDataRoot *string `xml:"SwapFileDataRoot"`
|
||||
VirtualSystemIdentifier *string `xml:"VirtualSystemIdentifier"`
|
||||
VirtualSystemType *string `xml:"VirtualSystemType"`
|
||||
}
|
||||
|
||||
/*
|
||||
Source: http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2.24.0/CIM_ResourceAllocationSettingData.xsd
|
||||
*/
|
||||
|
||||
type CIMResourceAllocationSettingData struct {
|
||||
ElementName string `xml:"ElementName"`
|
||||
InstanceID string `xml:"InstanceID"`
|
||||
|
||||
ResourceType *uint16 `xml:"ResourceType"`
|
||||
OtherResourceType *string `xml:"OtherResourceType"`
|
||||
ResourceSubType *string `xml:"ResourceSubType"`
|
||||
|
||||
AddressOnParent *string `xml:"AddressOnParent"`
|
||||
Address *string `xml:"Address"`
|
||||
AllocationUnits *string `xml:"AllocationUnits"`
|
||||
AutomaticAllocation *bool `xml:"AutomaticAllocation"`
|
||||
AutomaticDeallocation *bool `xml:"AutomaticDeallocation"`
|
||||
Caption *string `xml:"Caption"`
|
||||
Connection []string `xml:"Connection"`
|
||||
ConsumerVisibility *uint16 `xml:"ConsumerVisibility"`
|
||||
Description *string `xml:"Description"`
|
||||
HostResource []string `xml:"HostResource"`
|
||||
Limit *uint64 `xml:"Limit"`
|
||||
MappingBehavior *uint `xml:"MappingBehavior"`
|
||||
Parent *string `xml:"Parent"`
|
||||
PoolID *string `xml:"PoolID"`
|
||||
Reservation *uint64 `xml:"Reservation"`
|
||||
VirtualQuantity *uint `xml:"VirtualQuantity"`
|
||||
VirtualQuantityUnits *string `xml:"VirtualQuantityUnits"`
|
||||
Weight *uint `xml:"Weight"`
|
||||
}
|
||||
|
||||
/*
|
||||
Source: http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2.24.0/CIM_StorageAllocationSettingData.xsd
|
||||
*/
|
||||
type CIMStorageAllocationSettingData struct {
|
||||
ElementName string `xml:"ElementName"`
|
||||
InstanceID string `xml:"InstanceID"`
|
||||
|
||||
ResourceType *uint16 `xml:"ResourceType"`
|
||||
OtherResourceType *string `xml:"OtherResourceType"`
|
||||
ResourceSubType *string `xml:"ResourceSubType"`
|
||||
|
||||
Access *uint16 `xml:"Access"`
|
||||
Address *string `xml:"Address"`
|
||||
AddressOnParent *string `xml:"AddressOnParent"`
|
||||
AllocationUnits *string `xml:"AllocationUnits"`
|
||||
AutomaticAllocation *bool `xml:"AutomaticAllocation"`
|
||||
AutomaticDeallocation *bool `xml:"AutomaticDeallocation"`
|
||||
Caption *string `xml:"Caption"`
|
||||
ChangeableType *uint16 `xml:"ChangeableType"`
|
||||
ComponentSetting []types.AnyType `xml:"ComponentSetting"`
|
||||
ConfigurationName *string `xml:"ConfigurationName"`
|
||||
Connection []string `xml:"Connection"`
|
||||
ConsumerVisibility *uint16 `xml:"ConsumerVisibility"`
|
||||
Description *string `xml:"Description"`
|
||||
Generation *uint64 `xml:"Generation"`
|
||||
HostExtentName *string `xml:"HostExtentName"`
|
||||
HostExtentNameFormat *uint16 `xml:"HostExtentNameFormat"`
|
||||
HostExtentNameNamespace *uint16 `xml:"HostExtentNameNamespace"`
|
||||
HostExtentStartingAddress *uint64 `xml:"HostExtentStartingAddress"`
|
||||
HostResource []string `xml:"HostResource"`
|
||||
HostResourceBlockSize *uint64 `xml:"HostResourceBlockSize"`
|
||||
Limit *uint64 `xml:"Limit"`
|
||||
MappingBehavior *uint `xml:"MappingBehavior"`
|
||||
OtherHostExtentNameFormat *string `xml:"OtherHostExtentNameFormat"`
|
||||
OtherHostExtentNameNamespace *string `xml:"OtherHostExtentNameNamespace"`
|
||||
Parent *string `xml:"Parent"`
|
||||
PoolID *string `xml:"PoolID"`
|
||||
Reservation *uint64 `xml:"Reservation"`
|
||||
SoID *string `xml:"SoID"`
|
||||
SoOrgID *string `xml:"SoOrgID"`
|
||||
VirtualQuantity *uint `xml:"VirtualQuantity"`
|
||||
VirtualQuantityUnits *string `xml:"VirtualQuantityUnits"`
|
||||
VirtualResourceBlockSize *uint64 `xml:"VirtualResourceBlockSize"`
|
||||
Weight *uint `xml:"Weight"`
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Package ovf provides functionality to unmarshal and inspect the structure
|
||||
of an OVF file. It is not a complete implementation of the specification and
|
||||
is intended to be used to import virtual infrastructure into vSphere.
|
||||
|
||||
For a complete specification of the OVF standard, refer to:
|
||||
https://www.dmtf.org/sites/default/files/standards/documents/DSP0243_2.1.0.pdf
|
||||
*/
|
||||
package ovf
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package ovf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/xml"
|
||||
)
|
||||
|
||||
const (
|
||||
ovfEnvHeader = `<Environment
|
||||
xmlns="http://schemas.dmtf.org/ovf/environment/1"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:oe="http://schemas.dmtf.org/ovf/environment/1"
|
||||
xmlns:ve="http://www.vmware.com/schema/ovfenv"
|
||||
oe:id=""
|
||||
ve:esxId="%s">`
|
||||
ovfEnvPlatformSection = `<PlatformSection>
|
||||
<Kind>%s</Kind>
|
||||
<Version>%s</Version>
|
||||
<Vendor>%s</Vendor>
|
||||
<Locale>%s</Locale>
|
||||
</PlatformSection>`
|
||||
ovfEnvPropertyHeader = `<PropertySection>`
|
||||
ovfEnvPropertyEntry = `<Property oe:key="%s" oe:value="%s"/>`
|
||||
ovfEnvPropertyFooter = `</PropertySection>`
|
||||
ovfEnvFooter = `</Environment>`
|
||||
)
|
||||
|
||||
type Env struct {
|
||||
XMLName xml.Name `xml:"http://schemas.dmtf.org/ovf/environment/1 Environment"`
|
||||
ID string `xml:"id,attr"`
|
||||
EsxID string `xml:"http://www.vmware.com/schema/ovfenv esxId,attr"`
|
||||
|
||||
Platform *PlatformSection `xml:"PlatformSection"`
|
||||
Property *PropertySection `xml:"PropertySection"`
|
||||
}
|
||||
|
||||
type PlatformSection struct {
|
||||
Kind string `xml:"Kind"`
|
||||
Version string `xml:"Version"`
|
||||
Vendor string `xml:"Vendor"`
|
||||
Locale string `xml:"Locale"`
|
||||
}
|
||||
|
||||
type PropertySection struct {
|
||||
Properties []EnvProperty `xml:"Property"`
|
||||
}
|
||||
|
||||
type EnvProperty struct {
|
||||
Key string `xml:"key,attr"`
|
||||
Value string `xml:"value,attr"`
|
||||
}
|
||||
|
||||
// Marshal marshals Env to xml by using xml.Marshal.
|
||||
func (e Env) Marshal() (string, error) {
|
||||
x, err := xml.Marshal(e)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s%s", xml.Header, x), nil
|
||||
}
|
||||
|
||||
// MarshalManual manually marshals Env to xml suitable for a vApp guest.
|
||||
// It exists to overcome the lack of expressiveness in Go's XML namespaces.
|
||||
func (e Env) MarshalManual() string {
|
||||
var buffer bytes.Buffer
|
||||
|
||||
buffer.WriteString(xml.Header)
|
||||
buffer.WriteString(fmt.Sprintf(ovfEnvHeader, e.EsxID))
|
||||
buffer.WriteString(fmt.Sprintf(ovfEnvPlatformSection, e.Platform.Kind, e.Platform.Version, e.Platform.Vendor, e.Platform.Locale))
|
||||
|
||||
buffer.WriteString(fmt.Sprint(ovfEnvPropertyHeader))
|
||||
for _, p := range e.Property.Properties {
|
||||
buffer.WriteString(fmt.Sprintf(ovfEnvPropertyEntry, p.Key, p.Value))
|
||||
}
|
||||
buffer.WriteString(fmt.Sprint(ovfEnvPropertyFooter))
|
||||
|
||||
buffer.WriteString(fmt.Sprint(ovfEnvFooter))
|
||||
|
||||
return buffer.String()
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package ovf
|
||||
|
||||
type Envelope struct {
|
||||
References []File `xml:"References>File"`
|
||||
|
||||
// Package level meta-data
|
||||
Annotation *AnnotationSection `xml:"AnnotationSection"`
|
||||
Product *ProductSection `xml:"ProductSection"`
|
||||
Network *NetworkSection `xml:"NetworkSection"`
|
||||
Disk *DiskSection `xml:"DiskSection"`
|
||||
OperatingSystem *OperatingSystemSection `xml:"OperatingSystemSection"`
|
||||
Eula *EulaSection `xml:"EulaSection"`
|
||||
VirtualHardware *VirtualHardwareSection `xml:"VirtualHardwareSection"`
|
||||
ResourceAllocation *ResourceAllocationSection `xml:"ResourceAllocationSection"`
|
||||
DeploymentOption *DeploymentOptionSection `xml:"DeploymentOptionSection"`
|
||||
|
||||
// Content: A VirtualSystem or a VirtualSystemCollection
|
||||
VirtualSystem *VirtualSystem `xml:"VirtualSystem"`
|
||||
}
|
||||
|
||||
type VirtualSystem struct {
|
||||
Content
|
||||
|
||||
Annotation []AnnotationSection `xml:"AnnotationSection"`
|
||||
Product []ProductSection `xml:"ProductSection"`
|
||||
OperatingSystem []OperatingSystemSection `xml:"OperatingSystemSection"`
|
||||
Eula []EulaSection `xml:"EulaSection"`
|
||||
VirtualHardware []VirtualHardwareSection `xml:"VirtualHardwareSection"`
|
||||
}
|
||||
|
||||
type File struct {
|
||||
ID string `xml:"id,attr"`
|
||||
Href string `xml:"href,attr"`
|
||||
Size uint `xml:"size,attr"`
|
||||
Compression *string `xml:"compression,attr"`
|
||||
ChunkSize *int `xml:"chunkSize,attr"`
|
||||
}
|
||||
|
||||
type Content struct {
|
||||
ID string `xml:"id,attr"`
|
||||
Info string `xml:"Info"`
|
||||
Name *string `xml:"Name"`
|
||||
}
|
||||
|
||||
type Section struct {
|
||||
Required *bool `xml:"required,attr"`
|
||||
Info string `xml:"Info"`
|
||||
}
|
||||
|
||||
type AnnotationSection struct {
|
||||
Section
|
||||
|
||||
Annotation string `xml:"Annotation"`
|
||||
}
|
||||
|
||||
type ProductSection struct {
|
||||
Section
|
||||
|
||||
Class *string `xml:"class,attr"`
|
||||
Instance *string `xml:"instance,attr"`
|
||||
|
||||
Product string `xml:"Product"`
|
||||
Vendor string `xml:"Vendor"`
|
||||
Version string `xml:"Version"`
|
||||
FullVersion string `xml:"FullVersion"`
|
||||
ProductURL string `xml:"ProductUrl"`
|
||||
VendorURL string `xml:"VendorUrl"`
|
||||
AppURL string `xml:"AppUrl"`
|
||||
Property []Property `xml:"Property"`
|
||||
}
|
||||
|
||||
type Property struct {
|
||||
Key string `xml:"key,attr"`
|
||||
Type string `xml:"type,attr"`
|
||||
Qualifiers *string `xml:"qualifiers,attr"`
|
||||
UserConfigurable *bool `xml:"userConfigurable,attr"`
|
||||
Default *string `xml:"value,attr"`
|
||||
Password *bool `xml:"password,attr"`
|
||||
|
||||
Label *string `xml:"Label"`
|
||||
Description *string `xml:"Description"`
|
||||
|
||||
Values []PropertyConfigurationValue `xml:"Value"`
|
||||
}
|
||||
|
||||
type PropertyConfigurationValue struct {
|
||||
Value string `xml:"value,attr"`
|
||||
Configuration *string `xml:"configuration,attr"`
|
||||
}
|
||||
|
||||
type NetworkSection struct {
|
||||
Section
|
||||
|
||||
Networks []Network `xml:"Network"`
|
||||
}
|
||||
|
||||
type Network struct {
|
||||
Name string `xml:"name,attr"`
|
||||
|
||||
Description string `xml:"Description"`
|
||||
}
|
||||
|
||||
type DiskSection struct {
|
||||
Section
|
||||
|
||||
Disks []VirtualDiskDesc `xml:"Disk"`
|
||||
}
|
||||
|
||||
type VirtualDiskDesc struct {
|
||||
DiskID string `xml:"diskId,attr"`
|
||||
FileRef *string `xml:"fileRef,attr"`
|
||||
Capacity string `xml:"capacity,attr"`
|
||||
CapacityAllocationUnits *string `xml:"capacityAllocationUnits,attr"`
|
||||
Format *string `xml:"format,attr"`
|
||||
PopulatedSize *int `xml:"populatedSize,attr"`
|
||||
ParentRef *string `xml:"parentRef,attr"`
|
||||
}
|
||||
|
||||
type OperatingSystemSection struct {
|
||||
Section
|
||||
|
||||
ID int16 `xml:"id,attr"`
|
||||
Version *string `xml:"version,attr"`
|
||||
OSType *string `xml:"osType,attr"`
|
||||
|
||||
Description *string `xml:"Description"`
|
||||
}
|
||||
|
||||
type EulaSection struct {
|
||||
Section
|
||||
|
||||
License string `xml:"License"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Required *bool `xml:"required,attr"`
|
||||
Key string `xml:"key,attr"`
|
||||
Value string `xml:"value,attr"`
|
||||
}
|
||||
|
||||
type VirtualHardwareSection struct {
|
||||
Section
|
||||
|
||||
ID *string `xml:"id,attr"`
|
||||
Transport *string `xml:"transport,attr"`
|
||||
|
||||
System *VirtualSystemSettingData `xml:"System"`
|
||||
Item []ResourceAllocationSettingData `xml:"Item"`
|
||||
StorageItem []StorageAllocationSettingData `xml:"StorageItem"`
|
||||
Config []Config `xml:"Config"`
|
||||
ExtraConfig []Config `xml:"ExtraConfig"`
|
||||
}
|
||||
|
||||
type VirtualSystemSettingData struct {
|
||||
CIMVirtualSystemSettingData
|
||||
}
|
||||
|
||||
type ResourceAllocationSettingData struct {
|
||||
CIMResourceAllocationSettingData
|
||||
|
||||
Required *bool `xml:"required,attr"`
|
||||
Configuration *string `xml:"configuration,attr"`
|
||||
Bound *string `xml:"bound,attr"`
|
||||
}
|
||||
|
||||
type StorageAllocationSettingData struct {
|
||||
CIMStorageAllocationSettingData
|
||||
|
||||
Required *bool `xml:"required,attr"`
|
||||
Configuration *string `xml:"configuration,attr"`
|
||||
Bound *string `xml:"bound,attr"`
|
||||
}
|
||||
|
||||
type ResourceAllocationSection struct {
|
||||
Section
|
||||
|
||||
Item []ResourceAllocationSettingData `xml:"Item"`
|
||||
}
|
||||
|
||||
type DeploymentOptionSection struct {
|
||||
Section
|
||||
|
||||
Configuration []DeploymentOptionConfiguration `xml:"Configuration"`
|
||||
}
|
||||
|
||||
type DeploymentOptionConfiguration struct {
|
||||
ID string `xml:"id,attr"`
|
||||
Default *bool `xml:"default,attr"`
|
||||
|
||||
Label string `xml:"Label"`
|
||||
Description string `xml:"Description"`
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
Copyright (c) 2015-2017 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package ovf
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/methods"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type Manager struct {
|
||||
types.ManagedObjectReference
|
||||
|
||||
c *vim25.Client
|
||||
}
|
||||
|
||||
func NewManager(c *vim25.Client) *Manager {
|
||||
return &Manager{*c.ServiceContent.OvfManager, c}
|
||||
}
|
||||
|
||||
// CreateDescriptor wraps methods.CreateDescriptor
|
||||
func (m *Manager) CreateDescriptor(ctx context.Context, obj mo.Reference, cdp types.OvfCreateDescriptorParams) (*types.OvfCreateDescriptorResult, error) {
|
||||
req := types.CreateDescriptor{
|
||||
This: m.Reference(),
|
||||
Obj: obj.Reference(),
|
||||
Cdp: cdp,
|
||||
}
|
||||
|
||||
res, err := methods.CreateDescriptor(ctx, m.c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &res.Returnval, nil
|
||||
}
|
||||
|
||||
// CreateImportSpec wraps methods.CreateImportSpec
|
||||
func (m *Manager) CreateImportSpec(ctx context.Context, ovfDescriptor string, resourcePool mo.Reference, datastore mo.Reference, cisp types.OvfCreateImportSpecParams) (*types.OvfCreateImportSpecResult, error) {
|
||||
req := types.CreateImportSpec{
|
||||
This: m.Reference(),
|
||||
OvfDescriptor: ovfDescriptor,
|
||||
ResourcePool: resourcePool.Reference(),
|
||||
Datastore: datastore.Reference(),
|
||||
Cisp: cisp,
|
||||
}
|
||||
|
||||
res, err := methods.CreateImportSpec(ctx, m.c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &res.Returnval, nil
|
||||
}
|
||||
|
||||
// ParseDescriptor wraps methods.ParseDescriptor
|
||||
func (m *Manager) ParseDescriptor(ctx context.Context, ovfDescriptor string, pdp types.OvfParseDescriptorParams) (*types.OvfParseDescriptorResult, error) {
|
||||
req := types.ParseDescriptor{
|
||||
This: m.Reference(),
|
||||
OvfDescriptor: ovfDescriptor,
|
||||
Pdp: pdp,
|
||||
}
|
||||
|
||||
res, err := methods.ParseDescriptor(ctx, m.c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &res.Returnval, nil
|
||||
}
|
||||
|
||||
// ValidateHost wraps methods.ValidateHost
|
||||
func (m *Manager) ValidateHost(ctx context.Context, ovfDescriptor string, host mo.Reference, vhp types.OvfValidateHostParams) (*types.OvfValidateHostResult, error) {
|
||||
req := types.ValidateHost{
|
||||
This: m.Reference(),
|
||||
OvfDescriptor: ovfDescriptor,
|
||||
Host: host.Reference(),
|
||||
Vhp: vhp,
|
||||
}
|
||||
|
||||
res, err := methods.ValidateHost(ctx, m.c, &req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &res.Returnval, nil
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
Copyright (c) 2015 VMware, Inc. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package ovf
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/xml"
|
||||
)
|
||||
|
||||
func Unmarshal(r io.Reader) (*Envelope, error) {
|
||||
var e Envelope
|
||||
|
||||
dec := xml.NewDecoder(r)
|
||||
err := dec.Decode(&e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &e, nil
|
||||
}
|
|
@ -281,3 +281,14 @@ func (sm *Manager) CloneSession(ctx context.Context, ticket string) error {
|
|||
sm.userSession = &res.Returnval
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sm *Manager) UpdateServiceMessage(ctx context.Context, message string) error {
|
||||
req := types.UpdateServiceMessage{
|
||||
This: sm.Reference(),
|
||||
Message: message,
|
||||
}
|
||||
|
||||
_, err := methods.UpdateServiceMessage(ctx, sm.client, &req)
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue