Compare commits
No commits in common. 'c9' and 'c8' have entirely different histories.
@ -1,23 +1,22 @@
|
||||
SOURCES/backports-3.25.0.gem
|
||||
SOURCES/base64-0.2.0.gem
|
||||
SOURCES/childprocess-5.0.0.gem
|
||||
SOURCES/HAM-logo.png
|
||||
SOURCES/backports-3.24.1.gem
|
||||
SOURCES/dacite-1.8.1.tar.gz
|
||||
SOURCES/dataclasses-0.8.tar.gz
|
||||
SOURCES/ethon-0.16.0.gem
|
||||
SOURCES/ffi-1.16.3.gem
|
||||
SOURCES/mustermann-3.0.0.gem
|
||||
SOURCES/nio4r-2.7.3.gem
|
||||
SOURCES/pcs-0.11.8.tar.gz
|
||||
SOURCES/pcs-web-ui-0.1.20.tar.gz
|
||||
SOURCES/pcs-web-ui-node-modules-0.1.20.tar.xz
|
||||
SOURCES/puma-6.4.2.gem
|
||||
SOURCES/json-2.6.3.gem
|
||||
SOURCES/mustermann-2.0.2.gem
|
||||
SOURCES/nio4r-2.5.9.gem
|
||||
SOURCES/open4-1.3.4-1.gem
|
||||
SOURCES/pcs-0.10.18.tar.gz
|
||||
SOURCES/puma-6.4.0.gem
|
||||
SOURCES/pyagentx-0.4.pcs.2.tar.gz
|
||||
SOURCES/rack-3.0.11.gem
|
||||
SOURCES/rack-protection-4.0.0.gem
|
||||
SOURCES/rack-session-2.0.0.gem
|
||||
SOURCES/python-dateutil-2.8.2.tar.gz
|
||||
SOURCES/rack-2.2.8.1.gem
|
||||
SOURCES/rack-protection-2.2.4.gem
|
||||
SOURCES/rack-test-2.1.0.gem
|
||||
SOURCES/rackup-2.1.0.gem
|
||||
SOURCES/rexml-3.3.6.gem
|
||||
SOURCES/ruby2_keywords-0.0.5.gem
|
||||
SOURCES/sinatra-4.0.0.gem
|
||||
SOURCES/sinatra-2.2.4.gem
|
||||
SOURCES/tilt-2.3.0.gem
|
||||
SOURCES/tornado-6.4.0.tar.gz
|
||||
SOURCES/webrick-1.8.1.gem
|
||||
SOURCES/tornado-6.1.0.tar.gz
|
||||
|
@ -1,23 +1,22 @@
|
||||
7bfaf5b42c0992bbc5055d7bd4013f0ca4731775 SOURCES/backports-3.25.0.gem
|
||||
ea3a591bdfa93655d8eec9d7bdd7fb87ecb5616a SOURCES/base64-0.2.0.gem
|
||||
8f910640f84d085707138aa70d6eedb7df10ca73 SOURCES/childprocess-5.0.0.gem
|
||||
679a4ce22a33ffd4d704261a17c00cff98d9499a SOURCES/HAM-logo.png
|
||||
0ef72a288913e220695ad62718aeb75171924028 SOURCES/backports-3.24.1.gem
|
||||
07b26abbf7ff0dcba5c7f9e814ff7eebafefb058 SOURCES/dacite-1.8.1.tar.gz
|
||||
8b7598273d2ae6dad2b88466aefac55071a41926 SOURCES/dataclasses-0.8.tar.gz
|
||||
5b56a68268708c474bef04550639ded3add5e946 SOURCES/ethon-0.16.0.gem
|
||||
10e4cf0e11ef4581ec4ad5fe2cdf3c78b6077d39 SOURCES/ffi-1.16.3.gem
|
||||
e892678aaf02ccb27f3a6cd58482cda00aea6ce8 SOURCES/mustermann-3.0.0.gem
|
||||
632c455f6e27a5f568e9d24761b8a4246cfcc603 SOURCES/nio4r-2.7.3.gem
|
||||
ee97cec01761e5b727a265eb551d784dfdc6f548 SOURCES/pcs-0.11.8.tar.gz
|
||||
c75288254b282cb8aed7307fd18dbdd8dda9252d SOURCES/pcs-web-ui-0.1.20.tar.gz
|
||||
1dbe81ac08cfe60da25cc8650292cdc7c33cdb89 SOURCES/pcs-web-ui-node-modules-0.1.20.tar.xz
|
||||
623cb3ebec75de449cad3c9f50d5d370edf9e2f9 SOURCES/puma-6.4.2.gem
|
||||
6d78f730b7f3b25fb3f93684fe1364acf58bce6b SOURCES/json-2.6.3.gem
|
||||
f5f804366823c1126791dfefd98dd0539563785c SOURCES/mustermann-2.0.2.gem
|
||||
2f65d371f5f37460ad74afcedcb97d2b41a46806 SOURCES/nio4r-2.5.9.gem
|
||||
41a7fe9f8e3e02da5ae76c821b89c5b376a97746 SOURCES/open4-1.3.4-1.gem
|
||||
b3cd873042b17021355b68f1f7aa313f0c1f3fee SOURCES/pcs-0.10.18.tar.gz
|
||||
d6049c4555f3c9d198e6eb1d7e53ce9b68e175ff SOURCES/puma-6.4.0.gem
|
||||
3176b2f2b332c2b6bf79fe882e83feecf3d3f011 SOURCES/pyagentx-0.4.pcs.2.tar.gz
|
||||
a156440aaee17f60b83f2f681ec60fce2329a480 SOURCES/rack-3.0.11.gem
|
||||
f91158b296882aa5b3798ff6c24f01cdf233ef48 SOURCES/rack-protection-4.0.0.gem
|
||||
9e7935696af0b64cc5f5ce2dfeabdb7e0d3a84f0 SOURCES/rack-session-2.0.0.gem
|
||||
c2ba10c775b7a52a4b57cac4d4110a0c0f812a82 SOURCES/python-dateutil-2.8.2.tar.gz
|
||||
fcdee79d1b0bb7e3666bad96321fc124bc8215e9 SOURCES/rack-2.2.8.1.gem
|
||||
5347315a7283f0b04443e924ed4eaa17807432c8 SOURCES/rack-protection-2.2.4.gem
|
||||
ae09ea83748b55875edc3708fffba90db180cb8e SOURCES/rack-test-2.1.0.gem
|
||||
657a2dc63695e1bf9eb5feae4d9d65a7c6b900ad SOURCES/rackup-2.1.0.gem
|
||||
89f8446e89976f3677767d426a4edc6ccba574be SOURCES/rexml-3.3.6.gem
|
||||
d017b9e4d1978e0b3ccc3e2a31493809e4693cd3 SOURCES/ruby2_keywords-0.0.5.gem
|
||||
28c671c6d061475ed2bfd3e6a4a17970a0a12d8a SOURCES/sinatra-4.0.0.gem
|
||||
fa6a6c98f885e93f54c23dd0454cae906e82c31b SOURCES/sinatra-2.2.4.gem
|
||||
4a38a9a55887b2882182a2c5771e592efe514e5e SOURCES/tilt-2.3.0.gem
|
||||
ee95560139af1bb8d0d49d4acf0518deb04877d2 SOURCES/tornado-6.4.0.tar.gz
|
||||
0696afa9cc0b56f541aacb7483aecdb385a5bd37 SOURCES/webrick-1.8.1.gem
|
||||
c23c617c7a0205e465bebad5b8cdf289ae8402a2 SOURCES/tornado-6.1.0.tar.gz
|
||||
|
@ -0,0 +1,55 @@
|
||||
From 957856a556f5ed92129ce602538c3df3aebce7a3 Mon Sep 17 00:00:00 2001
|
||||
From: Ivan Devat <idevat@redhat.com>
|
||||
Date: Tue, 5 Dec 2023 15:18:35 +0100
|
||||
Subject: [PATCH 2/2] disable alternative webui routes
|
||||
|
||||
This commit is intended to be downstream only.
|
||||
|
||||
The new web ui was part of rhel8 as a technical preview. But new web ui
|
||||
is now the main in rhel9 and there is no need to keep it in rhel8.
|
||||
To prevent unnecessary maintenance burden it is disabled now.
|
||||
No handler code is removed, just routing disabled.
|
||||
---
|
||||
pcs/daemon/run.py | 26 ++++++++++++++++----------
|
||||
1 file changed, 16 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/pcs/daemon/run.py b/pcs/daemon/run.py
|
||||
index 7fdeda2a..0a6b1b21 100644
|
||||
--- a/pcs/daemon/run.py
|
||||
+++ b/pcs/daemon/run.py
|
||||
@@ -81,16 +81,22 @@ def configure_app(
|
||||
routes.extend(
|
||||
# old web ui by default
|
||||
[(r"/", RedirectHandler, dict(url="/manage"))]
|
||||
- + [(r"/ui", RedirectHandler, dict(url="/ui/"))]
|
||||
- + ui.get_routes(
|
||||
- url_prefix="/ui/",
|
||||
- app_dir=os.path.join(public_dir, "ui"),
|
||||
- fallback_page_path=os.path.join(
|
||||
- public_dir,
|
||||
- "ui_instructions.html",
|
||||
- ),
|
||||
- session_storage=session_storage,
|
||||
- )
|
||||
+ # The following disabled routes was for the new web ui. The new
|
||||
+ # web ui was here as a technical preview. But new web ui is now
|
||||
+ # the main in rhel9 and there is no need to keep it in rhel8.
|
||||
+ # To prevent unnecessary maintenance burden it is disabled now.
|
||||
+ # No handler code is removed, just routing disabled.
|
||||
+ #
|
||||
+ # + [(r"/ui", RedirectHandler, dict(url="/ui/"))]
|
||||
+ # + ui.get_routes(
|
||||
+ # url_prefix="/ui/",
|
||||
+ # app_dir=os.path.join(public_dir, "ui"),
|
||||
+ # fallback_page_path=os.path.join(
|
||||
+ # public_dir,
|
||||
+ # "ui_instructions.html",
|
||||
+ # ),
|
||||
+ # session_storage=session_storage,
|
||||
+ # )
|
||||
+ sinatra_ui.get_routes(
|
||||
session_storage, ruby_pcsd_wrapper, public_dir
|
||||
)
|
||||
--
|
||||
2.43.0
|
||||
|
@ -1,144 +0,0 @@
|
||||
From 7a2ea3c95c99b0f3eacc99816c9aa6febfad6c5e Mon Sep 17 00:00:00 2001
|
||||
From: Miroslav Lisik <mlisik@redhat.com>
|
||||
Date: Thu, 17 Oct 2024 17:04:37 +0200
|
||||
Subject: [PATCH] fix `pcs dr status`
|
||||
|
||||
* add command status.full_cluster_status_plaintext to the API_V1_MAP
|
||||
* fix ClusterStatusLegacyHandler
|
||||
* fix `pcs cluster node add-outside`
|
||||
* fix ClusterAddNodesLegacyHandler
|
||||
---
|
||||
pcs/common/reports/messages.py | 17 +++++++----------
|
||||
pcs/daemon/app/api_v1.py | 5 +++--
|
||||
pcs_test/smoke.sh.in | 14 +++++++-------
|
||||
pcsd/capabilities.xml.in | 7 +++++++
|
||||
4 files changed, 24 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/pcs/common/reports/messages.py b/pcs/common/reports/messages.py
|
||||
index ccf32a03..9a1543e1 100644
|
||||
--- a/pcs/common/reports/messages.py
|
||||
+++ b/pcs/common/reports/messages.py
|
||||
@@ -260,7 +260,7 @@ def _stonith_watchdog_timeout_reason_to_str(
|
||||
}.get(reason, reason)
|
||||
|
||||
|
||||
-@dataclass(frozen=True, init=False)
|
||||
+@dataclass(frozen=True)
|
||||
class LegacyCommonMessage(ReportItemMessage):
|
||||
"""
|
||||
This class is used for legacy report transport protocol from
|
||||
@@ -268,22 +268,19 @@ class LegacyCommonMessage(ReportItemMessage):
|
||||
should be replaced with transporting DTOs of reports in the future.
|
||||
"""
|
||||
|
||||
- def __init__(
|
||||
- self, code: types.MessageCode, info: Mapping[str, Any], message: str
|
||||
- ) -> None:
|
||||
- self.__code = code
|
||||
- self.info = info
|
||||
- self._message = message
|
||||
+ legacy_code: types.MessageCode
|
||||
+ legacy_info: Mapping[str, Any]
|
||||
+ legacy_message: str
|
||||
|
||||
@property
|
||||
def message(self) -> str:
|
||||
- return self._message
|
||||
+ return self.legacy_message
|
||||
|
||||
def to_dto(self) -> ReportItemMessageDto:
|
||||
return ReportItemMessageDto(
|
||||
- code=self.__code,
|
||||
+ code=self.legacy_code,
|
||||
message=self.message,
|
||||
- payload=dict(self.info),
|
||||
+ payload=dict(self.legacy_info),
|
||||
)
|
||||
|
||||
|
||||
diff --git a/pcs/daemon/app/api_v1.py b/pcs/daemon/app/api_v1.py
|
||||
index 8e8b8804..5babad1d 100644
|
||||
--- a/pcs/daemon/app/api_v1.py
|
||||
+++ b/pcs/daemon/app/api_v1.py
|
||||
@@ -101,6 +101,7 @@ API_V1_MAP: Mapping[str, str] = {
|
||||
"sbd-enable-sbd/v1": "sbd.enable_sbd",
|
||||
"scsi-unfence-node/v2": "scsi.unfence_node",
|
||||
"scsi-unfence-node-mpath/v1": "scsi.unfence_node_mpath",
|
||||
+ "status-full-cluster-status-plaintext/v1": "status.full_cluster_status_plaintext",
|
||||
# deprecated, use resource-agent-get-agent-metadata/v1 instead
|
||||
"stonith-agent-describe-agent/v1": "stonith_agent.describe_agent",
|
||||
# deprecated, use resource-agent-get-agents-list/v1 instead
|
||||
@@ -301,13 +302,13 @@ class LegacyApiV1Handler(_BaseApiV1Handler):
|
||||
class ClusterStatusLegacyHandler(LegacyApiV1Handler):
|
||||
@staticmethod
|
||||
def _get_cmd() -> str:
|
||||
- return "status.full_cluster_status_plaintext"
|
||||
+ return "status-full-cluster-status-plaintext/v1"
|
||||
|
||||
|
||||
class ClusterAddNodesLegacyHandler(LegacyApiV1Handler):
|
||||
@staticmethod
|
||||
def _get_cmd() -> str:
|
||||
- return "cluster.add_nodes"
|
||||
+ return "cluster-add-nodes/v1"
|
||||
|
||||
|
||||
def get_routes(scheduler: Scheduler, auth_provider: AuthProvider) -> RoutesType:
|
||||
diff --git a/pcs_test/smoke.sh.in b/pcs_test/smoke.sh.in
|
||||
index a4b3ac71..bfbb427e 100755
|
||||
--- a/pcs_test/smoke.sh.in
|
||||
+++ b/pcs_test/smoke.sh.in
|
||||
@@ -23,12 +23,6 @@ output_file=$(mktemp)
|
||||
token_file=$(mktemp)
|
||||
cookie_file=$(mktemp)
|
||||
|
||||
-# Sanity check of API V0
|
||||
-token=$(python3 -c "import json; print(json.load(open('@LOCALSTATEDIR@/lib/pcsd/known-hosts'))['known_hosts']['localhost']['token']);")
|
||||
-curl -kb "token=${token}" https://localhost:2224/remote/cluster_status_plaintext -d 'data_json={}' > "${output_file}"
|
||||
-cat "${output_file}"; echo ""
|
||||
-python3 -c "import json; import sys; json.load(open('${output_file}'))['status'] == 'exception' and (sys.exit(1))";
|
||||
-
|
||||
dd if=/dev/urandom bs=32 count=1 status=none | base64 > "${token_file}"
|
||||
custom_localhost_node_name="custom-node-name"
|
||||
|
||||
@@ -71,6 +65,12 @@ curl --insecure --cookie ${cookie_file} --header "X-Requested-With: XMLHttpReque
|
||||
cat "${output_file}"; echo ""
|
||||
[ "$(cat ${output_file})" = "Update Successful" ]
|
||||
|
||||
+# Sanity check of API V0
|
||||
+token=$(python3 -c "import json; print(json.load(open('@LOCALSTATEDIR@/lib/pcsd/known-hosts'))['known_hosts']['localhost']['token']);")
|
||||
+curl -kb "token=${token}" https://localhost:2224/remote/cluster_status_plaintext -d 'data_json={}' > "${output_file}"
|
||||
+cat "${output_file}"; echo ""
|
||||
+python3 -c "import json; import sys; json.load(open('${output_file}'))['status'] != 'success' and (sys.exit(1))";
|
||||
+
|
||||
# Sanity check of API V1
|
||||
curl -kb "token=${token}" https://localhost:2224/api/v1/resource-agent-get-agents-list/v1 --data '{}' > "${output_file}"
|
||||
cat "${output_file}"; echo ""
|
||||
@@ -98,5 +98,5 @@ rm "${output_file}"
|
||||
rm "${cookie_file}"
|
||||
rm "${pcsd_settings_conf_path}"
|
||||
pcs cluster destroy --force
|
||||
-userdel -r testuser
|
||||
+userdel -rf testuser
|
||||
exit 0
|
||||
diff --git a/pcsd/capabilities.xml.in b/pcsd/capabilities.xml.in
|
||||
index 99d5af3f..b9c28560 100644
|
||||
--- a/pcsd/capabilities.xml.in
|
||||
+++ b/pcsd/capabilities.xml.in
|
||||
@@ -2661,6 +2661,13 @@
|
||||
daemon urls: pacemaker_node_status
|
||||
</description>
|
||||
</capability>
|
||||
+ <capability id="status.pcmk.full-cluster-status-plaintext" in-pcs="0" in-pcsd="1">
|
||||
+ <description>
|
||||
+ Display status of the remote site cluster.
|
||||
+
|
||||
+ daemon urls: /api/v1/status-full-cluster-status-plaintext/v1
|
||||
+ </description>
|
||||
+ </capability>
|
||||
<capability id="status.pcmk.query.resource" in-pcs="1" in-pcsd="0">
|
||||
<description>
|
||||
Query status of resources.
|
||||
--
|
||||
2.47.0
|
||||
|
@ -0,0 +1,52 @@
|
||||
From 6142961fe0e39bdbba0d70f792fc27fb2bc096ba Mon Sep 17 00:00:00 2001
|
||||
From: Ivan Devat <idevat@redhat.com>
|
||||
Date: Thu, 7 Mar 2024 16:51:13 +0100
|
||||
Subject: [PATCH] stop sending http headers to ruby part of pcsd
|
||||
|
||||
---
|
||||
pcs/daemon/ruby_pcsd.py | 23 ++++++++++++++++++++++-
|
||||
1 file changed, 22 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pcs/daemon/ruby_pcsd.py b/pcs/daemon/ruby_pcsd.py
|
||||
index 4b3b0ea1..e07e17cc 100644
|
||||
--- a/pcs/daemon/ruby_pcsd.py
|
||||
+++ b/pcs/daemon/ruby_pcsd.py
|
||||
@@ -87,13 +87,34 @@ class RubyDaemonRequest(
|
||||
http_request: HTTPServerRequest = None,
|
||||
payload=None,
|
||||
):
|
||||
- headers = http_request.headers if http_request else HTTPHeaders()
|
||||
+ # Headers from request are not propagated to ruby part. Ruby part doesn't
|
||||
+ # work with standard headers in any special way. So, we send only path,
|
||||
+ # method, query, body and special headers for communication between
|
||||
+ # python part and ruby part. Tornado then adds necessary default
|
||||
+ # headers. The motivation here is to prevent processing potentially
|
||||
+ # maliciously crafted headers by rack.
|
||||
+ headers = HTTPHeaders()
|
||||
headers.add("X-Pcsd-Type", request_type)
|
||||
if payload:
|
||||
headers.add(
|
||||
"X-Pcsd-Payload",
|
||||
b64encode(json.dumps(payload).encode()).decode(),
|
||||
)
|
||||
+ if http_request:
|
||||
+ for key, val in http_request.headers.get_all():
|
||||
+ # From webui, POST request can come with either
|
||||
+ # application/x-www-form-urlencoded or application/json content
|
||||
+ # type. When we remove original HTTP headers, content type is
|
||||
+ # added by tornado. But in the case of original application/json,
|
||||
+ # tornado puts application/x-www-form-urlencoded there. To fix
|
||||
+ # this let's keep the original header here in this case.
|
||||
+ #
|
||||
+ # The token, CIB_user and CIB_user_groups are transferred by the
|
||||
+ # "Cookie" header and these information are evaluated in ruby.
|
||||
+ if (
|
||||
+ key.lower() == "content-type" and val == "application/json"
|
||||
+ ) or key.lower() == "cookie":
|
||||
+ headers.add(key, val)
|
||||
return super(RubyDaemonRequest, cls).__new__(
|
||||
cls,
|
||||
request_type,
|
||||
--
|
||||
2.47.0
|
||||
|
@ -1,38 +1,53 @@
|
||||
From 071b189a3a72610361f8d31d2ebbb0b9083c872f Mon Sep 17 00:00:00 2001
|
||||
From 854efcf148c82e5a5e4f0afd71cc3333ea4a8ce4 Mon Sep 17 00:00:00 2001
|
||||
From: Ivan Devat <idevat@redhat.com>
|
||||
Date: Tue, 20 Nov 2018 15:03:56 +0100
|
||||
Subject: [PATCH] do not support cluster setup with udp(u) transport in RHEL9
|
||||
Subject: [PATCH 1/2] do not support cluster setup with udp(u) transport
|
||||
|
||||
---
|
||||
pcs/pcs.8.in | 2 ++
|
||||
pcs/usage.py | 1 +
|
||||
2 files changed, 3 insertions(+)
|
||||
pcs/pcs.8.in | 2 ++
|
||||
pcs/usage.py | 1 +
|
||||
pcsd/public/css/style.css | 3 +++
|
||||
3 files changed, 6 insertions(+)
|
||||
|
||||
diff --git a/pcs/pcs.8.in b/pcs/pcs.8.in
|
||||
index 63c40b78..f69a75b8 100644
|
||||
index d504e8b4..93202d05 100644
|
||||
--- a/pcs/pcs.8.in
|
||||
+++ b/pcs/pcs.8.in
|
||||
@@ -479,6 +479,8 @@ By default, encryption is enabled with cipher=aes256 and hash=sha256. To disable
|
||||
@@ -438,6 +438,8 @@ By default, encryption is enabled with cipher=aes256 and hash=sha256. To disable
|
||||
|
||||
Transports udp and udpu:
|
||||
.br
|
||||
+WARNING: These transports are not supported in RHEL 9.
|
||||
+WARNING: These transports are not supported in RHEL 8.
|
||||
+.br
|
||||
These transports are limited to one address per node. They do not support traffic encryption nor compression.
|
||||
.br
|
||||
Transport options are: ip_version, netmtu
|
||||
diff --git a/pcs/usage.py b/pcs/usage.py
|
||||
index a4af30d4..7c7fc7ea 100644
|
||||
index f4b84202..ee10370a 100644
|
||||
--- a/pcs/usage.py
|
||||
+++ b/pcs/usage.py
|
||||
@@ -1490,6 +1490,7 @@ Commands:
|
||||
@@ -1038,6 +1038,7 @@ Commands:
|
||||
hash=sha256. To disable encryption, set cipher=none and hash=none.
|
||||
|
||||
Transports udp and udpu:
|
||||
+ WARNING: These transports are not supported in RHEL 9.
|
||||
+ WARNING: These transports are not supported in RHEL 8.
|
||||
These transports are limited to one address per node. They do not
|
||||
support traffic encryption nor compression.
|
||||
Transport options are:
|
||||
diff --git a/pcsd/public/css/style.css b/pcsd/public/css/style.css
|
||||
index 2f26e831..a7702ac4 100644
|
||||
--- a/pcsd/public/css/style.css
|
||||
+++ b/pcsd/public/css/style.css
|
||||
@@ -949,6 +949,9 @@ table.args-table td.reg {
|
||||
width: 6ch;
|
||||
text-align: right;
|
||||
}
|
||||
+#csetup-transport .transport-types {
|
||||
+ display: none;
|
||||
+}
|
||||
#csetup-transport-options.udp .knet-only,
|
||||
#csetup-transport-options.knet .without-knet
|
||||
{
|
||||
--
|
||||
2.45.2
|
||||
2.43.0
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue