diff --git a/cmd/openshift-install/main.go b/cmd/openshift-install/main.go index e964b1b2046..59672badf68 100644 --- a/cmd/openshift-install/main.go +++ b/cmd/openshift-install/main.go @@ -9,6 +9,7 @@ import ( "github.com/openshift/installer/pkg/asset" "github.com/openshift/installer/pkg/asset/stock" "github.com/openshift/installer/pkg/destroy" + _ "github.com/openshift/installer/pkg/destroy/libvirt" ) var ( @@ -77,7 +78,7 @@ func main() { } } case destroyCommand.FullCommand(): - destroyer, err := destroy.NewDestroyer(l, *dirFlag) + destroyer, err := destroy.New(l, *dirFlag) if err != nil { log.Fatalf("failed to create destroyer: %v", err) os.Exit(1) diff --git a/docs/dev/dependencies.md b/docs/dev/dependencies.md index 3e5e05c209f..17e903a7fd7 100644 --- a/docs/dev/dependencies.md +++ b/docs/dev/dependencies.md @@ -10,12 +10,16 @@ The following dependencies must be installed on your system before you can build sudo dnf install golang-bin gcc-c++ ``` +If you need support for [libvirt destroy](libvirt-howto#cleanup), you should also install `libvirt-devel`. + ### CentOS, RHEL ```sh sudo yum install golang-bin gcc-c++ ``` +If you need support for [libvirt destroy](libvirt-howto#cleanup), you should also install `libvirt-devel`. + ## Go We follow a hard flattening approach; i.e. direct and inherited dependencies are installed in the base `vendor/`. diff --git a/docs/dev/libvirt-howto.md b/docs/dev/libvirt-howto.md index 87e598cf8ea..7be8c341abd 100644 --- a/docs/dev/libvirt-howto.md +++ b/docs/dev/libvirt-howto.md @@ -184,6 +184,12 @@ EOF ## Build and run the installer With [libvirt configured](#install-and-enable-libvirt), you can proceed with [the usual quick-start](../../README.md#quick-start). +Set `TAGS` when building if you need `destroy-cluster` support for libvirt; this is not enabled by default because it requires [cgo][]: + +```sh +TAGS=libvirt_destroy hack/build.sh +``` + To avoid being prompted repeatedly, you can set [environment variables](../user/environment-variables.md) to reflect your libvirt choices. For example, selecting libvirt, setting [our earlier name choices](#pick-names), [our pull secret](#get-a-pull-secret), and telling both the installer and the machine-API operator to contact `libvirtd` at [the usual libvirt IP](#firewall), you can use: ```sh @@ -196,9 +202,13 @@ export OPENSHIFT_INSTALL_LIBVIRT_URI=qemu+tcp://192.168.122.1/system ## Cleanup -Be sure to destroy your cluster when you're done with it, or else you will need to manually use `virsh` to clean up the leaked resources. -The [`virsh-cleanup`](../../scripts/maintenance/virsh-cleanup.sh) script may help with this, but note it will currently destroy *all* libvirt resources. -We plan on adding `openshift-install destroy-cluster` support for libvirt in the near future. +If you compiled with `libvirt_destroy`, you can use: + +```sh +openshift-install destroy-cluster +``` + +If you did not compile with `libvirt_destroy`, you can use [`virsh-cleanup.sh`](../../scripts/maintenance/virsh-cleanup.sh), but note it will currently destroy *all* libvirt resources. ### Firewall @@ -328,6 +338,7 @@ If your issue is not reported, please do. [arch_firewall_superuser]: https://superuser.com/questions/1063240/libvirt-failed-to-initialize-a-valid-firewall-backend [brokenmacosissue201]: https://github.com/openshift/installer/issues/201 [bugzilla_libvirt_race]: https://bugzilla.redhat.com/show_bug.cgi?id=1576464 +[cgo]: https://golang.org/cmd/cgo/ [issues_libvirt]: https://github.com/openshift/installer/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+libvirt [libvirt_selinux_issues]: https://github.com/dmacvicar/terraform-provider-libvirt/issues/142#issuecomment-409040151 [tfprovider_libvirt_race]: https://github.com/dmacvicar/terraform-provider-libvirt/issues/402#issuecomment-419500064 diff --git a/hack/build.sh b/hack/build.sh index eb396c1e136..1439e7e4f8f 100755 --- a/hack/build.sh +++ b/hack/build.sh @@ -5,11 +5,12 @@ set -ex cd "$(dirname "$0")/.." MODE="${MODE:-release}" -TAGS= +TAGS="${TAGS:-}" +export CGO_ENABLED=0 case "${MODE}" in release) - TAGS=release + TAGS="${TAGS} release" GOPATH="${PWD}/vendor:${GOPATH}" go generate ./data ;; dev) @@ -19,4 +20,9 @@ dev) exit 1 esac -CGO_ENABLED=0 go build -tags "${TAGS}" -o ./bin/openshift-install ./cmd/openshift-install +if (echo "${TAGS}" | grep -q 'libvirt_destroy') +then + export CGO_ENABLED=1 +fi + +go build -tags "${TAGS}" -o ./bin/openshift-install ./cmd/openshift-install diff --git a/pkg/destroy/aws.go b/pkg/destroy/aws.go new file mode 100644 index 00000000000..390ebdeb468 --- /dev/null +++ b/pkg/destroy/aws.go @@ -0,0 +1,30 @@ +package destroy + +import ( + "os" + + atd "github.com/openshift/hive/contrib/pkg/awstagdeprovision" + "github.com/openshift/installer/pkg/types" + log "github.com/sirupsen/logrus" +) + +// NewAWS returns an AWS destroyer from ClusterMetadata. +func NewAWS(level log.Level, metadata *types.ClusterMetadata) (Destroyer, error) { + return &atd.ClusterUninstaller{ + Filters: metadata.ClusterPlatformMetadata.AWS.Identifier, + Region: metadata.ClusterPlatformMetadata.AWS.Region, + ClusterName: metadata.ClusterName, + Logger: log.NewEntry(&log.Logger{ + Out: os.Stdout, + Formatter: &log.TextFormatter{ + FullTimestamp: true, + }, + Hooks: make(log.LevelHooks), + Level: level, + }), + }, nil +} + +func init() { + Registry["aws"] = NewAWS +} diff --git a/pkg/destroy/destroyer.go b/pkg/destroy/destroyer.go index b20d22cea5f..26b713a8f5f 100644 --- a/pkg/destroy/destroyer.go +++ b/pkg/destroy/destroyer.go @@ -4,10 +4,8 @@ import ( "encoding/json" "fmt" "io/ioutil" - "os" "path/filepath" - atd "github.com/openshift/hive/contrib/pkg/awstagdeprovision" log "github.com/sirupsen/logrus" "github.com/openshift/installer/pkg/asset/metadata" @@ -20,60 +18,33 @@ type Destroyer interface { Run() error } -// NewDestroyer returns Destroyer based on `metadata.json` in `rootDir`. -func NewDestroyer(level log.Level, rootDir string) (Destroyer, error) { +// NewFunc is an interface for creating platform-specific destroyers. +type NewFunc func(level log.Level, metadata *types.ClusterMetadata) (Destroyer, error) + +// Registry maps ClusterMetadata.Platform() to per-platform Destroyer creators. +var Registry = make(map[string]NewFunc) + +// New returns a Destroyer based on `metadata.json` in `rootDir`. +func New(level log.Level, rootDir string) (Destroyer, error) { + path := filepath.Join(rootDir, metadata.MetadataFilename) raw, err := ioutil.ReadFile(filepath.Join(rootDir, metadata.MetadataFilename)) if err != nil { return nil, err } - var cmetadata types.ClusterMetadata + var cmetadata *types.ClusterMetadata if err := json.Unmarshal(raw, &cmetadata); err != nil { return nil, err } - var ret Destroyer - switch { - case cmetadata.ClusterPlatformMetadata.AWS != nil: - ret = NewAWSDestroyer(level, &cmetadata) - case cmetadata.ClusterPlatformMetadata.Libvirt != nil: - // ret = NewLibvirtDestroyer(level, &cmetadata) - return nil, fmt.Errorf("libvirt destroyer is not yet supported") - default: - return nil, fmt.Errorf("couldn't find Destroyer for %q", metadata.MetadataFilename) + platform := cmetadata.Platform() + if platform == "" { + return nil, fmt.Errorf("no platform configured in %q", path) } - return ret, nil -} - -// // NewLibvirtDestroyer returns libvirt Uninstaller from ClusterMetadata. -// func NewLibvirtDestroyer(level log.Level, metadata *types.ClusterMetadata) *lpd.ClusterUninstaller { -// return &lpd.ClusterUninstaller{ -// LibvirtURI: metadata.ClusterPlatformMetadata.Libvirt.URI, -// Filter: lpd.AlwaysTrueFilter(), //TODO: change to ClusterNamePrefixFilter when all resources are prefixed. -// Logger: log.NewEntry(&log.Logger{ -// Out: os.Stdout, -// Formatter: &log.TextFormatter{ -// FullTimestamp: true, -// }, -// Hooks: make(log.LevelHooks), -// Level: level, -// }), -// } -// } -// NewAWSDestroyer returns aws Uninstaller from ClusterMetadata. -func NewAWSDestroyer(level log.Level, metadata *types.ClusterMetadata) *atd.ClusterUninstaller { - return &atd.ClusterUninstaller{ - Filters: metadata.ClusterPlatformMetadata.AWS.Identifier, - Region: metadata.ClusterPlatformMetadata.AWS.Region, - ClusterName: metadata.ClusterName, - Logger: log.NewEntry(&log.Logger{ - Out: os.Stdout, - Formatter: &log.TextFormatter{ - FullTimestamp: true, - }, - Hooks: make(log.LevelHooks), - Level: level, - }), + creator, ok := Registry[platform] + if !ok { + return nil, fmt.Errorf("no destroyers registered for %q", platform) } + return creator(level, cmetadata) } diff --git a/pkg/destroy/libvirt/doc.go b/pkg/destroy/libvirt/doc.go new file mode 100644 index 00000000000..840332f583a --- /dev/null +++ b/pkg/destroy/libvirt/doc.go @@ -0,0 +1,2 @@ +// Package libvirt provides a cluster-destroyer for libvirt clusters. +package libvirt diff --git a/pkg/destroy/libvirt/libvirt_prefix_deprovision.go b/pkg/destroy/libvirt/libvirt_prefix_deprovision.go index 954dc67ded3..ef9ad1ba2dc 100644 --- a/pkg/destroy/libvirt/libvirt_prefix_deprovision.go +++ b/pkg/destroy/libvirt/libvirt_prefix_deprovision.go @@ -1,3 +1,5 @@ +// +build libvirt_destroy + package libvirt import ( @@ -6,6 +8,8 @@ import ( "time" libvirt "github.com/libvirt/libvirt-go" + "github.com/openshift/installer/pkg/destroy" + "github.com/openshift/installer/pkg/types" log "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/util/wait" ) @@ -239,3 +243,19 @@ func deleteNetwork(conn *libvirt.Connect, filter filterFunc, logger log.FieldLog } return true, nil } + +// New returns libvirt Uninstaller from ClusterMetadata. +func New(level log.Level, metadata *types.ClusterMetadata) (destroy.Destroyer, error) { + return &ClusterUninstaller{ + LibvirtURI: metadata.ClusterPlatformMetadata.Libvirt.URI, + Filter: AlwaysTrueFilter(), //TODO: change to ClusterNamePrefixFilter when all resources are prefixed. + Logger: log.NewEntry(&log.Logger{ + Out: os.Stdout, + Formatter: &log.TextFormatter{ + FullTimestamp: true, + }, + Hooks: make(log.LevelHooks), + Level: level, + }), + }, nil +} diff --git a/pkg/destroy/libvirt/register.go b/pkg/destroy/libvirt/register.go new file mode 100644 index 00000000000..8b5f6c7c022 --- /dev/null +++ b/pkg/destroy/libvirt/register.go @@ -0,0 +1,11 @@ +// +build libvirt_destroy + +package libvirt + +import ( + "github.com/openshift/installer/pkg/destroy" +) + +func init() { + destroy.Registry["libvirt"] = New +} diff --git a/pkg/types/clustermetadata.go b/pkg/types/clustermetadata.go index 332bdd66ab4..4c8722d0a75 100644 --- a/pkg/types/clustermetadata.go +++ b/pkg/types/clustermetadata.go @@ -13,6 +13,22 @@ type ClusterPlatformMetadata struct { Libvirt *ClusterLibvirtPlatformMetadata `json:"libvirt,omitempty"` } +// Platform returns a string representation of the platform +// (e.g. "aws" if AWS is non-nil). It returns an empty string if no +// platform is configured. +func (cpm *ClusterPlatformMetadata) Platform() string { + if cpm == nil { + return "" + } + if cpm.AWS != nil { + return "aws" + } + if cpm.Libvirt != nil { + return "libvirt" + } + return "" +} + // ClusterAWSPlatformMetadata contains AWS metadata. type ClusterAWSPlatformMetadata struct { Region string `json:"region"`