Add secrets flag in vcp config and modify vcp to use nodemanger connect method

This commit is contained in:
Abrar Shivani 2018-05-08 14:44:04 -07:00
parent 21a7e9b1cb
commit 6c9558334e

View File

@ -61,6 +61,18 @@ var datastoreFolderIDMap = make(map[string]map[string]string)
var cleanUpRoutineInitLock sync.Mutex var cleanUpRoutineInitLock sync.Mutex
var cleanUpDummyVMLock sync.RWMutex var cleanUpDummyVMLock sync.RWMutex
// Error Messages
const (
MissingUsernameErrMsg = "Username is missing"
MissingPasswordErrMsg = "Password is missing"
)
// Error constants
var (
ErrUsernameMissing = errors.New(MissingUsernameErrMsg)
ErrPasswordMissing = errors.New(MissingPasswordErrMsg)
)
// VSphere is an implementation of cloud provider Interface for VSphere. // VSphere is an implementation of cloud provider Interface for VSphere.
type VSphere struct { type VSphere struct {
cfg *VSphereConfig cfg *VSphereConfig
@ -68,8 +80,9 @@ type VSphere struct {
// Maps the VSphere IP address to VSphereInstance // Maps the VSphere IP address to VSphereInstance
vsphereInstanceMap map[string]*VSphereInstance vsphereInstanceMap map[string]*VSphereInstance
// Responsible for managing discovery of k8s node, their location etc. // Responsible for managing discovery of k8s node, their location etc.
nodeManager *NodeManager nodeManager *NodeManager
vmUUID string vmUUID string
isSecretInfoProvided bool
} }
// Represents a vSphere instance where one or more kubernetes nodes are running. // Represents a vSphere instance where one or more kubernetes nodes are running.
@ -131,6 +144,10 @@ type VSphereConfig struct {
// Combining the WorkingDir and VMName can form a unique InstanceID. // Combining the WorkingDir and VMName can form a unique InstanceID.
// When vm-name is set, no username/password is required on worker nodes. // When vm-name is set, no username/password is required on worker nodes.
VMName string `gcfg:"vm-name"` VMName string `gcfg:"vm-name"`
// Name of the secret were vCenter credentials are present.
SecretName string `gcfg:"secret-name"`
// Secret Namespace where secret will be present that has vCenter credentials.
SecretNamespace string `gcfg:"secret-namespace"`
} }
VirtualCenter map[string]*VirtualCenterConfig VirtualCenter map[string]*VirtualCenterConfig
@ -217,6 +234,18 @@ func (vs *VSphere) SetInformers(informerFactory informers.SharedInformerFactory)
return return
} }
if vs.isSecretInfoProvided {
secretCredentialManager := &SecretCredentialManager{
SecretName: vs.cfg.Global.SecretName,
SecretNamespace: vs.cfg.Global.SecretNamespace,
SecretLister: informerFactory.Core().V1().Secrets().Lister(),
Cache: &SecretCache{
VirtualCenter: make(map[string]*Credential),
},
}
vs.nodeManager.UpdateCredentialManager(secretCredentialManager)
}
// Only on controller node it is required to register listeners. // Only on controller node it is required to register listeners.
// Register callbacks for node updates // Register callbacks for node updates
glog.V(4).Infof("Setting up node informers for vSphere Cloud Provider") glog.V(4).Infof("Setting up node informers for vSphere Cloud Provider")
@ -226,6 +255,7 @@ func (vs *VSphere) SetInformers(informerFactory informers.SharedInformerFactory)
DeleteFunc: vs.NodeDeleted, DeleteFunc: vs.NodeDeleted,
}) })
glog.V(4).Infof("Node informers in vSphere cloud provider initialized") glog.V(4).Infof("Node informers in vSphere cloud provider initialized")
} }
// Creates new worker node interface and returns // Creates new worker node interface and returns
@ -247,19 +277,40 @@ func newWorkerNode() (*VSphere, error) {
func populateVsphereInstanceMap(cfg *VSphereConfig) (map[string]*VSphereInstance, error) { func populateVsphereInstanceMap(cfg *VSphereConfig) (map[string]*VSphereInstance, error) {
vsphereInstanceMap := make(map[string]*VSphereInstance) vsphereInstanceMap := make(map[string]*VSphereInstance)
isSecretInfoProvided := true
if cfg.Global.SecretName == "" || cfg.Global.SecretNamespace == "" {
glog.Warningf("SecretName and/or SecretNamespace is not provided. " +
"VCP will use username and password from config file")
isSecretInfoProvided = false
}
if isSecretInfoProvided {
if cfg.Global.User != "" {
glog.Warning("Global.User and Secret info provided. VCP will use secret to get credentials")
cfg.Global.User = ""
}
if cfg.Global.Password != "" {
glog.Warning("Global.Password and Secret info provided. VCP will use secret to get credentials")
cfg.Global.Password = ""
}
}
// Check if the vsphere.conf is in old format. In this // Check if the vsphere.conf is in old format. In this
// format the cfg.VirtualCenter will be nil or empty. // format the cfg.VirtualCenter will be nil or empty.
if cfg.VirtualCenter == nil || len(cfg.VirtualCenter) == 0 { if cfg.VirtualCenter == nil || len(cfg.VirtualCenter) == 0 {
glog.V(4).Infof("Config is not per virtual center and is in old format.") glog.V(4).Infof("Config is not per virtual center and is in old format.")
if cfg.Global.User == "" { if !isSecretInfoProvided {
glog.Error("Global.User is empty!") if cfg.Global.User == "" {
return nil, errors.New("Global.User is empty!") glog.Error("Global.User is empty!")
} return nil, ErrUsernameMissing
if cfg.Global.Password == "" { }
glog.Error("Global.Password is empty!") if cfg.Global.Password == "" {
return nil, errors.New("Global.Password is empty!") glog.Error("Global.Password is empty!")
return nil, ErrPasswordMissing
}
} }
if cfg.Global.WorkingDir == "" { if cfg.Global.WorkingDir == "" {
glog.Error("Global.WorkingDir is empty!") glog.Error("Global.WorkingDir is empty!")
return nil, errors.New("Global.WorkingDir is empty!") return nil, errors.New("Global.WorkingDir is empty!")
@ -285,6 +336,8 @@ func populateVsphereInstanceMap(cfg *VSphereConfig) (map[string]*VSphereInstance
RoundTripperCount: cfg.Global.RoundTripperCount, RoundTripperCount: cfg.Global.RoundTripperCount,
} }
// Note: If secrets info is provided username and password will be populated
// once secret is created.
vSphereConn := vclib.VSphereConnection{ vSphereConn := vclib.VSphereConnection{
Username: vcConfig.User, Username: vcConfig.User,
Password: vcConfig.Password, Password: vcConfig.Password,
@ -305,31 +358,44 @@ func populateVsphereInstanceMap(cfg *VSphereConfig) (map[string]*VSphereInstance
glog.Error(msg) glog.Error(msg)
return nil, errors.New(msg) return nil, errors.New(msg)
} }
for vcServer, vcConfig := range cfg.VirtualCenter { for vcServer, vcConfig := range cfg.VirtualCenter {
glog.V(4).Infof("Initializing vc server %s", vcServer) glog.V(4).Infof("Initializing vc server %s", vcServer)
if vcServer == "" { if vcServer == "" {
glog.Error("vsphere.conf does not have the VirtualCenter IP address specified") glog.Error("vsphere.conf does not have the VirtualCenter IP address specified")
return nil, errors.New("vsphere.conf does not have the VirtualCenter IP address specified") return nil, errors.New("vsphere.conf does not have the VirtualCenter IP address specified")
} }
if vcConfig.User == "" {
vcConfig.User = cfg.Global.User if !isSecretInfoProvided {
} if vcConfig.User == "" {
if vcConfig.Password == "" { vcConfig.User = cfg.Global.User
vcConfig.Password = cfg.Global.Password if vcConfig.User == "" {
} glog.Errorf("vcConfig.User is empty for vc %s!", vcServer)
if vcConfig.User == "" { return nil, ErrUsernameMissing
msg := fmt.Sprintf("vcConfig.User is empty for vc %s!", vcServer) }
glog.Error(msg) }
return nil, errors.New(msg) if vcConfig.Password == "" {
} vcConfig.Password = cfg.Global.Password
if vcConfig.Password == "" { if vcConfig.Password == "" {
msg := fmt.Sprintf("vcConfig.Password is empty for vc %s!", vcServer) glog.Errorf("vcConfig.Password is empty for vc %s!", vcServer)
glog.Error(msg) return nil, ErrPasswordMissing
return nil, errors.New(msg) }
}
} else {
if vcConfig.User != "" {
glog.Warningf("vcConfig.User for server %s and Secret info provided. VCP will use secret to get credentials", vcServer)
vcConfig.User = ""
}
if vcConfig.Password != "" {
glog.Warningf("vcConfig.Password for server %s and Secret info provided. VCP will use secret to get credentials", vcServer)
vcConfig.Password = ""
}
} }
if vcConfig.VCenterPort == "" { if vcConfig.VCenterPort == "" {
vcConfig.VCenterPort = cfg.Global.VCenterPort vcConfig.VCenterPort = cfg.Global.VCenterPort
} }
if vcConfig.Datacenters == "" { if vcConfig.Datacenters == "" {
if cfg.Global.Datacenters != "" { if cfg.Global.Datacenters != "" {
vcConfig.Datacenters = cfg.Global.Datacenters vcConfig.Datacenters = cfg.Global.Datacenters
@ -342,6 +408,8 @@ func populateVsphereInstanceMap(cfg *VSphereConfig) (map[string]*VSphereInstance
vcConfig.RoundTripperCount = cfg.Global.RoundTripperCount vcConfig.RoundTripperCount = cfg.Global.RoundTripperCount
} }
// Note: If secrets info is provided username and password will be populated
// once secret is created.
vSphereConn := vclib.VSphereConnection{ vSphereConn := vclib.VSphereConnection{
Username: vcConfig.User, Username: vcConfig.User,
Password: vcConfig.Password, Password: vcConfig.Password,
@ -365,7 +433,30 @@ var getVMUUID = GetVMUUID
// Creates new Controller node interface and returns // Creates new Controller node interface and returns
func newControllerNode(cfg VSphereConfig) (*VSphere, error) { func newControllerNode(cfg VSphereConfig) (*VSphere, error) {
var err error vs, err := buildVSphereFromConfig(cfg)
if err != nil {
return nil, err
}
vs.hostName, err = os.Hostname()
if err != nil {
glog.Errorf("Failed to get hostname. err: %+v", err)
return nil, err
}
vs.vmUUID, err = getVMUUID()
if err != nil {
glog.Errorf("Failed to get uuid. err: %+v", err)
return nil, err
}
runtime.SetFinalizer(vs, logout)
return vs, nil
}
// Initializes vSphere from vSphere CloudProvider Configuration
func buildVSphereFromConfig(cfg VSphereConfig) (*VSphere, error) {
isSecretInfoProvided := false
if cfg.Global.SecretName != "" && cfg.Global.SecretNamespace != "" {
isSecretInfoProvided = true
}
if cfg.Disk.SCSIControllerType == "" { if cfg.Disk.SCSIControllerType == "" {
cfg.Disk.SCSIControllerType = vclib.PVSCSIControllerType cfg.Disk.SCSIControllerType = vclib.PVSCSIControllerType
@ -394,20 +485,9 @@ func newControllerNode(cfg VSphereConfig) (*VSphere, error) {
nodeInfoMap: make(map[string]*NodeInfo), nodeInfoMap: make(map[string]*NodeInfo),
registeredNodes: make(map[string]*v1.Node), registeredNodes: make(map[string]*v1.Node),
}, },
cfg: &cfg, isSecretInfoProvided: isSecretInfoProvided,
cfg: &cfg,
} }
vs.hostName, err = os.Hostname()
if err != nil {
glog.Errorf("Failed to get hostname. err: %+v", err)
return nil, err
}
vs.vmUUID, err = getVMUUID()
if err != nil {
glog.Errorf("Failed to get uuid. err: %+v", err)
return nil, err
}
runtime.SetFinalizer(&vs, logout)
return &vs, nil return &vs, nil
} }
@ -480,7 +560,7 @@ func (vs *VSphere) getVSphereInstanceForServer(vcServer string, ctx context.Cont
return nil, errors.New(fmt.Sprintf("Cannot find node %q in vsphere configuration map", vcServer)) return nil, errors.New(fmt.Sprintf("Cannot find node %q in vsphere configuration map", vcServer))
} }
// Ensure client is logged in and session is valid // Ensure client is logged in and session is valid
err := vsphereIns.conn.Connect(ctx) err := vs.nodeManager.vcConnect(ctx, vsphereIns)
if err != nil { if err != nil {
glog.Errorf("failed connecting to vcServer %q with error %+v", vcServer, err) glog.Errorf("failed connecting to vcServer %q with error %+v", vcServer, err)
return nil, err return nil, err
@ -519,7 +599,7 @@ func (vs *VSphere) NodeAddresses(ctx context.Context, nodeName k8stypes.NodeName
return nil, err return nil, err
} }
// Ensure client is logged in and session is valid // Ensure client is logged in and session is valid
err = vsi.conn.Connect(ctx) err = vs.nodeManager.vcConnect(ctx, vsi)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -634,7 +714,7 @@ func (vs *VSphere) InstanceID(ctx context.Context, nodeName k8stypes.NodeName) (
return "", err return "", err
} }
// Ensure client is logged in and session is valid // Ensure client is logged in and session is valid
err = vsi.conn.Connect(ctx) err = vs.nodeManager.vcConnect(ctx, vsi)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -725,7 +805,7 @@ func (vs *VSphere) AttachDisk(vmDiskPath string, storagePolicyName string, nodeN
return "", err return "", err
} }
// Ensure client is logged in and session is valid // Ensure client is logged in and session is valid
err = vsi.conn.Connect(ctx) err = vs.nodeManager.vcConnect(ctx, vsi)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -792,7 +872,7 @@ func (vs *VSphere) DetachDisk(volPath string, nodeName k8stypes.NodeName) error
return err return err
} }
// Ensure client is logged in and session is valid // Ensure client is logged in and session is valid
err = vsi.conn.Connect(ctx) err = vs.nodeManager.vcConnect(ctx, vsi)
if err != nil { if err != nil {
return err return err
} }
@ -847,7 +927,7 @@ func (vs *VSphere) DiskIsAttached(volPath string, nodeName k8stypes.NodeName) (b
return false, err return false, err
} }
// Ensure client is logged in and session is valid // Ensure client is logged in and session is valid
err = vsi.conn.Connect(ctx) err = vs.nodeManager.vcConnect(ctx, vsi)
if err != nil { if err != nil {
return false, err return false, err
} }