pcm-coordinator/adaptor/pcm_pod/service/huawei_cci.go

245 lines
6.6 KiB
Go

package poder
import (
pbpod "code.gitlink.org.cn/JCCE/PCM.git/adaptor/pcm_pod/gen/idl"
"context"
"fmt"
util "github.com/alibabacloud-go/tea-utils/service"
"sync"
"k8s.io/apimachinery/pkg/api/resource"
"github.com/golang/glog"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
corev1 "k8s.io/api/core/v1"
huaweicci "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/clientcmd/api"
"code.gitlink.org.cn/JCCE/PCM.git/common/tenanter"
"github.com/pkg/errors"
)
var huaweiClientMutex sync.Mutex
type HuaweiCci struct {
cli *huaweicci.Clientset
region tenanter.Region
tenanter tenanter.Tenanter
}
func (cci *HuaweiCci) GetPodRegion(ctx context.Context, req *pbpod.GetPodRegionReq) (*pbpod.GetPodRegionResp, error) {
//todo
var (
regions []*pbpod.Region
)
huaweiRegionName, _ := tenanter.GetHuaweiRegionName(5)
region := &pbpod.Region{
Id: 5,
Name: huaweiRegionName,
}
regions = append(regions, region)
resp := &pbpod.GetPodRegionResp{
Regions: regions,
}
return resp, nil
}
// CCI auth through iam
const (
apiVersion = "client.authentication.k8s.io/v1beta1"
iamEndpoint = "https://iam.myhuaweicloud.com"
)
func newHuaweiCciClient(region tenanter.Region, tenant tenanter.Tenanter) (Poder, error) {
var (
client *huaweicci.Clientset
err error
)
cciEndpoint := "https://cci." + region.GetName() + ".myhuaweicloud.com"
cciConfig, err := clientcmd.BuildConfigFromFlags(cciEndpoint, "")
if err != nil {
return nil, err
}
switch t := tenant.(type) {
case *tenanter.AccessKeyTenant:
huaweiClientMutex.Lock()
var optionArgs []string
optionArgs = append(optionArgs, fmt.Sprintf("--iam-endpoint=%s", iamEndpoint))
optionArgs = append(optionArgs, fmt.Sprintf("--project-name=%s", region.GetName()))
optionArgs = append(optionArgs, fmt.Sprintf("--ak=%s", t.GetId()))
optionArgs = append(optionArgs, fmt.Sprintf("--sk=%s", t.GetSecret()))
cciConfig.ExecProvider = &api.ExecConfig{
Command: "cci-iam-authenticator",
APIVersion: apiVersion,
Args: append([]string{"token"}, optionArgs...),
Env: make([]api.ExecEnvVar, 0),
}
client, err = huaweicci.NewForConfig(cciConfig)
huaweiClientMutex.Unlock()
default:
}
if err != nil {
return nil, errors.Wrap(err, "init huawei pcm_pod client error")
}
return &HuaweiCci{
cli: client,
region: region,
tenanter: tenant,
}, nil
}
func (cci *HuaweiCci) CreatePod(ctx context.Context, req *pbpod.CreatePodReq) (*pbpod.CreatePodResp, error) {
pod := corev1.Pod{
TypeMeta: metav1.TypeMeta{
APIVersion: "core/V1",
Kind: "Pod",
},
ObjectMeta: metav1.ObjectMeta{
Name: req.PodName,
Namespace: req.Namespace,
Labels: map[string]string{"name": "test_api"},
},
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyAlways,
Containers: []corev1.Container{
{
Name: req.ContainerName,
Image: req.ContainerImage,
Resources: corev1.ResourceRequirements{
Limits: map[corev1.ResourceName]resource.Quantity{
corev1.ResourceCPU: resource.MustParse(req.CpuPod),
corev1.ResourceMemory: resource.MustParse(req.MemoryPod),
},
},
},
},
},
Status: corev1.PodStatus{},
}
resp, err := cci.cli.CoreV1().Pods(req.Namespace).Create(context.TODO(), &pod, metav1.CreateOptions{})
if err != nil {
return nil, err
}
isFinished := false
if len(resp.UID) > 0 {
isFinished = true
}
glog.Infof("--------------------Huawei CCI Instance created--------------------")
return &pbpod.CreatePodResp{
Finished: isFinished,
RequestId: "Create huawei pcm_pod request ID:" + resp.GenerateName,
PodId: string(resp.Generation),
PodName: resp.Name,
}, nil
}
func (cci *HuaweiCci) DeletePod(ctx context.Context, req *pbpod.DeletePodReq) (*pbpod.DeletePodResp, error) {
err := cci.cli.CoreV1().Pods(req.GetNamespace()).Delete(context.TODO(), req.PcmId, metav1.DeleteOptions{})
isFinished := true
if err != nil {
return nil, err
}
glog.Infof("--------------------Huawei CCI Instance deleted--------------------")
glog.Infof(*util.ToJSONString(util.ToMap(err)))
return &pbpod.DeletePodResp{
Finished: isFinished,
RequestId: "Delete huawei pcm_pod request ID:" + req.PodName,
PodId: req.PodName,
PodName: req.PodName,
}, nil
}
func (cci *HuaweiCci) UpdatePod(ctx context.Context, req *pbpod.UpdatePodReq) (*pbpod.UpdatePodResp, error) {
qresp, err := cci.cli.CoreV1().Pods(req.GetNamespace()).Get(context.TODO(), req.PcmId, metav1.GetOptions{})
if err != nil {
return nil, err
}
pod := corev1.Pod{
TypeMeta: qresp.TypeMeta,
ObjectMeta: metav1.ObjectMeta{
Name: req.PcmId,
Namespace: req.Namespace,
Labels: map[string]string{"name": req.Labels},
},
Spec: qresp.Spec,
Status: qresp.Status,
}
pod.Spec.Containers[0].Image = req.ContainerImage
resp, err := cci.cli.CoreV1().Pods(req.Namespace).Update(context.TODO(), &pod, metav1.UpdateOptions{})
glog.Info("Huawei update pcm_pod resp", resp)
if err != nil {
return nil, errors.Wrap(err, "Huaweiyun UpdatePod error")
}
glog.Infof("--------------------Huawei CCI Instance updated--------------------")
isFinished := false
if len(resp.UID) > 0 {
isFinished = true
}
return &pbpod.UpdatePodResp{
Finished: isFinished,
RequestId: "Update huawei pcm_pod request ID:" + resp.GenerateName,
PodId: string(resp.Generation),
PodName: resp.Name,
}, nil
}
func (cci *HuaweiCci) ListPodDetail(ctx context.Context, req *pbpod.ListPodDetailReq) (*pbpod.ListPodDetailResp, error) {
resp, err := cci.cli.CoreV1().Pods(req.GetNamespace()).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, err
}
glog.Info("Huaweiyun ListDetail pcm_pod success", resp.Items)
var pods = make([]*pbpod.PodInstance, len(resp.Items))
for k, v := range resp.Items {
pods[k] = &pbpod.PodInstance{
Provider: pbpod.CloudProvider_huawei,
AccountName: cci.tenanter.AccountName(),
PcmId: v.Name,
PodId: string(v.GetUID()),
PodName: v.Name,
RegionId: cci.region.GetId(),
ContainerImage: v.Spec.Containers[0].Image,
ContainerName: v.Spec.Containers[0].Name,
CpuPod: v.Spec.Containers[0].Resources.Requests.Cpu().String(),
MemoryPod: v.Spec.Containers[0].Resources.Requests.Memory().String(),
Namespace: v.Namespace,
Status: string(v.Status.Phase),
}
}
glog.Infof("--------------------Huawei CCI Instance updated--------------------")
isFinished := false
if len(pods) < int(req.PageSize) {
isFinished = true
}
return &pbpod.ListPodDetailResp{
Pods: pods,
Finished: isFinished,
PageNumber: req.PageNumber + 1,
PageSize: req.PageSize,
}, nil
}