Last active
August 17, 2016 14:03
-
-
Save carmark/16c5225881c29a1c4ad70e360cb9bb17 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"os" | |
"strings" | |
"github.com/hyperhq/hyper-api-router/pkg/auth" | |
"github.com/hyperhq/hyper-api-router/pkg/cell" | |
"github.com/hyperhq/hyper-api-router/pkg/daemon" | |
"github.com/hyperhq/hyper-api-router/pkg/errors" | |
"github.com/hyperhq/hyper-api-router/pkg/keystone" | |
"github.com/hyperhq/hyper-api-router/pkg/network" | |
"github.com/hyperhq/hyper-api-router/pkg/storage" | |
"github.com/golang/glog" | |
"github.com/rackspace/gophercloud" | |
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips" | |
"github.com/rackspace/gophercloud/pagination" | |
"github.com/spf13/pflag" | |
"gopkg.in/mgo.v2" | |
"gopkg.in/mgo.v2/bson" | |
"k8s.io/kubernetes/pkg/util" | |
) | |
type FipCleanUp struct { | |
DB string | |
KSC string | |
Fire bool | |
} | |
func (s *FipCleanUp) AddFlags(fs *pflag.FlagSet) { | |
fs.BoolVar(&s.Fire, "fire", s.Fire, "really do the operation") | |
fs.StringVar(&s.KSC, "ksc", s.KSC, "keystone config, default /etc/keystone.conf") | |
fs.StringVar(&s.DB, "db", s.DB, "url of the source db, default 127.0.0.1") | |
} | |
func (s *FipCleanUp) Run(_ []string) error { | |
var ( | |
mongo *mgo.Session | |
cell cell.CellConfig | |
ksconfig *keystone.KeystoneConfig | |
err error | |
) | |
mongo, err = mgo.Dial(s.DB) | |
if err != nil { | |
glog.Errorf(err.Error()) | |
return err | |
} | |
defer mongo.Close() | |
miter := mongo.Copy() | |
defer miter.Close() | |
ksconfig, err = keystone.GetKeystoneConfig(s.KSC) | |
if err != nil { | |
glog.Errorf(err.Error()) | |
return err | |
} | |
// 1 看有哪些 fip 的 tenant 不存在,用日志列出来 ip 和 tenant | |
// 2 如果不存在的话,看看同一个 ip,在这个表里有没有其他 fip 用了这个 ip | |
// 3 如果没有,查一下 neutron 里有没有这个 fip | |
// 4 如果 neutron 里有的话,再检查下数据库,如果数据库确实没有其他人用这个 ip,打印出来这个ip | |
// 5 如果 neutron 里没有的话,删数据库里的表项 | |
var fip network.FloatingIP | |
iter := miter.DB("hypernetes").C("fip").Find(bson.M{}).Iter() | |
for iter.Next(&fip) { | |
glog.Infof("find floating IP %s in %s", daemon.ConvertKeyToIP(fip.IP), fip.Tenant) | |
var tenant auth.TenantItem | |
err = mongo.DB("hypernetes").C("tenant").Find(bson.M{ | |
"tenantid": fip.Tenant, | |
}).One(&tenant) | |
if err != nil { | |
if !strings.Contains(err.Error(), "not found") { | |
return err | |
} | |
} | |
if tenant.TenantID == "" { | |
glog.Infof("cannot find tenant with id %s", fip.Tenant) | |
c, err := miter.DB("hypernetes").C("fip").Find(bson.M{"ip": fip.IP}).Count() | |
if err != nil { | |
glog.Error(err) | |
return err | |
} | |
if c > 1 { | |
glog.Infof("found another %d fip(s) with same IP, %v", c-1) | |
if s.Fire { | |
// delete fip from fip table | |
} | |
} else { | |
err = mongo.DB(storage.Database).C(storage.CellTable).Find(bson.M{"id": fip.Tenant}).One(&cell) | |
if err != nil { | |
glog.Error(err) | |
return err | |
} | |
// Create neutron clients | |
cell.Neutron, err = network.NewNeutronClient(cell.Id, ksconfig) | |
if err != nil { | |
glog.Error(err) | |
return err | |
} | |
_, err := getNeutronFip(cell.Neutron, daemon.ConvertKeyToIP(fip.IP), fip.Tenant) | |
if err != nil { | |
if err != errors.ErrorCodeNoSuchFip { | |
glog.Error(err) | |
return err | |
} | |
glog.Infof("no such fip(%s) in neutron", daemon.ConvertKeyToIP(fip.IP)) | |
if s.Fire { | |
// delete fip from fip table | |
err = miter.DB("hypernetes").C("fip").Remove(bson.M{"ip": fip.IP}) | |
if err != nil { | |
glog.Error(err) | |
return err | |
} | |
} | |
} | |
fc, err := miter.DB("hypernetes").C("fip").Find(bson.M{"ip": fip.IP}).Count() | |
if err != nil { | |
glog.Error(err) | |
return err | |
} | |
if fc == 1 { | |
glog.Infof("no more other tenant use this fip(s)", daemon.ConvertKeyToIP(fip.IP)) | |
if s.Fire { | |
/* | |
err = network.DeleteFloatingIP(cell.Neutron, daemon.ConvertKeyToIP(fip.IP), fip.Tenant) | |
if err != nil { | |
glog.Error(err) | |
return err | |
} | |
*/ | |
// delete fip from fip table | |
err = miter.DB("hypernetes").C("fip").Remove(bson.M{"ip": fip.IP}) | |
if err != nil { | |
glog.Error(err) | |
return err | |
} | |
} | |
} | |
} | |
} else { | |
glog.Infof("find tenant with id %s", fip.Tenant) | |
} | |
} | |
if err = iter.Err(); err != nil { | |
glog.Errorf(err.Error()) | |
return err | |
} | |
iter.Close() | |
return nil | |
} | |
func getNeutronFip(neutron *gophercloud.ServiceClient, floatingip, tenantID string) (*floatingips.FloatingIP, error) { | |
var fip *floatingips.FloatingIP | |
opts := floatingips.ListOpts{ | |
TenantID: tenantID, | |
FloatingIP: floatingip, | |
} | |
pager := floatingips.List(neutron, opts) | |
err := pager.EachPage(func(page pagination.Page) (bool, error) { | |
floatingipList, err := floatingips.ExtractFloatingIPs(page) | |
if err != nil { | |
glog.Errorf("Get openstack floatingips error: %v", err) | |
return false, errors.DecodeOpenstackError(err) | |
} | |
if len(floatingipList) > 0 { | |
fip = &floatingipList[0] | |
} | |
return true, nil | |
}) | |
if err != nil { | |
return nil, errors.DecodeOpenstackError(err) | |
} | |
if fip == nil { | |
return nil, errors.ErrorCodeNoSuchFip | |
} | |
return fip, nil | |
} | |
func NewFipCleanUp() *FipCleanUp { | |
return &FipCleanUp{ | |
DB: "127.0.0.1", | |
KSC: "/etc/keystone.conf", | |
} | |
} | |
func main() { | |
t := NewFipCleanUp() | |
t.AddFlags(pflag.CommandLine) | |
util.InitFlags() | |
util.InitLogs() | |
if err := t.Run(pflag.CommandLine.Args()); err != nil { | |
fmt.Fprintf(os.Stderr, "%v\n", err) | |
os.Exit(1) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment