99import hashlib
1010import httplib2
1111import io
12+ from typing import Callable
1213
1314from . import (
1415 check ,
@@ -117,7 +118,7 @@ def create(
117118 cls , name : str , architecture : str , content : io .IOBase , * ,
118119 title : str = None ,
119120 filetype : BootResourceFiletype = BootResourceFiletype .TGZ ,
120- chunk_size = (1 << 22 )):
121+ chunk_size = (1 << 22 ), progress_callback : Callable = None ):
121122 """Create a `BootResource`.
122123
123124 Creates an uploaded boot resource with `content`. The `content` is
@@ -139,6 +140,11 @@ def create(
139140 :param chunk_size: Size in bytes to upload to MAAS in chunks.
140141 (Default is 4 MiB).
141142 :type chunk_size: `int`
143+ :param progress_callback: Called to inform the current progress of the
144+ upload. One argument is passed with the progress as a precentage.
145+ If the resource was already complete and no content
146+ needed to be uploaded then this callback will never be called.
147+ :type progress_callback: Callable
142148 :returns: Create boot resource.
143149 :rtype: `BootResource`.
144150 """
@@ -178,6 +184,11 @@ def create(
178184 elif chunk_size <= 0 :
179185 raise ValueError (
180186 "chunk_size must be greater than 0, not %d" % chunk_size )
187+ if (progress_callback is not None and
188+ not isinstance (progress_callback , Callable )):
189+ raise TypeError (
190+ "progress_callback must be a Callable, not %s" % (
191+ type (progress_callback ).__name__ ))
181192
182193 size , sha256 = calc_size_and_sha265 (content , chunk_size )
183194 resource = cls ._object (cls ._handler .create (
@@ -191,12 +202,13 @@ def create(
191202 return resource
192203 else :
193204 # Upload in chunks and reload boot resource.
194- cls ._upload_chunks (rfile , content , chunk_size )
205+ cls ._upload_chunks (rfile , content , chunk_size , progress_callback )
195206 return cls ._object .read (resource .id )
196207
197208 @classmethod
198209 def _upload_chunks (
199- cls , rfile : BootResourceFile , content : io .IOBase , chunk_size : int ):
210+ cls , rfile : BootResourceFile , content : io .IOBase , chunk_size : int ,
211+ progress_callback : Callable = None ):
200212 """Upload the `content` to `rfile` in chunks using `chunk_size`."""
201213 content .seek (0 , io .SEEK_SET )
202214 upload_uri = "%s%s" % (
@@ -207,6 +219,8 @@ def _upload_chunks(
207219 length = len (buf )
208220 if length > 0 :
209221 cls ._put_chunk (upload_uri , buf )
222+ if progress_callback is not None :
223+ progress_callback (length / rfile .size )
210224 if length != chunk_size :
211225 break
212226
0 commit comments