diff --git a/cmd/kubestack/kubestack.go b/cmd/kubestack/kubestack.go index 03116ed..d2d321d 100644 --- a/cmd/kubestack/kubestack.go +++ b/cmd/kubestack/kubestack.go @@ -13,6 +13,7 @@ import ( kubestacktypes "git.openstack.org/openstack/stackube/pkg/kubestack/types" "git.openstack.org/openstack/stackube/pkg/openstack" "git.openstack.org/openstack/stackube/pkg/util" + "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" "github.com/containernetworking/cni/pkg/types/current" @@ -92,10 +93,16 @@ func initOpenstack(stdinData []byte) (OpenStack, string, error) { if n.KubestackConfig == "" { return OpenStack{}, "", fmt.Errorf("kubestack-config not specified") } - openStackClient, err := openstack.NewClient(n.KubestackConfig) + + if n.KubernetesConfig == "" { + return OpenStack{}, "", fmt.Errorf("kubernetes-config not specified") + } + + openStackClient, err := openstack.NewClient(n.KubestackConfig, n.KubernetesConfig) if err != nil { return OpenStack{}, "", err } + os := OpenStack{ Client: *openStackClient, } diff --git a/cmd/stackube-controller/stackube-controller.go b/cmd/stackube-controller/stackube-controller.go index f6334cf..7f18bca 100644 --- a/cmd/stackube-controller/stackube-controller.go +++ b/cmd/stackube-controller/stackube-controller.go @@ -44,8 +44,7 @@ func startControllers(kubeconfig, cloudconfig string) error { // Creates a new RBAC controller rm, err := rbacmanager.New(kubeconfig, - tc.GetTenantClient(), - nc.GetNetworkClient(), + tc.GetKubeCRDClient(), *systemCIDR, *systemGateway, ) @@ -92,7 +91,7 @@ func verifyClientSetting() error { return fmt.Errorf("Init kubernetes clientset failed: %v", err) } - _, err = openstack.NewClient(*cloudconfig) + _, err = openstack.NewClient(*cloudconfig, *kubeconfig) if err != nil { return fmt.Errorf("Init openstack client failed: %v", err) } diff --git a/devstack/plugin.sh b/devstack/plugin.sh index fce1735..cf93815 100644 --- a/devstack/plugin.sh +++ b/devstack/plugin.sh @@ -126,7 +126,7 @@ EOF' function install_master { sed -i "s/KEYSTONE_HOST/${SERVICE_HOST}/g" ${STACKUBE_ROOT}/kubeadm.yaml - sudo kubeadm init kubeadm init --pod-network-cidr ${CLUSTER_CIDR} --config ${STACKUBE_ROOT}/kubeadm.yaml + sudo kubeadm init --pod-network-cidr ${CLUSTER_CIDR} --config ${STACKUBE_ROOT}/kubeadm.yaml # Enable schedule pods on the master for testing. sudo cp /etc/kubernetes/admin.conf $HOME/ sudo chown $(id -u):$(id -g) $HOME/admin.conf diff --git a/pkg/auth-controller/client/auth/client.go b/pkg/auth-controller/client/auth/client.go deleted file mode 100644 index 2b00fa1..0000000 --- a/pkg/auth-controller/client/auth/client.go +++ /dev/null @@ -1,29 +0,0 @@ -package auth - -import ( - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/serializer" - "k8s.io/client-go/rest" - - crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1" -) - -func NewClient(cfg *rest.Config) (*rest.RESTClient, *runtime.Scheme, error) { - scheme := runtime.NewScheme() - if err := crv1.AddToScheme(scheme); err != nil { - return nil, nil, err - } - - config := *cfg - config.GroupVersion = &crv1.SchemeGroupVersion - config.APIPath = "/apis" - config.ContentType = runtime.ContentTypeJSON - config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: serializer.NewCodecFactory(scheme)} - - client, err := rest.RESTClientFor(&config) - if err != nil { - return nil, nil, err - } - - return client, scheme, nil -} diff --git a/pkg/auth-controller/rbacmanager/rbac_controller.go b/pkg/auth-controller/rbacmanager/rbac_controller.go index e73e55b..96032f1 100644 --- a/pkg/auth-controller/rbacmanager/rbac_controller.go +++ b/pkg/auth-controller/rbacmanager/rbac_controller.go @@ -6,6 +6,7 @@ import ( crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1" "git.openstack.org/openstack/stackube/pkg/auth-controller/rbacmanager/rbac" + crdClient "git.openstack.org/openstack/stackube/pkg/kubecrd" "git.openstack.org/openstack/stackube/pkg/util" "github.com/golang/glog" @@ -15,7 +16,6 @@ import ( "k8s.io/client-go/kubernetes" "k8s.io/client-go/pkg/api" "k8s.io/client-go/pkg/api/v1" - "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" ) @@ -28,16 +28,14 @@ type Controller struct { kclient *kubernetes.Clientset nsInf cache.SharedIndexInformer queue workqueue.RateLimitingInterface - tenantClient *rest.RESTClient - networkClient *rest.RESTClient + kubeCRDClient *crdClient.CRDClient systemCIDR string systemGateway string } // New creates a new RBAC controller. func New(kubeconfig string, - tenantClient *rest.RESTClient, - networkClient *rest.RESTClient, + kubeCRDClient *crdClient.CRDClient, systemCIDR string, systemGateway string, ) (*Controller, error) { @@ -53,8 +51,7 @@ func New(kubeconfig string, o := &Controller{ kclient: client, queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "rbacmanager"), - tenantClient: tenantClient, - networkClient: networkClient, + kubeCRDClient: kubeCRDClient, systemCIDR: systemCIDR, systemGateway: systemGateway, } @@ -157,7 +154,8 @@ func (c *Controller) handleNamespaceAdd(obj interface{}) { func (c *Controller) initSystemReservedTenantNetwork() error { tenant := &crv1.Tenant{ ObjectMeta: metav1.ObjectMeta{ - Name: util.SystemTenant, + Name: util.SystemTenant, + Namespace: util.SystemTenant, }, Spec: crv1.TenantSpec{ UserName: util.SystemTenant, @@ -165,13 +163,8 @@ func (c *Controller) initSystemReservedTenantNetwork() error { }, } - err := c.tenantClient.Post(). - Namespace(util.SystemTenant). - Resource(crv1.TenantResourcePlural). - Body(tenant). - Do().Error() - if err != nil && !apierrors.IsAlreadyExists(err) { - return fmt.Errorf("failed to create system Tenant: %v", err) + if err := c.kubeCRDClient.AddTenant(tenant); err != nil { + return err } // NOTE(harry): we do not support update Network, so although configurable, @@ -179,7 +172,8 @@ func (c *Controller) initSystemReservedTenantNetwork() error { // that system network. We may need to document this. network := &crv1.Network{ ObjectMeta: metav1.ObjectMeta{ - Name: util.SystemNetwork, + Name: util.SystemNetwork, + Namespace: util.SystemTenant, }, Spec: crv1.NetworkSpec{ CIDR: c.systemCIDR, @@ -188,13 +182,8 @@ func (c *Controller) initSystemReservedTenantNetwork() error { } // network controller will always check if Tenant is ready so we will not wait here - err = c.networkClient.Post(). - Resource(crv1.NetworkResourcePlural). - Namespace(util.SystemTenant). - Body(network). - Do().Error() - if err != nil && !apierrors.IsAlreadyExists(err) { - return fmt.Errorf("failed to create system Network: %v", err) + if err := c.kubeCRDClient.AddNetwork(network); err != nil { + return err } return nil diff --git a/pkg/auth-controller/tenant/tenant_controller.go b/pkg/auth-controller/tenant/tenant_controller.go index 83043df..4bf3f34 100644 --- a/pkg/auth-controller/tenant/tenant_controller.go +++ b/pkg/auth-controller/tenant/tenant_controller.go @@ -4,41 +4,32 @@ import ( "fmt" crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1" - crdClient "git.openstack.org/openstack/stackube/pkg/auth-controller/client/auth" + crdClient "git.openstack.org/openstack/stackube/pkg/kubecrd" "git.openstack.org/openstack/stackube/pkg/openstack" + "git.openstack.org/openstack/stackube/pkg/util" "github.com/golang/glog" apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" apierrors "k8s.io/apimachinery/pkg/api/errors" apismetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" - "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/client-go/kubernetes" apiv1 "k8s.io/client-go/pkg/api/v1" - "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" - "k8s.io/client-go/tools/clientcmd" ) -// TenantController manages lify cycle of Tenant. +// TenantController manages life cycle of Tenant. type TenantController struct { k8sClient *kubernetes.Clientset - tenantClient *rest.RESTClient - tenantScheme *runtime.Scheme + kubeCRDClient *crdClient.CRDClient openstackClient *openstack.Client } // NewTenantController creates a new tenant controller. func NewTenantController(kubeconfig, cloudconfig string) (*TenantController, error) { - // Create OpenStack client from config - openStackClient, err := openstack.NewClient(cloudconfig) - if err != nil { - return nil, fmt.Errorf("init openstack client failed: %v", err) - } - // Create the client config. Use kubeconfig if given, otherwise assume in-cluster. - config, err := buildConfig(kubeconfig) + config, err := util.NewClusterConfig(kubeconfig) if err != nil { return nil, fmt.Errorf("failed to build kubeconfig: %v", err) } @@ -58,15 +49,14 @@ func NewTenantController(kubeconfig, cloudconfig string) (*TenantController, err return nil, fmt.Errorf("failed to create kubernetes client: %v", err) } - // make a new config for our extension's API group, using the first config as a baseline - tenantClient, tenantScheme, err := crdClient.NewClient(config) + // Create OpenStack client from config + openStackClient, err := openstack.NewClient(cloudconfig, kubeconfig) if err != nil { - return nil, fmt.Errorf("failed to create client for CRD: %v", err) + return nil, fmt.Errorf("init openstack client failed: %v", err) } c := &TenantController{ - tenantClient: tenantClient, - tenantScheme: tenantScheme, + kubeCRDClient: openStackClient.CRDClient, k8sClient: k8sClient, openstackClient: openStackClient, } @@ -78,15 +68,8 @@ func NewTenantController(kubeconfig, cloudconfig string) (*TenantController, err return c, nil } -func buildConfig(kubeconfig string) (*rest.Config, error) { - if kubeconfig != "" { - return clientcmd.BuildConfigFromFlags("", kubeconfig) - } - return rest.InClusterConfig() -} - -func (c *TenantController) GetTenantClient() *rest.RESTClient { - return c.tenantClient +func (c *TenantController) GetKubeCRDClient() *crdClient.CRDClient { + return c.kubeCRDClient } // Run the controller. @@ -94,7 +77,7 @@ func (c *TenantController) Run(stopCh <-chan struct{}) error { defer utilruntime.HandleCrash() source := cache.NewListWatchFromClient( - c.tenantClient, + c.kubeCRDClient.Client, crv1.TenantResourcePlural, apiv1.NamespaceAll, fields.Everything()) @@ -116,11 +99,11 @@ func (c *TenantController) Run(stopCh <-chan struct{}) error { func (c *TenantController) onAdd(obj interface{}) { tenant := obj.(*crv1.Tenant) - glog.V(3).Infof("Tenant controller received new object %v\n", tenant) + glog.V(3).Infof("Tenant controller received new object %#v\n", tenant) - copyObj, err := c.tenantScheme.Copy(tenant) + copyObj, err := c.kubeCRDClient.Scheme.Copy(tenant) if err != nil { - glog.Errorf("ERROR creating a deep copy of tenant object: %v\n", err) + glog.Errorf("ERROR creating a deep copy of tenant object: %#v\n", err) return } @@ -138,7 +121,7 @@ func (c *TenantController) onDelete(obj interface{}) { return } - glog.V(3).Infof("Tenant controller received deleted tenant %v\n", tenant) + glog.V(3).Infof("Tenant controller received deleted tenant %#v\n", tenant) deleteOptions := &apismetav1.DeleteOptions{ TypeMeta: apismetav1.TypeMeta{ diff --git a/pkg/auth-controller/tenant/tenant_controller_helper.go b/pkg/auth-controller/tenant/tenant_controller_helper.go index 2f0af10..c858196 100644 --- a/pkg/auth-controller/tenant/tenant_controller_helper.go +++ b/pkg/auth-controller/tenant/tenant_controller_helper.go @@ -11,12 +11,12 @@ import ( apiv1 "k8s.io/client-go/pkg/api/v1" ) -func (c *TenantController) syncTenant(tenant *crv1.Tenant) error { +func (c *TenantController) syncTenant(tenant *crv1.Tenant) { roleBinding := rbac.GenerateClusterRoleBindingByTenant(tenant.Name) _, err := c.k8sClient.Rbac().ClusterRoleBindings().Create(roleBinding) if err != nil && !apierrors.IsAlreadyExists(err) { glog.Errorf("Failed create ClusterRoleBinding for tenant %s: %v", tenant.Name, err) - return err + return } glog.V(4).Infof("Created ClusterRoleBindings %s-namespace-creater for tenant %s", tenant.Name, tenant.Name) if tenant.Spec.TenantID != "" { @@ -24,29 +24,30 @@ func (c *TenantController) syncTenant(tenant *crv1.Tenant) error { err = c.openstackClient.CreateUser(tenant.Spec.UserName, tenant.Spec.Password, tenant.Spec.TenantID) if err != nil && !openstack.IsAlreadyExists(err) { glog.Errorf("Failed create user %s: %v", tenant.Spec.UserName, err) - return err + return } } else { // Create tenant if the tenant not exist in keystone tenantID, err := c.openstackClient.CreateTenant(tenant.Name) if err != nil { - return err + glog.Errorf("Failed create tenant %s: %v", tenant, err) + return } // Create user with the spec username and password in the created tenant err = c.openstackClient.CreateUser(tenant.Spec.UserName, tenant.Spec.Password, tenantID) if err != nil { - return err + glog.Errorf("Failed create user %s: %v", tenant.Spec.UserName, err) + return } } // Create namespace which name is the same as the tenant's name err = c.createNamespace(tenant.Name) if err != nil { - return err + glog.Errorf("Failed create namespace %s: %v", tenant.Name, err) + return } - glog.V(4).Infof("Created namespace %s for tenant %s", tenant.Name, tenant.Name) - return nil } func (c *TenantController) createClusterRoles() error { @@ -76,7 +77,6 @@ func (c *TenantController) createNamespace(namespace string) error { func (c *TenantController) deleteNamespace(namespace string) error { err := c.k8sClient.CoreV1().Namespaces().Delete(namespace, apismetav1.NewDeleteOptions(0)) if err != nil { - glog.Errorf("Failed delete namespace %s: %v", namespace, err) return err } return nil diff --git a/pkg/kubecrd/crdclient.go b/pkg/kubecrd/crdclient.go new file mode 100644 index 0000000..bded13d --- /dev/null +++ b/pkg/kubecrd/crdclient.go @@ -0,0 +1,113 @@ +package kubecrd + +import ( + "fmt" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/client-go/rest" + + crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1" + "github.com/golang/glog" +) + +type CRDClient struct { + Client *rest.RESTClient + Scheme *runtime.Scheme +} + +func NewCRDClient(cfg *rest.Config) (*CRDClient, error) { + scheme := runtime.NewScheme() + if err := crv1.AddToScheme(scheme); err != nil { + return nil, err + } + + config := *cfg + config.GroupVersion = &crv1.SchemeGroupVersion + config.APIPath = "/apis" + config.ContentType = runtime.ContentTypeJSON + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: serializer.NewCodecFactory(scheme)} + + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + + return &CRDClient{ + Client: client, + Scheme: scheme, + }, nil +} + +// UpdateNetwork updates Network CRD object by given object +func (c *CRDClient) UpdateNetwork(network *crv1.Network) { + err := c.Client.Put(). + Name(network.Name). + Namespace(network.Namespace). + Resource(crv1.NetworkResourcePlural). + Body(network). + Do(). + Error() + + if err != nil { + glog.Errorf("ERROR updating network: %v\n", err) + } else { + glog.V(3).Infof("UPDATED network: %#v\n", network) + } +} + +// UpdateTenant updates Network CRD object by given object +func (c *CRDClient) UpdateTenant(tenant *crv1.Tenant) { + err := c.Client.Put(). + Name(tenant.Name). + Namespace(tenant.Namespace). + Resource(crv1.TenantResourcePlural). + Body(tenant). + Do(). + Error() + + if err != nil { + glog.Errorf("ERROR updating tenant: %v\n", err) + } else { + glog.V(3).Infof("UPDATED tenant: %#v\n", tenant) + } +} + +func (c *CRDClient) GetTenant(tenantName string) (*crv1.Tenant, error) { + tenant := crv1.Tenant{} + // tenant always has same name and namespace + err := c.Client.Get(). + Resource(crv1.TenantResourcePlural). + Namespace(tenantName). + Name(tenantName). + Do().Into(&tenant) + if err != nil { + return nil, err + } + return &tenant, nil +} + +func (c *CRDClient) AddTenant(tenant *crv1.Tenant) error { + err := c.Client.Post(). + Namespace(tenant.GetNamespace()). + Resource(crv1.TenantResourcePlural). + Body(tenant). + Do().Error() + if err != nil && !apierrors.IsAlreadyExists(err) { + return fmt.Errorf("failed to create Tenant: %v", err) + } + return nil +} + +func (c *CRDClient) AddNetwork(network *crv1.Network) error { + err := c.Client.Post(). + Resource(crv1.NetworkResourcePlural). + Namespace(network.GetNamespace()). + Body(network). + Do().Error() + if err != nil && !apierrors.IsAlreadyExists(err) { + return fmt.Errorf("failed to create Network: %v", err) + } + return nil +} diff --git a/pkg/network-controller/client/network.go b/pkg/kubecrd/network.go similarity index 99% rename from pkg/network-controller/client/network.go rename to pkg/kubecrd/network.go index 21bfc66..602e3f6 100644 --- a/pkg/network-controller/client/network.go +++ b/pkg/kubecrd/network.go @@ -1,4 +1,4 @@ -package client +package kubecrd import ( "reflect" diff --git a/pkg/auth-controller/client/auth/tenant.go b/pkg/kubecrd/tenant.go similarity index 99% rename from pkg/auth-controller/client/auth/tenant.go rename to pkg/kubecrd/tenant.go index e0b555e..cd016e9 100644 --- a/pkg/auth-controller/client/auth/tenant.go +++ b/pkg/kubecrd/tenant.go @@ -1,4 +1,4 @@ -package auth +package kubecrd import ( "reflect" diff --git a/pkg/kubestack/types/types.go b/pkg/kubestack/types/types.go index 599f7d0..d66d7a4 100644 --- a/pkg/kubestack/types/types.go +++ b/pkg/kubestack/types/types.go @@ -8,7 +8,8 @@ import ( type NetConf struct { types.NetConf - KubestackConfig string `json:"kubestack-config"` + KubestackConfig string `json:"kubestack-config"` + KubernetesConfig string `json:"kubernetes-config"` } // K8sArgs is the valid CNI_ARGS used for Kubernetes diff --git a/pkg/network-controller/client/client.go b/pkg/network-controller/client/client.go deleted file mode 100644 index 7d2f837..0000000 --- a/pkg/network-controller/client/client.go +++ /dev/null @@ -1,29 +0,0 @@ -package client - -import ( - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/serializer" - "k8s.io/client-go/rest" - - crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1" -) - -func NewClient(cfg *rest.Config) (*rest.RESTClient, *runtime.Scheme, error) { - scheme := runtime.NewScheme() - if err := crv1.AddToScheme(scheme); err != nil { - return nil, nil, err - } - - config := *cfg - config.GroupVersion = &crv1.SchemeGroupVersion - config.APIPath = "/apis" - config.ContentType = runtime.ContentTypeJSON - config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: serializer.NewCodecFactory(scheme)} - - client, err := rest.RESTClientFor(&config) - if err != nil { - return nil, nil, err - } - - return client, scheme, nil -} diff --git a/pkg/network-controller/network_controller.go b/pkg/network-controller/network_controller.go index 7c21761..f70c56a 100644 --- a/pkg/network-controller/network_controller.go +++ b/pkg/network-controller/network_controller.go @@ -7,14 +7,11 @@ import ( apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/fields" - "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" - "k8s.io/client-go/tools/clientcmd" crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1" - crdClient "git.openstack.org/openstack/stackube/pkg/network-controller/client" + crdClient "git.openstack.org/openstack/stackube/pkg/kubecrd" osDriver "git.openstack.org/openstack/stackube/pkg/openstack" "git.openstack.org/openstack/stackube/pkg/util" @@ -23,20 +20,19 @@ import ( // Watcher is an network of watching on resource create/update/delete events type NetworkController struct { - networkClient *rest.RESTClient - networkScheme *runtime.Scheme + kubeCRDClient *crdClient.CRDClient driver *osDriver.Client } -func (c *NetworkController) GetNetworkClient() *rest.RESTClient { - return c.networkClient +func (c *NetworkController) GetKubeCRDClient() *crdClient.CRDClient { + return c.kubeCRDClient } func (c *NetworkController) Run(stopCh <-chan struct{}) error { defer utilruntime.HandleCrash() source := cache.NewListWatchFromClient( - c.networkClient, + c.kubeCRDClient.Client, crv1.NetworkResourcePlural, apiv1.NamespaceAll, fields.Everything()) @@ -57,22 +53,9 @@ func (c *NetworkController) Run(stopCh <-chan struct{}) error { return nil } -func buildConfig(kubeconfig string) (*rest.Config, error) { - if kubeconfig != "" { - return clientcmd.BuildConfigFromFlags("", kubeconfig) - } - return rest.InClusterConfig() -} - func NewNetworkController(kubeconfig, openstackConfigFile string) (*NetworkController, error) { - // Create OpenStack client from config - openstack, err := osDriver.NewClient(openstackConfigFile) - if err != nil { - return nil, fmt.Errorf("Couldn't initialize openstack: %#v", err) - } - // Create the client config. Use kubeconfig if given, otherwise assume in-cluster. - config, err := buildConfig(kubeconfig) + config, err := util.NewClusterConfig(kubeconfig) if err != nil { return nil, fmt.Errorf("failed to build kubeconfig: %v", err) } @@ -87,15 +70,14 @@ func NewNetworkController(kubeconfig, openstackConfigFile string) (*NetworkContr return nil, fmt.Errorf("failed to create CRD to kube-apiserver: %v", err) } - // make a new config for our extension's API group, using the first config as a baseline - networkClient, networkScheme, err := crdClient.NewClient(config) + // Create OpenStack client from config + openstack, err := osDriver.NewClient(openstackConfigFile, kubeconfig) if err != nil { - return nil, fmt.Errorf("failed to create client for CRD: %v", err) + return nil, fmt.Errorf("Couldn't initialize openstack: %#v", err) } networkController := &NetworkController{ - networkClient: networkClient, - networkScheme: networkScheme, + kubeCRDClient: openstack.CRDClient, driver: openstack, } return networkController, nil @@ -109,7 +91,7 @@ func (c *NetworkController) onAdd(obj interface{}) { // NEVER modify objects from the store. It's a read-only, local cache. // You can use networkScheme.Copy() to make a deep copy of original object and modify this copy // Or create a copy manually for better performance - copyObj, err := c.networkScheme.Copy(network) + copyObj, err := c.GetKubeCRDClient().Scheme.Copy(network) if err != nil { glog.Errorf("ERROR creating a deep copy of network object: %v\n", err) return diff --git a/pkg/network-controller/network_controller_helper.go b/pkg/network-controller/network_controller_helper.go index 7a363d2..58f118f 100644 --- a/pkg/network-controller/network_controller_helper.go +++ b/pkg/network-controller/network_controller_helper.go @@ -26,18 +26,21 @@ func (c *NetworkController) addNetworkToDriver(kubeNetwork *crv1.Network) { if err != nil || tenantID == "" { err = wait.Poll(2*time.Second, 10*time.Second, func() (bool, error) { tenantID, err = c.driver.GetTenantIDFromName(kubeNetwork.GetNamespace()) - if err != nil || tenantID == "" { - glog.V(5).Infof("failed to fetch tenantID for tenantName: %v, retrying\n", tenantName) + if err != nil { + glog.Errorf("failed to fetch tenantID for tenantName: %v, error: %v retrying\n", tenantName, err) + return false, nil + } + + if tenantID == "" { + glog.V(5).Infof("tenantID is empty for tenantName: %v, retrying\n", tenantName) return false, nil } return true, nil }) } if err != nil || tenantID == "" { - glog.Errorf("failed to fetch tenantID for tenantName: %v, abort! \n", tenantName) + glog.Errorf("failed to fetch tenantID for tenantName: %v, error: %v abort! \n", tenantName, err) return - } else { - glog.V(3).Infof("Got tenantID: %v for tenantName: %v", tenantID, tenantName) } networkName := util.BuildNetworkName(tenantName, kubeNetwork.GetName()) @@ -69,7 +72,7 @@ func (c *NetworkController) addNetworkToDriver(kubeNetwork *crv1.Network) { if !check { glog.Warningf("[NetworkController]: tenantID %s doesn't exist in network provider", driverNetwork.TenantID) kubeNetwork.Status.State = crv1.NetworkFailed - c.updateNetwork(kubeNetwork) + c.kubeCRDClient.UpdateNetwork(kubeNetwork) return } @@ -104,22 +107,5 @@ func (c *NetworkController) addNetworkToDriver(kubeNetwork *crv1.Network) { } kubeNetwork.Status.State = newNetworkStatus - c.updateNetwork(kubeNetwork) -} - -// updateNetwork updates Network CRD object by given object -func (c *NetworkController) updateNetwork(network *crv1.Network) { - err := c.networkClient.Put(). - Name(network.Name). - Namespace(network.Namespace). - Resource(crv1.NetworkResourcePlural). - Body(network). - Do(). - Error() - - if err != nil { - glog.Errorf("ERROR updating network status: %v\n", err) - } else { - glog.V(3).Infof("UPDATED network status: %#v\n", network) - } + c.kubeCRDClient.UpdateNetwork(kubeNetwork) } diff --git a/pkg/openstack/client.go b/pkg/openstack/client.go index 6461481..4eb9ae5 100644 --- a/pkg/openstack/client.go +++ b/pkg/openstack/client.go @@ -5,8 +5,11 @@ import ( "fmt" "os" + crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1" + crdClient "git.openstack.org/openstack/stackube/pkg/kubecrd" drivertypes "git.openstack.org/openstack/stackube/pkg/openstack/types" "git.openstack.org/openstack/stackube/pkg/util" + "github.com/docker/distribution/uuid" "github.com/golang/glog" "github.com/gophercloud/gophercloud" @@ -21,6 +24,7 @@ import ( "github.com/gophercloud/gophercloud/openstack/networking/v2/ports" "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets" "github.com/gophercloud/gophercloud/pagination" + gcfg "gopkg.in/gcfg.v1" ) @@ -51,6 +55,7 @@ type Client struct { ExtNetID string PluginName string IntegrationBridge string + CRDClient *crdClient.CRDClient } type PluginOpts struct { @@ -79,7 +84,7 @@ func toAuthOptions(cfg Config) gophercloud.AuthOptions { } } -func NewClient(config string) (*Client, error) { +func NewClient(config string, kubeConfig string) (*Client, error) { var opts gophercloud.AuthOptions cfg, err := readConfig(config) if err != nil { @@ -118,6 +123,16 @@ func NewClient(config string) (*Client, error) { return nil, err } + // Create CRD client + k8sConfig, err := util.NewClusterConfig(kubeConfig) + if err != nil { + return nil, fmt.Errorf("failed to build kubeconfig: %v", err) + } + kubeCRDClient, err := crdClient.NewCRDClient(k8sConfig) + if err != nil { + return nil, fmt.Errorf("failed to create client for CRD: %v", err) + } + client := &Client{ Identity: identity, Provider: provider, @@ -126,6 +141,7 @@ func NewClient(config string) (*Client, error) { ExtNetID: cfg.Global.ExtNetID, PluginName: cfg.Plugin.PluginName, IntegrationBridge: cfg.Plugin.IntegrationBridge, + CRDClient: kubeCRDClient, } return client, nil } @@ -147,8 +163,22 @@ func (c *Client) GetTenantIDFromName(tenantName string) (string, error) { if util.IsSystemNamespace(tenantName) { tenantName = util.SystemTenant } + + // If tenantID is specified, return it directly + var ( + tenant *crv1.Tenant + err error + ) + if tenant, err = c.CRDClient.GetTenant(tenantName); err != nil { + return "", err + } + if tenant.Spec.TenantID != "" { + return tenant.Spec.TenantID, nil + } + + // Otherwise, fetch tenantID from OpenStack var tenantID string - err := tenants.List(c.Identity, nil).EachPage(func(page pagination.Page) (bool, error) { + err = tenants.List(c.Identity, nil).EachPage(func(page pagination.Page) (bool, error) { tenantList, err1 := tenants.ExtractTenants(page) if err1 != nil { return false, err1 @@ -164,6 +194,9 @@ func (c *Client) GetTenantIDFromName(tenantName string) (string, error) { if err != nil { return "", err } + + glog.V(3).Infof("Got tenantID: %v for tenantName: %v", tenantID, tenantName) + return tenantID, nil } diff --git a/pkg/util/k8s_util.go b/pkg/util/k8s_util.go index 439f14a..8ac6ae5 100644 --- a/pkg/util/k8s_util.go +++ b/pkg/util/k8s_util.go @@ -14,13 +14,18 @@ import ( ) func NewClusterConfig(kubeConfig string) (*rest.Config, error) { - cfg, err := clientcmd.BuildConfigFromFlags("", kubeConfig) - if err != nil { - return nil, err + if kubeConfig != "" { + cfg, err := clientcmd.BuildConfigFromFlags("", kubeConfig) + if err != nil { + return nil, err + } + cfg.QPS = 100 + cfg.Burst = 100 + return cfg, nil + + } else { + return rest.InClusterConfig() } - cfg.QPS = 100 - cfg.Burst = 100 - return cfg, nil } func WaitForCRDReady(clientset apiextensionsclient.Interface, crdName string) error {