Skip to content

Commit

Permalink
Merge branch 'cloud-barista:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
yby654 authored Jul 29, 2024
2 parents 264f03b + e0725c0 commit fd37bfc
Show file tree
Hide file tree
Showing 43 changed files with 2,581 additions and 894 deletions.
73 changes: 56 additions & 17 deletions api-runtime/common-runtime/VMManager.go
Original file line number Diff line number Diff line change
Expand Up @@ -1364,7 +1364,7 @@ func ListVMStatus(connectionName string, rsType string) ([]*cres.VMStatusInfo, e
return infoList, nil
}

// (2) get VMStatusInfo List with iidInoList
// (2) get VMStatusInfo List with iidInfoList
infoList2 := []*cres.VMStatusInfo{}
for _, iidInfo := range iidInfoList {

Expand All @@ -1373,17 +1373,36 @@ func ListVMStatus(connectionName string, rsType string) ([]*cres.VMStatusInfo, e
*/

// 2. get CSP:VMStatus(SystemId)
statusInfo, err := handler.GetVMStatus(getDriverIID(cres.IID{NameId: iidInfo.NameId, SystemId: iidInfo.SystemId}))
if err != nil {
//vmSPLock.RUnlock(connectionName, iidInfo.IId.NameId)
if checkNotFoundError(err) {
cblog.Info(err)
continue
var statusInfo cres.VMStatus
driverIID := getDriverIID(cres.IID{NameId: iidInfo.NameId, SystemId: iidInfo.SystemId})

// need to wait for https://github.com/cloud-barista/cb-spider/pull/1244#issuecomment-2253741979
waiter := NewWaiter(3, 60) // 3 seconds sleep, 60 seconds timeout

for {
statusInfo, err = handler.GetVMStatus(driverIID)
if statusInfo == cres.NotExist {
err = fmt.Errorf("Not Found %s", driverIID.SystemId)
}
if err != nil {
if checkNotFoundError(err) {
statusInfo = cres.NotExist
break
}
cblog.Error(err)
return nil, err
}

if statusInfo == cres.Creating || statusInfo == cres.Running || statusInfo == cres.Suspending || statusInfo == cres.Suspended ||
statusInfo == cres.Resuming || statusInfo == cres.Rebooting || statusInfo == cres.Terminating || statusInfo == cres.Terminated ||
statusInfo == cres.NotExist || statusInfo == cres.Failed {
break
}

if !waiter.Wait() {
return nil, fmt.Errorf("Unable to provide current VM status for VM '%s'. Timeout after %v seconds", iidInfo.NameId, waiter.Timeout)
}
cblog.Error(err)
return nil, err
}
//vmSPLock.RUnlock(connectionName, iidInfo.IId.NameId)

infoList2 = append(infoList2, &cres.VMStatusInfo{IId: getUserIID(cres.IID{NameId: iidInfo.NameId, SystemId: iidInfo.SystemId}), VmStatus: statusInfo})
}
Expand Down Expand Up @@ -1433,14 +1452,34 @@ func GetVMStatus(connectionName string, rsType string, nameID string) (cres.VMSt
return "", err
}

// (2) get CSP:VMStatus(SystemId)
info, err := handler.GetVMStatus(getDriverIID(cres.IID{NameId: iidInfo.NameId, SystemId: iidInfo.SystemId}))
if err != nil {
cblog.Error(err)
return "", err
}
driverIID := getDriverIID(cres.IID{NameId: iidInfo.NameId, SystemId: iidInfo.SystemId})

return info, nil
// need to wait for https://github.com/cloud-barista/cb-spider/pull/1244#issuecomment-2253741979
waiter := NewWaiter(3, 60) // 3 seconds sleep, 60 seconds timeout

for {
info, err := handler.GetVMStatus(driverIID)
if info == cres.NotExist {
err = fmt.Errorf("Not Found %s", driverIID.SystemId)
}
if err != nil {
if checkNotFoundError(err) {
return "", err
}
cblog.Error(err)
return "", err
}

if info == cres.Creating || info == cres.Running || info == cres.Suspending || info == cres.Suspended ||
info == cres.Resuming || info == cres.Rebooting || info == cres.Terminating || info == cres.Terminated ||
info == cres.NotExist || info == cres.Failed {
return info, nil
}

if !waiter.Wait() {
return "", fmt.Errorf("Unable to provide current VM status for VM '%s'. Timeout after %v seconds", nameID, waiter.Timeout)
}
}
}

// (1) get IID(NameId)
Expand Down
93 changes: 61 additions & 32 deletions api-runtime/rest-runtime/admin-web/AdminWeb-Dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"net/http"
"os"
"path/filepath"
"sort"
"sync"

cr "github.com/cloud-barista/cb-spider/api-runtime/common-runtime"
"github.com/labstack/echo/v4"
Expand Down Expand Up @@ -36,7 +38,7 @@ type DashboardData struct {
ShowEmpty bool
}

// Add a function to filter out empty connections
// Filter out empty connections
func filterEmptyConnections(resourceCounts map[string][]ResourceCounts) map[string][]ResourceCounts {
filteredCounts := make(map[string][]ResourceCounts)
for provider, counts := range resourceCounts {
Expand All @@ -55,28 +57,17 @@ func filterEmptyConnections(resourceCounts map[string][]ResourceCounts) map[stri
return filteredCounts
}

// // Fetch all providers
// func fetchProviders() ([]string, error) {
// resp, err := http.Get("http://localhost:1024/spider/cloudos")
// if err != nil {
// return nil, fmt.Errorf("error fetching providers: %v", err)
// }
// defer resp.Body.Close()

// var providers Providers
// if err := json.NewDecoder(resp.Body).Decode(&providers); err != nil {
// return nil, fmt.Errorf("error decoding providers: %v", err)
// }

// return providers.Providers, nil
// }

type CountResponse struct {
Count int `json:"count"`
}

// Fetch resource counts using specific connection names
func fetchResourceCounts(config ConnectionConfig) (ResourceCounts, error) {
func fetchResourceCounts(config ConnectionConfig, provider string, wg *sync.WaitGroup, countsChan chan<- struct {
Provider string
Counts ResourceCounts
}, errorChan chan<- error) {
defer wg.Done()

var counts ResourceCounts
counts.ConnectionName = config.ConfigName

Expand All @@ -87,16 +78,19 @@ func fetchResourceCounts(config ConnectionConfig) (ResourceCounts, error) {
url := fmt.Sprintf("%s/count%s/%s", baseURL, resource, config.ConfigName)
resp, err := http.Get(url)
if err != nil {
return counts, fmt.Errorf("error fetching %s count for %s: %v", resource, config.ConfigName, err)
errorChan <- fmt.Errorf("error fetching %s count for %s: %v", resource, config.ConfigName, err)
return
}
defer resp.Body.Close()

var response CountResponse
if resp.StatusCode != http.StatusOK {
return counts, fmt.Errorf("received non-OK status %d while fetching %s count for %s", resp.StatusCode, resource, config.ConfigName)
errorChan <- fmt.Errorf("received non-OK status %d while fetching %s count for %s", resp.StatusCode, resource, config.ConfigName)
return
}
if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
return counts, fmt.Errorf("error decoding %s count for %s: %v", resource, config.ConfigName, err)
errorChan <- fmt.Errorf("error decoding %s count for %s: %v", resource, config.ConfigName, err)
return
}

switch resource {
Expand All @@ -120,7 +114,22 @@ func fetchResourceCounts(config ConnectionConfig) (ResourceCounts, error) {
counts.MyImages = response.Count
}
}
return counts, nil
countsChan <- struct {
Provider string
Counts ResourceCounts
}{Provider: provider, Counts: counts}
}

// Template cache
var tmplCache *template.Template

func init() {
templatePath := filepath.Join(os.Getenv("CBSPIDER_ROOT"), "/api-runtime/rest-runtime/admin-web/html/dashboard.html")
tmpl, err := template.ParseFiles(templatePath)
if err != nil {
panic(fmt.Errorf("error loading template: %v", err))
}
tmplCache = tmpl
}

// Dashboard renders the dashboard page.
Expand All @@ -143,24 +152,44 @@ func Dashboard(c echo.Context) error {
}

resourceCounts := make(map[string][]ResourceCounts)
var wg sync.WaitGroup
countsChan := make(chan struct {
Provider string
Counts ResourceCounts
}, len(connectionConfigs))
errorChan := make(chan error, len(connectionConfigs))

for provider, configs := range connectionConfigs {
for _, config := range configs {
counts, err := fetchResourceCounts(config)
if err != nil {
continue // Optionally handle error
}
resourceCounts[provider] = append(resourceCounts[provider], counts)
wg.Add(1)
go fetchResourceCounts(config, provider, &wg, countsChan, errorChan)
}
}

go func() {
wg.Wait()
close(countsChan)
close(errorChan)
}()

for result := range countsChan {
resourceCounts[result.Provider] = append(resourceCounts[result.Provider], result.Counts)
}

// Handle errors
for err := range errorChan {
fmt.Println("Error:", err)
}

if !showEmpty {
resourceCounts = filterEmptyConnections(resourceCounts)
}

templatePath := filepath.Join(os.Getenv("CBSPIDER_ROOT"), "/api-runtime/rest-runtime/admin-web/html/dashboard.html")
tmpl, err := template.ParseFiles(templatePath)
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "Error loading template"})
// Sort the resource counts for each provider by ConnectionName
for provider := range resourceCounts {
sort.Slice(resourceCounts[provider], func(i, j int) bool {
return resourceCounts[provider][i].ConnectionName < resourceCounts[provider][j].ConnectionName
})
}

data := DashboardData{
Expand All @@ -170,5 +199,5 @@ func Dashboard(c echo.Context) error {
ShowEmpty: showEmpty,
}

return tmpl.Execute(c.Response().Writer, data)
return tmplCache.Execute(c.Response().Writer, data)
}
4 changes: 2 additions & 2 deletions api-runtime/rest-runtime/admin-web/AdminWeb-VM.go
Original file line number Diff line number Diff line change
Expand Up @@ -590,8 +590,8 @@ func VM(c echo.Context) error {
imageName = "16681742-f408-444d-a430-dd21a4bef42c"
specName = "ETRI-small-2"
case "NCP":
imageName = "SPSW0LINUX000052"
specName = "SPSVRHICPUSSD002"
imageName = "SPSW0LINUX000139"
specName = "SPSVRSTAND000005"
case "NCPVPC":
imageName = "SW.VSVR.OS.LNX64.UBNTU.SVR2004.B050"
specName = "SVR.VSVR.HICPU.C004.M008.NET.SSD.B050.G002"
Expand Down
32 changes: 20 additions & 12 deletions api-runtime/rest-runtime/admin-web/html/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,8 @@ <h1>Multi-Cloud Dashboard</h1>
</div>
</div>
<div class="content">
{{range $provider, $counts := .ResourceCounts}}
{{range $provider := .Providers}}
{{if or $.ShowEmpty (index $.ResourceCounts $provider)}}
<h2>{{$provider}}</h2>
<table>
<tr>
Expand All @@ -242,22 +243,29 @@ <h2>{{$provider}}</h2>
<th>NLBs</th>
<th>Clusters</th>
</tr>
{{range $counts}}
{{if index $.ResourceCounts $provider}}
{{range $count := index $.ResourceCounts $provider}}
<tr>
<td>{{$count.ConnectionName}}</td>
<td class="{{if gt $count.VPCs 0}}highlight{{end}}"><a href="#" onclick="openOverlay('http://{{$.ServerIP}}/spider/adminweb/vpc/{{$count.ConnectionName}}'); return false;">{{$count.VPCs}}</a></td>
<td class="{{if gt $count.Subnets 0}}highlight{{end}}">{{$count.Subnets}}</td>
<td class="{{if gt $count.SecurityGroups 0}}highlight{{end}}"><a href="#" onclick="openOverlay('http://{{$.ServerIP}}/spider/adminweb/securitygroup/{{$count.ConnectionName}}'); return false;">{{$count.SecurityGroups}}</a></td>
<td class="{{if gt $count.KeyPairs 0}}highlight{{end}}"><a href="#" onclick="openOverlay('http://{{$.ServerIP}}/spider/adminweb/keypair/{{$count.ConnectionName}}'); return false;">{{$count.KeyPairs}}</a></td>
<td class="{{if gt $count.VMs 0}}highlight-vms{{end}}"><a href="#" onclick="openOverlay('http://{{$.ServerIP}}/spider/adminweb/vm/{{$count.ConnectionName}}'); return false;">{{$count.VMs}}</a></td>
<td class="{{if gt $count.Disks 0}}highlight{{end}}"><a href="#" onclick="openOverlay('http://{{$.ServerIP}}/spider/adminweb/disk/{{$count.ConnectionName}}'); return false;">{{$count.Disks}}</a></td>
<td class="{{if gt $count.MyImages 0}}highlight{{end}}"><a href="#" onclick="openOverlay('http://{{$.ServerIP}}/spider/adminweb/myimage/{{$count.ConnectionName}}'); return false;">{{$count.MyImages}}</a></td>
<td class="{{if gt $count.NetworkLoadBalancers 0}}highlight{{end}}"><a href="#" onclick="openOverlay('http://{{$.ServerIP}}/spider/adminweb/nlb/{{$count.ConnectionName}}'); return false;">{{$count.NetworkLoadBalancers}}</a></td>
<td class="{{if gt $count.Clusters 0}}highlight-clusters{{end}}"><a href="#" onclick="openOverlay('http://{{$.ServerIP}}/spider/adminweb/cluster/{{$count.ConnectionName}}'); return false;">{{$count.Clusters}}</a></td>
</tr>
{{end}}
{{else}}
<tr>
<td>{{.ConnectionName}}</td>
<td class="{{if gt .VPCs 0}}highlight{{end}}"><a href="#" onclick="openOverlay('http://{{$.ServerIP}}/spider/adminweb/vpc/{{.ConnectionName}}'); return false;">{{.VPCs}}</a></td>
<td class="{{if gt .Subnets 0}}highlight{{end}}">{{.Subnets}}</td>
<td class="{{if gt .SecurityGroups 0}}highlight{{end}}"><a href="#" onclick="openOverlay('http://{{$.ServerIP}}/spider/adminweb/securitygroup/{{.ConnectionName}}'); return false;">{{.SecurityGroups}}</a></td>
<td class="{{if gt .KeyPairs 0}}highlight{{end}}"><a href="#" onclick="openOverlay('http://{{$.ServerIP}}/spider/adminweb/keypair/{{.ConnectionName}}'); return false;">{{.KeyPairs}}</a></td>
<td class="{{if gt .VMs 0}}highlight-vms{{end}}"><a href="#" onclick="openOverlay('http://{{$.ServerIP}}/spider/adminweb/vm/{{.ConnectionName}}'); return false;">{{.VMs}}</a></td>
<td class="{{if gt .Disks 0}}highlight{{end}}"><a href="#" onclick="openOverlay('http://{{$.ServerIP}}/spider/adminweb/disk/{{.ConnectionName}}'); return false;">{{.Disks}}</a></td>
<td class="{{if gt .MyImages 0}}highlight{{end}}"><a href="#" onclick="openOverlay('http://{{$.ServerIP}}/spider/adminweb/myimage/{{.ConnectionName}}'); return false;">{{.MyImages}}</a></td>
<td class="{{if gt .NetworkLoadBalancers 0}}highlight{{end}}"><a href="#" onclick="openOverlay('http://{{$.ServerIP}}/spider/adminweb/nlb/{{.ConnectionName}}'); return false;">{{.NetworkLoadBalancers}}</a></td>
<td class="{{if gt .Clusters 0}}highlight-clusters{{end}}"><a href="#" onclick="openOverlay('http://{{$.ServerIP}}/spider/adminweb/cluster/{{.ConnectionName}}'); return false;">{{.Clusters}}</a></td>
<td colspan="10">No connections found for {{$provider}}</td>
</tr>
{{end}}
</table>
{{end}}
{{end}}
</div>
</body>
</html>
16 changes: 13 additions & 3 deletions api-runtime/rest-runtime/admin-web/html/left_menu.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8">
<style>
.menu-item {
margin: 10px 0;
margin: 3px 0; /* Further reduced margin */
padding: 10px;
font-size: 12px;
font-weight: bold;
Expand All @@ -20,17 +20,23 @@
}
.menu-item img {
vertical-align: middle;
height: 35px; /* Set height to 40px */
height: 30px; /* Set height to 30px */
width: auto; /* Maintain aspect ratio */
}
.logo img {
height: 47px; /* Set height to 50px */
height: 47px; /* Set height to 47px */
width: auto; /* Maintain aspect ratio */
}
.menu-text {
margin-top: 0; /* Remove or minimize the top margin */
text-align: center;
}
.divider {
width: 80%;
height: 1px;
background-color: #ccc;
margin: 5px auto; /* Add margin to separate the divider and center it */
}
</style>
<script>
function checkConnectionAndRedirect(menu, event) {
Expand Down Expand Up @@ -107,6 +113,7 @@
<a href="/spider/adminweb2" target="_top" class="menu-item logo">
<img src="./images/logo.png" border="0">
</a>
<div class="divider"></div> <!-- Divider after logo -->
<div class="menu-item" onclick="selectLeftMenu('dashboard')">
<img id="dashboard-img" src="./images/left-menu/dashboard.png" alt="Dashboard Icon">
<div class="menu-text">Dashboard</div>
Expand All @@ -115,6 +122,7 @@
<img id="connection-img" src="./images/left-menu/connection.png" alt="Connection Icon">
<div class="menu-text">Connection</div>
</div>
<div class="divider"></div> <!-- Divider after Connection -->
<div class="menu-item" onclick="checkConnectionAndRedirect('vpc', event)">
<img id="vpc-img" src="./images/left-menu/vpc.png" alt="VPC/Subnet Icon">
<div class="menu-text">VPC/Subnet</div>
Expand All @@ -127,6 +135,7 @@
<img id="keypair-img" src="./images/left-menu/keypair.png" alt="KeyPair Icon">
<div class="menu-text">KeyPair</div>
</div>
<div class="divider"></div> <!-- Divider after Keypair -->
<div class="menu-item" onclick="checkConnectionAndRedirect('vm', event)">
<img id="vm-img" src="./images/left-menu/vm.png" alt="VM Icon">
<div class="menu-text">VM</div>
Expand All @@ -143,6 +152,7 @@
<img id="nlb-img" src="./images/left-menu/nlb.png" alt="NLB Icon">
<div class="menu-text">NLB</div>
</div>
<div class="divider"></div> <!-- Divider after NLB -->
<div class="menu-item" onclick="checkConnectionAndRedirect('cluster', event)">
<img id="cluster-img" src="./images/left-menu/cluster.png" alt="Cluster Icon">
<div class="menu-text">Cluster</div>
Expand Down
2 changes: 1 addition & 1 deletion api-runtime/rest-runtime/admin-web/html/main.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
height: 100%;
}
.left-menu {
width: 150px;
width: 120px; /* Set width to 120px */
border-right: 1px solid #ccc;
height: 100%;
flex-shrink: 0;
Expand Down
Loading

0 comments on commit fd37bfc

Please sign in to comment.