-
Notifications
You must be signed in to change notification settings - Fork 61
/
Copy pathswpm2_parameters_inifile_generate.py
executable file
·238 lines (190 loc) · 10.3 KB
/
swpm2_parameters_inifile_generate.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
#!/usr/bin/env python
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
# Prerequisites:
# pip install beautifulsoup4 lxml
import sys
import os
import traceback
try:
from bs4 import BeautifulSoup
from lxml import etree
except ImportError:
HAS_ANOTHER_LIBRARY = False
ANOTHER_LIBRARY_IMPORT_ERROR = traceback.format_exc()
else:
HAS_ANOTHER_LIBRARY = True
# from bs4 import BeautifulSoup
# from lxml import etree
def debug_bs4():
# Diagnose XML file parsing errors in Beautiful Soup
# https://stackoverflow.com/questions/56942892/cannot-parse-iso-8859-15-encoded-xml-with-bs4/56947172#56947172
from bs4.diagnose import diagnose
with open('control.xml', 'rb') as f:
diagnose(f)
# SWPM2 control.xml conversion to utf8
def control_xml_utf8(filepath):
source = filepath + "/control.xml"
# Convert control.xml from iso-8859-1 to UTF-8, so it can be used with Beautiful Soup lxml-xml parser
# https://stackoverflow.com/questions/64629600/how-can-you-convert-a-xml-iso-8859-1-to-utf-8-using-python-3-7-7/64634454#64634454
with open(source, 'rb') as source:
parser = etree.XMLParser(encoding="iso-8859-1", strip_cdata=False)
root = etree.parse(source, parser)
string = etree.tostring(root, xml_declaration=True, encoding="UTF-8", pretty_print=True).decode('utf8').encode('iso-8859-1')
with open('control_utf8.xml', 'wb') as target:
target.write(string)
# SWPM2 Component and Parameters extract all as CSV
def control_xml_to_csv(filepath):
infile = open(filepath + "/control_utf8.xml", "r")
contents = infile.read()
soup = BeautifulSoup(markup=contents, features='lxml-xml')
space = soup.find('components')
component_list = space.findChildren("component", recursive=False)
csv_output = open('control_output.csv', 'w')
csv_header = ('"'
+ 'Component Name' + '","'
+ 'Component Display Name' + '","'
+ 'Parameter Name' + '","'
+ 'Parameter Inifile Key' + '","'
+ 'Parameter Access' + '","'
+ 'Parameter Encode' + '","'
+ 'Parameter Default Value' + '","'
+ 'Parameter Inifile description' + '"')
csv_output.write("%s\n" % csv_header)
for component in component_list:
for parameter in component.findChildren("parameter"):
component_key = parameter.findParent("component")
component_key_name_text = component_key["name"]
for child in component_key.findChildren("display-name"):
component_key_display_name_text = child.get_text().replace('\n', '')
component_parameter_key_name = parameter["name"]
component_parameter_key_inifile_name = parameter.get("defval-for-inifile-generation", "")
component_parameter_key_access = parameter.get("access", "")
component_parameter_key_encode = parameter.get("encode", "")
component_parameter_key_defval = parameter.get("defval", "")
component_parameter_contents_doclong_text = parameter.get_text().replace('\n', '')
component_parameter_contents_doclong_text_quote_replacement = component_parameter_contents_doclong_text.replace('"', '\'')
csv_string = ('"'
+ component_key_name_text + '","'
+ component_key_display_name_text + '","'
+ component_parameter_key_name + '","'
+ component_parameter_key_inifile_name + '","'
+ component_parameter_key_access + '","'
+ component_parameter_key_encode + '","'
+ component_parameter_key_defval + '","'
+ component_parameter_contents_doclong_text_quote_replacement + '"')
csv_output.write("%s\n" % csv_string)
csv_output.close()
# SWPM2 Component and Parameters extract all and generate template inifile.params
def control_xml_to_inifile_params(filepath):
infile = open(filepath + "/control_utf8.xml", "r")
contents = infile.read()
soup = BeautifulSoup(markup=contents, features='lxml-xml')
space = soup.find('components')
component_list = space.findChildren("component", recursive=False)
inifile_output = open('generated_inifile_params', 'w')
inifile_params_header = """############
# SWPM Unattended Parameters inifile.params generated export
#
#
# Export of all SWPM Component and the SWPM Unattended Parameters. Not all components have SWPM Unattended Parameters.
#
# All parameters are commented-out, each hash # before the parameter is removed to activate the parameter.
# When running SWPM in Unattended Mode, the activated parameters will create a new SWPM file in the sapinst directory.
# If any parameter is marked as 'encode', the plaintext value will be converted to DES hash for this parameter
# in the new SWPM file (in the sapinst directory).
#
# An inifile.params is otherwise obtained after running SWPM as GUI or Unattended install,
# and will be generated for a specific Product ID (such as 'NW_ABAP_OneHost:S4HANA1809.CORE.HDB.CP').
############
############
# MANUAL
############
# The folder containing all archives that have been downloaded from http://support.sap.com/swdc and are supposed to be
# used in this procedure
# archives.downloadBasket =
"""
inifile_output.write(inifile_params_header)
for component in component_list:
component_key_name_text = component["name"]
component_key_display_name = component.find("display-name")
if component_key_display_name is not None:
component_key_display_name_text = component_key_display_name.get_text()
inifile_output.write("\n\n\n\n############\n# Component: %s\n# Component Display Name: %s\n############\n" % (component_key_name_text, component_key_display_name_text)) # nopep8: line-too-long
for parameter in component.findChildren("parameter"):
# component_key = parameter.findParent("component")
component_parameter_key_encode = parameter.get("encode", None)
component_parameter_key_inifile_name = parameter.get("defval-for-inifile-generation", None)
component_parameter_key_defval = parameter.get("defval", "")
component_parameter_contents_doclong_text = parameter.get_text().replace('\n', '')
# component_parameter_contents_doclong_text_quote_replacement = component_parameter_contents_doclong_text.replace('"','\'')
if component_parameter_key_inifile_name is not None:
inifile_output.write("\n# %s" % (component_parameter_contents_doclong_text))
if component_parameter_key_encode == "true":
inifile_output.write("\n# Encoded parameter. Plaintext values will be converted to DES hash")
inifile_output.write("\n# %s = %s\n" % (component_parameter_key_inifile_name, component_parameter_key_defval))
inifile_output.close()
# SWPM2 product.catalog conversion to utf8
def product_catalog_xml_utf8(filepath):
source = filepath + "/product.catalog"
# Convert control.xml from iso-8859-1 to UTF-8, so it can be used with Beautiful Soup lxml-xml parser
# https://stackoverflow.com/questions/64629600/how-can-you-convert-a-xml-iso-8859-1-to-utf-8-using-python-3-7-7/64634454#64634454
with open(source, 'rb') as source:
parser = etree.XMLParser(encoding="iso-8859-1", strip_cdata=False)
root = etree.parse(source, parser)
string = etree.tostring(root, xml_declaration=True, encoding="UTF-8", pretty_print=True).decode('utf8').encode('iso-8859-1')
with open('product_catalog_utf8.xml', 'wb') as target:
target.write(string)
# SWPM2 Product Catalog entries to CSV
# Each Product Catalog entry is part of a components group,
# which may have attributes = output-dir, control-file,
# product-dir (link to SWPM directory of param file etc)
# Attributes possible for each entry = control-file, db, id, name,
# os, os-type, output-dir, ppms-component, ppms-component-release,
# product, product-dir, release, table
def product_catalog_xml_to_csv(filepath):
infile = open(filepath + "/product_catalog_utf8.xml", "r")
contents = infile.read()
soup = BeautifulSoup(markup=contents, features='lxml-xml')
space = soup.find_all('component')
csv_output = open('product_catalog_output.csv', 'w')
csv_header = ('"'
+ 'Product Catalog Component Name' + '","'
+ 'Product Catalog Component ID' + '","'
+ 'Product Catalog Component Table' + '","'
+ 'Product Catalog Component Output Dir' + '","'
+ 'Product Catalog Component Display Name' + '","'
+ 'Product Catalog Component UserInfo' + '"')
csv_output.write("%s\n" % csv_header)
for component in space:
component_name = component.get("name", "")
component_id = component.get("id", "")
component_table = component.get("table", "")
component_output_dir = component.get("output-dir", "")
for displayname in component.findChildren("display-name"):
component_displayname = displayname.get_text().strip()
for userinfo in component.findChildren("user-info"):
html_raw = userinfo.get_text().strip()
html_parsed = BeautifulSoup(html_raw, 'html.parser')
component_userinfo = html_parsed.get_text().replace('"', '\'')
csv_string = ('"'
+ component_name + '","'
+ component_id + '","'
+ component_table + '","'
+ component_output_dir + '","'
+ component_displayname + '","'
+ component_userinfo + '"')
csv_output.write("%s\n" % csv_string)
csv_output.close()
# Get arguments passed to Python script session
# Define path to control.xml, else assume in /tmp directory
if __name__ == "__main__":
if len(sys.argv) > 1:
control_xml_path = sys.argv[1]
else:
control_xml_path = "/tmp"
if control_xml_path == "":
control_xml_path = os.getcwd()
control_xml_utf8(control_xml_path)
control_xml_to_csv(control_xml_path)
control_xml_to_inifile_params(control_xml_path)