Skip to content

Commit a3896c9

Browse files
committed
Display chaincode status dynamically
Response chaincode status (CREATED, INSTALLED, APPROVED, COMMITTED) for the chaincode page. Signed-off-by: dodo920306 <dodo920306@gmail.com>
1 parent 31397fb commit a3896c9

File tree

18 files changed

+562
-1053
lines changed

18 files changed

+562
-1053
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.*
2+
cello
3+
hyperledger_cello_hyperledger_fabric_agent

src/agents/hyperledger-fabric/Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ RUN apt-get update\
1010
# Copy source code to the working dir
1111
COPY . .
1212

13+
RUN mkdir cello
14+
1315
# Install compiled code tools from Artifactory and copy it to opt folder.
1416
RUN curl -L --retry 5 --retry-delay 3 "https://github.com/hyperledger/fabric/releases/download/v2.5.14/hyperledger-fabric-linux-amd64-2.5.14.tar.gz" | tar xz -C ./cello/
1517

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from enum import Enum
2+
3+
4+
class ChaincodeStatus(Enum):
5+
CREATED = "CREATED"
6+
INSTALLED = 'INSTALLED'
7+
APPROVED = 'APPROVED'
8+
COMMITTED = 'COMMITTED'
9+

src/agents/hyperledger-fabric/chaincode/serializers.py

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,54 @@
11
import os
22
import threading
33

4-
from django.contrib.sessions.backends import file
54
from django.core.files.storage import FileSystemStorage
6-
from drf_spectacular.types import OpenApiTypes
7-
from drf_spectacular.utils import extend_schema_field
85
from rest_framework import serializers
96

107
from chaincode.service import create_chaincode, install_chaincode, approve_chaincode, get_chaincode_package_id, \
11-
commit_chaincode, get_metadata
8+
commit_chaincode, get_metadata, get_chaincode_status, get_chaincode_commit_readiness
129
from hyperledger_fabric.settings import CELLO_HOME
1310

1411

12+
class ChaincodeCommitReadinessResponse(serializers.Serializer):
13+
approvals = serializers.DictField(help_text="Chaincode Commit Readiness")
14+
15+
16+
class ChaincodeCommitReadinessRequest(serializers.Serializer):
17+
channel = serializers.CharField(help_text="Chaincode Channel Name")
18+
name = serializers.CharField(help_text="Chaincode Name")
19+
version = serializers.CharField(help_text="Chaincode Version")
20+
sequence = serializers.IntegerField(help_text="Chaincode Sequence")
21+
init_required = serializers.BooleanField(help_text="Chaincode Required Initialization")
22+
23+
def create(self, validated_data):
24+
return ChaincodeCommitReadinessResponse(dict(
25+
approvals=get_chaincode_commit_readiness(
26+
validated_data["channel"],
27+
validated_data["name"],
28+
validated_data["version"],
29+
validated_data["sequence"],
30+
validated_data["init_required"])))
31+
32+
33+
class ChaincodeStatusResponse(serializers.Serializer):
34+
status = serializers.CharField(help_text="Chaincode Status")
35+
36+
37+
class ChaincodeStatusRequest(serializers.Serializer):
38+
package_id = serializers.CharField(help_text="Chaincode Package ID")
39+
channel = serializers.CharField(help_text="Chaincode Channel Name")
40+
name = serializers.CharField(help_text="Chaincode Name")
41+
sequence = serializers.IntegerField(help_text="Chaincode Sequence")
42+
43+
def create(self, validated_data):
44+
return ChaincodeStatusResponse(dict(
45+
status=get_chaincode_status(
46+
validated_data["package_id"],
47+
validated_data["channel"],
48+
validated_data["name"],
49+
validated_data["sequence"]).name))
50+
51+
1552
class ChaincodeResponseSerializer(serializers.Serializer):
1653
label = serializers.CharField(help_text="Chaincode Label")
1754
language = serializers.CharField(help_text="Chaincode Language")

src/agents/hyperledger-fabric/chaincode/service.py

Lines changed: 229 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,241 @@
33
import os
44
import subprocess
55
import tarfile
6-
from typing import List, Optional, Dict, Any
76
import yaml
8-
from django.core.files.storage import FileSystemStorage
7+
from typing import List, Optional, Dict, Any
8+
9+
from chaincode.enums import ChaincodeStatus
910
from hyperledger_fabric.settings import CELLO_HOME, CRYPTO_CONFIG, FABRIC_TOOL
1011

1112
LOG = logging.getLogger(__name__)
1213

1314

15+
def get_chaincode_status(
16+
package_id: str,
17+
channel: str,
18+
name: str,
19+
sequence: int) -> ChaincodeStatus:
20+
with open(
21+
CRYPTO_CONFIG,
22+
"r",
23+
encoding="utf-8",
24+
) as f:
25+
crypto_config = yaml.safe_load(f)
26+
27+
peer_org = crypto_config["PeerOrgs"][0]
28+
peer_organization_directory = os.path.join(
29+
CELLO_HOME,
30+
"peerOrganizations",
31+
peer_org["Domain"]
32+
)
33+
peer_name = peer_org["Specs"][0]["Hostname"]
34+
peer_cmd = os.path.join(FABRIC_TOOL, "peer")
35+
peer_domain_name = "{}.{}".format(peer_name, peer_org["Domain"])
36+
peer_dir = os.path.join(
37+
peer_organization_directory,
38+
"peers",
39+
peer_domain_name
40+
)
41+
peer_env = {
42+
"CORE_PEER_TLS_ENABLED": "true",
43+
"CORE_PEER_LOCALMSPID": peer_org["Name"] + "MSP",
44+
"CORE_PEER_TLS_ROOTCERT_FILE": os.path.join(peer_dir, "tls", "ca.crt"),
45+
"CORE_PEER_MSPCONFIGPATH": os.path.join(
46+
peer_organization_directory,
47+
"users",
48+
"Admin@" + peer_org["Domain"],
49+
"msp"
50+
),
51+
"CORE_PEER_ADDRESS": peer_domain_name + ":7051",
52+
"FABRIC_CFG_PATH": peer_dir,
53+
}
54+
command = [
55+
peer_cmd,
56+
"lifecycle",
57+
"chaincode",
58+
"queryinstalled",
59+
"--output",
60+
"json"
61+
]
62+
LOG.info(peer_env)
63+
LOG.info(" ".join(command))
64+
try:
65+
installed_chaincode_package_ids = [
66+
installed_chaincode["package_id"] for installed_chaincode in json.loads(
67+
subprocess.run(
68+
command,
69+
env=peer_env,
70+
check=True,
71+
capture_output=True,
72+
text=True
73+
).stdout.rstrip("\n")
74+
)["installed_chaincodes"]
75+
]
76+
if package_id not in installed_chaincode_package_ids:
77+
return ChaincodeStatus.CREATED
78+
except (subprocess.CalledProcessError, KeyError):
79+
return ChaincodeStatus.CREATED
80+
81+
command = [
82+
peer_cmd,
83+
"lifecycle",
84+
"chaincode",
85+
"queryapproved",
86+
"-C",
87+
channel,
88+
"-n",
89+
name,
90+
"--sequence",
91+
str(sequence),
92+
"--output",
93+
"json"
94+
]
95+
LOG.info(peer_env)
96+
LOG.info(" ".join(command))
97+
try:
98+
subprocess.run(
99+
command,
100+
env=peer_env,
101+
check=True
102+
)
103+
except subprocess.CalledProcessError:
104+
return ChaincodeStatus.INSTALLED
105+
106+
orderer_domain_name = "{}.{}".format(
107+
crypto_config["OrdererOrgs"][0]["Specs"][0]["Hostname"],
108+
crypto_config["OrdererOrgs"][0]["Domain"])
109+
command = [
110+
peer_cmd,
111+
"lifecycle",
112+
"chaincode",
113+
"querycommitted",
114+
"-o",
115+
orderer_domain_name + ":7050",
116+
"-C",
117+
channel,
118+
"-n",
119+
name,
120+
"--tls",
121+
"--cafile",
122+
os.path.join(
123+
CELLO_HOME,
124+
"ordererOrganizations",
125+
crypto_config["OrdererOrgs"][0]["Domain"],
126+
"orderers",
127+
orderer_domain_name,
128+
"msp",
129+
"tlscacerts",
130+
"tlsca.{}-cert.pem".format(crypto_config["OrdererOrgs"][0]["Domain"])
131+
),
132+
"--output",
133+
"json"
134+
]
135+
LOG.info(peer_env)
136+
LOG.info(" ".join(command))
137+
try:
138+
subprocess.run(
139+
command,
140+
env=peer_env,
141+
check=True
142+
)
143+
return ChaincodeStatus.COMMITTED
144+
except subprocess.CalledProcessError:
145+
return ChaincodeStatus.APPROVED
146+
147+
148+
def get_chaincode_commit_readiness(
149+
channel: str,
150+
name: str,
151+
version: str,
152+
sequence: int,
153+
init_required: bool) -> Dict:
154+
with open(
155+
CRYPTO_CONFIG,
156+
"r",
157+
encoding="utf-8",
158+
) as f:
159+
crypto_config = yaml.safe_load(f)
160+
161+
peer_org = crypto_config["PeerOrgs"][0]
162+
peer_organization_directory = os.path.join(
163+
CELLO_HOME,
164+
"peerOrganizations",
165+
peer_org["Domain"]
166+
)
167+
peer_name = peer_org["Specs"][0]["Hostname"]
168+
peer_domain_name = "{}.{}".format(peer_name, peer_org["Domain"])
169+
peer_dir = os.path.join(
170+
peer_organization_directory,
171+
"peers",
172+
peer_domain_name
173+
)
174+
peer_env = {
175+
"CORE_PEER_TLS_ENABLED": "true",
176+
"CORE_PEER_LOCALMSPID": peer_org["Name"] + "MSP",
177+
"CORE_PEER_TLS_ROOTCERT_FILE": os.path.join(peer_dir, "tls", "ca.crt"),
178+
"CORE_PEER_MSPCONFIGPATH": os.path.join(
179+
peer_organization_directory,
180+
"users",
181+
"Admin@" + peer_org["Domain"],
182+
"msp"
183+
),
184+
"CORE_PEER_ADDRESS": peer_domain_name + ":7051",
185+
"FABRIC_CFG_PATH": peer_dir,
186+
}
187+
188+
orderer_domain_name = "{}.{}".format(
189+
crypto_config["OrdererOrgs"][0]["Specs"][0]["Hostname"],
190+
crypto_config["OrdererOrgs"][0]["Domain"])
191+
command = [
192+
os.path.join(FABRIC_TOOL, "peer"),
193+
"lifecycle",
194+
"chaincode",
195+
"checkcommitreadiness",
196+
"-o",
197+
orderer_domain_name + ":7050",
198+
"-C",
199+
channel,
200+
"-n",
201+
name,
202+
"--version",
203+
version,
204+
"--sequence",
205+
str(sequence),
206+
]
207+
if init_required:
208+
command.append("--init_required")
209+
command.extend([
210+
"--tls",
211+
"--cafile",
212+
os.path.join(
213+
CELLO_HOME,
214+
"ordererOrganizations",
215+
crypto_config["OrdererOrgs"][0]["Domain"],
216+
"orderers",
217+
orderer_domain_name,
218+
"msp",
219+
"tlscacerts",
220+
"tlsca.{}-cert.pem".format(crypto_config["OrdererOrgs"][0]["Domain"])
221+
),
222+
"--output",
223+
"json"
224+
])
225+
226+
LOG.info(peer_env)
227+
LOG.info(" ".join(command))
228+
try:
229+
res = subprocess.run(
230+
command,
231+
env=peer_env,
232+
check=True,
233+
capture_output=True,
234+
text=True
235+
).stdout.rstrip("\n")
236+
return json.loads(res)["approvals"]
237+
except subprocess.CalledProcessError:
238+
return {}
239+
240+
14241
def get_metadata(file_path) -> Optional[Dict[str, Any]]:
15242
res = None
16243
with tarfile.open(file_path, mode='r:gz') as tar:

src/agents/hyperledger-fabric/chaincode/views.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
from drf_spectacular.utils import extend_schema
22
from rest_framework import viewsets, status
33
from rest_framework.decorators import action
4-
from rest_framework.exceptions import ValidationError
54
from rest_framework.parsers import MultiPartParser, JSONParser
65
from rest_framework.response import Response
76

87
from chaincode.serializers import ChaincodeCreationSerializer, ChaincodeInstallationSerializer, \
9-
ChaincodeApprovementSerializer, ChaincodeCommitSerializer, ChaincodeResponseSerializer
8+
ChaincodeApprovementSerializer, ChaincodeCommitSerializer, ChaincodeResponseSerializer, ChaincodeStatusResponse, \
9+
ChaincodeStatusRequest, ChaincodeCommitReadinessRequest, ChaincodeCommitReadinessResponse
1010

1111

1212
# Create your views here.
@@ -64,3 +64,29 @@ def commit(self, request):
6464
serializer.is_valid(raise_exception=True)
6565
serializer.save()
6666
return Response(status=status.HTTP_204_NO_CONTENT)
67+
68+
@extend_schema(
69+
parameters=[ChaincodeStatusRequest],
70+
responses={200: ChaincodeStatusResponse}
71+
)
72+
@action(detail=False, methods=["GET"])
73+
def status(self, request):
74+
serializer = ChaincodeStatusRequest(data=request.query_params)
75+
serializer.is_valid(raise_exception=True)
76+
77+
return Response(
78+
data=serializer.save().data,
79+
status=status.HTTP_200_OK)
80+
81+
@extend_schema(
82+
parameters=[ChaincodeCommitReadinessRequest],
83+
responses={200: ChaincodeCommitReadinessResponse}
84+
)
85+
@action(detail=False, methods=["GET"], url_path="commit/readiness")
86+
def commit_readiness(self, request):
87+
serializer = ChaincodeCommitReadinessRequest(data=request.query_params)
88+
serializer.is_valid(raise_exception=True)
89+
90+
return Response(
91+
data=serializer.save().data,
92+
status=status.HTTP_200_OK)

src/api-engine/.dockerignore

Lines changed: 0 additions & 3 deletions
This file was deleted.

src/api-engine/Dockerfile

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ RUN apt-get update\
1111
# Copy source code to the working dir
1212
COPY . .
1313

14-
# Install compiled code tools from Artifactory and copy it to opt folder.
15-
RUN curl -L --retry 5 --retry-delay 3 "https://github.com/hyperledger/fabric/releases/download/v2.5.14/hyperledger-fabric-linux-amd64-2.5.14.tar.gz" | tar xz -C ./cello/
16-
1714
# Install python dependencies
1815
RUN pip3 install -r requirements.txt
1916

0 commit comments

Comments
 (0)