44package libvirt
55
66import (
7+ "net/url"
78 "strings"
89
9- "github.com/libvirt/libvirt-go "
10+ libvirt "github.com/digitalocean/go-libvirt "
1011 "github.com/pkg/errors"
1112 "github.com/sirupsen/logrus"
1213
@@ -39,7 +40,7 @@ var AlwaysTrueFilter = func() filterFunc {
3940}
4041
4142// deleteFunc is the interface a function needs to implement to be delete resources.
42- type deleteFunc func (conn * libvirt.Connect , filter filterFunc , logger logrus.FieldLogger ) error
43+ type deleteFunc func (conn * libvirt.Libvirt , filter filterFunc , logger logrus.FieldLogger ) error
4344
4445// ClusterUninstaller holds the various options for the cluster we want to delete.
4546type ClusterUninstaller struct {
@@ -59,17 +60,29 @@ func New(logger logrus.FieldLogger, metadata *types.ClusterMetadata) (providers.
5960
6061// Run is the entrypoint to start the uninstall process.
6162func (o * ClusterUninstaller ) Run () (* types.ClusterQuota , error ) {
62- conn , err := libvirt . NewConnect (o .LibvirtURI )
63+ uri , err := url . Parse (o .LibvirtURI )
6364 if err != nil {
64- return nil , errors . Wrap ( err , "failed to connect to Libvirt daemon" )
65+ return nil , err
6566 }
6667
68+ virt , err := libvirt .ConnectToURI (uri )
69+ if err != nil {
70+ return nil , err
71+ }
72+ defer func () {
73+ if err := virt .Disconnect (); err != nil {
74+ if o .Logger != nil {
75+ o .Logger .Warn ("failed to disconnect from libvirt" , err )
76+ }
77+ }
78+ }()
79+
6780 for _ , del := range []deleteFunc {
6881 deleteDomains ,
6982 deleteNetwork ,
7083 deleteStoragePool ,
7184 } {
72- err = del (conn , o .Filter , o .Logger )
85+ err = del (virt , o .Filter , o .Logger )
7386 if err != nil {
7487 return nil , err
7588 }
@@ -83,145 +96,124 @@ func (o *ClusterUninstaller) Run() (*types.ClusterQuota, error) {
8396// additional nodes after the initial list call. We continue deleting
8497// domains until we either hit an error or we have a list call with no
8598// matching domains.
86- func deleteDomains (conn * libvirt.Connect , filter filterFunc , logger logrus.FieldLogger ) error {
99+ func deleteDomains (virt * libvirt.Libvirt , filter filterFunc , logger logrus.FieldLogger ) error {
87100 logger .Debug ("Deleting libvirt domains" )
88101 var err error
89102 nothingToDelete := false
90103 for ! nothingToDelete {
91- nothingToDelete , err = deleteDomainsSinglePass (conn , filter , logger )
104+ nothingToDelete , err = deleteDomainsSinglePass (virt , filter , logger )
92105 if err != nil {
93106 return err
94107 }
95108 }
96109 return nil
97110}
98111
99- func deleteDomainsSinglePass (conn * libvirt.Connect , filter filterFunc , logger logrus.FieldLogger ) (nothingToDelete bool , err error ) {
100- domains , err := conn . ListAllDomains ( 0 )
112+ func deleteDomainsSinglePass (virt * libvirt.Libvirt , filter filterFunc , logger logrus.FieldLogger ) (nothingToDelete bool , err error ) {
113+ domains , _ , err := virt . ConnectListAllDomains ( 1 , 0 )
101114 if err != nil {
102115 return false , errors .Wrap (err , "list domains" )
103116 }
104117
105118 nothingToDelete = true
106119 for _ , domain := range domains {
107- defer domain .Free ()
108- dName , err := domain .GetName ()
109- if err != nil {
110- return false , errors .Wrap (err , "get domain name" )
111- }
112- if ! filter (dName ) {
120+ if ! filter (domain .Name ) {
113121 continue
114122 }
115123
116124 nothingToDelete = false
117- dState , _ , err := domain . GetState ( )
125+ dState , _ , err := virt . DomainGetState ( domain , 0 )
118126 if err != nil {
119- return false , errors .Wrapf (err , "get domain state %d" , dName )
127+ return false , errors .Wrapf (err , "get domain state %d" , domain . Name )
120128 }
121129
122- if dState != libvirt .DOMAIN_SHUTOFF && dState != libvirt .DOMAIN_SHUTDOWN {
123- if err := domain . Destroy ( ); err != nil {
124- return false , errors .Wrapf (err , "destroy domain %q" , dName )
130+ if libvirt . DomainState ( dState ) != libvirt .DomainShutoff && libvirt . DomainState ( dState ) != libvirt .DomainShutdown {
131+ if err := virt . DomainDestroy ( domain ); err != nil {
132+ return false , errors .Wrapf (err , "destroy domain %q" , domain . Name )
125133 }
126134 }
127- if err := domain . UndefineFlags ( libvirt .DOMAIN_UNDEFINE_NVRAM ); err != nil {
128- if e := err .(libvirt.Error ); e .Code == libvirt .ERR_NO_SUPPORT || e .Code == libvirt .ERR_INVALID_ARG {
129- logger .WithField ("domain" , dName ).Info ("libvirt does not support undefine flags: will try again without flags" )
130- if err := domain . Undefine ( ); err != nil {
131- return false , errors .Wrapf (err , "could not undefine libvirt domain: %q" , dName )
135+ if err := virt . DomainUndefineFlags ( domain , libvirt .DomainUndefineNvram ); err != nil {
136+ if e , ok := err .(libvirt.Error ); ok && ( libvirt . ErrorNumber ( e .Code ) == libvirt .ErrNoSupport || libvirt . ErrorNumber ( e .Code ) == libvirt .ErrInvalidArg ) {
137+ logger .WithField ("domain" , domain . Name ).Info ("libvirt does not support undefine flags: will try again without flags" )
138+ if err := virt . DomainUndefine ( domain ); err != nil {
139+ return false , errors .Wrapf (err , "could not undefine libvirt domain: %q" , domain . Name )
132140 }
133141 } else {
134- return false , errors .Wrapf (err , "could not undefine libvirt domain %q with flags" , dName )
142+ return false , errors .Wrapf (err , "could not undefine libvirt domain %q with flags" , domain . Name )
135143 }
136144 }
137- logger .WithField ("domain" , dName ).Info ("Deleted domain" )
145+ logger .WithField ("domain" , domain . Name ).Info ("Deleted domain" )
138146 }
139147
140148 return nothingToDelete , nil
141149}
142150
143- func deleteStoragePool (conn * libvirt.Connect , filter filterFunc , logger logrus.FieldLogger ) error {
151+ func deleteStoragePool (virt * libvirt.Libvirt , filter filterFunc , logger logrus.FieldLogger ) error {
144152 logger .Debug ("Deleting libvirt volumes" )
145153
146- pools , err := conn . ListStoragePools ( )
154+ pools , _ , err := virt . ConnectListAllStoragePools ( 1 , 0 )
147155 if err != nil {
148156 return errors .Wrap (err , "list storage pools" )
149157 }
150158
151- for _ , pname := range pools {
159+ for _ , pool := range pools {
152160 // pool name that returns true from filter
153- if ! filter (pname ) {
161+ if ! filter (pool . Name ) {
154162 continue
155163 }
156164
157- pool , err := conn .LookupStoragePoolByName (pname )
158- if err != nil {
159- return errors .Wrapf (err , "get storage pool %q" , pname )
160- }
161- defer pool .Free ()
162-
163165 // delete all vols that return true from filter.
164- vols , err := pool . ListAllStorageVolumes ( 0 )
166+ vols , _ , err := virt . StoragePoolListAllVolumes ( pool , 1 , 0 )
165167 if err != nil {
166- return errors .Wrapf (err , "list volumes in %q" , pname )
168+ return errors .Wrapf (err , "list volumes in %q" , pool . Name )
167169 }
168170
169171 for _ , vol := range vols {
170- defer vol .Free ()
171- vName , err := vol .GetName ()
172- if err != nil {
173- return errors .Wrapf (err , "get volume names in %q" , pname )
172+ if err := virt .StorageVolDelete (vol , 0 ); err != nil {
173+ return errors .Wrapf (err , "delete volume %q from %q" , vol .Name , pool .Name )
174174 }
175- if err := vol .Delete (0 ); err != nil {
176- return errors .Wrapf (err , "delete volume %q from %q" , vName , pname )
177- }
178- logger .WithField ("volume" , vName ).Info ("Deleted volume" )
175+ logger .WithField ("volume" , vol .Name ).Info ("Deleted volume" )
179176 }
180177
181178 // blow away entire pool.
182- if err := pool . Destroy ( ); err != nil {
183- return errors .Wrapf (err , "destroy pool %q" , pname )
179+ if err := virt . StoragePoolDestroy ( pool ); err != nil {
180+ return errors .Wrapf (err , "destroy pool %q" , pool . Name )
184181 }
185182
186- if err := pool . Delete ( 0 ); err != nil {
187- return errors .Wrapf (err , "delete pool %q" , pname )
183+ if err := virt . StoragePoolDelete ( pool , 0 ); err != nil {
184+ return errors .Wrapf (err , "delete pool %q" , pool . Name )
188185 }
189186
190- if err := pool . Undefine ( ); err != nil {
191- return errors .Wrapf (err , "undefine pool %q" , pname )
187+ if err := virt . StoragePoolUndefine ( pool ); err != nil {
188+ return errors .Wrapf (err , "undefine pool %q" , pool . Name )
192189 }
193- logger .WithField ("pool" , pname ).Info ("Deleted pool" )
190+ logger .WithField ("pool" , pool . Name ).Info ("Deleted pool" )
194191 }
195192
196193 return nil
197194}
198195
199- func deleteNetwork (conn * libvirt.Connect , filter filterFunc , logger logrus.FieldLogger ) error {
196+ func deleteNetwork (virt * libvirt.Libvirt , filter filterFunc , logger logrus.FieldLogger ) error {
200197 logger .Debug ("Deleting libvirt network" )
201198
202- networks , err := conn . ListNetworks ( )
199+ networks , _ , err := virt . ConnectListAllNetworks ( 1 , 0 )
203200 if err != nil {
204201 return errors .Wrap (err , "list networks" )
205202 }
206203
207- for _ , nName := range networks {
208- if ! filter (nName ) {
204+ for _ , network := range networks {
205+ if ! filter (network . Name ) {
209206 continue
210207 }
211- network , err := conn .LookupNetworkByName (nName )
212- if err != nil {
213- return errors .Wrapf (err , "get network %q" , nName )
214- }
215- defer network .Free ()
216208
217- if err := network . Destroy ( ); err != nil {
218- return errors .Wrapf (err , "destroy network %q" , nName )
209+ if err := virt . NetworkDestroy ( network ); err != nil {
210+ return errors .Wrapf (err , "destroy network %q" , network . Name )
219211 }
220212
221- if err := network . Undefine ( ); err != nil {
222- return errors .Wrapf (err , "undefine network %q" , nName )
213+ if err := virt . NetworkUndefine ( network ); err != nil {
214+ return errors .Wrapf (err , "undefine network %q" , network . Name )
223215 }
224- logger .WithField ("network" , nName ).Info ("Deleted network" )
216+ logger .WithField ("network" , network . Name ).Info ("Deleted network" )
225217 }
226218 return nil
227219}
0 commit comments