diff --git a/web/clui/conf/locale/locale_en-US.ini b/web/clui/conf/locale/locale_en-US.ini index ae6394a3..3cda095a 100644 --- a/web/clui/conf/locale/locale_en-US.ini +++ b/web/clui/conf/locale/locale_en-US.ini @@ -10,6 +10,7 @@ Compute_Storage = Compute & Storage Instances = Instances Flavors = Flavors Images = Images +Registry = Registry Volumes = Volumes Platform_Service = Platform Service Openshift = Openshift @@ -77,12 +78,16 @@ HyperID = HyperID ParentID = ParentID Children = Children Console = Console +Label = Label +OcpVersion = Ocp Version +RegistryContent = Registry Content User_Manage_Panel = User Manage Panel Organization_Manage_Panel = Organization Manage Panel Key_Manage_Panel = Key Manage Panel Instance_Manage_Panel = Instance Manage Panel Flavor_Manage_Panel = Flavor Manage Panel +Registry_Manage_Panel = Registry Manage Panel Image_Manage_Panel = Image Manage Panel Volume_Manage_Panel = Volume Manage Panel Openshift_Cluster_Manage_Panel = Openshift Cluster Manage Panel @@ -110,6 +115,7 @@ Create_an_OpenShift_cluster = Create an OpenShift cluster Advanced = Advanced Create New Flavor = Create New Flavor +Create New Registry = Create New Registry Create New Floating Ip = Create New Floating Ip Address = Address Type = Type @@ -213,6 +219,8 @@ Instance Deletion = Instance Deletion Instance_Deletion_Confirm = This instance is going to be deleted permanently, do you want to continue? Flavor Deletion = Flavor Deletion Flavor_Deletion_Confirm = This flavor is going to be deleted permanently, do you want to continue? +Registry Deletion = Registry Deletion +Registry_Deletion_Confirm = This registry is going to be deleted permanently, do you want to continue? FloatingIP Deletion = FloatingIP Deletion FloatingIP_Deletion_Confirm = This floating ip is going to be deleted permanently, do you want to continue? Gateway Deletion = Gateway Deletion @@ -270,4 +278,4 @@ additionalTrustBundle = additionalTrustBundle imageContentSources = imageContentSources -Default Username = Default Username \ No newline at end of file +Default Username = Default Username diff --git a/web/clui/conf/locale/locale_zh-CN.ini b/web/clui/conf/locale/locale_zh-CN.ini index 441dab81..640ba49b 100644 --- a/web/clui/conf/locale/locale_zh-CN.ini +++ b/web/clui/conf/locale/locale_zh-CN.ini @@ -16,6 +16,7 @@ Worker_Flavor = Worker配置 Worker Flavor = Worker配置 Console = 控制台 Images = 镜像 +Registry = 仓库 Volumes = 卷 Platform_Service = 平台 = 服务 Openshift = Openshift @@ -77,12 +78,16 @@ HyperID = 标识 ParentID = 父标识 Children = 下级数 Console = 控制台 +Label = 名称 +OcpVersion = Ocp版本 +RegistryContent = 配置内容 User_Manage_Panel = 用户管理面板 Organization_Manage_Panel = 组织管理面板 Key_Manage_Panel = 密钥管理面板 Instance_Manage_Panel = 实例管理面板 -Flavor_Manage_Panel = 配置管理面板 +Flavor_Manage_Panel = 配置管理面 +Registry_Manage_Panel = Registry Manage Panel Image_Manage_Panel = 镜像管理面板 Volume_Manage_Panel = 卷管理面板 Openshift_Cluster_Manage_Panel = Openshift集群管理面板 @@ -109,7 +114,8 @@ Use_your_instance_content = 其中用户名对应于CentOS, CoreOS, 和Ubuntu镜 Create_an_OpenShift_cluster = 创建OpenShift集群 Advanced = 高级 -Create New Flavor = 创建新的配置 +Create New Flavor = 创建新的配 +Create New Registry = 创建新的仓库 Create New Floating Ip = 创建新的浮动IP Address = 地址 Type = 类型 @@ -212,7 +218,9 @@ No = 否 Instance Deletion = 实例删除 Instance_Deletion_Confirm = 此实例将被永久删除,确定继续? Flavor Deletion = 配置删除 -Flavor_Deletion_Confirm = 此配置将被永久删除,确定继续? +Flavor_Deletion_Confirm = 此配置将被永久删除,确定继续 +Registry Deletion = Registry Deletion +Registry_Deletion_Confirm = This registry is going to be deleted permanently, do you want to continue? FloatingIP Deletion = 浮动IP删除 FloatingIP_Deletion_Confirm = 此浮动IP将被永久删除,确定继续? Gateway Deletion = 网关删除 diff --git a/web/clui/model/registry.go b/web/clui/model/registry.go new file mode 100644 index 00000000..0012874d --- /dev/null +++ b/web/clui/model/registry.go @@ -0,0 +1,22 @@ +/* +Copyright All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package model + +import ( + "github.com/IBM/cloudland/web/sca/dbs" +) + +type Registry struct { + Model + Label string `gorm:"type:varchar(128)"` + OcpVersion string `gorm:"type:varchar(128)"` + RegistryContent string `gorm:"type:varchar(128)"` +} + +func init() { + dbs.AutoMigrate(&Registry{}) +} diff --git a/web/clui/routes/instance.go b/web/clui/routes/instance.go index c10ffd9b..a40d860e 100644 --- a/web/clui/routes/instance.go +++ b/web/clui/routes/instance.go @@ -220,7 +220,7 @@ func (a *InstanceAdmin) Create(ctx context.Context, count int, prefix, userdata } } } - hyperGroup, err := instanceAdmin.getHyperGroup(image.HypervisorType, zoneID) + hyperGroup, err := instanceAdmin.getHyperGroup(image.VirtType, zoneID) if err != nil { log.Println("No valid hypervisor", err) return diff --git a/web/clui/routes/registry.go b/web/clui/routes/registry.go new file mode 100644 index 00000000..2b1df596 --- /dev/null +++ b/web/clui/routes/registry.go @@ -0,0 +1,190 @@ +/* +Copyright All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 + +*/ + +package routes + +import ( + "fmt" + "log" + "net/http" + + "github.com/IBM/cloudland/web/clui/model" + "github.com/IBM/cloudland/web/sca/dbs" + "github.com/go-macaron/session" + macaron "gopkg.in/macaron.v1" +) + +var ( + registryAdmin = &RegistryAdmin{} + registryView = &RegistryView{} +) + +type RegistryAdmin struct{} +type RegistryView struct{} + +func (a *RegistryAdmin) Create(label, ocpVersion, registryContent string) (registry *model.Registry, err error) { + db := DB() + registry = &model.Registry{ + Label: label, + OcpVersion: ocpVersion, + RegistryContent: registryContent, + } + err = db.Create(registry).Error + return +} + +func (a *RegistryAdmin) Delete(id int64) (err error) { + db := DB() + db = db.Begin() + defer func() { + if err == nil { + db.Commit() + } else { + db.Rollback() + } + }() + if err = db.Delete(&model.Registry{Model: model.Model{ID: id}}).Error; err != nil { + log.Println("Failed to delete registry", err) + return + } + return +} + +func (a *RegistryAdmin) List(offset, limit int64, order, query string) (total int64, registrys []*model.Registry, err error) { + db := DB() + if limit == 0 { + limit = 16 + } + + if order == "" { + order = "created_at" + } + if query != "" { + query = fmt.Sprintf("label like '%%%s%%'", query) + } + + registrys = []*model.Registry{} + if err = db.Model(&model.Registry{}).Where(query).Count(&total).Error; err != nil { + return + } + db = dbs.Sortby(db.Offset(offset).Limit(limit), order) + if err = db.Where(query).Find(®istrys).Error; err != nil { + return + } + + return +} + +func (v *RegistryView) List(c *macaron.Context, store session.Store) { + offset := c.QueryInt64("offset") + limit := c.QueryInt64("limit") + if limit == 0 { + limit = 16 + } + order := c.Query("order") + if order == "" { + order = "-created_at" + } + query := c.QueryTrim("q") + total, registrys, err := registryAdmin.List(offset, limit, order, query) + if err != nil { + if c.Req.Header.Get("X-Json-Format") == "yes" { + c.JSON(500, map[string]interface{}{ + "error": err.Error(), + }) + return + } + c.Data["ErrorMsg"] = err.Error() + c.HTML(500, "500") + return + } + pages := GetPages(total, limit) + c.Data["Registrys"] = registrys + c.Data["Total"] = total + c.Data["Pages"] = pages + c.Data["Query"] = query + if c.Req.Header.Get("X-Json-Format") == "yes" { + c.JSON(200, map[string]interface{}{ + "registrys": registrys, + "total": total, + "pages": pages, + "query": query, + }) + return + } + c.HTML(200, "registrys") +} + +func (v *RegistryView) Delete(c *macaron.Context, store session.Store) (err error) { + memberShip := GetMemberShip(c.Req.Context()) + permit := memberShip.CheckPermission(model.Admin) + if !permit { + log.Println("Not authorized for this operation") + c.Data["ErrorMsg"] = "Not authorized for this operation" + c.HTML(http.StatusBadRequest, "error") + return + } + id := c.ParamsInt64("id") + if id <= 0 { + c.Data["ErrorMsg"] = "id <= 0" + c.HTML(http.StatusBadRequest, "error") + return + } + err = registryAdmin.Delete(id) + if err != nil { + c.Data["ErrorMsg"] = err.Error() + c.HTML(http.StatusBadRequest, "error") + return + } + c.JSON(200, map[string]interface{}{ + "redirect": "registrys", + }) + return +} + +func (v *RegistryView) New(c *macaron.Context, store session.Store) { + memberShip := GetMemberShip(c.Req.Context()) + permit := memberShip.CheckPermission(model.Admin) + if !permit { + log.Println("Not authorized for this operation") + c.Data["ErrorMsg"] = "Not authorized for this operation" + c.HTML(http.StatusBadRequest, "error") + return + } + c.HTML(200, "registrys_new") +} + +func (v *RegistryView) Create(c *macaron.Context, store session.Store) { + memberShip := GetMemberShip(c.Req.Context()) + permit := memberShip.CheckPermission(model.Admin) + if !permit { + log.Println("Not authorized for this operation") + c.Data["ErrorMsg"] = "Not authorized for this operation" + c.HTML(http.StatusBadRequest, "error") + return + } + redirectTo := "../registrys" + label := c.Query("label") + ocpVersion := c.Query("ocpversion") + registryContent := c.Query("registrycontent") + registry, err := registryAdmin.Create(label, ocpVersion, registryContent) + if err != nil { + log.Println("Create registry failed", err) + if c.Req.Header.Get("X-Json-Format") == "yes" { + c.JSON(500, map[string]interface{}{ + "error": err.Error(), + }) + return + } + c.HTML(500, "500") + return + } else if c.Req.Header.Get("X-Json-Format") == "yes" { + c.JSON(200, registry) + return + } + c.Redirect(redirectTo) +} diff --git a/web/clui/routes/routes.go b/web/clui/routes/routes.go index 13818fd4..69ca4d57 100644 --- a/web/clui/routes/routes.go +++ b/web/clui/routes/routes.go @@ -135,6 +135,10 @@ func New() (m *macaron.Macaron) { m.Get("/flavors/new", flavorView.New) m.Post("/flavors/new", flavorView.Create) m.Delete("/flavors/:id", flavorView.Delete) + m.Get("/registrys", registryView.List) + m.Get("/registrys/new", registryView.New) + m.Post("/registrys/new", registryView.Create) + m.Delete("/registrys/:id", registryView.Delete) m.Get("/images", imageView.List) m.Get("/images/new", imageView.New) m.Post("/images/new", imageView.Create) diff --git a/web/clui/templates/_left.tmpl b/web/clui/templates/_left.tmpl index 48986d1f..2fd5e9eb 100644 --- a/web/clui/templates/_left.tmpl +++ b/web/clui/templates/_left.tmpl @@ -20,6 +20,11 @@ {{.i18n.Tr "Images"}} + {{ if $.IsAdmin }} + + {{.i18n.Tr "Registry"}} + + {{ end }}
{{.i18n.Tr "Platform_Service"}}
{{.i18n.Tr "Openshift"}} diff --git a/web/clui/templates/images.tmpl b/web/clui/templates/images.tmpl index 0f3703c6..2cb85036 100644 --- a/web/clui/templates/images.tmpl +++ b/web/clui/templates/images.tmpl @@ -49,10 +49,10 @@ {{.CreatedAt}} {{.OsVersion}} - {{ if eq .HypervisorType "zkvm" }} + {{ if eq .VirtType "zkvm" }} KVM on Z {{ else }} - {{ if eq .HypervisorType "zvm" }} + {{ if eq .VirtType "zvm" }} z/VM {{ else }} KVM on x86-64 diff --git a/web/clui/templates/instances_new.tmpl b/web/clui/templates/instances_new.tmpl index 618b1a61..8f074670 100644 --- a/web/clui/templates/instances_new.tmpl +++ b/web/clui/templates/instances_new.tmpl @@ -107,15 +107,15 @@ {{ if eq .Status "available" }}
- {{ if eq .HypervisorType "zvm" }} + {{ if eq .VirtType "zvm" }} {{.Name}} for z/VM - {{ else if eq .HypervisorType "zkvm" }} + {{ else if eq .VirtType "zkvm" }} {{.Name}} for KVM on Z - {{ else if eq .HypervisorType "xkvm" }} + {{ else if eq .VirtType "xkvm" }} {{.Name}} for KVM on x86-64 diff --git a/web/clui/templates/registrys.tmpl b/web/clui/templates/registrys.tmpl new file mode 100644 index 00000000..1ec671db --- /dev/null +++ b/web/clui/templates/registrys.tmpl @@ -0,0 +1,71 @@ +{{template "_head" .}} +
+
+
+ {{template "_left" .}} +
+

+ {{.i18n.Tr "Registry_Manage_Panel"}} ({{.i18n.Tr "Total"}}: {{.Total}}) + +

+
+
+
+ + +
+
+
+
+ + + + + + + + + + + + {{ $Link := .Link }} + {{ range .Registrys }} + + + + + + + + {{ end }} + +
{{.i18n.Tr "ID"}}{{.i18n.Tr "Label"}}{{.i18n.Tr "OcpVersion"}}{{.i18n.Tr "RegistryContent"}}{{.i18n.Tr "Delete"}}
{{.ID}}{{.Label}}{{.OcpVersion}}{{.RegistryContent}}
+
+
+ {{ if .Pages}} + + {{ end }} +
+
+
+
+
+ +{{template "_footer" .}} diff --git a/web/clui/templates/registrys_new.tmpl b/web/clui/templates/registrys_new.tmpl new file mode 100644 index 00000000..52595a5d --- /dev/null +++ b/web/clui/templates/registrys_new.tmpl @@ -0,0 +1,59 @@ +{{template "_head" .}} +
+ +
+ +
+ + {{template "_left" .}} + +
+
+
+{{template "_footer" .}} +