Tim Edwards | dae621a | 2021-09-08 09:28:02 -0400 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
emayecs | 5966a53 | 2021-07-29 10:07:02 -0400 | [diff] [blame] | 2 | # |
| 3 | # cace_datasheet_upload.py |
| 4 | # |
| 5 | # Send newly-created challenge datasheet and associated |
| 6 | # design files (testbench schematics and netlists) to |
| 7 | # the marketplace server for storage. |
| 8 | # |
| 9 | |
| 10 | import os |
| 11 | import json |
| 12 | import re |
| 13 | import sys |
| 14 | import requests |
| 15 | import subprocess |
| 16 | |
| 17 | import file_compressor |
| 18 | import file_request_hash |
| 19 | |
emayecs | b2487ae | 2021-08-05 10:30:13 -0400 | [diff] [blame] | 20 | import config |
emayecs | 5966a53 | 2021-07-29 10:07:02 -0400 | [diff] [blame] | 21 | |
| 22 | """ |
emayecs | 1474831 | 2021-08-05 14:21:26 -0400 | [diff] [blame] | 23 | standalone script. |
emayecs | 5966a53 | 2021-07-29 10:07:02 -0400 | [diff] [blame] | 24 | Makes rest calls to marketplace REST server to save datasheet |
| 25 | and associated file(s). Request hash is generated so the two |
| 26 | requests can be associated on the server side. This action |
| 27 | has no other side effects. |
| 28 | """ |
| 29 | |
emayecs | b2487ae | 2021-08-05 10:30:13 -0400 | [diff] [blame] | 30 | mktp_server_url = config.mktp_server_url |
emayecs | 5966a53 | 2021-07-29 10:07:02 -0400 | [diff] [blame] | 31 | |
| 32 | # Make request to server sending json passed in. |
| 33 | def send_doc(doc): |
| 34 | result = requests.post(mktp_server_url + '/cace/save_datasheet', json=doc) |
| 35 | print('send_doc', result.status_code) |
| 36 | |
| 37 | # Pure HTTP post here. Add the file to files object and the hash/filename |
| 38 | # to the data params. |
| 39 | def send_file(hash, file, file_name): |
| 40 | files = {'file': file.getvalue()} |
| 41 | data = {'request-hash': hash, 'file-name': file_name} |
| 42 | result = requests.post(mktp_server_url + '/cace/save_files', files=files, data=data) |
| 43 | print('send_file', result.status_code) |
| 44 | |
| 45 | |
| 46 | if __name__ == '__main__': |
| 47 | |
| 48 | # Divide up command line into options and arguments |
| 49 | options = [] |
| 50 | arguments = [] |
| 51 | for item in sys.argv[1:]: |
| 52 | if item.find('-', 0) == 0: |
| 53 | options.append(item) |
| 54 | else: |
| 55 | arguments.append(item) |
| 56 | |
| 57 | # There should be two arguments passed to the script. One is |
| 58 | # the path and filename of the datasheet JSON file, and the |
| 59 | # other a path to the location of testbenches (netlists and/or |
| 60 | # schematics). If there is only one argument, then datasheet_filepath |
| 61 | # is assumed to be in the same path as netlist_filepath. |
| 62 | |
| 63 | datasheet_filepath = [] |
| 64 | netlist_filepath = [] |
| 65 | |
| 66 | for argval in arguments: |
| 67 | if os.path.isfile(argval): |
| 68 | datasheet_filepath = argval |
| 69 | elif os.path.isdir(argval): |
| 70 | netlist_filepath = argval |
| 71 | elif os.path.splitext(argval)[1] == '': |
| 72 | argname = argval + '.json' |
| 73 | if os.path.isfile(argval): |
| 74 | datasheet_filepath = argname |
| 75 | |
| 76 | if not datasheet_filepath: |
| 77 | # Check for JSON file 'project.json' in the netlist filepath directory |
| 78 | # or the directory above it. |
| 79 | if netlist_filepath: |
| 80 | argtry = netlist_filepath + '/project.json' |
| 81 | if os.path.isfile(argtry): |
| 82 | datasheet_filepath = argtry |
| 83 | else: |
| 84 | argtry = os.path.split(netlist_filepath)[0] + '/project.json' |
| 85 | if os.path.isfile(argtry): |
| 86 | datasheet_filepath = argtry |
| 87 | |
| 88 | # Legacy behavior support |
| 89 | if not os.path.isfile(datasheet_filepath): |
| 90 | # Check for JSON file with same name as netlist filepath, |
| 91 | # but with a .json extension, in the netlist filepath directory |
| 92 | # or the directory above it. |
| 93 | if netlist_filepath: |
| 94 | argtry = netlist_filepath + '/' + os.path.basename(netlist_filepath) + '.json' |
| 95 | if os.path.isfile(argtry): |
| 96 | datasheet_filepath = argtry |
| 97 | else: |
| 98 | argtry = os.path.split(netlist_filepath)[0] + '/' + os.path.basename(netlist_filepath) + '.json' |
| 99 | if os.path.isfile(argtry): |
| 100 | datasheet_filepath = argtry |
| 101 | |
| 102 | if not datasheet_filepath: |
| 103 | print('Error: No datasheet JSON file specified.\n') |
| 104 | sys.exit(1) |
| 105 | |
| 106 | if not os.path.isfile(datasheet_filepath): |
| 107 | print('Error: No datasheet JSON file ' + datasheet_filepath + ' found.\n') |
| 108 | sys.exit(1) |
| 109 | |
| 110 | # Technically okay to have null netlist_filepath, but unlikely, |
| 111 | # so flag a warning. |
| 112 | |
| 113 | if not netlist_filepath: |
| 114 | print('Warning: No netlist filepath given. No files will be ' |
| 115 | + 'transmitted with the datasheet.\n') |
| 116 | |
| 117 | dsheet = {} |
| 118 | with open(datasheet_filepath, 'r') as user_doc_file: |
| 119 | docinfo = json.load(user_doc_file) |
| 120 | dsheet = docinfo['data-sheet'] |
| 121 | try: |
| 122 | name = dsheet['ip-name'] |
| 123 | except KeyError: |
| 124 | datasheet_file = os.path.split(datasheet_filepath)[1] |
| 125 | name = os.path.splitext(datasheet_file)[0] |
| 126 | dsheet['ip-name'] = name |
| 127 | |
| 128 | # Behavior starting 4/27/2017: the UID is required to be a |
| 129 | # numeric value, but the datasheet upload is generally being |
| 130 | # done as user admin from the remote CACE host, and admin has |
| 131 | # no official UID number. So always attach ID 9999 to datasheet |
| 132 | # uploads. |
| 133 | |
| 134 | if 'UID' in docinfo: |
| 135 | uid = docinfo['UID'] |
| 136 | else: |
| 137 | uid = 9999 |
| 138 | docinfo['UID'] = uid |
| 139 | |
| 140 | # Get a request hash and add it to the JSON document |
| 141 | rhash, timestamp = file_request_hash.get_hash(name) |
| 142 | docinfo['request-hash'] = rhash |
| 143 | |
| 144 | # Put the current git system state into the target directory |
| 145 | # prior to tarballing |
| 146 | if os.path.isfile('/ef/.ef-version'): |
| 147 | with open('/ef/.ef-version', 'r') as f: |
| 148 | ef_version = f.read().rstrip() |
| 149 | docinfo['ef-version'] = ef_version |
| 150 | |
| 151 | # Now send the datasheet |
| 152 | if '-test' in options: |
| 153 | print("Test: running send_doc( <docinfo> )\n") |
| 154 | print(" with docinfo['UID'] = " + uid + "\n") |
| 155 | else: |
| 156 | send_doc(docinfo) |
| 157 | |
| 158 | # Send the merged JSON file and the tarballed design file directory |
| 159 | # to the marketplace server for storage. |
| 160 | |
| 161 | if netlist_filepath: |
| 162 | # Use the version below to ignore the 'spi' directory. However, it may |
| 163 | # be the intention of the challenge creator to seed the challenge with |
| 164 | # an example. This is normally not the case. So use '-include' option |
| 165 | # to avoid excluding the 'spi' folder contents. |
| 166 | if '-includeall' in options: |
| 167 | print('Including netlist/schematic and simulation files in project folder.') |
| 168 | tar = file_compressor.tar_directory_contents(netlist_filepath, |
| 169 | exclude=['elec/\.java', 'elec/electric\.log', name + '\.log', |
| 170 | '.*\.raw', 'ngspice/run/\.allwaves']) |
| 171 | elif '-include' in options: |
| 172 | print('Including netlist/schematic files in project folder.') |
| 173 | tar = file_compressor.tar_directory_contents(netlist_filepath, |
| 174 | exclude=['ngspice', 'elec/\.java', 'elec/electric\.log', |
| 175 | name + '\.log']) |
| 176 | else: |
| 177 | print('Excluding netlist/schematic and simulation files in project folder.') |
| 178 | tar = file_compressor.tar_directory_contents(netlist_filepath, |
| 179 | exclude=['spi', 'ngspice', 'elec/\.java', 'mag', 'elec/electric\.log', |
| 180 | 'elec/' + name + '\.delib/' + name + '\.sch', name + '\.log']) |
| 181 | tarballname = name + '.tar.gz' |
| 182 | |
| 183 | # Now send the netlist file tarball |
| 184 | if '-test' in options: |
| 185 | print('Test: running send_file(' + rhash + ' <tarball> ' + tarballname + ')') |
| 186 | print('Saving tarball locally as ' + tarballname) |
| 187 | file_compressor.tar_directory_contents_to_file(netlist_filepath, |
| 188 | tarballname, exclude=['spi', 'ngspice', 'elec/\.java', 'mag', |
| 189 | 'elec/electric\.log', 'elec/' + name + '\.delib/' + name + '\.sch', |
| 190 | name + '\.log']) |
| 191 | else: |
| 192 | send_file(rhash, tar, tarballname) |
| 193 | |