Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/grafana/rmf-app/oxygen-webhelp/app/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ define(function() {

if(id === 'index-1' || id === 'index-2' || id === 'index-3' || id === 'stopwords'
||id === 'htmlFileInfoList' || id === 'keywords') {
args = '20250529171030';
args = '20250725185622';
}

return (url.indexOf('?') === -1 ? '?' : '&') + args;
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Binary file modified docs/grafana/rmf-app/pdf/rmf_grafana.pdf
Binary file not shown.
27 changes: 27 additions & 0 deletions docs/grafana/rmf-app/rn.html
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,33 @@ <h1 class="- topic/title title topictitle1" id="ariaid-title1">Release notes</h1
<span class="- topic/tm tm">IBM<span class="- topic/tmmark tmmark ">®</span></span> RMF for z/OS Grafana plugin.</p>
<section class="- topic/section section" id="rn__section_y2g_rfq_pyb" data-ofbid="rn__section_y2g_rfq_pyb"><h2 class="- topic/title title sectiontitle">What's new</h2>

<dl class="- topic/dl dl" id="rn__dl_w3g_byf_cgc" data-ofbid="rn__dl_w3g_byf_cgc">

<dt class="- topic/dt dt dlterm">July 2025 v1.0.11</dt>
<dd class="- topic/dd dd">
<ul class="- topic/ul ul" id="rn__ul_zv3_11g_cgc" data-ofbid="rn__ul_zv3_11g_cgc">
<li class="- topic/li li">Fixed issues that caused dashboards showing maximum 20 systems per
sysplex.</li>
<li class="- topic/li li">
<div class="- topic/p p">The following dashboards are updated:<ul class="- topic/ul ul" id="rn__ul_rbt_c1g_cgc" data-ofbid="rn__ul_rbt_c1g_cgc">
<li class="- topic/li li">Common Storage Activity (Timeline)</li>
<li class="- topic/li li">Common Storage Activity</li>
<li class="- topic/li li">General Activity (Timeline)</li>
<li class="- topic/li li">General Activity</li>
<li class="- topic/li li">Overall Image Activity (Timeline)</li>
<li class="- topic/li li">Overall Image Activity</li>
</ul><div class="- topic/note note note note_note" id="rn__note_sbt_c1g_cgc" data-ofbid="rn__note_sbt_c1g_cgc"><span class="note__title">Note:</span> You may need to re-import the
dashboards to utilize the latest enhancements in the
dashboards, depending on your installation
method.</div></div>
</li>
<li class="- topic/li li">
<p class="- topic/p p">Fixed internally found defects.</p>
</li>
</ul>
</dd>

</dl>
<dl class="- topic/dl dl" id="rn__dl_sdl_gr3_mfc" data-ofbid="rn__dl_sdl_gr3_mfc">

<dt class="- topic/dt dt dlterm">May 2025 v1.0.10</dt>
Expand Down
14 changes: 14 additions & 0 deletions grafana/rmf-app/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Change Log

## 1.0.11 (2025-07-25)

- Fixed issues that caused dashboards showing maximum 20 systems per sysplex.
- The following dashboards are updated:
- Common Storage Activity (Timeline)
- Common Storage Activity
- General Activity (Timeline)
- General Activity
- Overall Image Activity (Timeline)
- Overall Image Activity

**Note:** You may need to re-import the dashboards to utilize the latest enhancements in the dashboards, depending on your installation method.
- Fixed internally found defects.

## 1.0.10 (2025-05-30)

- Fixed a Windows-specific regression that caused the plugin to serve data points with the incorrect TZ offset.
Expand Down
8,805 changes: 7,448 additions & 1,357 deletions grafana/rmf-app/NOTICES

Large diffs are not rendered by default.

Binary file modified grafana/rmf-app/doc/src/pdf/rmf_grafana.pdf
Binary file not shown.
27 changes: 27 additions & 0 deletions grafana/rmf-app/doc/src/rn.dita
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,33 @@
<refbody>
<section id="section_y2g_rfq_pyb">
<title>What's new</title>
<dl id="dl_w3g_byf_cgc">
<dlentry>
<dt>July 2025 v1.0.11</dt>
<dd>
<ul id="ul_zv3_11g_cgc">
<li>Fixed issues that caused dashboards showing maximum 20 systems per
sysplex.</li>
<li>
<p>The following dashboards are updated:<ul id="ul_rbt_c1g_cgc">
<li>Common Storage Activity (Timeline)</li>
<li>Common Storage Activity</li>
<li>General Activity (Timeline)</li>
<li>General Activity</li>
<li>Overall Image Activity (Timeline)</li>
<li>Overall Image Activity</li>
</ul><note id="note_sbt_c1g_cgc">You may need to re-import the
dashboards to utilize the latest enhancements in the
dashboards, depending on your installation
method.</note></p>
</li>
<li>
<p conref="conref.dita#conref/p_lxj_4jw_hfc"/>
</li>
</ul>
</dd>
</dlentry>
</dl>
<dl id="dl_sdl_gr3_mfc">
<dlentry>
<dt>May 2025 v1.0.10</dt>
Expand Down
4 changes: 0 additions & 4 deletions grafana/rmf-app/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
services:
grafana:
user: root
container_name: 'ibm-rmf'

build:
Expand All @@ -12,9 +11,6 @@ services:
ports:
- 3000:3000/tcp
- 2345:2345/tcp # delve
security_opt:
- 'apparmor:unconfined'
- 'seccomp:unconfined'
cap_add:
- SYS_PTRACE
volumes:
Expand Down
44 changes: 22 additions & 22 deletions grafana/rmf-app/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"author": "IBM",
"name": "ibm-rmf",
"version": "1.0.10",
"version": "1.0.11",
"description": "IBM RMF for z/OS",
"license": "Apache-2.0",
"scripts": {
Expand All @@ -28,39 +28,39 @@
"upgrade": "yarn upgrade --latest"
},
"devDependencies": {
"@babel/core": "^7.27.1",
"@grafana/eslint-config": "^8.0.0",
"@babel/core": "^7.28.0",
"@grafana/eslint-config": "^8.1.0",
"@grafana/tsconfig": "^2.0.0",
"@playwright/test": "^1.52.0",
"@swc/core": "^1.11.24",
"@playwright/test": "^1.53.2",
"@swc/core": "^1.12.11",
"@swc/helpers": "^0.5.17",
"@swc/jest": "^0.2.38",
"@swc/jest": "^0.2.39",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@types/jest": "^29.5.14",
"@types/lodash": "^4.17.16",
"@types/node": "^22.15.17",
"@types/jest": "^30.0.0",
"@types/lodash": "^4.17.20",
"@types/node": "^24.0.12",
"@types/react-router-dom": "^5.3.3",
"copy-webpack-plugin": "^13.0.0",
"css-loader": "^7.1.2",
"eslint-plugin-deprecation": "^3.0.0",
"eslint-webpack-plugin": "^5.0.1",
"eslint-webpack-plugin": "^5.0.2",
"fork-ts-checker-webpack-plugin": "^9.1.0",
"glob": "^11.0.2",
"glob": "^11.0.3",
"identity-obj-proxy": "^3.0.0",
"imports-loader": "^5.0.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"prettier": "^3.5.3",
"jest": "^30.0.4",
"jest-environment-jsdom": "^30.0.4",
"prettier": "^3.6.2",
"replace-in-file-webpack-plugin": "^1.0.6",
"sass": "^1.87.0",
"sass": "^1.89.2",
"sass-loader": "^16.0.5",
"style-loader": "^4.0.0",
"swc-loader": "^0.2.6",
"ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.8.3",
"webpack": "^5.99.8",
"webpack": "^5.99.9",
"webpack-cli": "^6.0.1",
"webpack-livereload-plugin": "^3.0.2",
"webpack-virtual-modules": "^0.6.2"
Expand All @@ -70,16 +70,16 @@
},
"dependencies": {
"@emotion/css": "^11.13.5",
"@grafana/data": "^12.0.0",
"@grafana/runtime": "^12.0.0",
"@grafana/schema": "^12.0.0",
"@grafana/ui": "^12.0.0",
"@grafana/data": "^12.0.2",
"@grafana/runtime": "^12.0.2",
"@grafana/schema": "^12.0.2",
"@grafana/ui": "^12.0.2",
"antlr4": "^4.13.2",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-router-dom": "^7.6.0",
"react-router-dom": "^7.6.3",
"rxjs": "^7.8.2",
"tslib": "^2.8.1"
},
"packageManager": "[email protected].1"
"packageManager": "[email protected].2"
}
94 changes: 66 additions & 28 deletions grafana/rmf-app/pkg/plugin/dds/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ import (
"errors"
"fmt"
"io"
"mime"
"net/http"
"net/url"
"strings"
"sync"
"sync/atomic"
"time"

"github.com/IBM/RMF/grafana/rmf-app/pkg/plugin/log"
Expand All @@ -38,13 +40,20 @@ const UpdateInterval = 15 * time.Minute
const DefaultTimeOffset = 0
const DefaultMinTime = 100

const IndexPath = "/gpm/index.xml"
const RootPath = "/gpm/root.xml"
const ContainedPath = "/gpm/contained.xml"
const PerformPath = "/gpm/perform.xml"
const IndexPath = "/gpm/index"
const RootPath = "/gpm/root"
const ContainedPath = "/gpm/contained"
const PerformPath = "/gpm/perform"
const XslHeadersPath = "/gpm/include/reptrans.xsl"
const FullReportPath = "/gpm/rmfm3.xml"
const FullReportPath = "/gpm/rmfm3"

var MayHaveExt = map[string]bool{
IndexPath: true,
RootPath: true,
ContainedPath: true,
PerformPath: true,
FullReportPath: true,
}
var ErrParse = errors.New("unable to parse DDS response")
var ErrUnauthorized = errors.New("not authorized to access DDS")

Expand All @@ -55,6 +64,7 @@ type Client struct {
httpClient *http.Client
headerMap *HeaderMap
timeData *TimeData
useXmlExt atomic.Bool

stopChan chan struct{}
closeOnce sync.Once
Expand Down Expand Up @@ -142,6 +152,14 @@ func (c *Client) Get(path string, params ...string) (*Response, error) {

func (c *Client) GetRaw(path string, params ...string) ([]byte, error) {
logger := log.Logger.With("func", "GetRaw")

_, mayHaveExt := MayHaveExt[path]
useXmlExt := c.useXmlExt.Load()
ofs := 0
if useXmlExt {
ofs = 1
}

path = strings.TrimLeft(path, "/")
values := url.Values{}
for i := 0; i < len(params)-1; i += 2 {
Expand All @@ -150,30 +168,50 @@ func (c *Client) GetRaw(path string, params ...string) ([]byte, error) {
}
values.Add(params[i], params[i+1])
}
fullURL := fmt.Sprintf("%s/%s?%s", c.baseUrl, path, values.Encode())
// nolint:noctx
req, err := http.NewRequest(http.MethodGet, fullURL, http.NoBody)
if err != nil {
return nil, err
}
req.Header.Add("Accept", "application/json")
if strings.TrimSpace(c.username) != "" {
req.SetBasicAuth(c.username, c.password)
}
logger.Debug("requesting DDS data", "url", fullURL)
response, err := c.httpClient.Do(req)
if err != nil {
logger.Debug("failed to fetch DDS data", "error", err)
return nil, err
}
logger.Debug("fetched DDS data", "url", fullURL, "status", response.Status)
if response.StatusCode == http.StatusUnauthorized {
return nil, ErrUnauthorized
} else if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected HTTP status (%s)", response.Status)

// Newer versions of DDS have JSON endpoints without the XML extension.
// Also, it may run in a mode not fully compliant with HTTP emulating DDS v1 behavior.
// We need to support either variation.
for i := range 2 {
if mayHaveExt && (i+ofs)%2 == 1 {
path += ".xml"
}
fullURL := fmt.Sprintf("%s/%s?%s", c.baseUrl, path, values.Encode())
// nolint:noctx
req, err := http.NewRequest(http.MethodGet, fullURL, http.NoBody)
if err != nil {
return nil, err
}
req.Header.Add("Accept", "application/json")
if strings.TrimSpace(c.username) != "" {
req.SetBasicAuth(c.username, c.password)
}
logger.Debug("requesting DDS data", "url", fullURL)
response, err := c.httpClient.Do(req)
if err != nil {
logger.Debug("failed to fetch DDS data", "error", err)
return nil, err
}
logger.Debug("fetched DDS data", "url", fullURL, "status", response.Status)
mediaType, _, err := mime.ParseMediaType(response.Header.Get("Content-Type"))
if response.StatusCode == http.StatusUnauthorized {
return nil, ErrUnauthorized
} else if mayHaveExt && i == 0 &&
( // DDS v2 version without JSON only endpoints (no extention)
response.StatusCode == http.StatusNotFound ||
// Future DDS v2 version without JSON support for old XML endpoints
response.StatusCode == http.StatusNotAcceptable ||
// DDS v1 compatible mode
err != nil || mediaType != "application/json") {
c.useXmlExt.Store(!useXmlExt)
continue
} else if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected HTTP status (%s)", response.Status)
}
defer response.Body.Close()
return io.ReadAll(response.Body)
}
defer response.Body.Close()
return io.ReadAll(response.Body)
return nil, errors.New("unexpected return while requesting DDS data")
}

func (c *Client) GetRawIndex(ctx context.Context) ([]byte, error) {
Expand Down
Loading
Loading