-
Notifications
You must be signed in to change notification settings - Fork 28
/
Copy pathiosxr_store_box.py
executable file
·208 lines (173 loc) · 8.23 KB
/
iosxr_store_box.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
#!/usr/bin/python
'''
Author: Rich Wellum ([email protected])
A tool to upload an image to a maven repo like artifactory using curl, the image
typically being a vagrant virtualbox, but could be anything.
E.g. iosxrv-x64-vbox/iosxr_store_box.py -b iosxrv-fullk9-x64.box --release --verbose --message "A new box because..."')
This was originally part of iosxr_ios2vbox.py, but doesn't belong to the
generation of a box. Also future plans are to store images via jenkins so this will
be a temporarily living tool.
User can select snapshot or release, the release images get synced to
devhub.cisco.com - where they are available to customers.
This tool also sends an email out to an email address or an alias to inform them
of the new image.
It is designed to be called from other tools, like iosxr_ios2vbox.py.
It will rely on the following environment variables to work:
ARTIFACTORY_USERNAME
ARTIFACTORY_PASSWORD
ARTIFACTORY_LOCATION_SNAPSHOT
ARTIFACTORY_LOCATION_RELEASE
ARTIFACTORY_SENDER
ARTIFACTORY_RECEIVER
'''
from __future__ import print_function
import sys
import os
import smtplib
from iosxr_iso2vbox import run, set_logging
import argparse
from argparse import RawDescriptionHelpFormatter
import logging
import hashlib
logger = logging.getLogger(__name__)
set_logging()
def generate_hash(file):
global hash_file
# SHA256 the box file and store in same location
sha256_hash = hashlib.sha256(open(file, 'rb').read()).hexdigest()
logger.debug('SHA256: %s' % sha256_hash)
hash_file = os.path.basename(file) + '.sha256.txt'
f = open(hash_file, 'w')
f.write(sha256_hash)
f.close()
logger.debug('Hash file is %s' % hash_file)
def main(argv):
input_box = ''
test_only = False
artifactory_release = False
# Get info from environment and check it's all there
artifactory_username = os.environ.get('ARTIFACTORY_USERNAME')
artifactory_password = os.environ.get('ARTIFACTORY_PASSWORD')
sender = os.environ.get('ARTIFACTORY_SENDER')
receiver = os.environ.get('ARTIFACTORY_RECEIVER')
if artifactory_username is None:
sys.exit("Please set ARTIFACTORY_USERNAME in your environment\n"
"E.g., 'export ARTIFACTORY_USERNAME=<username>'")
if artifactory_password is None:
sys.exit("Please set ARTIFACTORY_PASSWORD in your environment\n"
"E.g. export 'ARTIFACTORY_PASSWORD=<PASSWORD>'")
if sender is None:
sys.exit("Please set SENDER in your environment\n"
"E.g. export '[email protected]'")
if receiver is None:
sys.exit("Please set RECEIVER in your environment\n"
"E.g. export '[email protected]'")
# Suck in the input BOX and handle errors
parser = argparse.ArgumentParser(
formatter_class=RawDescriptionHelpFormatter,
description='A tool to upload an image to a maven repo like artifactory ' +
'using curl, the image typically being a vagrant virtualbox.\n' +
'User can select snapshot or release, the release images get synced to ' +
'devhub.cisco.com - where they are available to customers.\n' +
'This tool also sends an email out to an email address or an alias to ' +
'inform them of the new image.\n' +
'It is designed to be called from other tools, like iosxr_ios2vbox.py.\n\n' +
'It will rely on the following environment variables to work:\n ' +
'ARTIFACTORY_USERNAME\n ' +
'ARTIFACTORY_PASSWORD\n ' +
'ARTIFACTORY_LOCATION_SNAPSHOT\n ' +
'ARTIFACTORY_LOCATION_RELEASE\n ' +
'ARTIFACTORY_SENDER\n ' +
'ARTIFACTORY_RECEIVER',
epilog="E.g.:\n" +
"iosxrv-x64-vbox/iosxr_store_box.py iosxrv-fullk9-x64.box --release --verbose --message 'A new box because...'\n" +
"iosxrv-x64-vbox/iosxr_store_box.py iosxrv-fullk9-x64.box --release, --message 'A new box because...'\n"
"iosxrv-x64-vbox/iosxr_store_box.py iosxrv-fullk9-x64.box -r -v -m 'Latest box for release.'\n")
parser.add_argument('BOX_FILE',
help='BOX filename')
parser.add_argument('-m', '--message',
default='No reason for update specified',
help='Optionally specify a reason for uploading this box')
parser.add_argument('-r', '--release', action='store_true',
help="upload to '$ARTIFACTORY_LOCATION_RELEASE' rather than '$ARTIFACTORY_LOCATION_SNAPSHOT'.")
parser.add_argument('-s', '--subdirectory', dest='subdir', required=True,
help="subdirectory to upload to, e.g '6.1.1', 'stable'")
parser.add_argument('-v', '--verbose',
action='store_const', const=logging.DEBUG,
default=logging.INFO, help='turn on verbose messages')
parser.add_argument('-t', '--test_only', action='store_true',
help='test only, do not store the box or send an email')
args = parser.parse_args()
input_box = args.BOX_FILE
if args.message is None:
# User did not add -m at all - and we always need a message
args.message = 'No reason for update specified'
message = args.message
artifactory_release = args.release
test_only = args.test_only
subdir = args.subdir
if not input_box:
sys.exit('No input box detected, use -b to specify a box')
if not os.path.exists(input_box):
sys.exit('%s does not exist' % input_box)
boxname = os.path.basename(os.path.splitext(input_box)[0]) + '.box'
logger.setLevel(level=args.verbose)
logger.debug("Input box is: '%s'" % input_box)
logger.debug("Message is: '%s'" % message)
logger.debug("Sender is: '%s'" % sender)
logger.debug("Receiver is: '%s'" % receiver)
logger.debug("Release is: '%s'" % artifactory_release)
logger.debug("Test Only is: '%s'" % test_only)
logger.debug("Sub dir is: '%s'" % subdir)
'''
Copy the box to artifactory. This will most likely change to Atlas, or maybe both.
The code below shows how to make two copies, one is the latest and one has a date on it.
'''
# Find the appopriate LOCATION
if artifactory_release is True:
location = os.environ.get('ARTIFACTORY_LOCATION_RELEASE')
else:
location = os.environ.get('ARTIFACTORY_LOCATION_SNAPSHOT')
if location is None:
sys.exit("Please set LOCATION_RELEASE or LOCATION_SNAPSHOT in your environment\n"
"E.g.: export 'ARTIFACTORY_LOCATION_SNAPSHOT=http://location', or: \n"
"E.g.: export 'ARTIFACTORY_LOCATION_RELEASE=http://location'")
box_out = os.path.join(location, subdir, boxname)
generate_hash(input_box)
hash_out = os.path.join(location, subdir, os.path.basename(hash_file))
if test_only is True:
logger.debug('Test only: copying %s to %s' % (input_box, box_out))
logger.debug('Test only: copying %s to %s' % (hash_file, hash_out))
else:
# Copy to artifactory
logger.debug('Copying %s to %s' % (input_box, box_out))
run(['curl', '-X', 'PUT', '-u', artifactory_username + ':' + artifactory_password, '-T', input_box, box_out, '--progress-bar'])
logger.debug('Copying %s to %s' % (hash_file, hash_out))
run(['curl', '-X', 'PUT', '-u', artifactory_username + ':' + artifactory_password, '-T', hash_file, hash_out])
# Format an email message and send to the interest list
email = """From: <%s>
To: IOS XRv (64-bit) Box Interest <%s>
Subject: A new IOS XRv (64-bit) vagrant box has been posted to artifactory %s
Reason for update: %s
\nVagrant Box: %s
\nHash File : %s
\nTo use:
\n vagrant init 'IOS XRv'
\n vagrant box add --name 'IOS XRv' %s --force
\n vagrant up
\n vagrant ssh
""" % (sender, receiver, location, message, box_out, hash_out, box_out)
if args.verbose == logging.DEBUG or test_only:
print('Email is:')
print(email)
if test_only is False:
try:
smtpObj = smtplib.SMTP('mail.cisco.com')
smtpObj.sendmail(sender, receiver, email)
logger.info('Successfully sent update email')
except smtplib.SMTPException:
logger.error('Unable to send update email')
else:
logger.debug('Test only: Not sending email')
if __name__ == '__main__':
main(sys.argv[1:])