Merge ~gavin.lin/cc-lab-manager:add-main into cc-lab-manager:master
- Git
- lp:~gavin.lin/cc-lab-manager
- add-main
- Merge into master
Proposed by
Gavin Lin
Status: | Merged |
---|---|
Approved by: | Gavin Lin |
Approved revision: | e83324914f0fbda4313bdac902f2ea3494738591 |
Merged at revision: | 335a4ab8693473435f127bac4fe2c539bef2f791 |
Proposed branch: | ~gavin.lin/cc-lab-manager:add-main |
Merge into: | cc-lab-manager:master |
Diff against target: |
1512 lines (+1005/-62) 32 files modified
build/lib/cc_lab_manager/c3_db/c3_db.py (+22/-5) build/lib/cc_lab_manager/commands/__init__.py (+0/-0) build/lib/cc_lab_manager/commands/cc_lab_manager.py (+49/-0) build/lib/cc_lab_manager/dhcp/__init__.py (+0/-0) build/lib/cc_lab_manager/dhcp/dhcp_config_generator.py (+31/-14) build/lib/cc_lab_manager/gen_config/__init__.py (+0/-0) build/lib/cc_lab_manager/gen_config/gen_agent_tf_config.py (+35/-25) build/lib/cc_lab_manager/gsheet_db/__init__.py (+0/-0) build/lib/cc_lab_manager/gsheet_db/db_gsheet.py (+7/-7) build/lib/cc_lab_manager/maas/__init__.py (+0/-0) build/lib/cc_lab_manager/maas/create_maas_node.py (+11/-10) cc_lab_manager.egg-info/PKG-INFO (+11/-0) cc_lab_manager.egg-info/SOURCES.txt (+23/-0) cc_lab_manager.egg-info/dependency_links.txt (+1/-0) cc_lab_manager.egg-info/entry_points.txt (+3/-0) cc_lab_manager.egg-info/requires.txt (+4/-0) cc_lab_manager.egg-info/top_level.txt (+1/-0) cc_lab_manager/__init__.py (+0/-0) cc_lab_manager/c3_db/__init__.py (+0/-0) cc_lab_manager/c3_db/c3_db.py (+128/-0) cc_lab_manager/commands/__init__.py (+0/-0) cc_lab_manager/commands/cc_lab_manager.py (+49/-0) cc_lab_manager/dhcp/__init__.py (+0/-0) cc_lab_manager/dhcp/dhcp_config_generator.py (+96/-0) cc_lab_manager/gen_config/__init__.py (+0/-0) cc_lab_manager/gen_config/gen_agent_tf_config.py (+203/-0) cc_lab_manager/gsheet_db/__init__.py (+0/-0) cc_lab_manager/gsheet_db/db_gsheet.py (+107/-0) cc_lab_manager/gsheet_db/gsheet_db.py (+91/-0) cc_lab_manager/maas/__init__.py (+0/-0) cc_lab_manager/maas/create_maas_node.py (+124/-0) setup.py (+9/-1) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Kevin Yeh | Approve | ||
Review via email: mp+421633@code.launchpad.net |
Commit message
Combine functions into a workflow and work in a single command.
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/cc-lab-manager/c3-db/__init__.py b/build/lib/cc_lab_manager/__init__.py | |||
2 | 0 | similarity index 100% | 0 | similarity index 100% |
3 | 1 | rename from cc-lab-manager/c3-db/__init__.py | 1 | rename from cc-lab-manager/c3-db/__init__.py |
4 | 2 | rename to build/lib/cc_lab_manager/__init__.py | 2 | rename to build/lib/cc_lab_manager/__init__.py |
5 | diff --git a/cc-lab-manager/dhcp/__init__.py b/build/lib/cc_lab_manager/c3_db/__init__.py | |||
6 | 3 | similarity index 100% | 3 | similarity index 100% |
7 | 4 | rename from cc-lab-manager/dhcp/__init__.py | 4 | rename from cc-lab-manager/dhcp/__init__.py |
8 | 5 | rename to build/lib/cc_lab_manager/c3_db/__init__.py | 5 | rename to build/lib/cc_lab_manager/c3_db/__init__.py |
9 | diff --git a/cc-lab-manager/c3-db/c3-db.py b/build/lib/cc_lab_manager/c3_db/c3_db.py | |||
10 | 6 | similarity index 86% | 6 | similarity index 86% |
11 | 7 | rename from cc-lab-manager/c3-db/c3-db.py | 7 | rename from cc-lab-manager/c3-db/c3-db.py |
12 | 8 | rename to build/lib/cc_lab_manager/c3_db/c3_db.py | 8 | rename to build/lib/cc_lab_manager/c3_db/c3_db.py |
13 | index a9f6779..b9b0d7e 100644 | |||
14 | --- a/cc-lab-manager/c3-db/c3-db.py | |||
15 | +++ b/build/lib/cc_lab_manager/c3_db/c3_db.py | |||
16 | @@ -1,7 +1,9 @@ | |||
17 | 1 | import sqlite3 | 1 | import sqlite3 |
18 | 2 | import logging | 2 | import logging |
19 | 3 | import argparse | ||
20 | 3 | import c3.api.query as c3query | 4 | import c3.api.query as c3query |
21 | 4 | from c3.api.api_utils import APIQuery | 5 | from c3.api.api_utils import APIQuery |
22 | 6 | import os | ||
23 | 5 | 7 | ||
24 | 6 | logger = logging.getLogger('cc-lab-manager') | 8 | logger = logging.getLogger('cc-lab-manager') |
25 | 7 | 9 | ||
26 | @@ -22,6 +24,8 @@ def c3_to_db(db_path): | |||
27 | 22 | for cid_db in cid_list: | 24 | for cid_db in cid_list: |
28 | 23 | cid = ''.join(cid_db) | 25 | cid = ''.join(cid_db) |
29 | 24 | logger.info('Processing {}...'.format(cid)) | 26 | logger.info('Processing {}...'.format(cid)) |
30 | 27 | if '-' not in cid or 'TEL' in cid: | ||
31 | 28 | continue | ||
32 | 25 | 29 | ||
33 | 26 | # Query hardware info from c3 | 30 | # Query hardware info from c3 |
34 | 27 | result = '' | 31 | result = '' |
35 | @@ -94,17 +98,30 @@ def c3_to_db(db_path): | |||
36 | 94 | hwdb.close() | 98 | hwdb.close() |
37 | 95 | 99 | ||
38 | 96 | 100 | ||
39 | 101 | def environ_or_required(key): | ||
40 | 102 | if os.environ.get(key): | ||
41 | 103 | return {'default': os.environ.get(key)} | ||
42 | 104 | else: | ||
43 | 105 | return {'required': True} | ||
44 | 106 | |||
45 | 107 | |||
46 | 97 | def main(): | 108 | def main(): |
47 | 109 | parser = argparse.ArgumentParser() | ||
48 | 110 | parser.add_argument('--conf', help="Config file for C3 API", default = os.environ.get('CCLM_CC_TOOL_BOX') + '/config/c3-cli/my_conf.ini') | ||
49 | 111 | parser.add_argument('--c3user', help="C3 User Account", **environ_or_required('CCLM_C3_USERNAME')) | ||
50 | 112 | parser.add_argument('--c3apikey', help="C3 API Key", **environ_or_required('CCLM_C3_APIKEY')) | ||
51 | 113 | parser.add_argument('--hwdb', help="C3 API Key", **environ_or_required('CCLM_HARDWARE_DB')) | ||
52 | 114 | args = parser.parse_args() | ||
53 | 115 | |||
54 | 98 | ci = c3query.configuration.get_instance() | 116 | ci = c3query.configuration.get_instance() |
56 | 99 | ci.read_configuration('my_conf.ini') | 117 | ci.read_configuration(args.conf) |
57 | 100 | 118 | ||
58 | 101 | api = APIQuery(ci.config['C3']['URI']) | 119 | api = APIQuery(ci.config['C3']['URI']) |
61 | 102 | rparam = {"username": ci.config['C3']['UserName'], | 120 | rparam = {"username": args.c3user, |
62 | 103 | "api_key": ci.config['C3']['APIKey']} | 121 | "api_key": args.c3apikey} |
63 | 104 | 122 | ||
64 | 105 | c3query.api_instance.set_api_params(api, rparam) | 123 | c3query.api_instance.set_api_params(api, rparam) |
67 | 106 | hwdb = './hardware.db' | 124 | c3_to_db(args.hwdb) |
66 | 107 | c3_to_db(hwdb) | ||
68 | 108 | 125 | ||
69 | 109 | 126 | ||
70 | 110 | if __name__ == '__main__': | 127 | if __name__ == '__main__': |
71 | diff --git a/build/lib/cc_lab_manager/commands/__init__.py b/build/lib/cc_lab_manager/commands/__init__.py | |||
72 | 111 | new file mode 100644 | 128 | new file mode 100644 |
73 | index 0000000..e69de29 | |||
74 | --- /dev/null | |||
75 | +++ b/build/lib/cc_lab_manager/commands/__init__.py | |||
76 | diff --git a/build/lib/cc_lab_manager/commands/cc_lab_manager.py b/build/lib/cc_lab_manager/commands/cc_lab_manager.py | |||
77 | 112 | new file mode 100644 | 129 | new file mode 100644 |
78 | index 0000000..7da03df | |||
79 | --- /dev/null | |||
80 | +++ b/build/lib/cc_lab_manager/commands/cc_lab_manager.py | |||
81 | @@ -0,0 +1,49 @@ | |||
82 | 1 | import logging | ||
83 | 2 | import os | ||
84 | 3 | import sys | ||
85 | 4 | |||
86 | 5 | from cc_lab_manager.gsheet_db import gsheet_db | ||
87 | 6 | from cc_lab_manager.gsheet_db import db_gsheet | ||
88 | 7 | from cc_lab_manager.c3_db import c3_db | ||
89 | 8 | from cc_lab_manager.dhcp import dhcp_config_generator | ||
90 | 9 | from cc_lab_manager.maas import create_maas_node | ||
91 | 10 | from cc_lab_manager.gen_config import gen_agent_tf_config | ||
92 | 11 | |||
93 | 12 | logger = logging.getLogger('cc-lab-manager') | ||
94 | 13 | |||
95 | 14 | def main(): | ||
96 | 15 | # Read data from the google sheet to db | ||
97 | 16 | gsheet_db.main() | ||
98 | 17 | |||
99 | 18 | # Get needed information from c3 | ||
100 | 19 | c3_db.main() | ||
101 | 20 | |||
102 | 21 | # Generate DHCP config for each subnets | ||
103 | 22 | # TODO: Currently these config files need to be copied | ||
104 | 23 | # manually, then MAAS will apply it automatically | ||
105 | 24 | dhcp_config_generator.main() | ||
106 | 25 | |||
107 | 26 | # Create MAAS nodes for DUTs | ||
108 | 27 | create_maas_node.main() | ||
109 | 28 | |||
110 | 29 | # Create agent configs for DUTs | ||
111 | 30 | # TODO: Currently these configs need to be push/pull | ||
112 | 31 | # and applied manually | ||
113 | 32 | gen_agent_tf_config.main() | ||
114 | 33 | |||
115 | 34 | # Write data in db back to the google sheet | ||
116 | 35 | db_gsheet.main() | ||
117 | 36 | |||
118 | 37 | #ci = c3query.configuration.get_instance() | ||
119 | 38 | |||
120 | 39 | #api = APIQuery(ci.config['C3']['URI']) | ||
121 | 40 | #rparam = {"username": ci.config['C3']['UserName'], | ||
122 | 41 | # "api_key": ci.config['C3']['APIKey']} | ||
123 | 42 | |||
124 | 43 | #c3query.api_instance.set_api_params(api, rparam) | ||
125 | 44 | #hwdb = './hardware.db' | ||
126 | 45 | #c3_to_db(hwdb) | ||
127 | 46 | |||
128 | 47 | |||
129 | 48 | if __name__ == '__main__': | ||
130 | 49 | main() | ||
131 | diff --git a/build/lib/cc_lab_manager/dhcp/__init__.py b/build/lib/cc_lab_manager/dhcp/__init__.py | |||
132 | 0 | new file mode 100644 | 50 | new file mode 100644 |
133 | index 0000000..e69de29 | |||
134 | --- /dev/null | |||
135 | +++ b/build/lib/cc_lab_manager/dhcp/__init__.py | |||
136 | diff --git a/cc-lab-manager/dhcp/dhcp-config-generator.py b/build/lib/cc_lab_manager/dhcp/dhcp_config_generator.py | |||
137 | 1 | similarity index 69% | 51 | similarity index 69% |
138 | 2 | rename from cc-lab-manager/dhcp/dhcp-config-generator.py | 52 | rename from cc-lab-manager/dhcp/dhcp-config-generator.py |
139 | 3 | rename to build/lib/cc_lab_manager/dhcp/dhcp_config_generator.py | 53 | rename to build/lib/cc_lab_manager/dhcp/dhcp_config_generator.py |
140 | index 4ea854f..e586dd4 100644 | |||
141 | --- a/cc-lab-manager/dhcp/dhcp-config-generator.py | |||
142 | +++ b/build/lib/cc_lab_manager/dhcp/dhcp_config_generator.py | |||
143 | @@ -1,7 +1,8 @@ | |||
144 | 1 | import sqlite3 | 1 | import sqlite3 |
145 | 2 | import logging | 2 | import logging |
146 | 3 | import argparse | ||
147 | 4 | import os | ||
148 | 3 | from jinja2 import Template | 5 | from jinja2 import Template |
149 | 4 | import c3.api.query as c3query | ||
150 | 5 | 6 | ||
151 | 6 | logger = logging.getLogger('cc-lab-manager') | 7 | logger = logging.getLogger('cc-lab-manager') |
152 | 7 | 8 | ||
153 | @@ -38,15 +39,19 @@ host {{Lab}}-{{Frame}}-S{{Shelf}}-P{{Partition}}-ctl { | |||
154 | 38 | 39 | ||
155 | 39 | ''' | 40 | ''' |
156 | 40 | 41 | ||
159 | 41 | def generate_dhcp_conf(self, ip_mac_list, dhcp_conf): | 42 | def generate_dhcp_conf(self, ip_mac_list, dhcp_conf_path): |
160 | 42 | dhcp_conf_data = '' | 43 | dhcp_conf_data = {} |
161 | 43 | for ip_mac in ip_mac_list: | 44 | for ip_mac in ip_mac_list: |
162 | 44 | if ip_mac['IP'] == '' or ip_mac['Controller_IP'] == ''\ | 45 | if ip_mac['IP'] == '' or ip_mac['Controller_IP'] == ''\ |
163 | 45 | or ip_mac['Lab'] == '' or ip_mac['Frame'] == ''\ | 46 | or ip_mac['Lab'] == '' or ip_mac['Frame'] == ''\ |
164 | 46 | or ip_mac['Shelf'] == '' or ip_mac['Partition'] == '': | 47 | or ip_mac['Shelf'] == '' or ip_mac['Partition'] == '': |
166 | 47 | logger.error("Missing required information for", ip_mac['CID']) | 48 | if ip_mac['CID'] == '': |
167 | 49 | ip_mac_list.remove(ip_mac) | ||
168 | 50 | else: | ||
169 | 51 | logger.info("Missing required information for", ip_mac['CID']) | ||
170 | 48 | continue | 52 | continue |
171 | 49 | 53 | ||
172 | 54 | # Generate MAC for dummy devices or devices without fixed MAC | ||
173 | 50 | if ip_mac['MAC'] == '': | 55 | if ip_mac['MAC'] == '': |
174 | 51 | ip = ip_mac['IP'].split('.') | 56 | ip = ip_mac['IP'].split('.') |
175 | 52 | ip_mac['MAC'] = (f'ff:ff:ff:{int(ip[1]):02x}:' | 57 | ip_mac['MAC'] = (f'ff:ff:ff:{int(ip[1]):02x}:' |
176 | @@ -56,23 +61,35 @@ host {{Lab}}-{{Frame}}-S{{Shelf}}-P{{Partition}}-ctl { | |||
177 | 56 | ip_mac['Controller_MAC'] = (f'ff:ff:ff:{int(ip[1]):02x}:' | 61 | ip_mac['Controller_MAC'] = (f'ff:ff:ff:{int(ip[1]):02x}:' |
178 | 57 | f'{int(ip[2]):02x}:' | 62 | f'{int(ip[2]):02x}:' |
179 | 58 | f'{int(ip[3]):02x}') | 63 | f'{int(ip[3]):02x}') |
180 | 64 | |||
181 | 59 | tm = Template(self.dhcp_template) | 65 | tm = Template(self.dhcp_template) |
182 | 60 | machine_ip = tm.render(ip_mac) | 66 | machine_ip = tm.render(ip_mac) |
186 | 61 | dhcp_conf_data += machine_ip | 67 | if ip_mac['Lab'] not in dhcp_conf_data: |
187 | 62 | with open(dhcp_conf, 'w') as out: | 68 | dhcp_conf_data[ip_mac['Lab']] = machine_ip |
188 | 63 | out.write(dhcp_conf_data) | 69 | else: |
189 | 70 | dhcp_conf_data[ip_mac['Lab']] += machine_ip | ||
190 | 64 | 71 | ||
191 | 72 | for lab_id in dhcp_conf_data: | ||
192 | 73 | with open(os.path.join(dhcp_conf_path, 'cert-' + lab_id.lower() + '-dhcpd-pool.conf'), 'w') as out: | ||
193 | 74 | out.write(dhcp_conf_data[lab_id]) | ||
194 | 65 | 75 | ||
195 | 66 | def main(): | ||
196 | 67 | 76 | ||
199 | 68 | ci = c3query.configuration.get_instance() | 77 | def environ_or_required(key): |
200 | 69 | ci.read_configuration('my_conf.ini') | 78 | if os.environ.get(key): |
201 | 79 | return {'default': os.environ.get(key)} | ||
202 | 80 | else: | ||
203 | 81 | return {'required': True} | ||
204 | 82 | |||
205 | 83 | |||
206 | 84 | def main(): | ||
207 | 85 | parser = argparse.ArgumentParser() | ||
208 | 86 | parser.add_argument('--cctoolbox', help="Path to cc-tool-box for storing dhcp config", **environ_or_required('CCLM_CC_TOOL_BOX')) | ||
209 | 87 | parser.add_argument('--hwdb', help="Hardware db to read ip mapping", **environ_or_required('CCLM_HARDWARE_DB')) | ||
210 | 88 | args = parser.parse_args() | ||
211 | 70 | 89 | ||
215 | 71 | hwdb = ci.config['CC-LAB-MANAGER']['HWDB'] | 90 | ip_mac_list = read_data_from_db(args.hwdb) |
213 | 72 | dhcp_conf = ci.config['CC-LAB-MANAGER']['DHCP_CONFIG'] | ||
214 | 73 | ip_mac_list = read_data_from_db(hwdb) | ||
216 | 74 | dm = DhcpManager() | 91 | dm = DhcpManager() |
218 | 75 | dm.generate_dhcp_conf(ip_mac_list, dhcp_conf) | 92 | dm.generate_dhcp_conf(ip_mac_list, os.path.join(args.cctoolbox, 'config', 'dhcp')) |
219 | 76 | 93 | ||
220 | 77 | 94 | ||
221 | 78 | if __name__ == '__main__': | 95 | if __name__ == '__main__': |
222 | diff --git a/build/lib/cc_lab_manager/gen_config/__init__.py b/build/lib/cc_lab_manager/gen_config/__init__.py | |||
223 | 79 | new file mode 100644 | 96 | new file mode 100644 |
224 | index 0000000..e69de29 | |||
225 | --- /dev/null | |||
226 | +++ b/build/lib/cc_lab_manager/gen_config/__init__.py | |||
227 | diff --git a/cc-lab-manager/gen-config/gen-agent-tf-config.py b/build/lib/cc_lab_manager/gen_config/gen_agent_tf_config.py | |||
228 | 80 | similarity index 73% | 97 | similarity index 73% |
229 | 81 | rename from cc-lab-manager/gen-config/gen-agent-tf-config.py | 98 | rename from cc-lab-manager/gen-config/gen-agent-tf-config.py |
230 | 82 | rename to build/lib/cc_lab_manager/gen_config/gen_agent_tf_config.py | 99 | rename to build/lib/cc_lab_manager/gen_config/gen_agent_tf_config.py |
231 | index 337fe3e..8056656 100644 | |||
232 | --- a/cc-lab-manager/gen-config/gen-agent-tf-config.py | |||
233 | +++ b/build/lib/cc_lab_manager/gen_config/gen_agent_tf_config.py | |||
234 | @@ -6,7 +6,7 @@ import argparse | |||
235 | 6 | agent_config = {"device_ip": None, | 6 | agent_config = {"device_ip": None, |
236 | 7 | "secure_id": None, | 7 | "secure_id": None, |
237 | 8 | "node_id": None, | 8 | "node_id": None, |
239 | 9 | "maas_user": "sru-pool", | 9 | "maas_user": "cert_maas_admin", |
240 | 10 | "agent_name": None, | 10 | "agent_name": None, |
241 | 11 | "node_name": None, | 11 | "node_name": None, |
242 | 12 | "reset_efi": "true", | 12 | "reset_efi": "true", |
243 | @@ -65,27 +65,32 @@ def read_data_from_db(cursor): | |||
244 | 65 | results = cursor.fetchall() | 65 | results = cursor.fetchall() |
245 | 66 | return list(results) | 66 | return list(results) |
246 | 67 | 67 | ||
248 | 68 | def create_agent_config_dir(db_machine_list): | 68 | def create_agent_config_dir(db_machine_list, cfg_path): |
249 | 69 | 69 | ||
250 | 70 | for machine in db_machine_list: | 70 | for machine in db_machine_list: |
251 | 71 | 71 | ||
253 | 72 | agent_name = "sru"+machine["cid"].replace("-","") | 72 | if machine['lab'] == '': |
254 | 73 | continue | ||
255 | 74 | agent_name = "dut"+machine["cid"].replace("-","") | ||
256 | 73 | try: | 75 | try: |
258 | 74 | os.makedirs("{}".format(agent_name)) | 76 | os.makedirs(os.path.join(cfg_path, 'data-' + machine['lab'].lower(), agent_name)) |
259 | 75 | except: | 77 | except: |
260 | 76 | print("dir exist") | 78 | print("dir exist") |
261 | 77 | 79 | ||
263 | 78 | def generate_agent_config(db_machine_list): | 80 | def generate_agent_config(db_machine_list, cfg_path): |
264 | 79 | 81 | ||
265 | 80 | for machine in db_machine_list: | 82 | for machine in db_machine_list: |
266 | 81 | 83 | ||
267 | 84 | if machine['lab'] == '': | ||
268 | 85 | continue | ||
269 | 82 | agent_conf = agent_config.copy() | 86 | agent_conf = agent_config.copy() |
271 | 83 | agent_name = "sru" + machine["cid"].replace("-","") | 87 | agent_name = "dut" + machine["cid"].replace("-","") |
272 | 84 | secure_id = machine["SecureID"] | 88 | secure_id = machine["SecureID"] |
273 | 85 | ip = machine["IP"] | 89 | ip = machine["IP"] |
274 | 86 | node_id = machine["MAAS_Node_ID"] | 90 | node_id = machine["MAAS_Node_ID"] |
277 | 87 | node_name = machine["Model"].replace(")","",).replace("(","",).replace(" ","-")+ "-" + \ | 91 | # node_name = machine["Model"].replace(")","",).replace("(","",).replace(" ","-")+ "-" + \ |
278 | 88 | machine["sku"].replace(" ","").split("-")[-1] + "-" + machine["cid"] | 92 | # machine["sku"].replace(" ","").split("-")[-1] + "-" + machine["cid"] |
279 | 93 | node_name = machine["cid"] | ||
280 | 89 | 94 | ||
281 | 90 | agent_conf["node_name"] = node_name.lower() | 95 | agent_conf["node_name"] = node_name.lower() |
282 | 91 | agent_conf["agent_name"] = agent_name | 96 | agent_conf["agent_name"] = agent_name |
283 | @@ -95,7 +100,7 @@ def generate_agent_config(db_machine_list): | |||
284 | 95 | agent_conf["env"]["HEXR_DEVICE_SECURE_ID"] = secure_id | 100 | agent_conf["env"]["HEXR_DEVICE_SECURE_ID"] = secure_id |
285 | 96 | agent_conf["env"]["DEVICE_IP"] = ip | 101 | agent_conf["env"]["DEVICE_IP"] = ip |
286 | 97 | 102 | ||
288 | 98 | with open("{}/default.yaml".format(agent_name), "w+") as f: | 103 | with open(os.path.join(cfg_path, 'data-' + machine['lab'].lower(), agent_name, 'default.yaml'), "w+") as f: |
289 | 99 | 104 | ||
290 | 100 | for key in agent_config: | 105 | for key in agent_config: |
291 | 101 | if key == "env": | 106 | if key == "env": |
292 | @@ -108,36 +113,39 @@ def generate_agent_config(db_machine_list): | |||
293 | 108 | f.write("{key}: {value}\n".format(key=key,value=agent_conf[key])) | 113 | f.write("{key}: {value}\n".format(key=key,value=agent_conf[key])) |
294 | 109 | 114 | ||
295 | 110 | 115 | ||
297 | 111 | def generate_tf_config(db_machine_list): | 116 | def generate_tf_config(db_machine_list, cfg_path): |
298 | 112 | 117 | ||
299 | 113 | for machine in db_machine_list: | 118 | for machine in db_machine_list: |
300 | 119 | if machine['lab'] == '': | ||
301 | 120 | continue | ||
302 | 114 | tf_conf = tf_config.copy() | 121 | tf_conf = tf_config.copy() |
303 | 115 | 122 | ||
305 | 116 | agent_name = "sru" + machine["cid"].replace("-","") | 123 | agent_name = "dut" + machine["cid"].replace("-","") |
306 | 117 | tf_conf["agent_id"] = agent_name | 124 | tf_conf["agent_id"] = agent_name |
307 | 118 | tf_conf["execution_basedir"] = tf_conf["execution_basedir"].format(agent_name) | 125 | tf_conf["execution_basedir"] = tf_conf["execution_basedir"].format(agent_name) |
308 | 119 | tf_conf["logging_basedir"] = tf_conf["logging_basedir"].format(agent_name) | 126 | tf_conf["logging_basedir"] = tf_conf["logging_basedir"].format(agent_name) |
309 | 120 | tf_conf["results_basedir"] = tf_conf["results_basedir"].format(agent_name) | 127 | tf_conf["results_basedir"] = tf_conf["results_basedir"].format(agent_name) |
310 | 121 | 128 | ||
312 | 122 | with open("{}/testflinger-agent.conf".format(agent_name), "w+") as f: | 129 | with open(os.path.join(cfg_path, 'data-' + machine['lab'].lower(), agent_name, 'testflinger-agent.conf'), "w+") as f: |
313 | 123 | for key in tf_conf: | 130 | for key in tf_conf: |
314 | 124 | if key == "job_queues": | 131 | if key == "job_queues": |
315 | 125 | f.write(key+":\n"+"- "+machine["cid"] + "\n") | 132 | f.write(key+":\n"+"- "+machine["cid"] + "\n") |
316 | 126 | else: | 133 | else: |
317 | 127 | f.write(key + ": " + tf_conf[key] + "\n") | 134 | f.write(key + ": " + tf_conf[key] + "\n") |
318 | 128 | 135 | ||
320 | 129 | def create_agent_yaml(db_machine_list): | 136 | def create_agent_yaml(db_machine_list, cfg_path): |
321 | 130 | 137 | ||
323 | 131 | if not os.path.isfile("ce-tf-agents.yaml"): | 138 | # TODO: We need to separate configs for labs |
324 | 139 | if not os.path.isfile(os.path.join(cfg_path, "ce-tf-agents-tel-l5.yaml")): | ||
325 | 132 | 140 | ||
327 | 133 | with open("ce-tf-agents.yaml","w") as f: | 141 | with open(os.path.join(cfg_path, "ce-tf-agents-tel-l5.yaml"),"w") as f: |
328 | 134 | data = { | 142 | data = { |
329 | 135 | "series": "focal", | 143 | "series": "focal", |
330 | 136 | "description": "cert-testflinger-agents", | 144 | "description": "cert-testflinger-agents", |
331 | 137 | "applications":{ | 145 | "applications":{ |
333 | 138 | "agent-host-server":{ | 146 | "agent-host-server" + "-tel-l5":{ |
334 | 139 | "series": "focal", | 147 | "series": "focal", |
336 | 140 | "constraints": "tags=agent-host", | 148 | "constraints": "tags=agent-host" + "-tel-l5", |
337 | 141 | "charm": "../charms/testflinger-agent-host-charm", | 149 | "charm": "../charms/testflinger-agent-host-charm", |
338 | 142 | "num_units": 1, | 150 | "num_units": 1, |
339 | 143 | "resources":{ | 151 | "resources":{ |
340 | @@ -149,19 +157,21 @@ def create_agent_yaml(db_machine_list): | |||
341 | 149 | } | 157 | } |
342 | 150 | yaml.dump(data, f, default_flow_style=False, encoding='utf-8', allow_unicode=True, sort_keys=False) | 158 | yaml.dump(data, f, default_flow_style=False, encoding='utf-8', allow_unicode=True, sort_keys=False) |
343 | 151 | 159 | ||
345 | 152 | with open("ce-tf-agents.yaml","r+") as f: | 160 | with open(os.path.join(cfg_path, "ce-tf-agents-tel-l5.yaml"),"r+") as f: |
346 | 153 | 161 | ||
347 | 154 | data = yaml.safe_load(f) | 162 | data = yaml.safe_load(f) |
348 | 155 | for machine in db_machine_list: | 163 | for machine in db_machine_list: |
350 | 156 | agent_name = "sru" + machine["cid"].replace("-","") | 164 | if machine['lab'] == '': |
351 | 165 | continue | ||
352 | 166 | agent_name = "dut" + machine["cid"].replace("-","") | ||
353 | 157 | if agent_name in data["applications"]: | 167 | if agent_name in data["applications"]: |
354 | 158 | print("exist") | 168 | print("exist") |
355 | 159 | else: | 169 | else: |
356 | 160 | data["applications"][agent_name] = { | 170 | data["applications"][agent_name] = { |
357 | 161 | "charm":"../charms/testflinger-agent-charm", | 171 | "charm":"../charms/testflinger-agent-charm", |
358 | 162 | "resources":{ | 172 | "resources":{ |
361 | 163 | "device_configfile":"data/{}/default.yaml".format(agent_name), | 173 | "device_configfile":os.path.join(cfg_path, 'data-' + machine['lab'].lower(), agent_name, 'default.yaml'), |
362 | 164 | "testflinger_agent_configfile":"data/{}/testflinger-agent.conf".format(agent_name) | 174 | "testflinger_agent_configfile":os.path.join(cfg_path, 'data-' + machine['lab'].lower(), agent_name, 'testflinger-agent.conf') |
363 | 165 | }, | 175 | }, |
364 | 166 | "to": ["agent-host-server"] | 176 | "to": ["agent-host-server"] |
365 | 167 | } | 177 | } |
366 | @@ -183,10 +193,10 @@ def main(): | |||
367 | 183 | db = get_db_obj(args.database) | 193 | db = get_db_obj(args.database) |
368 | 184 | cursor = get_cursor_obj(db) | 194 | cursor = get_cursor_obj(db) |
369 | 185 | machine_list = read_data_from_db(cursor) | 195 | machine_list = read_data_from_db(cursor) |
374 | 186 | create_agent_config_dir(machine_list) | 196 | create_agent_config_dir(machine_list, os.path.join(os.environ.get('CCLM_CERT_JUJU'), 'ce-cert')) |
375 | 187 | generate_agent_config(machine_list) | 197 | generate_agent_config(machine_list, os.path.join(os.environ.get('CCLM_CERT_JUJU'), 'ce-cert')) |
376 | 188 | generate_tf_config(machine_list) | 198 | generate_tf_config(machine_list, os.path.join(os.environ.get('CCLM_CERT_JUJU'), 'ce-cert')) |
377 | 189 | create_agent_yaml(machine_list) | 199 | create_agent_yaml(machine_list, os.path.join(os.environ.get('CCLM_CERT_JUJU'), 'ce-cert')) |
378 | 190 | close_db(db) | 200 | close_db(db) |
379 | 191 | 201 | ||
380 | 192 | if __name__ == '__main__': | 202 | if __name__ == '__main__': |
381 | diff --git a/build/lib/cc_lab_manager/gsheet_db/__init__.py b/build/lib/cc_lab_manager/gsheet_db/__init__.py | |||
382 | 193 | new file mode 100644 | 203 | new file mode 100644 |
383 | index 0000000..e69de29 | |||
384 | --- /dev/null | |||
385 | +++ b/build/lib/cc_lab_manager/gsheet_db/__init__.py | |||
386 | diff --git a/cc-lab-manager/gsheet-db/db-gsheet.py b/build/lib/cc_lab_manager/gsheet_db/db_gsheet.py | |||
387 | 194 | similarity index 92% | 204 | similarity index 92% |
388 | 195 | rename from cc-lab-manager/gsheet-db/db-gsheet.py | 205 | rename from cc-lab-manager/gsheet-db/db-gsheet.py |
389 | 196 | rename to build/lib/cc_lab_manager/gsheet_db/db_gsheet.py | 206 | rename to build/lib/cc_lab_manager/gsheet_db/db_gsheet.py |
390 | index a0c7100..c535445 100644 | |||
391 | --- a/cc-lab-manager/gsheet-db/db-gsheet.py | |||
392 | +++ b/build/lib/cc_lab_manager/gsheet_db/db_gsheet.py | |||
393 | @@ -35,9 +35,9 @@ def iter_all_strings(): | |||
394 | 35 | if tmp_string == "az": | 35 | if tmp_string == "az": |
395 | 36 | return col_position_list | 36 | return col_position_list |
396 | 37 | 37 | ||
398 | 38 | def get_column_to_be_updated(): | 38 | def get_column_to_be_updated(token_file): |
399 | 39 | 39 | ||
401 | 40 | gc = pygsheets.authorize(service_file='token.json') | 40 | gc = pygsheets.authorize(service_file=token_file) |
402 | 41 | sht = gc.open_by_url(gsheet_url) | 41 | sht = gc.open_by_url(gsheet_url) |
403 | 42 | wks = sht[0] | 42 | wks = sht[0] |
404 | 43 | machine_list = wks.get_all_records(empty_value='', head=1, majdim='ROWS', numericise_data=False) | 43 | machine_list = wks.get_all_records(empty_value='', head=1, majdim='ROWS', numericise_data=False) |
405 | @@ -61,7 +61,7 @@ def sync_c3_data_to_sheet(db_machine_list,token_file): | |||
406 | 61 | wks = sht[0] | 61 | wks = sht[0] |
407 | 62 | 62 | ||
408 | 63 | # mapping table for position of column | 63 | # mapping table for position of column |
410 | 64 | col_to_be_updated = get_column_to_be_updated() | 64 | col_to_be_updated = get_column_to_be_updated(token_file) |
411 | 65 | 65 | ||
412 | 66 | row_num = 2 | 66 | row_num = 2 |
413 | 67 | cell_list = [] # list for storing cell that are waiting for update. | 67 | cell_list = [] # list for storing cell that are waiting for update. |
414 | @@ -73,9 +73,9 @@ def sync_c3_data_to_sheet(db_machine_list,token_file): | |||
415 | 73 | wks.update_cells(cell_list) | 73 | wks.update_cells(cell_list) |
416 | 74 | 74 | ||
417 | 75 | 75 | ||
419 | 76 | def read_data_from_db(cursor): | 76 | def read_data_from_db(cursor, token_file): |
420 | 77 | 77 | ||
422 | 78 | col_in_c3 = list(get_column_to_be_updated().keys()) | 78 | col_in_c3 = list(get_column_to_be_updated(token_file).keys()) |
423 | 79 | sqlcmd = 'select {} from lab_hw'.format(",".join(col_in_c3[0:])) | 79 | sqlcmd = 'select {} from lab_hw'.format(",".join(col_in_c3[0:])) |
424 | 80 | cursor.execute(sqlcmd) | 80 | cursor.execute(sqlcmd) |
425 | 81 | results = cursor.fetchall() | 81 | results = cursor.fetchall() |
426 | @@ -99,9 +99,9 @@ def main(): | |||
427 | 99 | gsheet_url = args.url | 99 | gsheet_url = args.url |
428 | 100 | db = get_db_obj(args.database) | 100 | db = get_db_obj(args.database) |
429 | 101 | cursor = get_cursor_obj(db) | 101 | cursor = get_cursor_obj(db) |
431 | 102 | sync_c3_data_to_sheet(read_data_from_db(cursor),args.token) | 102 | sync_c3_data_to_sheet(read_data_from_db(cursor, args.token),args.token) |
432 | 103 | close_db(db) | 103 | close_db(db) |
433 | 104 | 104 | ||
434 | 105 | 105 | ||
435 | 106 | if __name__ == '__main__': | 106 | if __name__ == '__main__': |
436 | 107 | main() | ||
437 | 108 | \ No newline at end of file | 107 | \ No newline at end of file |
438 | 108 | main() | ||
439 | diff --git a/cc-lab-manager/gsheet-db/gsheet-db.py b/build/lib/cc_lab_manager/gsheet_db/gsheet_db.py | |||
440 | 109 | similarity index 100% | 109 | similarity index 100% |
441 | 110 | rename from cc-lab-manager/gsheet-db/gsheet-db.py | 110 | rename from cc-lab-manager/gsheet-db/gsheet-db.py |
442 | 111 | rename to build/lib/cc_lab_manager/gsheet_db/gsheet_db.py | 111 | rename to build/lib/cc_lab_manager/gsheet_db/gsheet_db.py |
443 | diff --git a/build/lib/cc_lab_manager/maas/__init__.py b/build/lib/cc_lab_manager/maas/__init__.py | |||
444 | 112 | new file mode 100644 | 112 | new file mode 100644 |
445 | index 0000000..e69de29 | |||
446 | --- /dev/null | |||
447 | +++ b/build/lib/cc_lab_manager/maas/__init__.py | |||
448 | diff --git a/cc-lab-manager/maas/create-maas-node.py b/build/lib/cc_lab_manager/maas/create_maas_node.py | |||
449 | 113 | similarity index 88% | 113 | similarity index 88% |
450 | 114 | rename from cc-lab-manager/maas/create-maas-node.py | 114 | rename from cc-lab-manager/maas/create-maas-node.py |
451 | 115 | rename to build/lib/cc_lab_manager/maas/create_maas_node.py | 115 | rename to build/lib/cc_lab_manager/maas/create_maas_node.py |
452 | index e57d8a5..05be6dc 100644 | |||
453 | --- a/cc-lab-manager/maas/create-maas-node.py | |||
454 | +++ b/build/lib/cc_lab_manager/maas/create_maas_node.py | |||
455 | @@ -33,12 +33,11 @@ def read_data_from_db(cursor): | |||
456 | 33 | 33 | ||
457 | 34 | return list(results) | 34 | return list(results) |
458 | 35 | 35 | ||
460 | 36 | def get_maas_session(maas_ip): | 36 | def get_maas_session(maas_ip, maas_admin, maas_admin_password): |
461 | 37 | client = login( | 37 | client = login( |
462 | 38 | "http://{}:5240/MAAS/".format(maas_ip), | 38 | "http://{}:5240/MAAS/".format(maas_ip), |
464 | 39 | username="ubuntu", password="ubuntu", | 39 | username=maas_admin, password=maas_admin_password, |
465 | 40 | ) | 40 | ) |
466 | 41 | print(type(client)) | ||
467 | 42 | return client | 41 | return client |
468 | 43 | 42 | ||
469 | 44 | def get_mac_list(machine_list): | 43 | def get_mac_list(machine_list): |
470 | @@ -63,7 +62,7 @@ def get_maas_mac_list(client): | |||
471 | 63 | 62 | ||
472 | 64 | return mac_list | 63 | return mac_list |
473 | 65 | 64 | ||
475 | 66 | def create_maas_node(machine_list): | 65 | def create_maas_node(machine_list, maas_admin, maas_admin_password): |
476 | 67 | 66 | ||
477 | 68 | mass_is_connecting = "" | 67 | mass_is_connecting = "" |
478 | 69 | client = "" | 68 | client = "" |
479 | @@ -72,28 +71,28 @@ def create_maas_node(machine_list): | |||
480 | 72 | 71 | ||
481 | 73 | if not mass_is_connecting: | 72 | if not mass_is_connecting: |
482 | 74 | mass_is_connecting = machine["MAAS_Server"] | 73 | mass_is_connecting = machine["MAAS_Server"] |
484 | 75 | client = get_maas_session(mass_is_connecting) | 74 | client = get_maas_session(mass_is_connecting, maas_admin, maas_admin_password) |
485 | 76 | maas_mac_list = get_maas_mac_list(client) | 75 | maas_mac_list = get_maas_mac_list(client) |
486 | 77 | elif machine["MAAS_Server"] != mass_is_connecting: | 76 | elif machine["MAAS_Server"] != mass_is_connecting: |
487 | 78 | mass_is_connecting = machine["MAAS_Server"] | 77 | mass_is_connecting = machine["MAAS_Server"] |
489 | 79 | client = get_maas_session(mass_is_connecting) | 78 | client = get_maas_session(mass_is_connecting, maas_admin, maas_admin_password) |
490 | 80 | maas_mac_list = get_maas_mac_list(client) | 79 | maas_mac_list = get_maas_mac_list(client) |
491 | 81 | 80 | ||
492 | 82 | power_type = machine["Power"].lower() if machine["Power"] != "" else "manual" | 81 | power_type = machine["Power"].lower() if machine["Power"] != "" else "manual" |
493 | 83 | power_parameter = {} | 82 | power_parameter = {} |
494 | 84 | node_name = (machine["Model"].replace(")","",).replace("(","",).replace(" ","-")+ "-" + \ | 83 | node_name = (machine["Model"].replace(")","",).replace("(","",).replace(" ","-")+ "-" + \ |
495 | 85 | machine["sku"].replace(" ","").split("-")[-1] + "-" + machine["cid"]).lower() | 84 | machine["sku"].replace(" ","").split("-")[-1] + "-" + machine["cid"]).lower() |
496 | 85 | node_name = machine["cid"].lower() | ||
497 | 86 | 86 | ||
499 | 87 | if machine["MAC"] in maas_mac_list: | 87 | if machine["MAC"] in maas_mac_list or machine["MAC"] == '': |
500 | 88 | continue | 88 | continue |
501 | 89 | if power_type == "apc" or power_type == "raritan": | 89 | if power_type == "apc" or power_type == "raritan": |
502 | 90 | power_parameter["power_address"] = machine["PDU_IP"] | 90 | power_parameter["power_address"] = machine["PDU_IP"] |
503 | 91 | power_parameter["node_outlet"] = machine["PDU_Outlet"] | 91 | power_parameter["node_outlet"] = machine["PDU_Outlet"] |
504 | 92 | power_parameter["power_on_delay"] = 30 | 92 | power_parameter["power_on_delay"] = 30 |
505 | 93 | |||
506 | 94 | elif power_type == "amt": | 93 | elif power_type == "amt": |
507 | 95 | power_parameter["power_address"] = machine["IP"] | 94 | power_parameter["power_address"] = machine["IP"] |
509 | 96 | power_parameter["power_pass"] = "Insecure_101" | 95 | power_parameter["power_pass"] = "Insecure-101" |
510 | 97 | 96 | ||
511 | 98 | maas_node = client.machines.create("amd64",machine["MAC"], "manual",hostname=node_name) | 97 | maas_node = client.machines.create("amd64",machine["MAC"], "manual",hostname=node_name) |
512 | 99 | 98 | ||
513 | @@ -111,11 +110,13 @@ def main(): | |||
514 | 111 | 110 | ||
515 | 112 | parser = argparse.ArgumentParser() | 111 | parser = argparse.ArgumentParser() |
516 | 113 | parser.add_argument('--database', help="Database location",**environ_or_required('CCLM_HARDWARE_DB')) | 112 | parser.add_argument('--database', help="Database location",**environ_or_required('CCLM_HARDWARE_DB')) |
517 | 113 | parser.add_argument('--maas_admin', help="MAAS Admin account",**environ_or_required('CCLM_MAAS_ADMIN')) | ||
518 | 114 | parser.add_argument('--maas_admin_password', help="Password for MAAS Admin account",**environ_or_required('CCLM_MAAS_ADMIN_PASSWD')) | ||
519 | 114 | args = parser.parse_args() | 115 | args = parser.parse_args() |
520 | 115 | db = get_db_obj(args.database) | 116 | db = get_db_obj(args.database) |
521 | 116 | cursor = get_cursor_obj(db) | 117 | cursor = get_cursor_obj(db) |
522 | 117 | machine_list = read_data_from_db(cursor) | 118 | machine_list = read_data_from_db(cursor) |
524 | 118 | create_maas_node(machine_list) | 119 | create_maas_node(machine_list, args.maas_admin, args.maas_admin_password) |
525 | 119 | update_node_id(cursor) | 120 | update_node_id(cursor) |
526 | 120 | close_db(db) | 121 | close_db(db) |
527 | 121 | 122 | ||
528 | diff --git a/cc_lab_manager.egg-info/PKG-INFO b/cc_lab_manager.egg-info/PKG-INFO | |||
529 | 122 | new file mode 100644 | 123 | new file mode 100644 |
530 | index 0000000..03809d0 | |||
531 | --- /dev/null | |||
532 | +++ b/cc_lab_manager.egg-info/PKG-INFO | |||
533 | @@ -0,0 +1,11 @@ | |||
534 | 1 | Metadata-Version: 1.1 | ||
535 | 2 | Name: cc-lab-manager | ||
536 | 3 | Version: 0.1 | ||
537 | 4 | Summary: Automated managing hardwares in Canonical Certification Labs | ||
538 | 5 | Home-page: https://code.launchpad.net/cc-lab-manager/ | ||
539 | 6 | Author: Gavin Lin (gavin.lin) | ||
540 | 7 | Author-email: gavin.lin@canonical.com | ||
541 | 8 | License: UNKNOWN | ||
542 | 9 | Description: UNKNOWN | ||
543 | 10 | Platform: UNKNOWN | ||
544 | 11 | Classifier: Programming Language :: Python | ||
545 | diff --git a/cc_lab_manager.egg-info/SOURCES.txt b/cc_lab_manager.egg-info/SOURCES.txt | |||
546 | 0 | new file mode 100644 | 12 | new file mode 100644 |
547 | index 0000000..7cfee1b | |||
548 | --- /dev/null | |||
549 | +++ b/cc_lab_manager.egg-info/SOURCES.txt | |||
550 | @@ -0,0 +1,23 @@ | |||
551 | 1 | README.md | ||
552 | 2 | setup.cfg | ||
553 | 3 | setup.py | ||
554 | 4 | cc_lab_manager/__init__.py | ||
555 | 5 | cc_lab_manager.egg-info/PKG-INFO | ||
556 | 6 | cc_lab_manager.egg-info/SOURCES.txt | ||
557 | 7 | cc_lab_manager.egg-info/dependency_links.txt | ||
558 | 8 | cc_lab_manager.egg-info/entry_points.txt | ||
559 | 9 | cc_lab_manager.egg-info/requires.txt | ||
560 | 10 | cc_lab_manager.egg-info/top_level.txt | ||
561 | 11 | cc_lab_manager/c3_db/__init__.py | ||
562 | 12 | cc_lab_manager/c3_db/c3_db.py | ||
563 | 13 | cc_lab_manager/commands/__init__.py | ||
564 | 14 | cc_lab_manager/commands/cc_lab_manager.py | ||
565 | 15 | cc_lab_manager/dhcp/__init__.py | ||
566 | 16 | cc_lab_manager/dhcp/dhcp_config_generator.py | ||
567 | 17 | cc_lab_manager/gen_config/__init__.py | ||
568 | 18 | cc_lab_manager/gen_config/gen_agent_tf_config.py | ||
569 | 19 | cc_lab_manager/gsheet_db/__init__.py | ||
570 | 20 | cc_lab_manager/gsheet_db/db_gsheet.py | ||
571 | 21 | cc_lab_manager/gsheet_db/gsheet_db.py | ||
572 | 22 | cc_lab_manager/maas/__init__.py | ||
573 | 23 | cc_lab_manager/maas/create_maas_node.py | ||
574 | 0 | \ No newline at end of file | 24 | \ No newline at end of file |
575 | diff --git a/cc_lab_manager.egg-info/dependency_links.txt b/cc_lab_manager.egg-info/dependency_links.txt | |||
576 | 1 | new file mode 100644 | 25 | new file mode 100644 |
577 | index 0000000..8b13789 | |||
578 | --- /dev/null | |||
579 | +++ b/cc_lab_manager.egg-info/dependency_links.txt | |||
580 | @@ -0,0 +1 @@ | |||
581 | 1 | |||
582 | diff --git a/cc_lab_manager.egg-info/entry_points.txt b/cc_lab_manager.egg-info/entry_points.txt | |||
583 | 0 | new file mode 100644 | 2 | new file mode 100644 |
584 | index 0000000..21bd2e3 | |||
585 | --- /dev/null | |||
586 | +++ b/cc_lab_manager.egg-info/entry_points.txt | |||
587 | @@ -0,0 +1,3 @@ | |||
588 | 1 | [console_scripts] | ||
589 | 2 | cc-lab-manager = cc_lab_manager.commands.cc_lab_manager:main | ||
590 | 3 | |||
591 | diff --git a/cc_lab_manager.egg-info/requires.txt b/cc_lab_manager.egg-info/requires.txt | |||
592 | 0 | new file mode 100644 | 4 | new file mode 100644 |
593 | index 0000000..26dccbc | |||
594 | --- /dev/null | |||
595 | +++ b/cc_lab_manager.egg-info/requires.txt | |||
596 | @@ -0,0 +1,4 @@ | |||
597 | 1 | aiohttp==3.7.2 | ||
598 | 2 | jinja2 | ||
599 | 3 | pysheets | ||
600 | 4 | python-libmaas | ||
601 | diff --git a/cc_lab_manager.egg-info/top_level.txt b/cc_lab_manager.egg-info/top_level.txt | |||
602 | 0 | new file mode 100644 | 5 | new file mode 100644 |
603 | index 0000000..b831c50 | |||
604 | --- /dev/null | |||
605 | +++ b/cc_lab_manager.egg-info/top_level.txt | |||
606 | @@ -0,0 +1 @@ | |||
607 | 1 | cc_lab_manager | ||
608 | diff --git a/cc_lab_manager/__init__.py b/cc_lab_manager/__init__.py | |||
609 | 0 | new file mode 100644 | 2 | new file mode 100644 |
610 | index 0000000..e69de29 | |||
611 | --- /dev/null | |||
612 | +++ b/cc_lab_manager/__init__.py | |||
613 | diff --git a/cc_lab_manager/c3_db/__init__.py b/cc_lab_manager/c3_db/__init__.py | |||
614 | 1 | new file mode 100644 | 3 | new file mode 100644 |
615 | index 0000000..e69de29 | |||
616 | --- /dev/null | |||
617 | +++ b/cc_lab_manager/c3_db/__init__.py | |||
618 | diff --git a/cc_lab_manager/c3_db/c3_db.py b/cc_lab_manager/c3_db/c3_db.py | |||
619 | 2 | new file mode 100644 | 4 | new file mode 100644 |
620 | index 0000000..b9b0d7e | |||
621 | --- /dev/null | |||
622 | +++ b/cc_lab_manager/c3_db/c3_db.py | |||
623 | @@ -0,0 +1,128 @@ | |||
624 | 1 | import sqlite3 | ||
625 | 2 | import logging | ||
626 | 3 | import argparse | ||
627 | 4 | import c3.api.query as c3query | ||
628 | 5 | from c3.api.api_utils import APIQuery | ||
629 | 6 | import os | ||
630 | 7 | |||
631 | 8 | logger = logging.getLogger('cc-lab-manager') | ||
632 | 9 | |||
633 | 10 | |||
634 | 11 | def c3_to_db(db_path): | ||
635 | 12 | """ | ||
636 | 13 | Query machine info from c3 and write to db. | ||
637 | 14 | """ | ||
638 | 15 | |||
639 | 16 | # Read CID from db | ||
640 | 17 | try: | ||
641 | 18 | hwdb = sqlite3.connect(db_path) | ||
642 | 19 | cur = hwdb.execute('SELECT cid FROM lab_hw') | ||
643 | 20 | cid_list = cur.fetchall() | ||
644 | 21 | except Exception as e: | ||
645 | 22 | logger.error('Error when reading db: ', e) | ||
646 | 23 | |||
647 | 24 | for cid_db in cid_list: | ||
648 | 25 | cid = ''.join(cid_db) | ||
649 | 26 | logger.info('Processing {}...'.format(cid)) | ||
650 | 27 | if '-' not in cid or 'TEL' in cid: | ||
651 | 28 | continue | ||
652 | 29 | |||
653 | 30 | # Query hardware info from c3 | ||
654 | 31 | result = '' | ||
655 | 32 | try: | ||
656 | 33 | result = c3query.query_over_api_hardware(cid) | ||
657 | 34 | except Exception as e: | ||
658 | 35 | logger.error("Error when query c3: ", e) | ||
659 | 36 | |||
660 | 37 | if result: | ||
661 | 38 | # Map hardware info from c3 to db column | ||
662 | 39 | try: | ||
663 | 40 | location = result['location']['name'] | ||
664 | 41 | except Exception as e: | ||
665 | 42 | logger.warning('Failed Reading location: {}'.format(e)) | ||
666 | 43 | location = 'None' | ||
667 | 44 | try: | ||
668 | 45 | account = result['account']['name'] | ||
669 | 46 | except Exception as e: | ||
670 | 47 | logger.warning('Failed reading account: {}'.format(e)) | ||
671 | 48 | account = 'None' | ||
672 | 49 | try: | ||
673 | 50 | platform_name = result['platform']['name'] | ||
674 | 51 | codename = result['platform']['codename'] | ||
675 | 52 | form_factor = result['platform']['form_factor'] | ||
676 | 53 | model = result['platform']['aliases'] | ||
677 | 54 | except Exception as e: | ||
678 | 55 | logger.warning('Failed reading platform: {}'.format(e)) | ||
679 | 56 | platform_name = 'None' | ||
680 | 57 | codename = 'None' | ||
681 | 58 | form_factor = 'None' | ||
682 | 59 | model = 'None' | ||
683 | 60 | try: | ||
684 | 61 | canonical_contact = result['canonical_contact']['display_name'] | ||
685 | 62 | except Exception as e: | ||
686 | 63 | logger.warning('Failed reading canonical_contact: {}' | ||
687 | 64 | .format(e)) | ||
688 | 65 | canonical_contact = 'None' | ||
689 | 66 | try: | ||
690 | 67 | holder = result['holder']['name'] | ||
691 | 68 | except Exception as e: | ||
692 | 69 | logger.warning('Failed reading holder: {}'.format(e)) | ||
693 | 70 | holder = 'None' | ||
694 | 71 | hw_info = {'Location': location, | ||
695 | 72 | 'Status': result['status'], | ||
696 | 73 | 'Account': account, | ||
697 | 74 | 'Project': result['project_name'], | ||
698 | 75 | 'Model': model, | ||
699 | 76 | 'CanonicalLabel': result['canonical_label'], | ||
700 | 77 | 'PlatformName': platform_name, | ||
701 | 78 | 'CodeName': codename, | ||
702 | 79 | 'SKU': result['sku'], | ||
703 | 80 | 'HardwareBuild': result['hardware_build'], | ||
704 | 81 | 'Form': form_factor, | ||
705 | 82 | 'CanonicalContact': canonical_contact, | ||
706 | 83 | 'Holder': holder, | ||
707 | 84 | 'SecureID': result['secure_id']} | ||
708 | 85 | |||
709 | 86 | # Write hardware info to db | ||
710 | 87 | try: | ||
711 | 88 | for key in hw_info: | ||
712 | 89 | sql_cmd = 'UPDATE lab_hw SET {} = "{}" WHERE CID = "{}"' \ | ||
713 | 90 | .format(key, hw_info[key], | ||
714 | 91 | result['canonical_id']) | ||
715 | 92 | hwdb.execute(sql_cmd) | ||
716 | 93 | hwdb.commit() | ||
717 | 94 | except Exception as e: | ||
718 | 95 | logger.error('Error writing to db: ', e) | ||
719 | 96 | hwdb.close() | ||
720 | 97 | |||
721 | 98 | hwdb.close() | ||
722 | 99 | |||
723 | 100 | |||
724 | 101 | def environ_or_required(key): | ||
725 | 102 | if os.environ.get(key): | ||
726 | 103 | return {'default': os.environ.get(key)} | ||
727 | 104 | else: | ||
728 | 105 | return {'required': True} | ||
729 | 106 | |||
730 | 107 | |||
731 | 108 | def main(): | ||
732 | 109 | parser = argparse.ArgumentParser() | ||
733 | 110 | parser.add_argument('--conf', help="Config file for C3 API", default = os.environ.get('CCLM_CC_TOOL_BOX') + '/config/c3-cli/my_conf.ini') | ||
734 | 111 | parser.add_argument('--c3user', help="C3 User Account", **environ_or_required('CCLM_C3_USERNAME')) | ||
735 | 112 | parser.add_argument('--c3apikey', help="C3 API Key", **environ_or_required('CCLM_C3_APIKEY')) | ||
736 | 113 | parser.add_argument('--hwdb', help="C3 API Key", **environ_or_required('CCLM_HARDWARE_DB')) | ||
737 | 114 | args = parser.parse_args() | ||
738 | 115 | |||
739 | 116 | ci = c3query.configuration.get_instance() | ||
740 | 117 | ci.read_configuration(args.conf) | ||
741 | 118 | |||
742 | 119 | api = APIQuery(ci.config['C3']['URI']) | ||
743 | 120 | rparam = {"username": args.c3user, | ||
744 | 121 | "api_key": args.c3apikey} | ||
745 | 122 | |||
746 | 123 | c3query.api_instance.set_api_params(api, rparam) | ||
747 | 124 | c3_to_db(args.hwdb) | ||
748 | 125 | |||
749 | 126 | |||
750 | 127 | if __name__ == '__main__': | ||
751 | 128 | main() | ||
752 | diff --git a/cc_lab_manager/commands/__init__.py b/cc_lab_manager/commands/__init__.py | |||
753 | 0 | new file mode 100644 | 129 | new file mode 100644 |
754 | index 0000000..e69de29 | |||
755 | --- /dev/null | |||
756 | +++ b/cc_lab_manager/commands/__init__.py | |||
757 | diff --git a/cc_lab_manager/commands/cc_lab_manager.py b/cc_lab_manager/commands/cc_lab_manager.py | |||
758 | 1 | new file mode 100644 | 130 | new file mode 100644 |
759 | index 0000000..7da03df | |||
760 | --- /dev/null | |||
761 | +++ b/cc_lab_manager/commands/cc_lab_manager.py | |||
762 | @@ -0,0 +1,49 @@ | |||
763 | 1 | import logging | ||
764 | 2 | import os | ||
765 | 3 | import sys | ||
766 | 4 | |||
767 | 5 | from cc_lab_manager.gsheet_db import gsheet_db | ||
768 | 6 | from cc_lab_manager.gsheet_db import db_gsheet | ||
769 | 7 | from cc_lab_manager.c3_db import c3_db | ||
770 | 8 | from cc_lab_manager.dhcp import dhcp_config_generator | ||
771 | 9 | from cc_lab_manager.maas import create_maas_node | ||
772 | 10 | from cc_lab_manager.gen_config import gen_agent_tf_config | ||
773 | 11 | |||
774 | 12 | logger = logging.getLogger('cc-lab-manager') | ||
775 | 13 | |||
776 | 14 | def main(): | ||
777 | 15 | # Read data from the google sheet to db | ||
778 | 16 | gsheet_db.main() | ||
779 | 17 | |||
780 | 18 | # Get needed information from c3 | ||
781 | 19 | c3_db.main() | ||
782 | 20 | |||
783 | 21 | # Generate DHCP config for each subnets | ||
784 | 22 | # TODO: Currently these config files need to be copied | ||
785 | 23 | # manually, then MAAS will apply it automatically | ||
786 | 24 | dhcp_config_generator.main() | ||
787 | 25 | |||
788 | 26 | # Create MAAS nodes for DUTs | ||
789 | 27 | create_maas_node.main() | ||
790 | 28 | |||
791 | 29 | # Create agent configs for DUTs | ||
792 | 30 | # TODO: Currently these configs need to be push/pull | ||
793 | 31 | # and applied manually | ||
794 | 32 | gen_agent_tf_config.main() | ||
795 | 33 | |||
796 | 34 | # Write data in db back to the google sheet | ||
797 | 35 | db_gsheet.main() | ||
798 | 36 | |||
799 | 37 | #ci = c3query.configuration.get_instance() | ||
800 | 38 | |||
801 | 39 | #api = APIQuery(ci.config['C3']['URI']) | ||
802 | 40 | #rparam = {"username": ci.config['C3']['UserName'], | ||
803 | 41 | # "api_key": ci.config['C3']['APIKey']} | ||
804 | 42 | |||
805 | 43 | #c3query.api_instance.set_api_params(api, rparam) | ||
806 | 44 | #hwdb = './hardware.db' | ||
807 | 45 | #c3_to_db(hwdb) | ||
808 | 46 | |||
809 | 47 | |||
810 | 48 | if __name__ == '__main__': | ||
811 | 49 | main() | ||
812 | diff --git a/cc_lab_manager/dhcp/__init__.py b/cc_lab_manager/dhcp/__init__.py | |||
813 | 0 | new file mode 100644 | 50 | new file mode 100644 |
814 | index 0000000..e69de29 | |||
815 | --- /dev/null | |||
816 | +++ b/cc_lab_manager/dhcp/__init__.py | |||
817 | diff --git a/cc_lab_manager/dhcp/dhcp_config_generator.py b/cc_lab_manager/dhcp/dhcp_config_generator.py | |||
818 | 1 | new file mode 100644 | 51 | new file mode 100644 |
819 | index 0000000..e586dd4 | |||
820 | --- /dev/null | |||
821 | +++ b/cc_lab_manager/dhcp/dhcp_config_generator.py | |||
822 | @@ -0,0 +1,96 @@ | |||
823 | 1 | import sqlite3 | ||
824 | 2 | import logging | ||
825 | 3 | import argparse | ||
826 | 4 | import os | ||
827 | 5 | from jinja2 import Template | ||
828 | 6 | |||
829 | 7 | logger = logging.getLogger('cc-lab-manager') | ||
830 | 8 | |||
831 | 9 | |||
832 | 10 | def read_data_from_db(path_to_db): | ||
833 | 11 | db = sqlite3.connect(path_to_db) | ||
834 | 12 | db.row_factory = sqlite3.Row | ||
835 | 13 | col_in_db = ["CID", "MAC", "Controller_MAC", "Provision", "IP", | ||
836 | 14 | "Controller_IP", "Lab", "Frame", "Shelf", "Partition"] | ||
837 | 15 | sqlcmd = ('select {},{},{},{},{},{},{},{},{},{} from lab_hw' | ||
838 | 16 | .format(*col_in_db)) | ||
839 | 17 | db_row_objs = db.execute(sqlcmd).fetchall() | ||
840 | 18 | db.close() | ||
841 | 19 | db_dict_list = [] | ||
842 | 20 | for row_obj in db_row_objs: | ||
843 | 21 | db_dict_list.append({k: row_obj[k] for k in row_obj.keys()}) | ||
844 | 22 | return db_dict_list | ||
845 | 23 | |||
846 | 24 | |||
847 | 25 | class DhcpManager: | ||
848 | 26 | def __init__(self): | ||
849 | 27 | self.dhcp_template = ''' | ||
850 | 28 | # {{CID}} | ||
851 | 29 | host {{Lab}}-{{Frame}}-S{{Shelf}}-P{{Partition}} { | ||
852 | 30 | hardware ethernet {{MAC}}; | ||
853 | 31 | fixed-address {{IP}}; | ||
854 | 32 | } | ||
855 | 33 | |||
856 | 34 | # {{CID}}-controller | ||
857 | 35 | host {{Lab}}-{{Frame}}-S{{Shelf}}-P{{Partition}}-ctl { | ||
858 | 36 | hardware ethernet {{Controller_MAC}}; | ||
859 | 37 | fixed-address {{Controller_IP}}; | ||
860 | 38 | } | ||
861 | 39 | |||
862 | 40 | ''' | ||
863 | 41 | |||
864 | 42 | def generate_dhcp_conf(self, ip_mac_list, dhcp_conf_path): | ||
865 | 43 | dhcp_conf_data = {} | ||
866 | 44 | for ip_mac in ip_mac_list: | ||
867 | 45 | if ip_mac['IP'] == '' or ip_mac['Controller_IP'] == ''\ | ||
868 | 46 | or ip_mac['Lab'] == '' or ip_mac['Frame'] == ''\ | ||
869 | 47 | or ip_mac['Shelf'] == '' or ip_mac['Partition'] == '': | ||
870 | 48 | if ip_mac['CID'] == '': | ||
871 | 49 | ip_mac_list.remove(ip_mac) | ||
872 | 50 | else: | ||
873 | 51 | logger.info("Missing required information for", ip_mac['CID']) | ||
874 | 52 | continue | ||
875 | 53 | |||
876 | 54 | # Generate MAC for dummy devices or devices without fixed MAC | ||
877 | 55 | if ip_mac['MAC'] == '': | ||
878 | 56 | ip = ip_mac['IP'].split('.') | ||
879 | 57 | ip_mac['MAC'] = (f'ff:ff:ff:{int(ip[1]):02x}:' | ||
880 | 58 | f'{int(ip[2]):02x}:{int(ip[3]):02x}') | ||
881 | 59 | if ip_mac['Controller_MAC'] == '': | ||
882 | 60 | ip = ip_mac['Controller_IP'].split('.') | ||
883 | 61 | ip_mac['Controller_MAC'] = (f'ff:ff:ff:{int(ip[1]):02x}:' | ||
884 | 62 | f'{int(ip[2]):02x}:' | ||
885 | 63 | f'{int(ip[3]):02x}') | ||
886 | 64 | |||
887 | 65 | tm = Template(self.dhcp_template) | ||
888 | 66 | machine_ip = tm.render(ip_mac) | ||
889 | 67 | if ip_mac['Lab'] not in dhcp_conf_data: | ||
890 | 68 | dhcp_conf_data[ip_mac['Lab']] = machine_ip | ||
891 | 69 | else: | ||
892 | 70 | dhcp_conf_data[ip_mac['Lab']] += machine_ip | ||
893 | 71 | |||
894 | 72 | for lab_id in dhcp_conf_data: | ||
895 | 73 | with open(os.path.join(dhcp_conf_path, 'cert-' + lab_id.lower() + '-dhcpd-pool.conf'), 'w') as out: | ||
896 | 74 | out.write(dhcp_conf_data[lab_id]) | ||
897 | 75 | |||
898 | 76 | |||
899 | 77 | def environ_or_required(key): | ||
900 | 78 | if os.environ.get(key): | ||
901 | 79 | return {'default': os.environ.get(key)} | ||
902 | 80 | else: | ||
903 | 81 | return {'required': True} | ||
904 | 82 | |||
905 | 83 | |||
906 | 84 | def main(): | ||
907 | 85 | parser = argparse.ArgumentParser() | ||
908 | 86 | parser.add_argument('--cctoolbox', help="Path to cc-tool-box for storing dhcp config", **environ_or_required('CCLM_CC_TOOL_BOX')) | ||
909 | 87 | parser.add_argument('--hwdb', help="Hardware db to read ip mapping", **environ_or_required('CCLM_HARDWARE_DB')) | ||
910 | 88 | args = parser.parse_args() | ||
911 | 89 | |||
912 | 90 | ip_mac_list = read_data_from_db(args.hwdb) | ||
913 | 91 | dm = DhcpManager() | ||
914 | 92 | dm.generate_dhcp_conf(ip_mac_list, os.path.join(args.cctoolbox, 'config', 'dhcp')) | ||
915 | 93 | |||
916 | 94 | |||
917 | 95 | if __name__ == '__main__': | ||
918 | 96 | main() | ||
919 | diff --git a/cc_lab_manager/gen_config/__init__.py b/cc_lab_manager/gen_config/__init__.py | |||
920 | 0 | new file mode 100644 | 97 | new file mode 100644 |
921 | index 0000000..e69de29 | |||
922 | --- /dev/null | |||
923 | +++ b/cc_lab_manager/gen_config/__init__.py | |||
924 | diff --git a/cc_lab_manager/gen_config/gen_agent_tf_config.py b/cc_lab_manager/gen_config/gen_agent_tf_config.py | |||
925 | 1 | new file mode 100644 | 98 | new file mode 100644 |
926 | index 0000000..8056656 | |||
927 | --- /dev/null | |||
928 | +++ b/cc_lab_manager/gen_config/gen_agent_tf_config.py | |||
929 | @@ -0,0 +1,203 @@ | |||
930 | 1 | import sqlite3 | ||
931 | 2 | import os | ||
932 | 3 | import yaml | ||
933 | 4 | import argparse | ||
934 | 5 | |||
935 | 6 | agent_config = {"device_ip": None, | ||
936 | 7 | "secure_id": None, | ||
937 | 8 | "node_id": None, | ||
938 | 9 | "maas_user": "cert_maas_admin", | ||
939 | 10 | "agent_name": None, | ||
940 | 11 | "node_name": None, | ||
941 | 12 | "reset_efi": "true", | ||
942 | 13 | "env":{"HEXR_DEVICE_SECURE_ID": None, | ||
943 | 14 | "WPA_BG_SSID": "ubuntu-cert-bg-wpa-tpelab", | ||
944 | 15 | "WPA_BG_PSK": "insecure", | ||
945 | 16 | "WPA_N_SSID": "ubuntu-cert-n-wpa-tpelab", | ||
946 | 17 | "WPA_N_PSK": "insecure", | ||
947 | 18 | "WPA_AC_SSID": "ubuntu-cert-ac-wpa-tpelab", | ||
948 | 19 | "WPA_AC_PSK": "insecure", | ||
949 | 20 | "OPEN_BG_SSID": "ubuntu-cert-bg-open-tpelab", | ||
950 | 21 | "OPEN_N_SSID": "ubuntu-cert-n-open-tpelab", | ||
951 | 22 | "OPEN_AC_SSID": "ubuntu-cert-ac-open-tpelab", | ||
952 | 23 | "DEVICE_IP": None | ||
953 | 24 | } | ||
954 | 25 | } | ||
955 | 26 | |||
956 | 27 | tf_config = {"agent_id": None, | ||
957 | 28 | "server_address": "https://testflinger.canonical.com", | ||
958 | 29 | "global_timeout": "43200", | ||
959 | 30 | "output_timeout": "8000", | ||
960 | 31 | "execution_basedir": "/home/ubuntu/testflinger/{}/run", | ||
961 | 32 | "logging_basedir": "/home/ubuntu/testflinger/{}/logs", | ||
962 | 33 | "results_basedir": "/home/ubuntu/testflinger/{}/results", | ||
963 | 34 | "logging_level": "INFO", | ||
964 | 35 | "job_queues": None, | ||
965 | 36 | "setup_command": "tf-setup", | ||
966 | 37 | "provision_command": "tf-provision", | ||
967 | 38 | "test_command": "tf-test", | ||
968 | 39 | "reserve_command": "tf-reserve", | ||
969 | 40 | "cleanup_command": "tf-cleanup", | ||
970 | 41 | "provision_type": "maas2" | ||
971 | 42 | } | ||
972 | 43 | |||
973 | 44 | def get_db_obj(path_to_db): | ||
974 | 45 | |||
975 | 46 | db = sqlite3.connect(path_to_db) | ||
976 | 47 | db.row_factory = sqlite3.Row | ||
977 | 48 | return db | ||
978 | 49 | |||
979 | 50 | def get_cursor_obj(db_obj): | ||
980 | 51 | |||
981 | 52 | cursor = db_obj.cursor() | ||
982 | 53 | return cursor | ||
983 | 54 | |||
984 | 55 | def close_db(db): | ||
985 | 56 | db.commit() | ||
986 | 57 | db.close() | ||
987 | 58 | |||
988 | 59 | def read_data_from_db(cursor): | ||
989 | 60 | |||
990 | 61 | col_in_c3 = ["CID","Lab","IP","SKU","MAAS_Node_ID","Model","SecureID"] | ||
991 | 62 | |||
992 | 63 | sqlcmd = 'select {},{},{},{},{},{},{} from lab_hw where CID not like \'TEL-%\''.format(*col_in_c3) | ||
993 | 64 | cursor.execute(sqlcmd) | ||
994 | 65 | results = cursor.fetchall() | ||
995 | 66 | return list(results) | ||
996 | 67 | |||
997 | 68 | def create_agent_config_dir(db_machine_list, cfg_path): | ||
998 | 69 | |||
999 | 70 | for machine in db_machine_list: | ||
1000 | 71 | |||
1001 | 72 | if machine['lab'] == '': | ||
1002 | 73 | continue | ||
1003 | 74 | agent_name = "dut"+machine["cid"].replace("-","") | ||
1004 | 75 | try: | ||
1005 | 76 | os.makedirs(os.path.join(cfg_path, 'data-' + machine['lab'].lower(), agent_name)) | ||
1006 | 77 | except: | ||
1007 | 78 | print("dir exist") | ||
1008 | 79 | |||
1009 | 80 | def generate_agent_config(db_machine_list, cfg_path): | ||
1010 | 81 | |||
1011 | 82 | for machine in db_machine_list: | ||
1012 | 83 | |||
1013 | 84 | if machine['lab'] == '': | ||
1014 | 85 | continue | ||
1015 | 86 | agent_conf = agent_config.copy() | ||
1016 | 87 | agent_name = "dut" + machine["cid"].replace("-","") | ||
1017 | 88 | secure_id = machine["SecureID"] | ||
1018 | 89 | ip = machine["IP"] | ||
1019 | 90 | node_id = machine["MAAS_Node_ID"] | ||
1020 | 91 | # node_name = machine["Model"].replace(")","",).replace("(","",).replace(" ","-")+ "-" + \ | ||
1021 | 92 | # machine["sku"].replace(" ","").split("-")[-1] + "-" + machine["cid"] | ||
1022 | 93 | node_name = machine["cid"] | ||
1023 | 94 | |||
1024 | 95 | agent_conf["node_name"] = node_name.lower() | ||
1025 | 96 | agent_conf["agent_name"] = agent_name | ||
1026 | 97 | agent_conf["secure_id"] = secure_id | ||
1027 | 98 | agent_conf["node_id"] = node_id | ||
1028 | 99 | agent_conf["device_ip"] = ip | ||
1029 | 100 | agent_conf["env"]["HEXR_DEVICE_SECURE_ID"] = secure_id | ||
1030 | 101 | agent_conf["env"]["DEVICE_IP"] = ip | ||
1031 | 102 | |||
1032 | 103 | with open(os.path.join(cfg_path, 'data-' + machine['lab'].lower(), agent_name, 'default.yaml'), "w+") as f: | ||
1033 | 104 | |||
1034 | 105 | for key in agent_config: | ||
1035 | 106 | if key == "env": | ||
1036 | 107 | f.write(key+" :\n") | ||
1037 | 108 | for env_key in agent_config["env"]: | ||
1038 | 109 | if "SSID" in env_key: | ||
1039 | 110 | agent_conf["env"][env_key] += machine["lab"][-1] | ||
1040 | 111 | f.write(" {key}: {value}\n".format(key=env_key,value=agent_conf["env"][env_key])) | ||
1041 | 112 | else: | ||
1042 | 113 | f.write("{key}: {value}\n".format(key=key,value=agent_conf[key])) | ||
1043 | 114 | |||
1044 | 115 | |||
1045 | 116 | def generate_tf_config(db_machine_list, cfg_path): | ||
1046 | 117 | |||
1047 | 118 | for machine in db_machine_list: | ||
1048 | 119 | if machine['lab'] == '': | ||
1049 | 120 | continue | ||
1050 | 121 | tf_conf = tf_config.copy() | ||
1051 | 122 | |||
1052 | 123 | agent_name = "dut" + machine["cid"].replace("-","") | ||
1053 | 124 | tf_conf["agent_id"] = agent_name | ||
1054 | 125 | tf_conf["execution_basedir"] = tf_conf["execution_basedir"].format(agent_name) | ||
1055 | 126 | tf_conf["logging_basedir"] = tf_conf["logging_basedir"].format(agent_name) | ||
1056 | 127 | tf_conf["results_basedir"] = tf_conf["results_basedir"].format(agent_name) | ||
1057 | 128 | |||
1058 | 129 | with open(os.path.join(cfg_path, 'data-' + machine['lab'].lower(), agent_name, 'testflinger-agent.conf'), "w+") as f: | ||
1059 | 130 | for key in tf_conf: | ||
1060 | 131 | if key == "job_queues": | ||
1061 | 132 | f.write(key+":\n"+"- "+machine["cid"] + "\n") | ||
1062 | 133 | else: | ||
1063 | 134 | f.write(key + ": " + tf_conf[key] + "\n") | ||
1064 | 135 | |||
1065 | 136 | def create_agent_yaml(db_machine_list, cfg_path): | ||
1066 | 137 | |||
1067 | 138 | # TODO: We need to separate configs for labs | ||
1068 | 139 | if not os.path.isfile(os.path.join(cfg_path, "ce-tf-agents-tel-l5.yaml")): | ||
1069 | 140 | |||
1070 | 141 | with open(os.path.join(cfg_path, "ce-tf-agents-tel-l5.yaml"),"w") as f: | ||
1071 | 142 | data = { | ||
1072 | 143 | "series": "focal", | ||
1073 | 144 | "description": "cert-testflinger-agents", | ||
1074 | 145 | "applications":{ | ||
1075 | 146 | "agent-host-server" + "-tel-l5":{ | ||
1076 | 147 | "series": "focal", | ||
1077 | 148 | "constraints": "tags=agent-host" + "-tel-l5", | ||
1078 | 149 | "charm": "../charms/testflinger-agent-host-charm", | ||
1079 | 150 | "num_units": 1, | ||
1080 | 151 | "resources":{ | ||
1081 | 152 | "ssh_priv_key": "agent-host/id_rsa", | ||
1082 | 153 | "ssh_pub_key": "agent-host/id_rsa.pub", | ||
1083 | 154 | }, | ||
1084 | 155 | } | ||
1085 | 156 | } | ||
1086 | 157 | } | ||
1087 | 158 | yaml.dump(data, f, default_flow_style=False, encoding='utf-8', allow_unicode=True, sort_keys=False) | ||
1088 | 159 | |||
1089 | 160 | with open(os.path.join(cfg_path, "ce-tf-agents-tel-l5.yaml"),"r+") as f: | ||
1090 | 161 | |||
1091 | 162 | data = yaml.safe_load(f) | ||
1092 | 163 | for machine in db_machine_list: | ||
1093 | 164 | if machine['lab'] == '': | ||
1094 | 165 | continue | ||
1095 | 166 | agent_name = "dut" + machine["cid"].replace("-","") | ||
1096 | 167 | if agent_name in data["applications"]: | ||
1097 | 168 | print("exist") | ||
1098 | 169 | else: | ||
1099 | 170 | data["applications"][agent_name] = { | ||
1100 | 171 | "charm":"../charms/testflinger-agent-charm", | ||
1101 | 172 | "resources":{ | ||
1102 | 173 | "device_configfile":os.path.join(cfg_path, 'data-' + machine['lab'].lower(), agent_name, 'default.yaml'), | ||
1103 | 174 | "testflinger_agent_configfile":os.path.join(cfg_path, 'data-' + machine['lab'].lower(), agent_name, 'testflinger-agent.conf') | ||
1104 | 175 | }, | ||
1105 | 176 | "to": ["agent-host-server"] | ||
1106 | 177 | } | ||
1107 | 178 | f.seek(0) | ||
1108 | 179 | yaml.dump(data, f, default_flow_style=False, encoding='utf-8', allow_unicode=True, sort_keys=False) | ||
1109 | 180 | |||
1110 | 181 | |||
1111 | 182 | def environ_or_required(key): | ||
1112 | 183 | if os.environ.get(key): | ||
1113 | 184 | return {'default': os.environ.get(key)} | ||
1114 | 185 | else: | ||
1115 | 186 | return {'required': True} | ||
1116 | 187 | |||
1117 | 188 | def main(): | ||
1118 | 189 | |||
1119 | 190 | parser = argparse.ArgumentParser() | ||
1120 | 191 | parser.add_argument('--database', help="Database location",**environ_or_required('CCLM_HARDWARE_DB')) | ||
1121 | 192 | args = parser.parse_args() | ||
1122 | 193 | db = get_db_obj(args.database) | ||
1123 | 194 | cursor = get_cursor_obj(db) | ||
1124 | 195 | machine_list = read_data_from_db(cursor) | ||
1125 | 196 | create_agent_config_dir(machine_list, os.path.join(os.environ.get('CCLM_CERT_JUJU'), 'ce-cert')) | ||
1126 | 197 | generate_agent_config(machine_list, os.path.join(os.environ.get('CCLM_CERT_JUJU'), 'ce-cert')) | ||
1127 | 198 | generate_tf_config(machine_list, os.path.join(os.environ.get('CCLM_CERT_JUJU'), 'ce-cert')) | ||
1128 | 199 | create_agent_yaml(machine_list, os.path.join(os.environ.get('CCLM_CERT_JUJU'), 'ce-cert')) | ||
1129 | 200 | close_db(db) | ||
1130 | 201 | |||
1131 | 202 | if __name__ == '__main__': | ||
1132 | 203 | main() | ||
1133 | diff --git a/cc_lab_manager/gsheet_db/__init__.py b/cc_lab_manager/gsheet_db/__init__.py | |||
1134 | 0 | new file mode 100644 | 204 | new file mode 100644 |
1135 | index 0000000..e69de29 | |||
1136 | --- /dev/null | |||
1137 | +++ b/cc_lab_manager/gsheet_db/__init__.py | |||
1138 | diff --git a/cc_lab_manager/gsheet_db/db_gsheet.py b/cc_lab_manager/gsheet_db/db_gsheet.py | |||
1139 | 1 | new file mode 100644 | 205 | new file mode 100644 |
1140 | index 0000000..c535445 | |||
1141 | --- /dev/null | |||
1142 | +++ b/cc_lab_manager/gsheet_db/db_gsheet.py | |||
1143 | @@ -0,0 +1,107 @@ | |||
1144 | 1 | import pygsheets | ||
1145 | 2 | import sqlite3 | ||
1146 | 3 | import sys | ||
1147 | 4 | from string import ascii_lowercase | ||
1148 | 5 | import itertools | ||
1149 | 6 | import argparse | ||
1150 | 7 | import os | ||
1151 | 8 | |||
1152 | 9 | gsheet_url = '' | ||
1153 | 10 | start_column_name = 'Location' | ||
1154 | 11 | |||
1155 | 12 | def get_db_obj(path_to_db): | ||
1156 | 13 | |||
1157 | 14 | db = sqlite3.connect(path_to_db) | ||
1158 | 15 | db.row_factory = sqlite3.Row | ||
1159 | 16 | return db | ||
1160 | 17 | |||
1161 | 18 | def get_cursor_obj(db_obj): | ||
1162 | 19 | |||
1163 | 20 | cursor = db_obj.cursor() | ||
1164 | 21 | return cursor | ||
1165 | 22 | |||
1166 | 23 | def close_db(db): | ||
1167 | 24 | db.commit() | ||
1168 | 25 | db.close() | ||
1169 | 26 | |||
1170 | 27 | def iter_all_strings(): | ||
1171 | 28 | # generate alphabet list a,b,c.........az for accessing cell's position. | ||
1172 | 29 | |||
1173 | 30 | col_position_list = [] | ||
1174 | 31 | for size in itertools.count(1): | ||
1175 | 32 | for s in itertools.product(ascii_lowercase,repeat = size): | ||
1176 | 33 | tmp_string = "".join(s) | ||
1177 | 34 | col_position_list.append("".join(tmp_string)) | ||
1178 | 35 | if tmp_string == "az": | ||
1179 | 36 | return col_position_list | ||
1180 | 37 | |||
1181 | 38 | def get_column_to_be_updated(token_file): | ||
1182 | 39 | |||
1183 | 40 | gc = pygsheets.authorize(service_file=token_file) | ||
1184 | 41 | sht = gc.open_by_url(gsheet_url) | ||
1185 | 42 | wks = sht[0] | ||
1186 | 43 | machine_list = wks.get_all_records(empty_value='', head=1, majdim='ROWS', numericise_data=False) | ||
1187 | 44 | keylist = list(machine_list[0].keys()) | ||
1188 | 45 | |||
1189 | 46 | started_index = keylist.index(start_column_name) | ||
1190 | 47 | col_to_be_updated = dict.fromkeys(keylist[started_index:]) | ||
1191 | 48 | col_position_list = iter_all_strings() | ||
1192 | 49 | |||
1193 | 50 | for key in col_to_be_updated: | ||
1194 | 51 | col_to_be_updated[key] = col_position_list[started_index] | ||
1195 | 52 | started_index += 1 | ||
1196 | 53 | |||
1197 | 54 | return col_to_be_updated | ||
1198 | 55 | |||
1199 | 56 | |||
1200 | 57 | def sync_c3_data_to_sheet(db_machine_list,token_file): | ||
1201 | 58 | |||
1202 | 59 | gc = pygsheets.authorize(service_file=token_file) | ||
1203 | 60 | sht = gc.open_by_url(gsheet_url) | ||
1204 | 61 | wks = sht[0] | ||
1205 | 62 | |||
1206 | 63 | # mapping table for position of column | ||
1207 | 64 | col_to_be_updated = get_column_to_be_updated(token_file) | ||
1208 | 65 | |||
1209 | 66 | row_num = 2 | ||
1210 | 67 | cell_list = [] # list for storing cell that are waiting for update. | ||
1211 | 68 | for machine in db_machine_list: | ||
1212 | 69 | for key in col_to_be_updated: | ||
1213 | 70 | cell_list.append(pygsheets.Cell(col_to_be_updated[key]+str(row_num),machine[key])) | ||
1214 | 71 | |||
1215 | 72 | row_num += 1 | ||
1216 | 73 | wks.update_cells(cell_list) | ||
1217 | 74 | |||
1218 | 75 | |||
1219 | 76 | def read_data_from_db(cursor, token_file): | ||
1220 | 77 | |||
1221 | 78 | col_in_c3 = list(get_column_to_be_updated(token_file).keys()) | ||
1222 | 79 | sqlcmd = 'select {} from lab_hw'.format(",".join(col_in_c3[0:])) | ||
1223 | 80 | cursor.execute(sqlcmd) | ||
1224 | 81 | results = cursor.fetchall() | ||
1225 | 82 | |||
1226 | 83 | return list(results) | ||
1227 | 84 | |||
1228 | 85 | def environ_or_required(key): | ||
1229 | 86 | if os.environ.get(key): | ||
1230 | 87 | return {'default': os.environ.get(key)} | ||
1231 | 88 | else: | ||
1232 | 89 | return {'required': True} | ||
1233 | 90 | |||
1234 | 91 | def main(): | ||
1235 | 92 | |||
1236 | 93 | parser = argparse.ArgumentParser() | ||
1237 | 94 | parser.add_argument('--url', help="Google sheets URL",**environ_or_required('CCLM_GOOGLE_SHEET')) | ||
1238 | 95 | parser.add_argument('--token', help="Google API token",**environ_or_required('CCLM_GOOGLE_TOKEN')) | ||
1239 | 96 | parser.add_argument('--database', help="Database location",**environ_or_required('CCLM_HARDWARE_DB')) | ||
1240 | 97 | args = parser.parse_args() | ||
1241 | 98 | global gsheet_url | ||
1242 | 99 | gsheet_url = args.url | ||
1243 | 100 | db = get_db_obj(args.database) | ||
1244 | 101 | cursor = get_cursor_obj(db) | ||
1245 | 102 | sync_c3_data_to_sheet(read_data_from_db(cursor, args.token),args.token) | ||
1246 | 103 | close_db(db) | ||
1247 | 104 | |||
1248 | 105 | |||
1249 | 106 | if __name__ == '__main__': | ||
1250 | 107 | main() | ||
1251 | diff --git a/cc_lab_manager/gsheet_db/gsheet_db.py b/cc_lab_manager/gsheet_db/gsheet_db.py | |||
1252 | 0 | new file mode 100644 | 108 | new file mode 100644 |
1253 | index 0000000..1b11014 | |||
1254 | --- /dev/null | |||
1255 | +++ b/cc_lab_manager/gsheet_db/gsheet_db.py | |||
1256 | @@ -0,0 +1,91 @@ | |||
1257 | 1 | import pygsheets | ||
1258 | 2 | import sqlite3 | ||
1259 | 3 | import sys | ||
1260 | 4 | import argparse | ||
1261 | 5 | import os | ||
1262 | 6 | |||
1263 | 7 | gsheet_url = '' | ||
1264 | 8 | |||
1265 | 9 | def get_machine_list(token_file): | ||
1266 | 10 | |||
1267 | 11 | gc = pygsheets.authorize(service_file=token_file) | ||
1268 | 12 | sht = gc.open_by_url(gsheet_url) | ||
1269 | 13 | wks = sht[0] | ||
1270 | 14 | machine_list = wks.get_all_records(empty_value='', head=1, majdim='ROWS', numericise_data=False) | ||
1271 | 15 | |||
1272 | 16 | return machine_list | ||
1273 | 17 | |||
1274 | 18 | def get_db_obj(path_to_db): | ||
1275 | 19 | |||
1276 | 20 | db = sqlite3.connect(path_to_db) | ||
1277 | 21 | return db | ||
1278 | 22 | |||
1279 | 23 | def get_cursor_obj(db_obj): | ||
1280 | 24 | |||
1281 | 25 | cursor = db_obj.cursor() | ||
1282 | 26 | return cursor | ||
1283 | 27 | |||
1284 | 28 | def close_db(db): | ||
1285 | 29 | db.commit() | ||
1286 | 30 | db.close() | ||
1287 | 31 | |||
1288 | 32 | def check_db_table_exist(cursor,table_name): | ||
1289 | 33 | |||
1290 | 34 | sqlcmd = 'select name from sqlite_master where type=\'table\' and name="{table_name}"'.format(table_name=table_name) | ||
1291 | 35 | cursor.execute(sqlcmd) | ||
1292 | 36 | result = cursor.fetchone() | ||
1293 | 37 | return result | ||
1294 | 38 | |||
1295 | 39 | def write_machine_list_to_db(cursor,token_file): | ||
1296 | 40 | |||
1297 | 41 | machine_list = get_machine_list(token_file) | ||
1298 | 42 | keylist = [*machine_list[0]] | ||
1299 | 43 | create_cmd = "CREATE TABLE lab_hw ({})".format(keylist[0]+ " PRIMARY KEY," +",".join(keylist[1:])) | ||
1300 | 44 | |||
1301 | 45 | #check table is exist or not | ||
1302 | 46 | if check_db_table_exist(cursor,"lab_hw"): | ||
1303 | 47 | print('table exist') | ||
1304 | 48 | cursor.execute("DELETE FROM lab_hw") | ||
1305 | 49 | |||
1306 | 50 | else: | ||
1307 | 51 | try: | ||
1308 | 52 | cursor.execute(create_cmd) | ||
1309 | 53 | |||
1310 | 54 | except sqlite3.Error as er: | ||
1311 | 55 | print('SQLite error: %s' % (' '.join(er.args))) | ||
1312 | 56 | |||
1313 | 57 | insert_cmd_fmt = 'insert into lab_hw values("{}")' | ||
1314 | 58 | |||
1315 | 59 | for machine in machine_list: | ||
1316 | 60 | if machine["CID"] == "": | ||
1317 | 61 | print("1") | ||
1318 | 62 | machine["CID"] = machine["Lab"] + machine["Frame"] + machine["Shelf"] + machine["Partition"] | ||
1319 | 63 | insert_cmd = insert_cmd_fmt.format('","'.join(machine.values())) | ||
1320 | 64 | try: | ||
1321 | 65 | cursor.execute(insert_cmd) | ||
1322 | 66 | |||
1323 | 67 | except sqlite3.Error as er: | ||
1324 | 68 | print('SQLite error: %s' % (' '.join(er.args))) | ||
1325 | 69 | |||
1326 | 70 | def environ_or_required(key): | ||
1327 | 71 | if os.environ.get(key): | ||
1328 | 72 | return {'default': os.environ.get(key)} | ||
1329 | 73 | else: | ||
1330 | 74 | return {'required': True} | ||
1331 | 75 | |||
1332 | 76 | def main(): | ||
1333 | 77 | |||
1334 | 78 | parser = argparse.ArgumentParser() | ||
1335 | 79 | parser.add_argument('--url', help="Google sheets URL",**environ_or_required('CCLM_GOOGLE_SHEET')) | ||
1336 | 80 | parser.add_argument('--token', help="Google API token",**environ_or_required('CCLM_GOOGLE_TOKEN')) | ||
1337 | 81 | parser.add_argument('--database', help="Database location",**environ_or_required('CCLM_HARDWARE_DB')) | ||
1338 | 82 | args = parser.parse_args() | ||
1339 | 83 | global gsheet_url | ||
1340 | 84 | gsheet_url = args.url | ||
1341 | 85 | db = get_db_obj(args.database) | ||
1342 | 86 | cursor = get_cursor_obj(db) | ||
1343 | 87 | write_machine_list_to_db(cursor,args.token) | ||
1344 | 88 | close_db(db) | ||
1345 | 89 | |||
1346 | 90 | if __name__ == '__main__': | ||
1347 | 91 | main() | ||
1348 | diff --git a/cc_lab_manager/maas/__init__.py b/cc_lab_manager/maas/__init__.py | |||
1349 | 0 | new file mode 100644 | 92 | new file mode 100644 |
1350 | index 0000000..e69de29 | |||
1351 | --- /dev/null | |||
1352 | +++ b/cc_lab_manager/maas/__init__.py | |||
1353 | diff --git a/cc_lab_manager/maas/create_maas_node.py b/cc_lab_manager/maas/create_maas_node.py | |||
1354 | 1 | new file mode 100644 | 93 | new file mode 100644 |
1355 | index 0000000..05be6dc | |||
1356 | --- /dev/null | |||
1357 | +++ b/cc_lab_manager/maas/create_maas_node.py | |||
1358 | @@ -0,0 +1,124 @@ | |||
1359 | 1 | from doctest import master | ||
1360 | 2 | from maas.client import connect | ||
1361 | 3 | from maas.client import login | ||
1362 | 4 | from maas.client.enum import LinkMode | ||
1363 | 5 | import argparse | ||
1364 | 6 | import os | ||
1365 | 7 | import sqlite3 | ||
1366 | 8 | |||
1367 | 9 | update_node_id_list = [] | ||
1368 | 10 | |||
1369 | 11 | def get_db_obj(path_to_db): | ||
1370 | 12 | |||
1371 | 13 | db = sqlite3.connect(path_to_db) | ||
1372 | 14 | db.row_factory = sqlite3.Row | ||
1373 | 15 | return db | ||
1374 | 16 | |||
1375 | 17 | def get_cursor_obj(db_obj): | ||
1376 | 18 | |||
1377 | 19 | cursor = db_obj.cursor() | ||
1378 | 20 | return cursor | ||
1379 | 21 | |||
1380 | 22 | def close_db(db): | ||
1381 | 23 | db.commit() | ||
1382 | 24 | db.close() | ||
1383 | 25 | |||
1384 | 26 | def read_data_from_db(cursor): | ||
1385 | 27 | |||
1386 | 28 | col_in_c3 = ["CID","MAC","Model","SKU","Power","IP","PDU_IP","PDU_Outlet","MAAS_Server","MAAS_Node_ID"] | ||
1387 | 29 | |||
1388 | 30 | sqlcmd = 'select {} from lab_hw where CID not like \'TEL-%\' order by MAAS_Server'.format(",".join(col_in_c3[0:])) | ||
1389 | 31 | cursor.execute(sqlcmd) | ||
1390 | 32 | results = cursor.fetchall() | ||
1391 | 33 | |||
1392 | 34 | return list(results) | ||
1393 | 35 | |||
1394 | 36 | def get_maas_session(maas_ip, maas_admin, maas_admin_password): | ||
1395 | 37 | client = login( | ||
1396 | 38 | "http://{}:5240/MAAS/".format(maas_ip), | ||
1397 | 39 | username=maas_admin, password=maas_admin_password, | ||
1398 | 40 | ) | ||
1399 | 41 | return client | ||
1400 | 42 | |||
1401 | 43 | def get_mac_list(machine_list): | ||
1402 | 44 | |||
1403 | 45 | mac_list = [] | ||
1404 | 46 | for machine in machine_list: | ||
1405 | 47 | mac_list.append(machine["mac"]) | ||
1406 | 48 | |||
1407 | 49 | return mac_list | ||
1408 | 50 | |||
1409 | 51 | def update_node_id(cursor): | ||
1410 | 52 | |||
1411 | 53 | sqlcmd = 'update lab_hw set MAAS_Node_ID=? where CID=?' | ||
1412 | 54 | cursor.executemany(sqlcmd, update_node_id_list) | ||
1413 | 55 | |||
1414 | 56 | def get_maas_mac_list(client): | ||
1415 | 57 | |||
1416 | 58 | mac_list = [] | ||
1417 | 59 | for machine in client.machines.list(): | ||
1418 | 60 | for key in machine.interfaces.by_name: | ||
1419 | 61 | mac_list.append(machine.interfaces.by_name[key].mac_address) | ||
1420 | 62 | |||
1421 | 63 | return mac_list | ||
1422 | 64 | |||
1423 | 65 | def create_maas_node(machine_list, maas_admin, maas_admin_password): | ||
1424 | 66 | |||
1425 | 67 | mass_is_connecting = "" | ||
1426 | 68 | client = "" | ||
1427 | 69 | |||
1428 | 70 | for machine in machine_list: | ||
1429 | 71 | |||
1430 | 72 | if not mass_is_connecting: | ||
1431 | 73 | mass_is_connecting = machine["MAAS_Server"] | ||
1432 | 74 | client = get_maas_session(mass_is_connecting, maas_admin, maas_admin_password) | ||
1433 | 75 | maas_mac_list = get_maas_mac_list(client) | ||
1434 | 76 | elif machine["MAAS_Server"] != mass_is_connecting: | ||
1435 | 77 | mass_is_connecting = machine["MAAS_Server"] | ||
1436 | 78 | client = get_maas_session(mass_is_connecting, maas_admin, maas_admin_password) | ||
1437 | 79 | maas_mac_list = get_maas_mac_list(client) | ||
1438 | 80 | |||
1439 | 81 | power_type = machine["Power"].lower() if machine["Power"] != "" else "manual" | ||
1440 | 82 | power_parameter = {} | ||
1441 | 83 | node_name = (machine["Model"].replace(")","",).replace("(","",).replace(" ","-")+ "-" + \ | ||
1442 | 84 | machine["sku"].replace(" ","").split("-")[-1] + "-" + machine["cid"]).lower() | ||
1443 | 85 | node_name = machine["cid"].lower() | ||
1444 | 86 | |||
1445 | 87 | if machine["MAC"] in maas_mac_list or machine["MAC"] == '': | ||
1446 | 88 | continue | ||
1447 | 89 | if power_type == "apc" or power_type == "raritan": | ||
1448 | 90 | power_parameter["power_address"] = machine["PDU_IP"] | ||
1449 | 91 | power_parameter["node_outlet"] = machine["PDU_Outlet"] | ||
1450 | 92 | power_parameter["power_on_delay"] = 30 | ||
1451 | 93 | elif power_type == "amt": | ||
1452 | 94 | power_parameter["power_address"] = machine["IP"] | ||
1453 | 95 | power_parameter["power_pass"] = "Insecure-101" | ||
1454 | 96 | |||
1455 | 97 | maas_node = client.machines.create("amd64",machine["MAC"], "manual",hostname=node_name) | ||
1456 | 98 | |||
1457 | 99 | update_node_id_list.append([maas_node.system_id, machine["CID"]]) | ||
1458 | 100 | maas_node.set_power(power_type=power_type.lower(),power_parameters=power_parameter) | ||
1459 | 101 | |||
1460 | 102 | |||
1461 | 103 | def environ_or_required(key): | ||
1462 | 104 | if os.environ.get(key): | ||
1463 | 105 | return {'default': os.environ.get(key)} | ||
1464 | 106 | else: | ||
1465 | 107 | return {'required': True} | ||
1466 | 108 | |||
1467 | 109 | def main(): | ||
1468 | 110 | |||
1469 | 111 | parser = argparse.ArgumentParser() | ||
1470 | 112 | parser.add_argument('--database', help="Database location",**environ_or_required('CCLM_HARDWARE_DB')) | ||
1471 | 113 | parser.add_argument('--maas_admin', help="MAAS Admin account",**environ_or_required('CCLM_MAAS_ADMIN')) | ||
1472 | 114 | parser.add_argument('--maas_admin_password', help="Password for MAAS Admin account",**environ_or_required('CCLM_MAAS_ADMIN_PASSWD')) | ||
1473 | 115 | args = parser.parse_args() | ||
1474 | 116 | db = get_db_obj(args.database) | ||
1475 | 117 | cursor = get_cursor_obj(db) | ||
1476 | 118 | machine_list = read_data_from_db(cursor) | ||
1477 | 119 | create_maas_node(machine_list, args.maas_admin, args.maas_admin_password) | ||
1478 | 120 | update_node_id(cursor) | ||
1479 | 121 | close_db(db) | ||
1480 | 122 | |||
1481 | 123 | if __name__ == '__main__': | ||
1482 | 124 | main() | ||
1483 | diff --git a/dist/cc_lab_manager-0.1-py3.8.egg b/dist/cc_lab_manager-0.1-py3.8.egg | |||
1484 | 0 | new file mode 100644 | 125 | new file mode 100644 |
1485 | index 0000000..cd9a0a4 | |||
1486 | 1 | Binary files /dev/null and b/dist/cc_lab_manager-0.1-py3.8.egg differ | 126 | Binary files /dev/null and b/dist/cc_lab_manager-0.1-py3.8.egg differ |
1487 | diff --git a/setup.py b/setup.py | |||
1488 | index a609291..d39888c 100644 | |||
1489 | --- a/setup.py | |||
1490 | +++ b/setup.py | |||
1491 | @@ -1,7 +1,7 @@ | |||
1492 | 1 | #!/usr/bin/env python3 | 1 | #!/usr/bin/env python3 |
1493 | 2 | from setuptools import setup, find_packages | 2 | from setuptools import setup, find_packages |
1494 | 3 | 3 | ||
1496 | 4 | INSTALL_REQUIRES = ['pysheets'] | 4 | INSTALL_REQUIRES = ['pysheets', 'jinja2', 'python-libmaas', 'aiohttp==3.7.2'] |
1497 | 5 | 5 | ||
1498 | 6 | setup( | 6 | setup( |
1499 | 7 | name='cc-lab-manager', | 7 | name='cc-lab-manager', |
1500 | @@ -12,4 +12,12 @@ setup( | |||
1501 | 12 | author_email='gavin.lin@canonical.com', | 12 | author_email='gavin.lin@canonical.com', |
1502 | 13 | url='https://code.launchpad.net/cc-lab-manager/', | 13 | url='https://code.launchpad.net/cc-lab-manager/', |
1503 | 14 | install_requires=INSTALL_REQUIRES, | 14 | install_requires=INSTALL_REQUIRES, |
1504 | 15 | entry_points={ | ||
1505 | 16 | 'console_scripts': [ | ||
1506 | 17 | 'cc-lab-manager=cc_lab_manager.commands.cc_lab_manager:main', | ||
1507 | 18 | ] | ||
1508 | 19 | }, | ||
1509 | 20 | classifiers=[ | ||
1510 | 21 | "Programming Language :: Python", | ||
1511 | 22 | ] | ||
1512 | 15 | ) | 23 | ) |
LGTM +1