1212# See the License for the specific language governing permissions and
1313# limitations under the License.
1414
15+ import base64
16+ import gzip
1517import hashlib
1618import os
1719import requests
18- import subprocess
20+ import six
21+ import StringIO
1922import time
2023
21- from ironic_python_agent import configdrive
2224from ironic_python_agent import errors
2325from ironic_python_agent .extensions import base
2426from ironic_python_agent import hardware
2527from ironic_python_agent .openstack .common import log
28+ from ironic_python_agent import utils
2629
2730LOG = log .getLogger (__name__ )
2831
@@ -47,28 +50,41 @@ def _write_image(image_info, device):
4750 script = _path_to_script ('shell/write_image.sh' )
4851 command = ['/bin/bash' , script , image , device ]
4952 LOG .info ('Writing image with command: {0}' .format (' ' .join (command )))
50- exit_code = subprocess . call ( command )
53+ exit_code = utils . execute ( * command )
5154 if exit_code != 0 :
5255 raise errors .ImageWriteError (exit_code , device )
5356 totaltime = time .time () - starttime
5457 LOG .info ('Image {0} written to device {1} in {2} seconds' .format (
5558 image , device , totaltime ))
5659
5760
58- def _copy_configdrive_to_disk (configdrive_dir , device ):
61+ def _write_configdrive_to_file (configdrive , filename ):
62+ LOG .debug ('Writing configdrive to {0}' .format (filename ))
63+ # configdrive data is base64'd, decode it first
64+ data = StringIO .StringIO (base64 .b64decode (configdrive ))
65+ gunzipped = gzip .GzipFile ('configdrive' , 'rb' , 9 , data )
66+ with open (filename , 'wb' ) as f :
67+ f .write (gunzipped .read ())
68+ gunzipped .close ()
69+
70+
71+ def _write_configdrive_to_partition (configdrive , device ):
72+ filename = _configdrive_location ()
73+ _write_configdrive_to_file (configdrive , filename )
74+
5975 starttime = time .time ()
6076 script = _path_to_script ('shell/copy_configdrive_to_disk.sh' )
61- command = ['/bin/bash' , script , configdrive_dir , device ]
77+ command = ['/bin/bash' , script , filename , device ]
6278 LOG .info ('copying configdrive to disk with command {0}' .format (
6379 ' ' .join (command )))
64- exit_code = subprocess . call ( command )
80+ exit_code = utils . execute ( * command )
6581
6682 if exit_code != 0 :
6783 raise errors .ConfigDriveWriteError (exit_code , device )
6884
6985 totaltime = time .time () - starttime
7086 LOG .info ('configdrive copied from {0} to {1} in {2} seconds' .format (
71- configdrive_dir ,
87+ configdrive ,
7288 device ,
7389 totaltime ))
7490
@@ -114,28 +130,22 @@ def _download_image(image_info):
114130
115131
116132def _verify_image (image_info , image_location ):
117- hashes = image_info ['hashes' ]
118- for k , v in hashes .items ():
119- algo = getattr (hashlib , k , None )
120- if algo is None :
121- continue
122- log_msg = 'Verifying image at {0} with algorithm {1} against hash {2}'
123- LOG .debug (log_msg .format (image_location , k , v ))
124- hash_ = algo (open (image_location ).read ()).hexdigest ()
125- if hash_ == v :
126- return True
127- else :
128- log_msg = ('Image verification failed. Location: {0};'
129- 'algorithm: {1}; image hash: {2};'
130- 'verification hash: {3}' )
131- LOG .warning (log_msg .format (image_location , k , hash_ , v ))
133+ checksum = image_info ['checksum' ]
134+ log_msg = 'Verifying image at {0} against MD5 checksum {1}'
135+ LOG .debug (log_msg .format (image_location , checksum ))
136+ hash_ = hashlib .md5 (open (image_location ).read ()).hexdigest ()
137+ if hash_ == checksum :
138+ return True
139+ log_msg = ('Image verification failed. Location: {0};'
140+ 'image hash: {1}; verification hash: {2}' )
141+ LOG .warning (log_msg .format (image_location , checksum , hash_ ))
132142 return False
133143
134144
135145def _validate_image_info (ext , image_info = None , ** kwargs ):
136146 image_info = image_info or {}
137147
138- for field in ['id' , 'urls' , 'hashes ' ]:
148+ for field in ['id' , 'urls' , 'checksum ' ]:
139149 if field not in image_info :
140150 msg = 'Image is missing \' {0}\' field.' .format (field )
141151 raise errors .InvalidCommandParamsError (msg )
@@ -144,10 +154,10 @@ def _validate_image_info(ext, image_info=None, **kwargs):
144154 raise errors .InvalidCommandParamsError (
145155 'Image \' urls\' must be a list with at least one element.' )
146156
147- if type (image_info ['hashes' ]) != dict or not image_info ['hashes' ]:
157+ if (not isinstance (image_info ['checksum' ], six .string_types )
158+ or not image_info ['checksum' ]):
148159 raise errors .InvalidCommandParamsError (
149- 'Image \' hashes\' must be a dictionary with at least one '
150- 'element.' )
160+ 'Image \' checksum\' must be a non-empty string.' )
151161
152162
153163class StandbyExtension (base .BaseAgentExtension ):
@@ -171,9 +181,7 @@ def cache_image(self, image_info=None, force=False):
171181 @base .async_command (_validate_image_info )
172182 def prepare_image (self ,
173183 image_info = None ,
174- metadata = None ,
175- files = None ):
176- location = _configdrive_location ()
184+ configdrive = None ):
177185 device = hardware .get_manager ().get_os_install_device ()
178186
179187 # don't write image again if already cached
@@ -182,16 +190,14 @@ def prepare_image(self,
182190 _write_image (image_info , device )
183191 self .cached_image_id = image_info ['id' ]
184192
185- LOG .debug ('Writing configdrive to {0}' .format (location ))
186- configdrive .write_configdrive (location , metadata , files )
187- _copy_configdrive_to_disk (location , device )
193+ _write_configdrive_to_partition (configdrive , device )
188194
189195 @base .async_command ()
190196 def run_image (self ):
191197 script = _path_to_script ('shell/reboot.sh' )
192198 LOG .info ('Rebooting system' )
193199 command = ['/bin/bash' , script ]
194200 # this should never return if successful
195- exit_code = subprocess . call ( command )
201+ exit_code = utils . execute ( * command )
196202 if exit_code != 0 :
197203 raise errors .SystemRebootError (exit_code )
0 commit comments