Skip to content

Instantly share code, notes, and snippets.

@carmark
Last active August 17, 2016 14:03
Show Gist options
  • Save carmark/16c5225881c29a1c4ad70e360cb9bb17 to your computer and use it in GitHub Desktop.
Save carmark/16c5225881c29a1c4ad70e360cb9bb17 to your computer and use it in GitHub Desktop.
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