diff --git a/config/crd/v1/bases/velero.io_backups.yaml b/config/crd/v1/bases/velero.io_backups.yaml index 47cbc37346..b4ead430f1 100644 --- a/config/crd/v1/bases/velero.io_backups.yaml +++ b/config/crd/v1/bases/velero.io_backups.yaml @@ -41,6 +41,10 @@ spec: spec: description: BackupSpec defines the specification for a Velero backup. properties: + cancel: + description: Cancel specifies whether to cancel the backup. + nullable: true + type: boolean csiSnapshotTimeout: description: |- CSISnapshotTimeout specifies the time used to wait for CSI VolumeSnapshot status turns to @@ -604,6 +608,8 @@ spec: - PartiallyFailed - Failed - Deleting + - Cancelling + - Cancelled type: string progress: description: |- diff --git a/config/crd/v1/bases/velero.io_schedules.yaml b/config/crd/v1/bases/velero.io_schedules.yaml index 7719a4b132..9f73a425d4 100644 --- a/config/crd/v1/bases/velero.io_schedules.yaml +++ b/config/crd/v1/bases/velero.io_schedules.yaml @@ -80,6 +80,10 @@ spec: Template is the definition of the Backup to be run on the provided schedule properties: + cancel: + description: Cancel specifies whether to cancel the backup. + nullable: true + type: boolean csiSnapshotTimeout: description: |- CSISnapshotTimeout specifies the time used to wait for CSI VolumeSnapshot status turns to diff --git a/config/crd/v1/crds/crds.go b/config/crd/v1/crds/crds.go index 7bc100e51d..fd6c7c95f9 100644 --- a/config/crd/v1/crds/crds.go +++ b/config/crd/v1/crds/crds.go @@ -30,14 +30,14 @@ import ( var rawCRDs = [][]byte{ []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xccXK\x8f۶\x13\xbf\xfbS\f\xf6\x7f\xfd\xcbnP\xb4(|K\xdc\x06\b\x9a\x04\v{\x91;-\x8dlf)\x92%\x87N\xdd\xc7w/\x86\x94lY\xa2\xad\xf5\x1e\x8a\xf2&r\u07bfy\xd9EQ̄\x95_\xd0yi\xf4\x12\x84\x95\xf8;\xa1\xe6/?\x7f\xfe\xc9ϥY\x1c\xde̞\xa5\xae\x96\xb0\n\x9eL\xb3Fo\x82+\xf1g\xac\xa5\x96$\x8d\x9e5H\xa2\x12$\x963\x00\xa1\xb5!\xc1מ?\x01J\xa3\xc9\x19\xa5\xd0\x15;\xd4\xf3\xe7\xb0\xc5m\x90\xaaB\x17\x85w\xaa\x0f\xdf\xcd\xdf\xfc8\xffa\x06\xa0E\x83K؊\xf29X\x87\xd6xI\xc6I\xf4\xf3\x03*tf.\xcd\xcc[,Y\xfaΙ`\x97p~Hܭ\xe6d\xf5\xbb(h\xdd\t:\xc6'%=\xfd\x9a}\xfe(=E\x12\xab\x82\x13*gH|\xf6R\xef\x82\x12nD\xc0\n|i,.\xe13\xdbbE\x89\xd5\f\xa0\xf54\xdaV\x80\xa8\xaa\x18;\xa1\x1e\x9dԄneTh\xba\x98\x15\xf0\xd5\x1b\xfd(h\xbf\x84y\x17\xddy\xe90\x06\xf6I6\xe8I46\xd2v\x01{\xbb\xc3\xf6\x9b\x8e\xac\xbc\x12\x84ca\x1c\xb9\xf9\xd9֧\xa3\xc5\v)\xe7@@\xef-I\xf4\xe4\xa4\xde\xcd\xceć7)\x14\xe5\x1e\x1b\xb1li\x8dE\xfd\xf6\xf1×\xef7\x17\xd7\x00\xd6\x19\x8b\x8ed\aO:\xbd\xf4\xeb\xdd\x02T\xe8K'-\xc5\xe4\xf8\xab\xb8x\x03`\x05\x89\v*\xceC\xf4@{\xecb\x8cUk\x13\x98\x1ah/=8\xb4\x0e=ꔙ|-4\x98\xedW,i>\x10\xbdA\xc7b\xc0\xefMP\x15\xa7\xef\x01\x1d\x81\xc3\xd2\xec\xb4\xfc\xe3$\xdb\x03\x99\xa8T\tBO\x10Q\xd4B\xc1A\xa8\x80\xff\a\xa1\xab\x81\xe4F\x1c\xc1!넠{\xf2\"\x83\x1f\xda\xf1\xc98\x04\xa9k\xb3\x84=\x91\xf5\xcb\xc5b'\xa9+\xca\xd24MВ\x8e\x8bX_r\x1b\xc88\xbf\xa8\xf0\x80j\xe1\xe5\xae\x10\xae\xdcK\u0092\x82Å\xb0\xb2\x88\x8e\xe8X\x98\xf3\xa6\xfa\x9fk\xcb\xd8_\xa8\x1d\x01\x9dN\xac\xa4;\xe0\xe1\xd2\x02\xe9A\xb4\xa2\x92\x8bg\x14\xf8\x8aC\xb7\xfee\xf3\x04\x9d%\t\xa9\x04ʙt\x14\x97\x0e\x1f\x8e\xa6\xd45\xba\xc4W;\xd3D\x99\xa8+k\xa4\xa6\xf8Q*\x89\x9a\xc0\x87m#\x89\xd3ව\x9e\x18\xba\xa1\xd8Ul\\\xb0E\b\x96K\xa7\x1a\x12|а\x12\r\xaa\x95\xf0\xf8/cŨ\xf8\x82Ax\x11Z\xfdv<$N\xe1\xed=t\xad\xf4\n\xb4\xc3\xf6\xb8\xb1X2\xb2\x1c\\f\x95\xb5,SM\xd5Ɓ\x18\xd1_F*\xdf\x02\xf8\xa4&\xba!\xe3\xc4\x0e?\x9a$sH4\x95v|\xde\xe5\x04u\x16s\xdbJ=\x01\xf3\x84\x19\x81\xb4\x17\xd4k\x06$\xa4>\xf5\x94\xac\x937\x90\x89\xe8\b\xee\x14Z\xe8\x12\xdf\xc7|\xd4\xe5q\xc2\xd1O\x19\x16vio\xbe\x81\xa9\tu_hkkƓ-\x82\v\xfa.c\xcf>\xae\x8c\xae\xe5nlh\x7f\x90]\x03wB\xc9\xc0\xdb\xf5@'{\xca\xc9u\xb6\xa5\xe82\x8f\x01\xa9\xe5.\xb8k\xe0\xd5\x12U5j!\x00:(%\xb6\n\x97@.\xe0\x95\x88\x8cj\xe52\"<\x1f'\x80[_\x10\x83\xd4\x15WK;\xacXI\x97\x8c\x9c\xfe\xa8+p\x97kJ\xff\xa0\x0e\xcdX]\x01\xcf\xc6J\x91\xb9w\xe8I\x96\x99\x87\x87\x87\xfb2\x80\xc5|\xa8\xb8\x1d\xd5\x12\xddkjr=\x90ѕc\x1d\x94j\x15\x14\xa5i\xac \xb9U\xd8\xcd\f\xc6\\&\x9ec.i`T\x86\xf0\x14'\x01c\xce*\x8cVG\b\x1e+\xf8\xb6G=\x02\xc3\xc3C\xd2\xfdpWI\x1cxQ\xc3\xd3j\xf7\x9ax|\xb9\x14\xd1\xefN\xe9\":\x96ZbϿ\xae\xfd\xf8\x8cHk\xaaֲ\x96/\xd6\xcc\x1d\x8eq_\x91\x0e\ac\xbe\xc87\xe6\x01M\xae\xa5\rH\x06Q{\xd1d\"A\xc1\xdf3\x9b\"C\x17\xcd28\x17g\x7f\xba\xe5\x95\xef\xd5\xd3I\tO\xbd&\xcc\v\xf8\x04\xee\x1f\xc7\x1c\x9da,\f\x88/\x18\xda~\xf02\xb8\xfaP\x96\x88\xd5x\x1d\x01Ʒ\x11\x94\x16\xfd\x82彮\xcb\xe5\x87\x14z/vSN~JTi\xd3kY@lM\xa0+\b\xd0>\xe7\xe3mT&,\xb5{\xe1\xa7\xec|d\x9a\\^\f\x96\x81[&\\k\xbf\x9f\xf1[\xe6v\x8d\xa2\x1a\xb7\xf0\x02>\x1b\xca?\xdd\xec\xc0%\xea~2M\x0e\x9d\x01={~\x81A+r\x94\x7fc\xaf%a\x93\x1d\xe7\xd7k%\x1dn\xe7\n\tO\xbfU\xf3d\x03\xd3WC\xae\x13h\xe9\x81W\xb9X9Ws\xa9\vٔc\xe9L\x97P:\x13\x85\x94\xce\xcd\r\an\x15U&\x12\xf7\x96\xd6\xd5P$\xb8_\x16\x8eI\x0f\x1c\xfa\xa0\xe8E\x0e\xac#i\x87_b<\xa7\xdf\xcb\xec\xc9\xd7\\:\x05l\xba\xd6x\x95⽐\xea\xea\U000e4cde\x84\xa3\xfb\xf2ws\xc1r\xfa\x9dķ\xfd\xbc\xfdO\xe6獝\xb7{\x14Ή\xe3\xf4\xe8\x1e]z\xfe\xc9^\xf5\x8c\xf3i\x9d\xe8߄\xed\xe9\x1f\x89%\xfc\xf9\xf7\xec\x9f\x00\x00\x00\xff\xff\x18\xd9g\x90\x9b\x14\x00\x00"), - []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xec}_s\x1c)\x92\xf8\xbb?\x05\xa1\xdf\xc3\xecntK\xeb\xf8\xdd]\\\xe8\xcd+\xdb;\x1d3c+,\x8d\xf6\x99\xae\xca\xeefDA-P-\xf7\xde\xddw\xbf \x81\xfa\xd3EUQ\xad\x96ƻg^luAB\xfe!3I\x12X.\x97oh\xc9\x1e@i&\xc55\xa1%\x83\xaf\x06\x84\xfdK_>\xfe\xa7\xbed\xf2j\xff\xf6\xcd#\x13\xf95\xb9\xa9\xb4\x91\xc5\x17вR\x19\xbc\x87\r\x13\xcc0)\xde\x14`hN\r\xbd~C\b\x15B\x1aj\x7f\xd6\xf6OB2)\x8c\x92\x9c\x83ZnA\\>VkXW\x8c\xe7\xa0\x10x\xe8z\xff\xe7˷\xffq\xf9\xefo\b\x11\xb4\x80k\xb2\xa6\xd9cU\xea\xcb=pP\xf2\x92\xc97\xba\x84̂\xdc*Y\x95פ\xf9\xe0\x9a\xf8\xee\xdcP\xff\x82\xad\xf1\aδ\xf9\xa9\xf5\xe3\xcfL\x1b\xfcP\xf2JQ^\xf7\x84\xbfi&\xb6\x15\xa7*\xfc\xfa\x86\x10\x9d\xc9\x12\xae\xc9'\xdbEI3\xc8\xdf\x10\xe2G\x8d].\xfd\x80\xf7o\x1d\x84l\a\x05uc!D\x96 \xdeݮ\x1e\xfe\xff]\xe7gBrЙb\xa5A\xdc\xff{Y\xffN\xfc(\tӄ\x92\ađ(Orbv\xd4\x10\x05\xa5\x02\r\xc2hbv@2Z\x9aJ\x01\x91\x1b\xf2S\xb5\x06%\xc0\x80n\xc1\xcbx\xa5\r(\xa2\r5@\xa8!\x94\x94\x92\tC\x98 \x86\x15@\xfe\xf0\xeevE\xe4\xfa7Ȍ&T\xe4\x84j-3F\r\xe4d/yU\x80k\xfb\xc7\xcb\x1aj\xa9d\tʰ@tWZ\x92\xd4\xfau\fW[,y\\+\x92[\x91\x02\x87\x96'1䞢\x16?\xb3c\xbaA\x1f\x85\xcc\xfeL\x85\x1f\xfe\xe5\x11\xe8;P\x16\f\xd1;Y\xf1\xdcJ\xe2\x1e\x94%`&\xb7\x82\xfd\xa3\x86\xad\x89\x91\xd8)\xa7\x06\xb4\xa5\x8c\x01%('{\xca+XX\xa2\x1cA.\xe8\x81(\xb0}\x92J\xb4\xe0a\x03}<\x8e_\xa4\x02\xc2\xc4F^\x93\x9d1\xa5\xbe\xbe\xba\xda2\x13\xe6W&\x8b\xa2\x12\xcc\x1c\xaep\xaa\xb0ue\xa4\xd2W9\xec\x81_i\xb6]R\x95혁̲\xf9\x8a\x96l\x89\x88\b\x9cc\x97E\xfe\xff\x82x\xe8N\xb7\xe6`\xc5V\x1b\xc5Ķ\xf5\x01\xe7\xc7\f\xf6ة\xe3\x84сr(6\\\xb0?Y\xd2}\xf9pw\xdf\x16T\xa6=SZ\xf2:\xc4\x1fKM&6\xa0\\\xbb\x8d\x92\x05\xc2\x04\x91;QE9\xe7\f\x84!\xbaZ\x17\xccX1\xf8{\x05\xda\xce\x01y\f\xf6\x06u\x10Y\x03\xa9\xca܊\xf1q\x85\x95 7\xb4\x00~C5\xbc2\xaf,W\xf4\xd22!\x89[m\xcdz\\ّ\xb7\xf5!(\xc8\x01\xd6:\xc5rWB֙h\xb6\x15۰\xccM\xa7\x8dT\x8d\xdeq:\xb0K\xa1\xf8Է%\xd3\xecN\xd0R魯g\x05\xc8\xca\x1cט\x925d\xde\xdd\xea\bJ\x18\xa1\x1f/\xea\xacJCn'\xed\x13e\x06\xc7|s\xb7\"\x0f\xa8\xacBkTZ\x95&\xa6R\xc2JI\xa4\xaf/@\xf3ý\xfcU\x03\xc9+\x14\xeeL\x01\xd2aAְ\xb1\x92\xa0\xc0\xb6\xb7\x9f@)K\x1b\x8d\x03\x90UO\xd9\xd8r\xbf\x03K[Zq\xe3\xe7\t\xd3\xe4\xed\x9fI\xc1Dez\xa26\xc8u\xa4\x145\xb4\x90{P\xa7\x10\xf1=5\xf4\x17\xdb\xf8\x88v\x16(A\xa8\x96xkO\xc7\xf5\x01?Ƹ\xed\xcajӂ\xc84\xb9\xb8 R\x91\vg\x81/\x16\xaeuŸY2\xd1\xee\xe3\x89q\x1ez\x99\x87\xbc\xa3\xa1c\xa8\xbe\x97\x1f\xb5\x13ޓh1\x00\xabE\x9a\xa7\x1d\x98\x1d(R\xca\xda\xe2m\x18\a\xa2\x0f\xda@\xe1\t\x13\xac\x88\xc7'\xd2\x13\xce\x1d\xce=\bm\xe9\xea\x11\xe9#/*\xce\xe9\x9a\xc351\xaa\x82\x01ڬ\xa5\xe4@\xc5\x04q\xbe\x806,;\ai\x1c\xa4\ba\x94\xffС\x00\x1aM\xfa\b\x84F@{\x9aY\xeb\xccy\x8b\xb0]\xaaD\xc7T*Ȭ־\xf6ր\x01G\v$$\xe1RlA\xb9ޭ\xa7\x12\x04L\x81\x15\xb8\x9cXE\xab\x80[kB6\x95\xd5\xc1\x97\xc4\xce\xeeA\x19`B\x1b\xa0\x11\xe1|\x06\x7f\xe0kƫ\x1c\xf2\x1b\xe7x\xddY\xff1\x0f^sOk\xa6\xf0\xe9\xc3(Do\x9d9\xcb\xd0\t\xf4\xfe\xde\x12\xfd֘\x986F\xfaP\x82s\x9d-+\xfd\xb0\x1b\xeb;\xaa\x0f4\x18\xdb\xe8\xe2O\x17\v\xe4p\xb7\xd7n\x1f\x9aP\x055Y\x92\xf5&\x14\xa59\xf4k3\x03E\x84\x8a\xa3\xfa$\x91\x9fT)z\x18\xe0f\xed\xff\x9f\x91\x9fC0\x8f8*B\xb5W\xe6\xe9q\xbf\xff\xca\\=\x0f\x1f5\xaev)\x13\x96\x7fv\xe1\xd9a\x9fv\xeb7K6!M\x04\x1e\x13\x0e\x1e.\xcdF\xb8\xf5;\x11\xeb,2?$\xe4\xb5ly\xe1\xfd\xa7\xa4\xd4N\xca\xc7)\xea\xfch\xeb4\x8b\"\x92aT\x85\xacaG\xf7L*\x8fzcj\xe1+d\x95\x89\xcezjH\xce6\x1bP\x16N\xb9\xa3\x1a\xb4[&\x0f\x13d\xd8}'-5\x12\xfdx\x84G\xc3H\xcb&\xc4|h\xe8֏8\xb6\x92\xa1\u0601Z\xf7\x1a\x8dq\xce\xf6,\xaf(G\xbbLE\xe6\xf0\xa1\xf5\xb8bZf\x84ɽ1G%\xd3\x15\xe7\x10\x04\xa4,\x93:+%)\xc0\xfa\xbc\x85]\x13\xf4\xab\x0ec\xbe\xa6\xd6W\x91C\xd8\x13d\x96\xaa8h\xdfU\x8end\xa33\x16\rS0\x10A8]\x03'\x1a8dF\xaa8E\xa6\xf8\xecJ\x8a\x12\x1c dD\xf3uW\x1a\r\x02# \t.\xe1v,\xdb9W\xcf\n\x11\xc2!\xb9\x04\xeb\xf0\x19B˒G\xccESF\x99\xef;\x19\x9b\xebM\x99\x98\xf5\xc7\xf0b\xf3\xbf)\t:\xb3)Q\xd26\xf3\xabK\xd9Z\x1c\xe2kڦ\xfck\x126h\xfe\x13\x84vd\xf6\x13\x8c\n%\xcb\xf4\xa0\xdcZ\xaa2З֝BOgA\x98\t\xbfN̈́\x8e\xcf\xd5\v\x96u\x88\xf0m\xf3f\xbe\xd0'\xb2&eN\xbc\x10c\xea.\xfe\t\xf9\x82&\xe3\xce[\x8cd\x9e\xfc\xdcn\xb5 lS\x13=_\x90\r\xe3\x06\xd4\x11\xf5OR\xf5\x813\xe7 F\x8a\xd5#\x18\xbe7\xd9\xee\xc3W\xeb\x82\xe9f\xa7*\x91.Ǎ\x9d#\x1b\xbc\xfd\xaey\x9e\x80K0\x8c\xcd\x14\x14\x18\x1e\xc7\x15S\xfb\x17t\xad\xde}z\x1f__\xb5K\x82\xe4\xf5\x10\x99\x98t\xae\xbc;¨=>\xef\u0087/\xe8\x03\xd5\v \xb7\x15\xb2 \x94<\xc2\xc1\xb9.T\x10\xcb\x1f\x1a*'t\xaf\x00\xf7dP\xce\x1e\xe1\x80`\xe2\x9b,\xfd\x92*\r\xae<\xc2!\xa5\xda\x11\r혘\xf6\x9bG\x96N\xf6\a$\x04\xc6\xd6S\xc5\xc0\x15?\x15\"[\x1a\xf1\x92\xa8KB\t\xb4?\x01\xcd$Qi\xf7\xd1ޥD\t\xf8A;^\xda\x19\xb3c%\xaaU\x8c8\xc8M2C]y\xa0\x9c\xe5uGn\x8e\xacĂ|\x92\xc6\xfe\xf3\xe1+\xd3~#\xf3\xbd\x04\xfdI\x1a\xfc\xe5E(\xea\x06\xfe\x92\xf4t=\xe0D\x13N\xcb[\x82\xb5\xb7\xe2\x9cM\xb3\xd2VӞi\xb2\x12v\xb9\xe2H\x92\xd8\x15\ueeba\xee\\GE\xa5q\x17MH\xb1ta\x9bXO\x9e\xdeRu\xc8\xfd\xecN}\x87\xf7\xd6X\xb8/n\xef\x97\xd3\f\xf2\xb0]\x83\x9b\x92\xd4\xc0\x96e\x89\xfd\x15\xa0\xb6@J\xab\xc2\xd3$\"Q\xb1zl\xe6\x89O\x9a\xf5n\x97\xaf\xcb\xc7z\x8f\x7fiM\xce\xd2C0\xb2H\xa0\x81\xd7\xdd\xf94>K;g\x13j\x05I\x98\xac:\xb0g9\\5\x85(\xcf \aZqtq&\xb9K\xf3\x1c\xf3\\(\xbf\x9daQf\xc8\xc2\\\xd5\xd0\x1a\xbb3\xc1\x05ŭ\x96\xff\xb2\x96\x16g\xd3\xff\x90\x922\xa5/\xc9;Li\xe1\xd0\xf9\xe6\x83f-0\t]bJ\x8a\x95\x9f=\xe5\xd6\xf6[\x05.\bp\xe7\t\xc8M\xcf/Z\x90\xa7\x9d\xd4\xcelכ8\x17\x8fpp;\x86\x93]\xb6\x95\xcc\xc5J\\8\x1f\xa2\xa70j\x87C\n~ \x17\xf8\xed\xe29\xaeT\xa2\xa4&V\xeb\x88hA\xcb4\tŔ\xa2TG\xdd.X\x83\x13b\x1b֩2\xd6\xc9\x1e\xc36IDK\xa9#\x1b\xf9\x03C\x99\x10\xde[\xa9\x8d\x8b\x97u|\xe6h@M\x86 \x1a\xa1\x1b\x97\xbf$UH6\xb1Jy*\xf4\xdb.\xf7;\xd0\xe0\xf7+|`\xce\x01\xb5+\xbb\x8bf~;m\x7f\xe1\xf6K\xb0\x13\x9a\xa1ǂmK%3\xd0ѽ\xec\xa6$؋HVF\x1b\xf7:\xe6H\xdd*ɥd\x8c\x87@CIwy-!f\xae\x17>|m\x05D\xedܷ\x7fO\xc9\xd8\xdcq\x11L\x19,\nz\x9c\xa6\x944\xc4\x1b\xd72\xcc\x06\x0f\xc8->ԶBM\x90j\xcbk\x01\xfc\x16\x1c\x85\x82\x89\x15v@\u07be\x80c\xe1uh,\xd9$VNseoB'\rw\xea\x1f\xdcT.%n\x15(\xe80\xaf\x1fUG?TH\xd3\nH\xccp7K\x99\xff\xa0Ɇ)m\xdaC\xd0\x03i*Q03\x17^\xe2\x83R'\xad\xbb>\xbb\x96\xadp\xd7N>\x85\xf4,G\x98D\xccq\x7f\t\b\xdb\x10f\b\x88LV\x02\x038v\x1ec\x17\x8e\xb8Nò\xd4I\x926\xfbm\x01Q\x15i\x04X\xa2\xa401\x1a\xe9iW\xffH\x19\x7f\t\xb6\x99\xa1,\xb6X9mN\x84\x14\xb7vB^A\xbf\xb2\xa2*\b-,\x8fИ\xb3\x02\xbaLo\x12\xdfl\v4\x13F\xda\x19Sr0\xe0\x93\xd7\x12ǐI\xa1Y\x0e\xb5q\xf5\x82 \x05\xa1dC\x19\xafT\xa2\x06\x9cE\xde9K\x11\xaf\tη\xc6H\xeb|\x89\xa4H\x88\xe6&\xfa\x8a\xe3ڸT\xe9\x1eߔ\x9b\xa5`\xbe\x97U*&1-\xf0̎\x96O\xa4\xa4\xe2\xf0\xdd\xd3J\x1d\xeawOk\xac|\xf7\xb4&\xcawO뻧\x95R\xf3\xbb\xa7\xf5\xdd\xd3j\x97\xff\x13\x9e\xd6Ԉ\xdcy\xbe\x81\x8f\x93\xa3Hت\x1e\x1b\xe2\b|\x9f\\\xe1s\xc0\x9f\x95\x8b\xb9\x8a\x83\x8a$\xfe\x0f\xa4uǔVc<\xea\xe4L;k\x82̻\xe3E\x13\xae\xe43\xb2\xeeC\xa7\xe7˺_\x8dBB\xbe\x89\x8c\xc0i\xe4;Ɂ~\x13\x1a\fݿ\xbd\xec~1ҧ\n\x92'fv\x11@O;\x10\xb8\xc3.\xb6\xed\x03\x00\xe1>\x02\x7f0\xffX\xc0\"\x80\xa4\"\x82q'y\xf5m\x06m\xb9#\x9fK\x17{\x9a\xedw\x8c\xc7TҒ\tON!\xec\xa6\b\x0e\xf8\xa5sw\xbb\xcfrd\xe2wI\r\x9c\x9f\x10\x98\x12\x11\x9bH\xfe;!\xe5/1\xb7\xf8\xd9\xdb\xf3)I}sV\xcc/\x96\xc0w\xfe\xb4\xbd$\xfaL\xa7\xe8͡\u038b\xa7\xe3\xbdb\x12\xde\xeb\xa4\xde%&ܝ/s>-\x1e{R\xe6\xd8t\xe8`8in2Un2\xb40\x85\xd8l\x94&S\xe0\xe6$\xbeMr'm\x9a\xbdZj۫%\xb4\xbdn\x1aۨ\x14\x8d~\x9c\x93\xa8\x16\xbf\x96\x86L\x1a[\xfeZ\xc2v*\x19\xa4긯'\xad\xaf>\x1f\xc1\xb0\x8c\x0f\xae\xdd+\xf9\xc8E\xc5\r+9n\xa4\xeeY\x1e\r6\x98\x1d\x1c\xea\v4~\x93x\xf4\xd4\xdf\x04\xf3\xf9K-\xb5\x97G\x9e>\xd5\xe4\t8'46\xafz\x98g\xee&\xa6L.\xc1\xda#;;\xfd\xc5 \xfe\xfa\xa6\x85\x13w<]\x8bV\xad\x88\x85\x98\xa8\x18\xbeEf\xd0p\xa4蛞\a\xeb\xfcp\xfc\xed\xef\x15\xa8\x03\xc1{lj?\xa79\x04\xe6'\xa6\xb6\v\xb1\xa0*\xbc\xda\x1a\x8a\x9f\xf7\x9c\xfef*\x93w\xc2Y\xdd\xe3\xf1`\x1b\xab#\x9aE\x8dU|v\xbd\x12\xedc\xa0\xb9\x90u\xebH\xb3)\a9\xf5\xb4\xd4\xcb.q\xe6/r&\xbd\x8at\xcf\xefw:\x05u\xca駴\x04\x80\xc9\xd3N/\xb5\xe4\x99Z\xf4$\xfbyi\xa7\x99\xe6m\x16\xbe\xe0饗8\xb5\x94H\xa9\x94SJ\xf3\xe8\xf4\n\xa7\x92^\xf54\xd2k\x9dBJ>}\x94\x94Ⓖ\v\x9c\x9a\xa2r\xe2q\x9a\xe9=\xde\xf1\xd3D\t\xa7\x88\x12v\x7f\xa7\x91<\x01\xbd\x84SB\xf3N\a%\xf0,u*\xbe\xe2)\xa0W<\xfd\xf3ڧ~&$k\xe2\xf3\xbc\xd3='oYH\x95\x83\x1a\xdd\xf6I\x95\xc2Q\xf9KY\xdbt\ar\xb4\xdf\x11n\xfd\xb3\xb5:\xfe2\x9a\a\x7f\xd1(^);\xb4}i%\xad\xe5mt\xf6\xa2\x1a\xf7\xa7\xebL\xfa{f\xddv\x95\x86\x92*\xbc\xbbx}p\xe9,Q\xd3\xfc\x81f\xbb#\xe8;\xaa\xc9F\xaa\x82\x1arQo\x00^9\xe0\xf6\xef\x8bKB>\xca:'\xa2}/\x8ffE\xc9\x0fv\x85B.\xda\rN\x93\x80\xa8\xb4\x85\xden%gY\xc4w\x8b\xde\xcd\xe4*\xf7.\xcb\xc0\x1b\xa3\xb2v\xca@i+\xc6]7t\xf3\xbaW`n$\xe7\xf2i\xe6ڟ\x96\xec\xafxs\xf73\xa2C\xefnW\b#\x88\a^\x05^'g\xd5ج\xc1\x9a\xe5\x06ϡ\xb9\xbf\xdat v\xf3\x1cۗ\xe3B\xee\xeeA\x0en\x81W\x9d\x99\xb4\xda\xe5v\xe5\xc61ԋ\x95\x19*\x0eDbF\x8d\xd91\x95/K\xaa\xcc\xc1%j,:c\b\xb6t,\xba3h=\xfaw;G\xc9\x1b\xaet\xc6\x1d\xcaC\xd9\xdd\xf4=\xa6\xdd)\xe3\x18>\xbd8yn\xf1\x8c\xe3\x18vK\x96H\xa9\xc8\xcf\xd1̯\xb3Eʹ\xbf\x99\xf8\x17\xb9\x87\xf7\xd1\xe8Y\x872\xb3\x19\xfe葫mT\x80\x7f\xe6\x1c\x04\xeb\xf3p\x0e\xfc#\xe3\xa0ݰ\x12\x14\xf0m\xbfU\xad\x8f\xabb\xed|\xb8\x8d\xfdXw0`\xe3\x1cZ\x18\x8a.AY/\xca\x05\xad+\x1ddu\x18\xf1\x86#L\x18\xd8B\x7f\x158\xa2\x81ݭ\xd2h>\x83:\xc1\xb5\xccO\xb1\xf8V\a\xf9\x87\xe1\x96G\x9cl\x85\xbcb7\xee9'\xe4\xf6\xe1F\x93J\xe4\x18.~\xf8\xeb\xdd,\xa9\xdbwn\xae\x0f\xb3uJ\xa9>\xc4[\xb5\x9c㖾pޱ\xdcD\x10\x18\x82\xd3z\a\xe4\x89\x19\x7fq\xd7yoZ\x1dZ\xf2\f\xbdp\x80W\xfaO\xbfq\xe0n\xfe\xf7/\xa3\xf8\xe9X)\xbc&տ\n\x80\u05ca\x9e\xf4\xcc\xc1\xbaNت\x93\xbf\xf4;c\xa0(M\xccטV\x87\x7f\x19\x03X\xfbi\xd2Pޚ\x954T\x88y\xda\xfa \xb2\xb1\xc42\xaf\x8dF\xb896\x1fc\x04\xb8\xf1\xe7!\xceF\x80\x1a\xe0\x10\x01t\x95e\xa0\xf5\xa6\xe2\xfcP\x1f\xc7\xf8F\xa8\xf1\x912~>R8h\x83\x82`\xd1\x1b\x854\x89\xb0O\xf7\x06\x91\x87\x99\x1e\x8e*\xcd#\x85\xe7\x82φԆ\x16'=\xd8p\xd3\a\x83O\xf6\xa8\xbc\x95TI\xeb\xb1Sݰ?f\\\x1ap\xae%.\xb2,4\xc8\t\xecA\x10k\x9d\x1d\x89ÛS3\xa1\xf8\x13\xae\xce\xc2\x05{\x17B!ч\x89\x88\x8fvh|\x00\xe7\a]\xc3\xc4\\Q|ϤO\x84\xbe\xf3\xeb\xa2\x15\xd7\xd6\xfb\x87\xa5\x05q\x9a\xd7\x1a\xd5͙f]\xbb\xf0<%ws\xb7\x1a\x02w\x8a\x8a\xeb?\xf7\xf2\xcci\xdcG\xf7Y*\xad\x8f\xee,\x85\x16\x81X\xcb\xf8\xf9qǩ~ڥ\xee\xd8\xd29\x1cY8CG9\xf7\a\x1d\vКn\xc3m\xeeOv\xe9\xb1\x05\x01.<\xe76O\"@\x9bSqݻ\xccݔ\xa1\x99\xa9\xa8\xef $\xf8\xb6j\xfd\xa0\t\x971\xa8\xf8\xa0\v\v/\x85\x855\xd9LB}-\x99JY\xc3}\xa8+Zڠ'\x8c\xdci\xdev\x03ζ̮u,\xe7\xb6T\xad\xe9\x16\x96\x99\xe4\x1cP[\xf7\xc7\xf5\x92sݟ=\xfc\x02TO\xa2\xf6\xb1]\xd7\xef\x00:n\xbb\x8do\xea\xd2\xdd\xf1\xf5.\xc3\x144\x0f\xe9\xf5\x06$\xb1\xe3Y\x8e\xb2\xa3B\xf4\x95\xb9\xfeH\xdbuì\xf3j\xd9\xc7y\xfd#s\v\x1f\x17\x88\xcbcA\x7f\x93jA\n&\xec?T\xe4n\x03/4\x9e5\xfe\x9d\x94\x8fw\x11'\xb67\xf8\x1f\xeb\x8a\xcdV\a\x13n\xd8x`t-+\xbf\xfb^;\xb4\xf1m\x15\xbc\x99\xff\xcc\xcbM\x849b\x0fz\xe8\fFt\x7f\xec@\x9a4\x05\xae\xe7\x01Xw\xe1%3\xce\x0f\x8bc\xc8G\xaf&6\xb0[/\x17x7\xa0\xb9\x8f`\xa0\xa3\xb0#\x15\x05R_|\xd1V觬z=\x99\x87\x9c\xc9\x1e\x8d\x7flj\x0f\xd1\xd1\r\xb3\xe5\xee\r \xd8q\x02ϻ`\xc7g*&\x84\xff\xd6֩\xef.h-\xdcB\x96\xd8`\x94.~\xf6}I>A\x7f\xbb\xc2\x1dg\x87\x1c33pVE\xaa\xacĭ\x92[\x05\xba/tK\xf27\xca\f\x13ۏR\xdd\xf2j\xcb\xc4\xe7\xe1\xa3;c\x95o\xa92\xcc\n\xad\x1bOl\xa0LP\xce\xfe\x11\xd3O\xed\x8fӀn\x06\x17JK\x920\x8c\xa1\x0f\xef\xc1\xfa\xaa\x83\xeb\xfb\xa8*,=]O\xf1;\x02O\xa6tc\xed\x134>E\xe8\xf6\x92|\x92\xd1\t\xeeӚX\x17\xa6u\xad@\x9b%l6R\x19\xb7\xeb\xbc\\\x12\xb6\tA\x04\xab;0\xfe\xe5ޜ$,\xb6]\\'\x8c4f\b\x83\xd7\n\xad)^I_Ѓ\xdba\xa2YVYO\xe9J\x1b\xca#\x8eʳ\x148Fk\xec$\x82\xfc\xd7g\xedȭڀ\xfa\xc1C\xecǑ\x14/\xc5p\xde\x1b\xb7(\x82 O\x8a\x19c}#9\x92\x12\xe0Ie\xac\x8f\xc49і\xd4'E\x11\x89S\x87\xab\xe1Ԛ4\x94\xefk(Cj\xd6c\x8d/,\xae\x916\xc4\xfa\xaf\x98E\xe4kY6g;*\xb6\x837\r씬\xb6\xbb \xc9\x03N1\xc9+\xc0\xa0+\xaa\x14\x1d\x1e\b6\x95\x12\xad\x94\x80\x91\xe3\xdb$\b\x03\x0e\x97f\x8f\xa4*\x17\xfe\x01^\xff\xbe\xf2\x95\x7f\xcbd\xb9Q\xb2X\xfa~1&\xba\xf0;\xf2\x8aI끘]\x94\xea\xc4y\xdf\xfe\xb9\x00\x94\x84\xb2\x04A\xa8\xf6='\xdc\xf8t\xb2\xb9ц*\xf3\xacp\xc4]\a\xc2D$\x02\xbb\x8b#q\xe7\x13\x13ܕW7\xfe\xa1\xd1\x1a\xf0\x82h&\xc2\x13\xcf.\xc9\xc1\xc9Gt\xcfK\xe0\x93\x8cR\xc5\xf3\x0e\xc7C\v]\x84^7\xaa\xb0\xafm퇓\x17\x9d\x0fG0\x8e\x8e/\xe3\v\x9cu\x95\xb0P\xfc\x03\x8bE\xbe1a5\xb3\xa8\xfc\xf1w?\x96\xbcOZ\xd4\xc4)2\xb6\xc6\xc1\xe5\xcb\xf0b\xa5\xfb\xe2\xe6-\a\xebzi\x80\xee\xf2i\xd62y\x7fƸ\xd19\x83F\xe11\xf3\xf3DM\xf6g\f\x17\xbdX\xac\xe8\xbc(?Q|\n\xf9\xa4Y\xfb7\xdf6\x12,\xf2`\xcf\x1d.jE\x8b\xc2\xc0_5^\x14\xb5J\xbd\x1fQO\xe7-m\xe1{\xf2\xbf\xfco\x00\x00\x00\xff\xff\xaf\x05\xd1\xf3\xa2\x81\x00\x00"), + []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xec}_s\xdb8\x92\xf8{>\x05ʿ\x87\xd9ݒ\xecM\xfd\uebae\xfc\x96u\x92\x1d\xd5\xcc$\xae\xd8\xe3}\x86Ȗ\x841\bp\x01P\x8e\xf6\xee\xbe\xfb\x15\x1a\x00\xff\x88 \tʲ'\xbb\x17\xbe$\x16\xc1\x06\xd0\xff\xd0\xddh4\x96\xcb\xe5\x1bZ\xb2\aP\x9aIqMh\xc9\xe0\xab\x01a\xffҗ\x8f\xff\xa9/\x99\xbcڿ}\xf3\xc8D~Mn*md\xf1\x05\xb4\xacT\x06\xefa\xc3\x043L\x8a7\x05\x18\x9aSC\xaf\xdf\x10B\x85\x90\x86ڟ\xb5\xfd\x93\x90L\n\xa3$砖[\x10\x97\x8f\xd5\x1a\xd6\x15\xe39(\x04\x1e\xba\xde\xff\xf9\xf2\xed\x7f\\\xfe\xfb\x1bB\x04-\xe0\x9a\xaci\xf6X\x95\xfar\x0f\x1c\x94\xbcd\xf2\x8d.!\xb3 \xb7JV\xe55i^\xb8O|wn\xa8\x7f\xc1\xaf\xf1\aδ\xf9\xa9\xf5\xe3\xcfL\x1b|Q\xf2JQ^\xf7\x84\xbfi&\xb6\x15\xa7*\xfc\xfa\x86\x10\x9d\xc9\x12\xae\xc9'\xdbEI3\xc8\xdf\x10\xe2G\x8d].\xfd\x80\xf7o\x1d\x84l\a\x05uc!D\x96 \xdeݮ\x1e\xfe\xff]\xe7gBrЙb\xa5\xc1\xb9\xff\xf7\xb2\xfe\x9d\xf8Q\x12\xa6\t%\x0f8G\xa2<ʉ\xd9QC\x14\x94\n4\b\xa3\x89\xd9\x01\xc9hi*\x05Dn\xc8O\xd5\x1a\x94\x00\x03\xba\x05/\xe3\x956\xa0\x886\xd4\x00\xa1\x86PRJ&\fa\x82\x18V\x00\xf9û\xdb\x15\x91\xeb\xdf 3\x9aP\x91\x13\xaa\xb5\xcc\x185\x90\x93\xbd\xe4U\x01\xee\xdb?^\xd6PK%KP\x86\x05\xa4\xbb\xa7\xc5I\xad_\xc7\xe6j\x1f\x8b\x1e\xf7\x15\xc9-K\x81\x9b\x96G1\xe4\x1e\xa3v~f\xc7t3}d2\xfb3\x15~\xf8\x97G\xa0\xef@Y0D\xefd\xc5sˉ{P\x16\x81\x99\xdc\n\xf6\x8f\x1a\xb6&Fb\xa7\x9c\x1a\xd0\x163\x06\x94\xa0\x9c\xec)\xaf`a\x91r\x04\xb9\xa0\a\xa2\xc0\xf6I*т\x87\x1f\xe8\xe3q\xfc\"\x15\x10&6\xf2\x9a\xec\x8c)\xf5\xf5\xd5Ֆ\x99 _\x99,\x8aJ0s\xb8BQa\xeb\xcaH\xa5\xafr\xd8\x03\xbf\xd2l\xbb\xa4*\xdb1\x03\x99%\xf3\x15-\xd9\x12'\"P\xc6.\x8b\xfc\xff\x05\xf6Нn\xcd\xc1\xb2\xad6\x8a\x89m\xeb\x05\xca\xc7\f\xf2X\xd1q\xcc\xe8@\xb9)6T\xb0?Y\xd4}\xf9pw\xdffT\xa6=QZ\xfc:D\x1f\x8bM&6\xa0\xdcw\x1b%\v\x84\t\"w\xac\x8a|\xce\x19\bCt\xb5.\x98\xb1l\xf0\xf7\n\xb4\x95\x01y\f\xf6\x06u\x10Y\x03\xa9\xcaܲ\xf1q\x83\x95 7\xb4\x00~C5\xbc2\xad,U\xf4\xd2\x12!\x89Zm\xcdz\xdcء\xb7\xf5\"(\xc8\x01\xd2:\xc5rWB\xd6\x114\xfb\x15۰̉\xd3F\xaaF\xef8\x1d\xd8\xc5P\\\xf4\xed\x93Q\x91\x01?\xfe\xf5h\x107\xd8(t\n\x9a<\xed\xc0\xec,\xe5\xa5\a\x80\x83\x8a\xf5l\x1fQqN\xd7\x1c\xae\x89Q\x15\xf4^;Ĭ\xa5\xe4@\xc5\xf1\xf04\xbb\x13\xb4\xd4;i\xeeY\x01\xb22\x13C퉂}n\xeeVGPZs\xb1#G\x95Zi\xc8팞(3\x88қ\xbb\x15y@]\x1a\xbeF\x9dZib*%,\x13G\xfa\xfa\x024?\xdc\xcb_5\x90\xbcB\xd9\xcb\x14 \x99\x16d\r\x1b˨\n\xec\xf7\xf6\x15(eI\xa7q\x00\xb2\xea\xe9B\xfb\xdc\xef\xc0\x92\x9eV\xdcx1f\x9a\xbc\xfd3)\x98\xa8LO\x12\x06\x99\x121E\r-\xe4\x1e\xd4)H|O\r\xfd\xc5~|\x84;\v\x94 T\x8b\xbc\xb5\xc7\xe3\xfa0\xca\x12\x84\xac6-\x88L\x93\x8b\v\"\x15\xb9p\x06\xc2\xc5\xc2}]1n\x96L\xb4\xfbxb\x9c\x87^\xe6M\xde\xe1\xd0\x11T\xdfˏ\xda\xc9\xd6I\xb8\x18\x80\x15\x11\x91R\xd6\v\xf2\x86q \xfa\xa0\r\x14\x1e1a\x91\xf3\xf3\x89\xf4\x84\xa2\u0379\a\xa1-^\xfdD\xce*g\xc7\xc8\xf9\x02ڰ\xec\x1c\xa8q\x90\"\x88Q\xfeE\a\x03\xb8\xa6\xd3G 4\x02\xda\xe3\xcc\x1a\x0f\x9c\xb7\x10\xdb\xc5JtL\xa5\x82\xcc.*\xd7~\xb1b\xc0q\x81\x14\x92p)\xb6\xa0\\\xef\u0590\n\f\xa6\xc02\\N\xec:\xa0\x80\xdbŎl*\xbbD\\\x12+݃<\xc0\x846@#\xcc\xf9\f\xfa\xc0\u05ccW9\xe47\xce.\xbc\xb3\xe6m\x1e\x8c\xfa\x9eRO\xa1ӇQ\x88\xdex\xe0,C\x1b՛\xa3K4\xabcl\xda\xd8\x10\x87\x12\x9ceoI\xe9\x87\xdd\x18\a\xa3\xfa@\x83\xb1\x1f]\xfc\xe9b\x81\x14\xee\xf6\xda\xedC\x13\xaa\xa0FK\xb2ބ\xa24\x87~kf\xa0\x88`qT\x9f$ғ*E\x0f\x03Ԭݓ3\xd2s\b\xe6\x11EEh\xf6\xca4=\xee\xf7_\x99\xaa硣Fg\x9c2a\xe9g\xfd\xe2\x0e\xf9\xb4s/-ڄ4\x11xL8x\xe89\x8eP\xebwB\xd6Yx~\x88\xc9k\xde\xf2\xcc\xfbO\x89\xa9\x9d\x94\x8fS\xd8\xf9Ѷi|6\x92aЇ\xacaG\xf7L*?\xf5f\xa9\x85\xaf\x90U&*\xf5Ԑ\x9cm6\xa0,\x9crG5h\xe7\xc5\x0f#dػ -5\x12}y4\x8f\x86\x90\x96L8\xf3\xa1\xa1[;\xe2x\x95\f\x8f\x1d\xa85\xafq1\xceٞ\xe5\x15\xe5\xb8.[g\x05\xe7C\xebqŴ\xcc\b\x91{c\x8er\xa6{\x9cA\x10&e\x89\xd4q\xe4\xa4\x00k\xf3\x16\xd6'\xe87\x1d\x9e\xf9\x9aZ[E\x0e͞ \xb1T\xc5A\xfb\xaer4#\x1b\x9d\xb1h\x88\x82q\x12\xc2\xe9\xda\xfaw\xc0!3R\xc512Eg\xf7\xa4(\xc1\x01DF4_\xd7\xd3h&0\x02\x92\xa0\v\xb7c\xd9Ιz\x96\x89\x10\x0e\xc9%X\x83\xcf\x10Z\x96<\xb2\\4\xcf(\xf1}'c\xb2\xde<\x13R\x7f\f/&\xff͓\xa03\x9b'\x8a\xdaF\xbe\xba\x98\xad\xd9!\xee\xd36Ͽ&b\x83\xe6?\x81iG\xa4\x9f`\xd0*\x99\xa7\a\xf9\xd6b\x95\x81\xbe\xb4\xe6\x14Z:\v\xc2L\xf8uJ\x12:6W/\x96\xd7A·M\x9b\xf9L\x9fH\x9a\x14\x99x!\xc2\xd4]\xfc\x13\xd2\x05\x97\x8c;\xbfb$\xd3\xe4\xe7\xf6W\v\xc265\xd2\xf3\x05\xd90n@\x1da\xff$U\x1f(s\x0ed\xa4\xacz\x04w\x17L\xb6\xfb\xf0՚`\xba\xd9HK\xc4\xcb\xf1\xc7ΐ\r\xd6~wy\x9e\x80K0\xca\xce\x14\x14\x18\xbdG\x8f\xa9\xfd\v\x9aV\xef>\xbd\x8f\xfbW\xed'\x81\xf3z\x13\x99\x10:\xf7\xbc;\x9aQ{|ބ\x0fo\xd0\x06\xaa\x1d \xb7S\xb3 \x94<\xc2\xc1\x99.T\x10K\x1f\x1a\x1a't\xaf\x00\xb7\x8c\x90\xcf\x1e\xe1\x80`\xe2{@\xfd'\x95\x1b\xdc\xf3\b\x87\x94fG8\xb4cb\xda\xefmY<\xd9\x1f\x10\x11\x18\xfaOe\x03\xf7xQ\x88\xec\xb8ğD]\x12\x9e\x80\xfb\x13\xa6\x99\xc4*\xed>ڛ\xa8\xc8\x01?hGK+1;V\xa2Zň\x83\xdc$\x13\xd4=\x0f\x94\xb3\xbc\xee\xc8\xc9\xc8J,\xc8'i\xec?\x1f\xbe2\xed\xf7Y\xdfKП\xa4\xc1_^\x04\xa3n\xe0/\x89O\xd7\x03\n\x9apZ\xde\"\xac\xbdS\xe8\xd64\xcbm5\xee\x99&+a\xdd\x15\x87\x92ĮpS\xd8u\xe7:**\x8d\x9b|B\x8a\xa5\v\xdb\xc4z\xf2\xf8\x96\xaa\x83\xeegw\xea;\xbc\xb7\x8b\x85{㶦9\xcd \x0f\xdb5\xb8gJ\rlY\x96\xd8_\x01j\v\xa4\xb4*<\x8d#\x12\x15\xab\x9f\xcd<\xf6I[\xbd\xdb\xcf\xd7\xe5c\x9d\x82\xb0\xb4K\xce\xd2C0\xb2H\xc0\x81\xd7\xdd\xf9\xf4|\x96Vf\x13Z\x05N\x98l:\xb0\xa5:\xdc4\x05)\xcf@\a\xae\xe2h\xe2LR\x97\xe69\xa6\xe1P~;cE\x99\xc1\vsUCk\xecn\t.(n\xb5\xfc\x97]iQ\x9a\xfe\x87\x94\x94)}I\xdea\xc6\r\x87\xce;\x1f4k\x81I\xe8\x123f,\xff\xec)\xb7k\xbfU\xe0\x82\x00w\x96\x80\xdc\xf4\xec\xa2\x05y\xdaI\xed\x96\xedz\x13\xe7\xe2\x11\x0en\xc7p\xb2˶\x92\xb9X\x89\vgC\xf4\x14FmpH\xc1\x0f\xe4\x02\xdf]<ǔJ\xe4\xd4\xc4f\x1d\x16-h\x99ơ\x98\xf1\x94j\xa8[\x875\x18!\xf6\xc3:\x93\xc7\x1a\xd9c\xb3Mb\xd1R\xea\xc8F\xfe\xc0P&\x98\xf7Vj\xe3\xe2e\x1d\x9b9\x1aP\x93!\x88F\xe8ƥWI\x15ra\xacR\x9e\n\xfd\xb6\x9f\xfb\x1dh\xf0\xfb\x15>0\xe7\x80Z\xcf\ue891o\xa7\xed/\xdc~\tvB3\xb4X\xf0\xdbR\xc9\ftt/\xbby\x12\u058bH\xd2H{\xeeȗ:/\xc9e\x8c\x8c\x87@Ón\xf2ZD\xcc\xf4\x17>|m\x05D\xad\xecۿ\xa7xl\xee\xb8\bf4\x16\x05=\u03a2J\x1a\xe2\x8d\xfb2H\x83\a\xe4\x9c\x0f\xb5\xadP\x13\xa4\xae\xe55\x03~\v\x86B\xc1\xc4\n; o_\xc0\xb0\xf0:4\x96l\x12{N3eoB'\ru\xea\x1f\x9c(\x97\x12\xb7\n\x14t\x88\u05cf\xaa\xa3\x1d*\xa4i\x05$f\x98\x9b\xa5\xcc\x7f\xd0dÔ6\xed!\xe8\x814\x95(\x98\x99\x8e\x97\xf8\xa0\xd4I~\xd7g\xf7e+ܵ\x93O!{\xcc!&q渿\x04\x84m\b3\x04D&+\x81\x01\x1c+\xc7\u0605C\xaeӰ,UHҤ\xdf> \xaa\"\r\x01K\xe4\x14&F#=\xed\xe6\x1f)\xe3/A63\x94\xc5\x16{N\x93\x89\x90\xe2\xd6\xce\x17,\xe8WVT\x05\xa1\x85\xa5\x11.欀.ћ\xc47\xfb\x05.\x13FZ\x89)9\x18\xf0\xc9k\x89cȤ\xd0,\x87zq\xf5\x8c \x05\xa1dC\x19\xafT\xa2\x06\x9c\x85\xde9\xae\x88\xd7\x04\xe7\xf31\xd2:_\"*\x12\xa2\xb9\x89\xb6\xe2\xb86.U\xba\xc57ef)\x98oe\x95\x8aIL\v<\xb3\xa1\xe5\x13)\xa98|\xb7\xb4R\x87\xfa\xdd\xd2\x1a{\xbe[Z\x13\xcfwK뻥\x95\xd2\xf2\xbb\xa5\xf5\xdd\xd2j?\xff',\xad\xa9\x11\xb9\xe3\x86\x03/'G\x91\xb0U=6\xc4\x11\xf8>\xb9\xc2\xe7\x80?+\x17s\x15\a\x15I\xfc\x1fH\xeb\x8e)\xadf\xf1\xa8\x933\xad\xd4\x04\x9ew\xa7\x9f&L\xc9gd݇Nϗu\xbf\x1a\x85x\xa6\xac{?\xeci\x1b\xfb\xa4\x9c\xfb\x80\x94y\xd9\xd9\v\x9f\xa8Q\x00\rau\xb7\r\x1f\x9b\xd7\x10\x87L\xf4\xffʉ\xb9\xbd\xac\xb13\xf2Njg\xf1'\xf3H\x94\xa4\x17\x7f\xba\xf8\xf6\xd0\x7f\x1e\x84\x0f\xa2\xb8\x8f;\x7f\xfc:\x02\xd5z\xa0\xed\xb4\xb0n\x16\u07b7\xc9\xc6g\xe1\xdb\xd4L\xfc\x1a\x89\x11X]\x96<\xc2ⷪ\v\f\x14\x9fK\xbf\"=\xe3\xa4\xea*\x02'\xe9\xac*\xd5\a\x91\xed\x94\x14\xb2\xd2>*aa\xbd\xcb\xdcy\xfb\x002ƬQ\t\xff7\xb2\x93U$\x13|\x04}\x13\x19\x81ӓ\xef$\a\xfaMh0t\xff\xf6\xb2\xfb\xc6H\x9f*H\x9e\x98\xd9E\x00=\xed@\xe0\x0e\xbbض\x0f\x00\x84r\t\xben\xc01\x83E\x00IE\x04\xe3\x8e\xf3\xeab\vm\xbe#\x9fK\x17{\x9amw\x8c\xc7TҒ\tON!\xec\xa6\b\x0eإsw\xbb\xcfrd\xe2wI\r\x9c\x9f\x10\x98\x12\x11\x9bH\xfe;!\xe5/1\xb7\xf8\xd9\xdb\xf3)I}s<\xe6\x17K\xe0;\x7f\xda^\x12~\xa6S\xf4\xe6`\xe7\xc5\xd3\xf1^1\t\xefuR\xef\x12\x13\xeeΗ9\x9f\x16\x8f=)sl:t0\x9c47\x99*7\x19Z\x98\x9a\xd8\xec)M\xa6\xc0\xcdI|\x9b\xa4N\x9a\x98\xbdZj۫%\xb4\xbdn\x1a\xdb(\x17\x8d\xbe\x9c\x93\xa8\x16\xaf\x9aC&\x17[\xfeZ\xccv*\x1a\xa4\ua62f'\xf9W\x9f\x8f`X\xc2\a\xd3\xee\x95l\xe4\xa2↕\x1c7R\xf7,\x8f\x06\x1b\xcc\x0e\x0eu\x01\x8d\xdf$\x1e=\xf5\x95`>\x7f\xa9\xb9\xf6\xf2\xc8ҧ\x9a<\x01\xe7\x84\xc6\xe4\xaa7\xf3\xcc\x15\x8a\xca\xe4\x12\xeczd\xa5\xd3\x17\x06\xf1ե\x16\x8e\xdd\xf1t-\xaejE,\xc4D\xc5p\x15\x99\xc1\x85#E\xdf\xf4,Xg\x87\xe3o\x7f\xaf@\x1d\bֱ\xa9\xed\x9c\xe6\x10\x98\x17Lm\x1d\xb1\xa0*\xbc\xda\x1a\x8a\x9f\xf7\x8c\xfeF\x94\xc9;\xe1V\xdd\xe3\xf1\xe07VG4N\x8dU|\xd6_\x89\xf61\xf0\xb9\x90\xf5בϦ\f\xe4\xd4\xd3R/\xeb\xe2\xccwr&\xad\x8at\xcb\xefw:\x05u\xca駴\x04\x80\xc9\xd3N/\xe5\xf2L9=\xc9v^\xdai\xa6y\x9b\x85/xz\xe9%N-%b*\xe5\x94\xd2<<\xbd©\xa4W=\x8d\xf4Z\xa7\x90\x92O\x1f%\xa5\xb8$\xef\x02\xa7\xa6\xa8\x9cx\x9cfz\x8fw\xfc4Q\xc2)\xa2\x84\xdd\xdf\xe9I\x9e0\xbd\x84SB\xf3N\a%\xd0,U\x14_\xf1\x14\xd0+\x9e\xfey\xedS?\x13\x9c5\xf1z\xde鞓\xb7,\xa4\xcaA\x8dn\xfb\xa4r\xe1(\xff\xa5\xf86݁\x1c\xedw\x84\xaa\x7f\xb6U\xc7^\xc6\xe5\xc1\xd7AŊ\xb7Cۗ\x96\xd3Z\xd6Fg/\xaa1\x7f\xbaƤ/\x83붫4\x94Tai\xe5\xf5\xc1\xa5\xb3D\x97\xe6\x0f4\xdb\x1dA\xdfQM6R\x15Ԑ\x8bz\x03\xf0\xca\x01\xb7\x7f_\\\x12\xf2Q\xd69\x11\xed\xba<\x9a\x15%?X\x0f\x85\\\xb4?8\x8d\x03\xa2\xdc\x16z\xbb\x95\x9ce\x11\xdb-Z\x9b\xc95\xee\x15\xcb\xc0\x8aQY;e\xa0\xb4\r\xe3\xa6\x1b\x9ay\xdd\x12\x98\x1bɹ|\x9a\xe9\xfbӒ\xfd\x15\v\x8b?#:\xf4\xeev\x850\x02{`\xa5\xf2:9\xab\x9e\xcd\x1a\xec\xb2\xdc\xccsH\xf6W\x9b\x0e\xc4n\x9ec\xbbv/\xe4\xaeLs0\v\xbc\xea̤\xd5.\xb7+7\x8e\xa1^,\xcfPq ҕ\xe1\xdd1\x95/K\xaa\xcc\xc1%j,:c\bk\xe9Xtgp\xf5藞\x8e\xa27T\x9c\xc6\x1d\xcaC\xd9\xdd\xf4=\xc6\xdd)\xe3\x18>\xbd8yn\xf1\x8c\xe3\x186K\x96\x88\xa9\xc8\xcf\xd1̯\xb3Eʹ\xafL\xfc\x8b\xdc\xc3\xfbh\xf4\xac\x83\x9e\xbb\xa3\xe6\x91\xf4\xac\x00\xd1\x15\xdd\x1d\xccR]\x03\x16\xe4\xed\xbfzF\xbeU\xe8\xda\xd7T=%Pv\xd7\x05\x11\xafY\x8d\x15fCg1\xfd\x84\xf5\xe9\x0f\xe4\xf6\x01}\xb4Z\xb5y\x11\xf5>Z\b\x95\x85\xcd\xe0\b\x1c\xff\xc1_Ο\x9a\xa6\x8dTt\v?KW\x02|\x8a\xec\xdd֝\xd2\xf0\xde\xea\t\xf9\xa3Ahb\x05x}1\xf2#`M\xcew\xaf\xa8\xb1\x1d\xe5\xcc2\xcd\xc6LU#\x8f\xd2\xfd\xfe\xfeg7+\xc3\n\xb8|_\xb9t\a\xab\x135X\x14\x87\xd9:Hk\xfbߝ|\xc2\xe2\xbf\xf18f\xb8ҡ\x99\x8c\x02L6\xc7\x14\xc4YS\xaaJ.i\x0e\xeaF\x8a\r\xdbN\xcc\xee\xd7N\xe3\xa3e6\xc3\x1f\xfd\xe4\xea5*\xc0?s\x0e\x82\xb5y8\a\xfe\x91q\xd0nX\t\n\xf8\xb6\xffU\xad\x8f\xabb\xedl\xb8\x8d}Yw0\xb0ƹia(\xba\x04e\xad(\x17\xb4\xaet\xe0\xd5\xe1\x897\x14a\xc2\xc0\x16\xfa^\xe0\x88\x06vU\xa5q\xf9\f\xea\x04}\x99\x9fb\xf1\xad\xce\xe4\x1f\x86\xbf<\xa2d+\xe4\x15\xab\xb8猐ۇ\x1bM*\x91c\xb8\xf8\xe1\xafw\xb3\xb8nߩ\\\x1f\xa4uJ\xa9>Ŀj\x19\xc7-}\xe1\xacc\xb9\x89L`\bN뚒'f|\xe1\xae\xf3VZ\x1dry\x86.`\xc0\x92\xfe\xd3W0\xb8\xca\xff\xfe\xe2\x16/\x8e\x95\xc22\xa9\xfeV\x00,+z\xd2-\f\xeb:a\xabN\xfe\xd2\uf301\xa241[cZ\x1d\xfee\f`m\xa7ICyK*ih\x10\xb3\xb4\xf5Adc\x89e^\x1b\x8dPsL\x1ec\b\xb8\xf1\xe7!Ά\x80\x1a\xe0\x10\x02t\x95e\xa0\xf5\xa6\xe2\xfcP\x1f\xc7\xf8F\xb0\xf1\x912~>T8h\x83\x8c`\xa77\nir\xc2>\xdd\x1bD\x1e$=\x1cU\x9a\x87\nO\x05\x9f\r\xa9\r-N\xba\xb0\xe1\xa6\x0f\x06o\x14Ry+\xa9\x92\xd6c\xa7\xba!\x7flqi\xc0\xb9/\xd1ɲ\xd0 '\xb0\aA\xec\xea\xecP\x1c\xaeĚ\tşpu+\\X\xefB($zo\x12\xf1\xd1\x0e\x8d\xf7\xf3\xfc\xa0k\x98\x98+\x8a\xf7\x99\xf4\x91\xd07~]\xb4\xe2\xdaZ\xff\xb0\xb4 N\xb3Z\xa3\xba9Ӭ\xbb.\x9e5\xfe\x9d\x94\x8fw\x11#\xb67\xf8\x1f\xeb\x86\xcdV\a\x13n\xd8x`t-+\xbf\xfb^\x1b\xb4\xf1m\x15\xac\xcc\x7ffw\x13a\x8e\xac\a\xbd\xe9\fFt\x7f\xec@\x9a\\\n\\\xcf\x03\xb0\xee\xc2Ek\x9c\x1f\x16ǐ\x8f.ul`\xb7n.\xf0f@S\x8f`\xa0\xa3\xb0#\x15\x05R\x17\xbeh+\xf4S\xbc^\x8f\xe6!c\xb2\x87\xe3\x1f\x9b\xd6Cxt\xc3l\x99{\x03\x13\xec\x18\x81\xe7u\xd8\xf1\x9a\x8a\t濵m\xea\xda\x05-\xc7-d\x89\rF\xe9\xe2gߗ\xe4\x13\xf4\xb7+\xdcqv\xc813\x03\xa5*\xd2d%n\x95\xdc*\xd0}\xa6[\x92\xbfQf\x98\xd8~\x94\xea\x96W[&>\x0f\x1f\xdd\x19k|K\x95a\x96i\xddxb\x03e\x82r\xf6\x8f\x98~j\xbf\x9c\x06t3\xe8(-I\xc20\x86^\xbc\ak\xabFG\xe7\xee#\xe4\xa3/#0Gth\xe9\tr\x8a\xc1\x12\x889\xa5Tkc\xa21FB\xb7\x97䓌j\x06\x9f\x0fź0\xadM\x06\xda,a\xb3\x91ʸ\xed\xea咰M\x88>X\xa5\x83\x813w\x97&a\xb1}\xe6:ӤY\xbf0\xea\xadp\x19\xc6Z\xf6\x05=\xb8\xad)\x9ae\x955\xb1\xae\xb4\xa1k+o\xd5\x06ԏ:b?\x0e\xa5XMÙ}\xdcN\x11\x04yR\xcc\x18kTɑ\\\x02\x8f*c\x8d+Ή\xb6\xa8>)\xfcH\x9c\x1e]\r\xe7\xe4\xa4M\xf9\xbe\x862\xa4\x9f\xfd\xac\xf1j\xc65\xe2\x86X\xc3\x17ӏ|+K\xe6lG\xc5v\xb0D\xc1N\xc9j\xbb\v\x9c<`M\x93\xbc\x02\x8c֢.\xd2\xe1\xe2cS)\xd1\xca%\x189\xf7M\x023\xe0pi\xf6H\xaar\xe1/\x16\xf6\xf7F_\xf9KP\x96\x1b%\x8b\xa5\xef\x17\x83\xa9\v\xbf\x95\xaf\x98\xb4\xa6\x8b\xd9E\xb1N\x9c\xd9\xee\xef\x19@N(K\x10\x84j\xdfsB\xa9\xa8\x93\xd7)m\xa82ϊc\xdcu L\x840\xb0\xbb\xf8$\xee|F\x83\xab\x95u\xe3o(\xad\x01/\x88f\"\\]\xed\xb2#\x1c\x7fD7\xcb\x04\xde\xe5(Ulq\x8aؕ*\xdec͂\xf2]Q\xc9J\xaa\xeb\x97\xd7b\xb5\xc8\xe7\"\x9d\xba\xba\xf1\xfd\xd5\\\xbauc\x8cB\x96\xa8\xa4]\x87\xb7\xc9\v\xf9\x0e\x1b\xb6̛M\x8b\xfa\xe1\xe9\xc3\xcbo\xd7W\xd30\xe6H\xbd\xa0 ñ\x8emvh\x11^b\xfc%\xbb\xb9,ڙ&\x80\xd9\xfc\x8c\xdc_\x8c\xd8ZӢ\xf5\xb2\x04K\x1a\x1d,\xea\xcc\xf6x\xfaWu\xb5\x06@b\xa4S \b\x940\xf9U\x8e\x1f\x14Yr05\xf8\x9dt`\xb1\xb5\xe8P'\x98\xa2i\xa63\x83\xf3\x1e\xe95Z\"C\xb1\x1d\x94 ,;\xa0\xf5`\x91\x9b\xad\x96\xff8\xd3v\xe0Mvf\x8f\xceC\x8cP\xcd\x149k\xc0\x1f\x81iѣܰ\x13X\xa4;!\xe8\x0e\xbdx\xc0\xf5\xf9\xf8H\xd1 um\x96\xb0\xf3\xbeu\xcb\xc5b+}Ahn\x9a&h\xe9O\x8b\b\xb6r\x13\xbc\xb1n!\xf0\x80j\xe1\xe4\xb6b\x96\xef\xa4G\xee\x83\xc5\x05ke\x15\x05\xd1\tR\x1b\xf1\xbd͘\uebae\x1d\x84t\x1a\x11R_a\x1e\x82\xd7\xe42\x89T\x12\xf1b\x05\x9a\"\xd5}\xfe\xe3\xfa\x19\n'\xc9R\xc9(\x97\xad\x03\xbd\x14\xfb\x906\xa5\xaeѦs\xb55M\xa4\x89Z\xb4Fj\x1f\x7fp%Q{pa\xd3HOn\xf0\xf7\x80Γ\xe9\xfadW1\x8b\xc1\x06!\xb4\x11$\xfa\x1b>hX\xb1\x06Պ9\xfc\x85mEVq\x15\x19\xe1.kuss\x7fsRog\xa1\xe4\xd4\tӎ\xa2\xc1\xbaE~\x15w\x02\x9d\xb4\x14\x19\x9ey\x8c\xd1\xd5SP\x86\x8a\xe9\xa4\\\xc68H\xd0`\x9c\xa3s\x1f\x8d\xc0\xfeJ\x8f\xe5\x87\xf3\xc6+\x1e[\xb4\x8dt1\xbdBml?\xf3\xb03\x92wGA\xbc\xbe\xc1\x01P\x87f\xc8H\x05\x9f\x91\x89OZ\x9d&\x96\xfef\xa5\x1f^4aH\x1a\x89\xc5\xf5I\xf3'\xb4҈\x1b¿\xebm?\xab`g\x8ePG\xff\xd7^\x9d\b\xbb\xdcI\xf3!j\x97\xf1\xf0\xf4\xa1 x\x8a\xad\x1c\x98YWsx\xc8Amjx\x03B:*$\\$:T\x96\x0e*\x16\x1aK\xf06\xbcJ|nt-\xb7C\xa1\xbb\xb5є\xc7\xdc \xdd\xd3\xdc*\xdeD\xa8E\xde\xd1Zs\x90\x02mE\xf1!k\xc93'\xc1\xa6\fRKTb\x80M\x93Q\x16E\xb1((\xa8\x99\xbaa\xc3\xd5yc\xac\xa4\x99\xd4Ƀ/\x04\"\xd6\xd8&\xa7f\xedQ\v\xecg\x9bȍ\x89\x80\xe6P\xc0Q\xfa]BJ5\x16w\xf0\xd5أ\xb1\xc7\xd3\xd8t\x8f\xf7\xe7\x1d\xd2Δx\x11\x1cr\x8b>z\x1b*r\x1fr\xa59\xc0\xc7\xe0\"\xd6\xf6q\xa2\x8cX\xf0\x95\xd3{<\r\x15\r\xb7\x8c\x9bK\xa1\t\x96c\x11\xb5\x84ᄏ-\xd2 \xbb\x95A\xa5{\x11\xd4b\x8d\x16\xf5\xa0\x9a(\xe39\xe6(r\x1a\xf20\xack\xe4^\x1eP\x9dbN\"\xf0\xfc\x116\xc1\x83\b\x18\xad\xc6\xf8\xfeȬp\xc0M\xd32/7RI\x7f\x02\xe9&\xe83\xa5\xcc\x11E\xb686\xad?\xcd\xe1\x83v\x9ei\x8e\xee\\\a\x91ƒ+0\x9dv\xe5(\x8e\x05\x1d\xb3c\x18\x98\xc87\xc6y\xe0h\xc9\x1d\xd5\t\x8e\xd6\xe8픰#\xe9\x90z@\xab\xd1c̈\xc2pGɐc\xeb\xdd\xc2\x1c\xd0\x1e$\x1e\x17Gc\xf7Ro+b\xb0\xcaೈ\x9d\xdd\xe2\xfb\xf8\xe7[\xbc\xc0\xb4\t'\xeep\xdeu\x8c\xf5\x13\x95\xb7~\x87)E\xac\x93\x0f\x1a\vT@\x90k7\xd9w\x13\xb2\x8e\x85\xddX]\xde\x1d\xc5\xe4c\xf9c\x8f\xc3\xd4\xf1\x15P\x01\xf8R]t[5\xac\xad\xd2n\xe6M#\xf9\xac/m\xf2\xfb\xaf\xe3OiV\xa4\x16\x92Sq{\x8d\x1b\xa5\x89\x13W=͈\x1a\xfa]\xce\x14Z\x8e\xab)\x89\x9bk\x85\x1b\x1c\x7f\xea\uef74\xbe\t\xbas\xfew\xe8\xa9\xeet\xa0\x91\xea\x03f\x87z\x8e\x80ɍքT\xde\x00;\xa7\x81\x1f\\?\xff\xbd\x12=7\x81\xefqD\xf1\x03Q\xdeōE\xc7\xe9\x18\xf1\x12\x1c\xc6\xc4t\x8b\r\xb8\x1d\x11\x9c\xad\xd0\xde\xc3\xcb\xea\x816\x9eK\b\x06\xab\a\xd8\x04-\x14\x16\x8e\x8e;\xd4\xd4u\xc9\xfa4~\x17\x8d\xe7\xc7u\xd1j\xac\xber\xdfTt;.C\xcaoK\u061cF\xea\xa5;\x84l-\xd6\xf2\xcb\x1dB>ōE\xe1-\xf3;\x90\xdaI\x81\xc0Fԟ\n\xd9\tAϵѧ\x8c9\xdf`\x9e\xafaCb\xe75\xf0Pt|#~\x9e\xf2\xb6\xb3\x16\xca\xef\x9cݮ\xeb\xe4\xa98\x1e\x95\xe8p~\x94\xf9S\xaa>\xf9H\x19q\xc5\xcc\xcb\xf0\xc4W\xaa\xd8\xf244\x16\xccT3\x19kѵF\v\xea9\xef\xaba/,\xff\xef*\xd9q\xb3V\xd7(\xd7[+V\xb8\xab\x8d\x8b\xcf`\xafn\xe4\xd2\xe3`\xb7M2\x1bG\r\xf6\xa5\x97\xeb\xc9\xf8\x8b\xb4p\xa3%W\xa7\xaf\x93\x8eꗠce\x1b\xab\xaa\xf9l\xe4\xc4{l-R\x06\x13K\x92\xcdƃ\xda\x1c\xe9p\x87Z*ˌN\xf9\x9ez[\xa6E~U\xa0\xa5\x11\xcaG\xa9\x14\xd5\x00\x16\x1bCʢ\xb2\xdcR5\xc7b\xadu\xf8\xcd\xfc\xcd\xff\xafeT\xccy\xea\x00Q|ƃ\x1c>\xadݧ\xee\xc7\x01\x95\x82\x0e瘡\x1f?\x95׆\x85\xcd\xdb~\x82Z*\xaa\xff:\xd0qGu0\xf20\xfcn\xfd\xf8\x83\x8b=\x10j\xef\xe0H\x16t\x91%jzL~\xe1\t\xceS\x12\xb9i\xffn\x01\xae\r(\xa3\xb7h\xcbk\x0f\x15xɛ\x8c\x05\x81\x9er\x95\xde\x02\xdf1\xbd\xa5\xc8\x18\x83\xfc\xc8p\xe6\xbe\xcb'yϤ\x83H=\xe1\x1dw\x19\xf4Y\x8e\xb54\xaf1\xe6\xf43\xfc\x99\xffl\xd9\xcbkoO\xefSP[,\xd1_,\xa9\x9c\x14]\xf9\xcb\xd3\xfce|\xfb\xfb\xc0\xf0\xdd\xff[\xd5\xf3_}\xa9\x18|\xa1\xf8U(\xa7\xa1:\xf7f\xf1\xfc1\xedJ\xef\xb5\xf9\b\xb0\x8d\t~$\xf7w\x1c~4\xa6\xe3ǘ\xd7\xf0\x18?1\xdd*OhO\xb1\b\x0f\xd6\xc67\xdd\xf2\xd6\x18\x91b,+ݏ\xc0\x0f\xbd/aݵ\xe1w\xb2;\xe4\x1a\xcd҃ɔi;v\xcdJ\xee΄\xcd\xf9\xa5~\t\xff\xfc\xf7\xec?\x01\x00\x00\xff\xff\x03f\x86Y\xc0\x1d\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xbcVMo\x1b7\x10\xbd\xebW\f\xd0kwU\xa3hQ\xec\xadqr0\xda\x06\x82\x1d\xe4N\x91#-c.\xc9\xce\f\xe5\xba\x1f\xff\xbd \xb9+K\xab\x95\x93\\\xb27\x91Ù\xc7\xf7f\x1e\xd54\xcdJE\xfb\x11\x89m\xf0\x1d\xa8h\xf1/A\x9f\x7fq\xfb\xf8\v\xb76\xac\x0f7\xabG\xebM\a\xb7\x89%\f\xf7\xc8!\x91Ʒ\xb8\xb3ފ\r~5\xa0(\xa3Du+\x00\xe5}\x10\x95\x979\xff\x04\xd0\xc1\v\x05琚=\xfa\xf61mq\x9b\xac3H%\xf9T\xfa\xf0C{\xf3s\xfb\xd3\n\xc0\xab\x01;0\xe8Pp\xab\xf4c\x8a\x84\x7f&d\xe1\xf6\x80\x0e)\xb46\xac8\xa2\xce\xf9\xf7\x14R\xec\xe0e\xa3\x9e\x1fkW\xdcoK\xaa7%\xd5}MUv\x9de\xf9\xedZ\xc4\xefv\x8c\x8a.\x91rˀJ\x00[\xbfON\xd1b\xc8\n\x80u\x88\xd8\xc1\xfb\f+*\x8df\x050^\xbb\xc0l@\x19S\x88TnC\xd6\v\xd2mpi\x98\bl\xc0 k\xb2Q\nQ\x1fz,W\x84\xb0\x03\xe9\x11j9\x90\x00[\x1c\x11\x98r\x0e\xe0\x13\a\xbfQ\xd2w\xd0f\xbe\xda\x1a\x9a\x81\x8c\x01\x95\xea7\xf3ey\u0380Y\xc8\xfa\xfd5\b,J\x12O J]\x1b<\xd0\t\xbf\xe7\x00J|\x1b{\xc5\xe7\xd5\x1f\xcaƵ\xca5\xe6pS\x99\xd6=\x0e\xaa\x1bcCD\xff\xeb\xe6\xee\xe3\x8f\x0fg\xcbp\x8euAZ\xb0\fjB\x9a\x89\xab\xacA\xf0\b\x81`\b4\xb1\xca\xed1i\xa4\x10\x91\xc4N\xadU\xbf\x93\xe19Y\x9dA\xf8\xb79\xdb\x03Ȩ\xeb)0y\x8a\x90\v\x89cS\xa0\x19/Zɵ\f\x84\x91\x90\xd1\u05f9\xca\xcb\xcaC\xd8~B-\xed,\xf5\x03RN\x03܇\xe4L\x1e\xbe\x03\x92\x00\xa1\x0e{o\xff>\xe6\xe6|\xef\\\xd4))\x94\xe4\xb6\xf3\xca\xc1A\xb9\x84߃\xf2f\x96yP\xcf@\x98kB\xf2'\xf9\xca\x01\x9e\xe3\xf8#\x93h\xfd.tЋD\xee\xd6뽕\xc9Rt\x18\x86\xe4\xad<\xaf\x8b;\xd8m\x92@\xbc6x@\xb7f\xbbo\x14\xe9\xde\njI\x84k\x15mS.⋭\xb4\x83\xf9\x8eF\x13Ⳳ\x17\xddS\xbf\xe2\x02_!O\xf6\x84\xda#5U\xbd\xe2\x8b\ny)Sw\xff\xee\xe1\x03LH\xaaRU\x94\x97\xd0\v^&}2\x9b\xd6\xef\x90\xea\xb9\x1d\x85\xa1\xe4Dob\xb0^\xca\x0f\xed,z\x01N\xdb\xc1\nO\x1d\x9b\xa5\x9b\xa7\xbd-\xb6\x9b\x1d E\xa3\x04\xcd<\xe0\xceí\x1a\xd0\xdd*\xc6o\xacUV\x85\x9b,\xc2\x17\xa9u\xfa\x98̃+\xbd'\x1b\xd33pEڅ\xe1\x7f\x88\xa8\xb3\xb8\x99\xdf|\xda\ueb2ec\xb5\v\x04O\xbd\xd5\xfd4\xfc3\x9a\x8eFq\xce߲1\xe4\xef\xc5n\xe7;W/\x0fEdK8k\xd8\x06.\xbc\xfbu^\x8a\xa9~%3\xd5\xd1Gnt\"*\xcdw\xf4y\xb5t\xe8K\xb9@\xa2@\x17\xab3P\xefJP\xf9Ǡ\xacgP\xfey<\b\xd2+\x81'\xa4\r\x97\x95\x1ax\x8fO\v\xabw~CaO\xc8\xf3\x96ϛ\x9b\xca\x1e\xce߃WXZlʋE\xceVhNXd\t\xa4\xf6\xa7\xbcr\xda\x1e\x9d\xbe\x83\x7f\xfe[\xfd\x1f\x00\x00\xff\xff\xbeM\x1a\xea\xb1\n\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xbcWMo\xe36\x10\xbd\xfbW\f\xd0K\v\xac\xe4\x06E\x8b·\xd6\xd9C\xb0\xe96\x88\xb7\xb9S\xd4HbC\x91,9t6E\x7f|1\xa4\xe4\x0fYv\x9c\xcb\xea\xe6\xe1p\xf8\xe6\xcd\xcc#]\x14\xc5B8\xf5\x84>(kV \x9c¯\x84\x86\x7f\x85\xf2\xf9\xd7P*\xbb\xdc\xde,\x9e\x95\xa9W\xb0\x8e\x81l\xff\x88\xc1F/\xf1\x16\x1be\x14)k\x16=\x92\xa8\x05\x89\xd5\x02@\x18cI\xb09\xf0O\x00i\ry\xab5\xfa\xa2ES>\xc7\n\xab\xa8t\x8d>\x05\x1f\x8f\xde\xfeX\xde\xfcR\xfe\xbc\x000\xa2\xc7\x15\xd4\xf6\xc5h+j\x8f\xffD\f\x14\xca-j\xf4\xb6Tv\x11\x1cJ\x8e\xddz\x1b\xdd\n\xf6\vy\xefpn\xc6|;\x84y\xccaҊV\x81>ͭޫ\xc1\xc3\xe9\xe8\x85>\x05\x91\x16\x832m\xd4\u009f,/\x00\x82\xb4\x0eW\xf0\x99a8!\xb1^\x00\f)&XŐ\xdd\xf6&\x87\x92\x1d\xf6\"\xe3\x05\xb0\x0e\xcdo\x0fwO?m\x8e\xcc\x005\x06镣D\xd4\x7f\xc5\xce\x0e\xd3\x04@\x05\x100\xc0\x01\xb2;\x84 \f\bO\xaa\x11\x92\xa0\xf1\xb6\x87J\xc8\xe7\xe8\xc0V\x7f\xa3$\bd\xbdh\xf1\x03\x84(;\x10\x1c%;\x1c\x9c\xa5m\v\x8d\xd2X\xeel\xce[\x87\x9e\xd4Hy\xfe\x0e\x1a\xea\xc0z)\v\xfe8\xf1\xbc\vj\xee,\f@\x1d\x8e\xe4a=p\x05\xb6\x01\xeaT\x00\x8f\xcec@\x93{\x8d\xcd\xc2\fٔ\x93\xd0\x1b\xf4\x1c\x06Bg\xa3\xae\xb9!\xb7\xe8\t\x1aE\xaf\xcb41\xaa\x8ad}XָE\xbd\f\xaa-\x84\x97\x9d\"\x94\x14=.\x85SEJĤQ+\xfb\xfa;?\ff8:\x96^\xb9!\x03yeڃ\x854\x1d\xef(\x0f\xcfK\xee\xae\x1c*\xa7\xb8\xaf\x02\x9b\x98\xbaǏ\x9b/0\"ɕ\x1aZl\xe7z\xc2\xcbX\x1ffS\x99\x06}ޗڔc\xa2\xa9\x9dU\x86\xd2\x0f\xa9\x15\x1a\x82\x10\xab^Q\x18{\x9dK7\r\xbbNR\x04\x15Bt\xb5 \xac\xa7\x0ew\x06֢G\xbd\x16\x01\xbfq\xad\xb8*\xa1\xe0\"\\U\xadC\x81\x9d:gz\x0f\x16Fy&j^\x01\x128\xe1[\xa4\xa9u\x82\xe5Kr\xe2\xe3_:q,X\xdfcٖ\xac9a\x00\x92\xf5\xe8\x87i\xa1.a\x80\xd9F\x9fE2\xf67\xd3\xc0\xbc\xb2\xa0\xb0\xd8\x1db:=\x9a?4\xb1\x9f?\xa0\x80\xdf\x13\xe6{\xdb^\\_[C<\x17\x17\x9d\x9e\xac\x8e=n\x8cp\xa1\xb3o\xf8\xde\x11\xf6\x7f:\xf4\xf9\x1a\xbe\xe8:\xde滫\xef\x82c\xd4g\xcf}D\xbeA\xf0|\xa6\x83\xc3UQ\xae\xc04x^\x95\xe8zs\xf7\x1e\nϸ\xbf\xa3Hw\xa6\xb1o\xa4\xb8w\x9c\xf5;#\x03\xe3\x97\xde\x10o\xf74\xbfBƞ\xe6-\xf9\xeeD\xf8\x14+\xf4\x06\t\xc3^\xa9_\x14u\xb3\x11\x01^:%\xbb\xb41\r\x04_\x02!X\xa9\xe6$\xf5\n\xf8\xac#\xca\xe3\xccP\x16iXg\xcc\f\xfe\xc4|F\xfd\xce\x1dP\f\x8at\x95\x82\x92\xa0\x18ޡ\xa1\xc9\x7f\xa4ZF\xef\xd3\x15\x95\xad\xfc2\x99n\xb8VDG\xe5\xf9\xeb\xf1\xfe\r%\xbd\xdd{\xa6\x17\xb7P&\xa3q\x1e\x8b\xa0Z~A\xf1\x1akiҸS2\xf2w\xfc\xc2;&j\xb6\xa2\xf8թ<\x80o@\xfc\xb8ŝ\x8f&\xdf\xf3\xd37l\n\x88\x81\x9f[ \x85\x99\xc1X!Ԩ\x91\xb0\x86\xea5\xdf\\\xaf\x81\xb0?\xc5\xddX\xdf\vZ\x01\xdf\xff\x05\xa9\x9962QkQi\\\x01\xf9x\xae\xcbf\x13w\x9d\b3cx\x94\xf3\x03\xfb\xcc5\xc6n\x18/v\x06\x9c\xbd_\n\xf8\x8c/3\xd6\ao%\x86\x80\xa7ct6\x93\xd9!81\x06~\xa4\xd5\a,\r\x7f\x19\x06\xcb\xff\x01\x00\x00\xff\xffx\xae@\xbaJ\x0e\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xc4ZK\x93\x1b\xb7\x11\xbe\xef\xaf\xe8Z\x1flWi\xc8HI\\)ޤU\x9c\xda\xc4V\xb6ĕ..\x1f\xc0A\x93\x03\xef\f\x80\x00\x18R\x8c\xe3\xff\x9ej<\x86\xf3\x00\xc9]\xca\xf2\xe2\xb2K<\x1a\x8d\xaf\x1b\xfd\xc2\x14EqŴ\xf8\x88\xc6\n%\x17\xc0\xb4\xc0O\x0e%\xfd\xb2\xb3\x87\xbfٙP\xf3\xed˫\a!\xf9\x02nZ\xebT\xf3\x1e\xadjM\x89oq-\xa4pBɫ\x06\x1d\xe3̱\xc5\x15\x00\x93R9Fݖ~\x02\x94J:\xa3\xea\x1aM\xb1A9{hW\xb8jE\xcd\xd1x\xe2i\xeb\xed\x9ff/\xbf\x9b\xfd\xf5\n@\xb2\x06\x17\xa0\x15ߪ\xbamp\xc5ʇV\xdb\xd9\x16k4j&ԕ\xd5X\x12\xed\x8dQ\xad^\xc0a \xac\x8d\xfb\x06\x9e\xef\x14\xff\xe8ɼ\xf1d\xfcH-\xac\xfbWn\xf4\aa\x9d\x9f\xa1\xebְzʄ\x1f\xb4Bnښ\x99\xc9\xf0\x15\x80-\x95\xc6\x05\xbc#64+\x91_\x01\xc4#z\xb6\n`\x9c{\xd0X}g\x84thn\x88B\x02\xab\x00\x8e\xb64B;\x0fʈ?\xb0\x8e\xb9ւm\xcb\n\x98\x85w\xb8\x9b\xdf\xca;\xa36\x06m`\x0e\xe0\x17\xab\xe4\x1ds\xd5\x02fa\xfaLW\xccb\x1c\r\xe0.\xfd@\xecr{b\xd9:#\xe4&\xc7Ľh\x10xk\xbcP\xe9\xf4%\x82\xab\x84\x9dp\xb7c\x9684\xce\x1f;ϋ\x1f'\x8aֱF\x8f\x99\xea-\r\\q\xe60\xc7Ӎjt\x8d\x0e9\xac\xf6\x0e\xd3I\xd6\xca4\xcc-@H\xf7\xdd_\x8e\xc3\x11\xf1\x9a\xf9\xa5o\x95\x1cb\xf3\x86z\xa1\xd7\x1d8!Ym\xd0d\x01R\x8e՟È#\x02oz\xeb\x03'\x81n\xbf\xff,+\xa4x\xa0\xd6\xe0*\x84(\x95\xa5S\x86m\x10~Pe\x90\xe0\xaeB\x13%\xb8\x8ajU\xa9\xb6\xe6\xb0J'\x06\xb0N\x99\xac\x145\x96\xb3\xb0*\xd2MdG\xa2\x1c\xee\xf9%4\xad4Ȳ\x9a\x96\xac\xd1\xcc\xcf\x10J\xe6\xd5\xed\xf5\x06\x1f\xa5j}H\xa5\xe2\xd8\xe1\x87\x13\xb6\x84\x05mT\x89֞\xb8\x01Dc\xc0ȻC\xc7Y\x80*\xf4s\x12?\xad\xae\x15\xe3h\xc0)\xa8\x98\xe45\xd21\x188ä]G\x15\x99\n0-\xbb\xdf\xeb!+\x1f\xe2\xc01v¬\xed\xcb`\a\xcb\n\x1b\xb6\x88s\x95F\xf9\xfa\xee\xf6㟗\x83n D4\x1a'\x92]\x0e\xad\xe7uz\xbd0<\xee\xff\x8a\xc1\x18\x00m\x10V\x01'\xf7\x83\xd6\xc3\x10-,\xf2\xc8S\x80GX0\xa8\rZ\x94\xc1!Q7\x93\xa0V\xbf`\xe9f#\xd2K4D&݅R\xc9-\x1a\a\x06K\xb5\x91\xe2\xbf\x1dmKXӦ5sh\x9d\xbf\x8cF\xb2\x1a\xb6\xacn\xf1\x050\xc9G\x94\x1b\xb6\a\x83\xb4'\xb4\xb2G\xcf/\xb0c>~T\x06AȵZ@圶\x8b\xf9|#\\\xf2ťj\x9aV\n\xb7\x9f{\xb7*V\xadS\xc6\xce9n\xb1\x9e[\xb1)\x98)+\xe1\xb0t\xad\xc19Ӣ\xf0\a\x91\xde\x1f\xcf\x1a\xfe\x95\x89\xde\xdb\x0e\xb6\x9d\b:4\xefB\x9f \x1er\xaat\tX$\x15\x8ex\x90\x02u\x11t\xef\xff\xbe\xbc\x87\xc4I\x90T\x10\xcaa\xea\x04\x97$\x1fBS\xc85\xe9<\xad[\x1b\xd5x\x9a(\xb9VB:\xff\xa3\xac\x05J\a\xb6]5\u0091\x1a\xfc\xa7E\xebHtc\xb27>^\x81\x15\xdd%\xb2\x00|<\xe1V\xc2\rk\xb0\xbea\x16\xff`Y\x91TlABx\x94\xb4\xfaQ\xd8xr\x80\xb77\x90b\xa8#\xa2\x1dY\xb6\xa5ƒ\x04K\xd8\xd2J\xb1\x16љ\xac\x95\x016\x9e>\xc4)o\x00\xa8e\x1d\xc9x\xd29\xa5\xa3\xf6&G(1,{\x06<9\xbc\xe8\x9f\xea\xa1\x7f귃\x95\x8fk\fje\x85SfO\x84\x83\x83\x1c+\xc4Q\xd9P+\x99,\xb1\xbe\xe4x7~%\b\xc9\tv\xec\x14\x9aLQ\xa0\xea\x19Ur\xa3芍\xa5\x01\xb7\x8e\xa6\x91\x92[t\xf9\xb3\xcac\x0eMH8\x84\x98\xd0\x0f%LJ^)U#\x1bcI\xee\xee̙\xc9\x01\xe6\x84彭\xab\x98K\xbc\xd1$\xd3J9Ŗ\x9a\x92O\x12\x87V\xfc\f_qG\x06\x06\xd7h\xd0G#\xc1\xf6k\xe5=\x84cB&\x9b\x16\x12\x01p*\xc3\xd9*(\x11r\x18\xdf\r8y?\xe0\x84\xa3\xccr\xfc\xfa\xee69\xc3\x04b\xe4}\xe2\xef\xce\xe2Cm-\xb0\xe6>r8\xbfwVs\xa9ݮ\x03\x13\xde#8\x05\f\xb4\xc0\x12\a\xde\x18\x84\xb4\x0e\x19\x8f\x9dd\x04\rƱ\x17\xc1\xd2\x1fe\x92\xda\xc1k\x93L\x80\x91\xe7\x11\x1c\xfe\xb9\xfc\xf7\xbb\xf9?T8\a\xb0\x92B3\x9fDa\x83ҽ\xe8\x12)\x8eV\x18\xe4\x94\x16\xe1\xacaR\xacѺY\xa4\x86\xc6\xfe\xf4\xea\xe7<~\x00\xdf+\x03\xf8\x89Q:\xf2\x02D\xc0\xbcsfIm\x84\r\a\xef(\xc2N\xb8\xca3\xaa\x15\x8f\a\xdc\xf9#8\xf6@79\x1c\xa1E\xa8\xc5C\xe6\xfe\x84v\xed\xa3\xb9\x03\x9b\xbf\xd2\xed\xf9\xed\x1a\xbe\t\xc6\xeb\x9a~^\a6\xba\xb0\xa5\x7f\xc1\x0e\xec\x84[f\xc4f\x83\x87\xb8\x7f\xa2,\xe4f\xc9A}\v\xca\xd0Y\xa5\xea\x91\xf0\x84IN\xc1? \x9f\xb0\xf7ӫ\x9f\xaf\xe1\x9b!\x06G\xb6\x12\x92\xe3'xE\xd6\xc7c\xa3\x15\xffv\x06\xf7^\x0f\xf6ұO\xb4SY)\x8b\x12\x94\xac\xf7!\x00\xde\"X\xd5 찮\x8b\x10 rر=\xa8\xf5\x91}\x92\x88H5\x19hf\xdc\xc9 1\xe2p\xfa\xd2L\xa3\xa6\xd4\x1ew_|\x14\xf5\xa8\xdb\xfbl\x11\xc8#\x91\xf0\xe9\xc2g \xd1O\xbd.@\xe2\xa1]\xa1\x91\xe8Ѓ\xc1Ui\t\x87\x12\xb5\xb3s\xb5E\xb3\x15\xb8\x9b\xef\x94y\x10rS\x902\x16A\xeav\xee\xcbH\xf3\xaf\xfc\x9fK\x0f\xee\xeb?\x9f{zO\xe4\xf9 \xa0\xdd\xed\xfc\x12\x04Rt\xffx\xdfu\x14\x87e\f8\xc74\xe9\xce\xef*QV)\xd7\xebYۆ\xf1`\x8e\x99\xdc?\xd3\xdd!\x9c[C\x1c\xed\x8bX\x03-\x98\xe4\xf4\xbf\x15\xd6Q\xff%\xc0\xb6Ⳍˇ۷\xcfy\xa3Zq\x89%9\x92Ä\xf6\xa98pU4L\x17a6s\xaa\x11\xe5h6\xc5\U00037704\xb4\x16h΄\x7f\xef\a\x93S\x80\x9a\xc9\x06\xba9O\x8a?\x1d\xdbd\x02\xbe~y\xf8TXx\x12\xaf\xf3\xaap\xcf6\x16\x98A`\xd00M\x1a\xf1\x80\xfb\"D\x1c\x9a\t\n\x17(\"\xe8\n\x83\xc0\xb4\xaeɧ\x87(\"C1ƿ\x11\x1ef\xfd\xf9\x8e\x01\x92\x15e\xaaJ-\xd19!\x9f\x11\x9c\x0f#F~_\xa0\xba\x9a]\xa9\xe4Zlb\xb5s\x8a\x94l뚭j\\\x803\xed\xb1\x9c\xeb$\x90\xf74\xe5\xf4\xf9?\xf4\xa6&\r?S`̟jPv\x9c\x1e\x06e\xdbLY)\xe0Ai\xc12\xfd\x06\xad\x9b\xdc^\x1a\xb8\xbe~\xca\x1d\vJyI\xca\x1d\xd2\xe0\\V\x1a\x15=\x06\xf0)3u\xea\x90\xe5e\x85\xfe\x04\xdb@\xd9=\xa5#C\xbe\x8b|\xb9d4\xa7W]N]Z\xf1Q\xcf\xd0\f\x8e\x06\xc3\xf9\x1eUC\xf2\x05\xed'T\x91\xc2\xebU\xc448G\x97\u07b4(쾴\x8eD\x89\x9dvȻB\xff%\x12\x7f=&\xe2k\xbf\x86\xc7K!\x1a\xecR\xff\xa1\xad\v\xc9\xdd\nA\x1b\xd4,[\x15\x02_\xb9\xb7\xbe\x84\xf9\xb5\rĄ\x85\xd6\"\xf7\x15\xb4\xc9\xde\x13\n\xe9E\x893\x87\x05\xad\xbf\xcc^\xe4\vS\xe11\xad\xffRrQ\x95jJf\n!K\xa8\xf9'\x9c\xf4\x8a\x97C\xec@\xae\xc3+PC\xee\xb3PJ\x92\xd7L\xd4\xc8!=\x11?\x91\xca\n\xd7\x14\xe2\x04\x1b\x97\xea8\x91\xbd\xe3\xf9\xdfiIf@\x98\x06<_R\x98\rZ\xcb6\xe7lޏaV(o\xc5%\xc0V\xaauy%\xff\xda\xc6{\xfa\xb4\x12[\xb6r44\x11\xccU\xc9\"\xacۺ\xf6k\xfa\xc6\xf5\xf0\xf9\x80\xe7j\x85\xf9\xb0\xf8D}\xed\x14\x83\x15\xb3砺\xa399\xa3\xd5y\x84\x93V\vNx\xbfw\xb8\xcb\xf4&c\x90\x19\xba\x8b\x16&34\xf9\x0e\xa0?\x18\n\xc89\xe4\xd2X\x96f\xf7ʞ\x19\xfb\xde_\xbd'\x81\x1d\xf9\xbbĶt\x05\xe8J\xd5ɜ\xf8\xd7q\xd96+4$\t\xff\xfe>r\xd2L\xf2\xbe\xd8r\x99\xfaa}Ҡ@)V\x9bb\xdd\xdc\xdfo\xa7\x80\v\xabk\xb6\xef\xce\xe2\xf3#\xba\xcc\xf9G\x84ÍJfE\xe3\xb1x\xeft\x19\xb8\xfbV!\x9f\xfc\xe5>8\x18\xb6\xe9\xa7\x03\xa3\xf1\xee\x1b\x84/\xb3Éx\xd5J\xa6m\xa5\xdc\xed\xdb3\xaa\xb1\xec&\xa6\xfbxȽ\xbc\xf5\xf5\xefSqRT\x85\f\xab\a\xeb\xf6$c1\xfct\xe5\x12-^\x0e(\x9cq\x8e\xf1K\x9a\x9c\vZ\x92\x15 \x03\xe4_?oƟ9\xbc\xe8>\x9d`.V\x91ˊ\xc9M\xb6\x96\xa5\xa4\x0f\xb6\x95\x99>E\xc3Yo7<\xd0\x1f\xe9\xe8\xb2\xea4\xe9\xf4\x9c\xf3\x1e\xed\xf8\xf0\xd7\xefiWݛ\xf8\x02~\xfd\xed\xea\xff\x01\x00\x00\xff\xff\xd9H\xdbA\x14'\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xc4Z_\x93۶\x11\x7fקع<$\x991\xa5\xc6m3\x1d\xbd\xd9\xe7\xa6smr\xbd\xb1l\xbfd\xf2\xb0\"V\x12\"\x12@\x01P\xb2\x9a\xe6\xbbw\x16 )\xfe\x81\xa4\x93<\x8e\xf9b\v\x00\x97?\xfc\xf6/\x16\x97e\xd9\x04\x8d\xfc@\xd6I\xad\xe6\x80F\xd2GO\x8a\x7f\xb9\xe9\xf6on*\xf5l\xf7\xddd+\x95\x98\xc3}\xe5\xbc.ߒӕ\xcd\xe9\r\xad\xa4\x92^j5)ɣ@\x8f\xf3\t\x00*\xa5=\xf2\xb0\xe3\x9f\x00\xb9V\xde\xea\xa2 \x9b\xadIM\xb7Ւ\x96\x95,\x04\xd9 \xbc\xf9\xf4\xeeO\xd3゚\xfeu\x02\xa0\xb0\xa49\x18-v\xba\xa8J\xb2伶\xe4\xa6;*\xc8\xea\xa9\xd4\x13g(g\xe1k\xab+3\x87\xe3D|\xb9\xfep\x04\xfd\xa4Ň \xe7m\x94\x13\xa6\n\xe9\xfc\xbf\x92\xd3?J\xe7\xc3\x12ST\x16\x8b\x04\x8e0\xeb\xa4ZW\x05\xda\xf1\xfc\x04\xc0\xe5\xda\xd0\x1c\x1e\x19\x8a\xc1\x9c\xc4\x04\xa0\xdeg\x80\x96\x01\n\x11\x98\xc3\xe2\xc9J\xe5\xc9\u07b3\x88\x86\xb1\f\x04\xb9\xdcJ\xe3\x033C\x88\xe0<\xfaʁ\xab\xf2\r\xa0\x83G\xda\xcf\x1eԓ\xd5kK.\xc2\x03\xf8\xd5i\xf5\x84~3\x87i\\>5\x1btT\xcfF\x8a\x17a\xa2\x1e\xf2\a\xc6켕j\x9dB\xf1N\x96\x04\xa2\xb2A\xb5\xbc\xff\x9c\xc0o\xa4\x1b\xc3ۣc\x88և\x8d\xa7\xc1\x84y\x16\xe9<\x96f\x88\xaa\xf3j\x84%\xd0S\nԽ.MA\x9e\x04,\x0f\x9e\x9a\xad\xac\xb4-\xd1\xcfA*\xff\xfd_N\xf3Q\x136\r\xaf\xbeѪO\xcek\x1e\x85\xcepD\xc2\xdaZ\x93M2\xa4=\x16\x9f\x02ij\x80ם\xf7#\x92(\xb7;~\x11\n\x9b\x1e\xe8\x15\xf8\r\xc1k̷\x95\x81\x85\xd7\x16\xd7\x04?\xea<\xaap\xbf!Ka\xc52\xae`\x0f\x06ɺ\xd36\xa9:C\xf94\xae\xad\x855\xb2\x06\xfa\xeb\x7f\xe8\xb3\xd8Wn\t\x93\xf6Մ\xa2iX!\xb5J\x1b٫5=\xcb\xc0\xbaD*-\xa8\xc3\xda\b\x97t`\xac\xceɹ3\x86\xcfBzH\x1e\x8f\x03\x17)\xdaPX\xd3\x00\xaaL\xa1Q\x90\x05\xafa\x83J\x14\x14u\xe8-*\xb7\xaa-c\xac\xc2\xe6\xb5w\aӇ\xf2\xbe\x91י\x19a\x8aKw\xdf\xc50\x98o\xa8\xc4y\xbdV\x1bR\xaf\x9e\x1e>\xfcy\xd1\x1b\x06\xa6Ő\xf5\xb2\x89\xcc\xf1\xe9$\x9e\xce(\xf4\xf7\xfc\xbf\xac7\a\xc0\x1f\x88o\x81\xe0\fD.pQ\xc7W\x125\xa6ȑt`\xc9Xr\xa4bN\xe2aT\xa0\x97\xbfR\xee\xa7\x03\xd1\v\xb2,\x06\xdcFW\x85\xe0ĵ#\xeb\xc1R\xae\xd7J\xfe\xb7\x95\xed\x98p\xfeh\x81\x9e\x9c\x0f\x8eh\x15\x16\xb0â\xa2\x17\x80J\f$\x97x\x00K\xfcM\xa8TG^x\xc1\rq\xfc\x14\xacI\xad\xf4\x1c6\xde\x1b7\x9f\xcd\xd6\xd27\xe98\xd7eY)\xe9\x0f\xb3\x90Y\xe5\xb2\xf2ں\x99\xa0\x1d\x153'\xd7\x19\xda|#=徲4C#\xb3\xb0\x11\x15R\xf2\xb4\x14_\xd9:\x81\xbb\xdegG\x8a\x8eOH\xa2W\xa8\x87\xb3*{\x02֢\xe2\x16\x8fZ\xe0!\xa6\xee\xed\xdf\x17\xef\xa0A\x125\x15\x95r\\:\xe2\xa5\xd1\x0f\xb3)Պ\r\x9f\xdf[Y]\x06\x99\xa4\x84\xd1R\xf9\xf0#/$)\x0f\xaeZ\x96ҳ\x19\xfc\xa7\"\xe7YuC\xb1\xf7\xa1d\x81%;\x14\xc7\x011\\\xf0\xa0\xe0\x1eK*\xee\xd1\xd1\x1f\xac+֊\xcbX\t\xcf\xd2V\xb7\x10\x1b.\x8e\xf4v&\x9a*\xea\x84j\x87\xf1ma(g\xcd2\xb9\xfc\xaa\\\xc9:\x93\xac\xb4\x05\x1c\xad\xef3\x95\x0e\x01\xfc$3\xcap\xd1%\xb3\xe3\xe7uJP\x83Xu\x02y\x9d\xef\\\x9d\xa8\x8a~\xa2\xea>\xa3\x1ci\xc9h'\xbd\xb6\x87c\xa6\x1c\x9a\xc4I\xed\xf0\x93\xa3ʩ\xb8e{\xf7\xe1M\x90J0\xefԚ4\a\xa3(5\x00\xd5j\xad\xd9\xc9F\xea\x80\a\xcf\xeb\xd8\xce\x1d\xf9\xf4f\xd5\xc9\xcc&\x15\x1ckL\xe8֒\xc3m/\xb5.\b\x87l\x1a-.l\xfaIׁ\xc3Ҋ,\x85\xfc\x1fì\xd1!\x18{\x94\xaa\t\x1f\xb1\xe4\x06\xaf\x13\xfbXr\xb89\xa5\x9a\xd3v\bgRR\x12𫧇&\xed4\x96UC\x1fe\x96.?I\xb3\xe0g%\xa9\x10!Q_\xfev\xd2B\xf8yXE\x10!\xf6z\r\bFRN\xbd\xbc\aR9O(\xeaA\x0e7\x96\xea\xb9\x171\xa6\x9e\x04\xc9\xcf1?\xb2J\x009\xc6K\x01\xff\\\xfc\xfbq\xf6\x0f\x1d\xf7\x01\x98s%\x14\xce*T\x92\xf2/\xda\xf3\x8a '-\t>}дD%W\xe4\xfc\xb4\x96F\xd6\xfd\xfc\xf2\x974\x7f\x00?h\v\xf4\x11\xb9\xe8\x7f\x012rަ\x8d\xc6j\xa4\x8b\x1bo%\xc2^\xfaM\x00j\xb4\xa87\xb8\x0f[\xf0\xb8e\x8f\x89[\xa8\b\n\xb9\xa54\xfb\x00w\xa1x:\xc2\xfc\x8dC\xca\xefw\xf0M\f\x12w\xfc\xf3.\xc2h\v\x84n\xd49\xc2\xf1\x1b\xf4\xe0\xad\\\xaf\xe9Xh\x8f\x8c\x85\x13\x1a\xa7\x82oA[ޫ\xd2\x1d\x11A0\xeb)\x06b\x12#x?\xbf\xfc\xe5\x0e\xbe\xe9sp\xe2SR\t\xfa\b/\xd9\xc7\x037F\x8bo\xa7\xf0.\xd8\xc1Ay\xfc\xc8_\xca7ڑ\x02\xad\x8aC\xac7w\x04N\x97\x04{*\x8a,\x96b\x02\xf6x\x00\xbd:\xf1\x9dFEl\x9a\b\x06\xad?[\x8e\xd5<\x9cw\x9aq}\xd2<\xcf\xf3\x97P\xaf<\xcb{\xbfX\xae\x7f&\x13\xa10\xff\x04&\xbaG\x9d\x1b\x98\xd8VK\xb2\x8a<\x052\x84\xce\x1d\xf3\x90\x93\xf1n\xa6wdw\x92\xf6\xb3\xbd\xb6[\xa9\xd6\x19\x1bc\x16\xb5\xeef\xa1e3\xfb*\xfcs\xeb\xc6C\x9f\xe5Sw\x1f\x84|9\n\xf8\xebnv\v\x03M\x1d\xfd\xfc\xdcu\x92\x87E]\xd9\re\xb2\xcf\xef72\xdf4\xa7\xaaN\xb4-Q\xc4p\x8c\xea\xf0\x85|\x87y\xae,#:du\xc31C%\xf8\xffN:\xcf\xe3\xb7\x10[\xc9O\n.\xef\x1f\xde|I\x8f\xaa\xe4-\x91\xe4\xc4i!>\x1f\xb3#\xaa\xacD\x93\xc5\xd5\xe8u)\xf3\xc1j\xae\x95\x1f\x04+i%\xc9^\xa8\xfe\xde\xf6\x167U{\xa2\xean\xd7\\Uv;\x85\xc6m\xb4\x7fxs\x01Ǣ]\xd8`8\xea\xb0.:\x1bY\xec\x12gk\xcdsx\x82o=\x9e\x8e\\}P\xfd\xd5\r2m\xe5Z*,\x8e\x110\x1c\xc5\x14\x96\x18~%t_\xa21R\xad\xaf\xc2\xda\xf4\x8b\x16\xe4\xf9\xf8\x9e(\x9c\xbb\xed\xecs\xe5\xf5Y\xbb\xbb\xecR\xef\a@\x00-\x01\xf2\x9eXC[:d\xb1\x8a3(\xb9\x04\xe3*\xab.U\x97\x04hL\xc1uR\xac\xccR\xbe\xdet\xbfr\xadVr]w\"\xc7L\xa9\xaa(pY\xd0\x1c\xbc\xadN\x1d\x82\x92\xee\xd3m\xbc]\xd0\xf8\xfb\xce\xd2F\xdd\x17Z\x7f\xe9]\xf5\x1a\x82\xe3͐\xaa\xca1\x94\f\xb6\xdaHL\x8c\xb3\xb1\x8f\x1c\x9d'\xee\xee\xae1\xa9\xe8I\x178\x88g\xd0\xd4\x01\xbevĺ\xac\xaf\x8f\xac\xd1\x1d\xd3\xd9\xf1Z\a\xe5\xa35\x9fQ\xfa\b\xb3t\xafb\xb0\xc6h1\x19\x92֍m\x83\xc9cd\x1aN\xf4\x9d~0\x1b)xV\x9b'4\x9e\xafi\xf4\xc4륚\xf7\x98V}s\xe9\xc4\x05\xfbͭ\x1e>\x13\x1aO\xa2\xed\xc9\xdf\xd2\ay5\x14\x12\x1a\xb4V\xd4N\"Kj\x9b\x06\xb5\x9d\xd8c\x1b#\x86lc\xc9`\xd2\" 4\xd9]h4~\xed\xa24\xe9\xa0r$Bl\x1d}|$\xa1\xb9\xf3\x11\xe8)\xe3\xf7o\v \xe9\xe6Q\xbc\xee\xea\xdej\xdc\xd4I\x1a\x8b\x19s\x88-mᾥ\xb9hKQv\x94\xd7\x12\x16ő\bGX>a\xafP\x16$\xa0\xbd̽\x9a\xf9\x04\xe8qq\xf39\xc9/\xc99\\_\nZ?\xc5U\xb1\x93U\xbf\x02\xb8ԕ?a\x95_\xbbڵ\xae\xca\xc9J\x8bKH\x1e\xb5\b0\xd4\xe9+\xac1\x9a\x84Z\xba\xd7ZWa\fM\xc2KM?^\x93\n5-\xe4\xf3\xb1\x06\xce\xe4\xb0G\xda'F\x1b\x0fNL=\xd5a!15\xba_\xefN\xc6\xcel\xaa\xa6i\xe6\x922\xdb\xcb\xeb\xc4\xdc\x0f\xc1]\xaeb\xbb\xc6wK@h\xfb\xba\x1b]41 \\:\xab\xaa\\\x92eU\x84k\xedF'm\x05\x8cJt5\x97:\x9c\xb7\x12\x9a4\x1cE\xd5\xfd\xa5\xba!\x1d\xbc\xdck\x10ҙ\x02\x0f\xedf\u0089\x88]:ݞ?\xfaU\x13\xab8\xf3\x9c\xa8\xdb\xcew~\xdb?\x02H\x9f\xf7R7\xf9\xfdg|'?\x98o/\xf7?\xcf\x17\xceԝ\xfd?\xb6\xb8\xc5@\x16=\t\x97\x92E\xfd\xc7\x1f\xd7\xc7\xf8\xfeg\xfe\xc8\xf0\x9edo4\x18\x90\x8b\x8e\xec\xfa\n\xa9;R-\xdb\xfb\xd59\xfc\xf6\xfb\xe4\xff\x01\x00\x00\xff\xff\xec\xe3\xc3\ac%\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xdc=[s\xdb8w\xef\xf9\x15\x98\xf4a\xdb\x19\xcbi\xa6\x97\xe9\xf8\xcd\xf5:\x8d\xfb}\xebx\xec4\xfb\f\x91G\">\x83\x00\x17\x00\xa5h\xdb\xfe\xf7\x0e\x0e.$%\x90\x84d˛-^2\xa6\x80\x03\xe0\xdc\xcf\xc1\x01\xb2X,\xdeц}\x03\xa5\x99\x14W\x846\f\xbe\x1b\x10\xf6/}\xf9\xfco\xfa\x92\xc9\x0f\x9b\x8f\uf799(\xaf\xc8M\xab\x8d\xac\x1fA\xcbV\x15\xf03\xac\x98`\x86I\xf1\xae\x06CKj\xe8\xd5;B\xa8\x10\xd2P\xfbY\xdb?\t)\xa40Jr\x0ej\xb1\x06q\xf9\xdc.a\xd92^\x82B\xe0a\xea\xcd?^~\xfc\xd7\xcb\x7fyG\x88\xa05\\\x11\x05\xdaH\x05\xfar\x03\x1c\x94\xbcd\xf2\x9dn\xa0\xb00\xd7J\xb6\xcd\x15\xe9~pc\xfc|n\xad\x8fn8~\xe1L\x9b\xbf\xf4\xbf\xfe\x95i\x83\xbf4\xbcU\x94w\x93\xe1G\xcdĺ\xe5T\xc5\xcf\xef\bхl\xe0\x8a\xdc\xdbi\x1aZ@\xf9\x8e\x10\xbft\x9cv\xe1W\xbd\xf9\xe8@\x14\x15\xd4ԭ\x87\x10ـ\xb8~\xb8\xfb\xf6OO\x83τ\x94\xa0\v\xc5\x1a\x83\b\xf8\x9fE\xfcN\xc2B\tӄ\x92o\xb8Q\xbb\x1aD<1\x155DA\xa3@\x830\x9a\x98\n\bm\x1a\xce\n\xc4;\x91\xab\x1e\xa40J\x93\x95\x92u\amI\x8b\xe7\xb6!F\x12J\fUk0\xe4/\xed\x12\x94\x00\x03\x9a\x14\xbc\xd5\x06\xd4e\x04\xd4(ـ2,`ٵ\x1e\xef\xf4\xbeNm\xcc6\x8b\v7\x8a\x94\x96\x89\xc0m\xc1\xe3\x13J\x8f>\"W\xc4TLw[\r\xdb#T\x10\xb9\xfc\x1b\x14\xe6r\x0f\xf4\x13(\v\x86\xe8J\xb6\xbc\xb4\xbc\xb7\x01e\x91Uȵ`\xbfG\xd8\xdan\xdcNʩ\x01m\b\x13\x06\x94\xa0\x9cl(o\xe1\x82PQ\xeeA\xae\xe9\x8e(\xb0s\x92V\xf4\xe0\xe1\x00\xbd\xbf\x8e_\x90xb%\xafHeL\xa3\xaf>|X3\x13$\xaa\x90u\xdd\nfv\x1fP8ز5R\xe9\x0f%l\x80\x7f\xd0l\xbd\xa0\xaa\xa8\x98\x81´\n>І-p#\x02\xa5\xea\xb2.\xff.\x12u0\xad\xd9Y\x1e\xd5F1\xb1\xee\xfd\x80\x02q\x04y\xac\xa88\xc6s\xa0\xdc\x16;*\xd8O\x16u\x8f\xb7O_\xfbLɴ'J\x8f7\xc7\xe8c\xb1\xc9\xc4\n\x94\x1b\x87\xacia\x82(\x1bɄ\xc1?\n\xce@\x18\xa2\xdbe͌e\x83\xdfZЖ\xdf\xe5>\xd8\x1b\xd4:d\t\xa4mJj\xa0\xdc\xefp'\xc8\r\xad\x81\xdfP\roL+K\x15\xbd\xb0DȢV_\x97\xeewv\xe8\xed\xfd\x104\xe2\bi\xbd\x16yj\xa0\x18H\x9a\x1d\xc6VA]\xac\xa4\x1a(\x19;d\x88\xa3\xb4\xf0\xdb洈U\x8b\xfb\xbf\xccq\x99m\xff\x1eG[~\xb3+k\x05\xfb\xad\x05T\xa6N\xfc\xe1P_\xa9\x9ej\x1f6\xcbF\xfb\xd4\x1dE\xb4m\xf0\xbd\xe0m\te\xd4\xeb\a\x1b\xcc\xd9\xc6\xed\x01\x144z\x94\t+D\xd6\xfaؽ\x88\xeeWT\xe0T\x01\x11\xd2$\xe01\xe1\xe0\x11&\x10\x03I\x9a`G\x03ubœ[&D\xb4\x9c\xd3%\x87+bT{\x88F7\x96*Ew#\xd8\n\x1e\xc0\x8b\x90\x15\x81xU\xc3Y\x81$\x8f\n\x05\xf1\xf5\xe7E\x15\xd3VQ\x86]>HΊ\xdd\f\xben\x93\x83\x82\xb4z\xd9\xf5;$K\xa8\xe8\x86I\x95\x12\x03\xa9\xb0kϞwjZZ-\xe9\x81\xec۸\xcc\r'\x91UI\xf9<\xc7\x10\x9fm\x9f\xce:\x90\x02\x1dʸ\x15Omo\xbb\x97@\xe0;\x14\xadI,\x93\x90\xb2E\xd3$\x15i\xa46\xe3t\x1fW]\xa4\xef\x1c\xa5~\x9c`\x9a\x83\x9d%Y\xdd5\xaf\x84\x03Q-\x0e\x06\nY\n\xb0ۨ-Q\xbb\xbeJ\xb6\xae\xef(RȒj(\x89\x14\xa33#\xbb\xb4\x1c\xb4\x9f\xabD\xce\xe8\xf4\xd0E\xb7\x7f\xf4x\b\xa7K\xe0D\x03\x87\xc2Hu\x88\xcc\x1c\x94\xba\x96\xa3XGP\x99ЦC\t\xe860\x01\x92XN\xdfV\xac\xa8\x9c\x87a\xd9\x13\xe1\x90R\x82\xb6\xda\x04]\xe6\xdd\xd8&\xc9\x1c\xf9\xfd$Sڣk3b\xb5\x0f/\xa5Q\xba\x96\xa1\x86\xbb\x96Dm\xa7{\x0ft\x8b\xffn\xe4\xe4\xb6\xff\x7f\"6\x18\x93\x13\x98vB\xfe\t\xba\x9f\xd9<=ʷ\x18ၾ$w+\x02ucv\x17\x84\x99\xf0uN\x12(\xe7\xbd9\xfeĴ9\x9e\xe93I\x93#\x13g\"L\x9c\xe2OH\x174\x19O\xdebd\xd3\xe4\xaf\xfdQ\x17\x84\xad\"\xd2\xcb\v\xb2b܀\xda\xc3\xfeI\xaa>P\xe65\x90\x91c\xf5\b\xe6\tLQ\xdd~\xb7.\x8e\xee\x92`\x99x\xd9\x1f\xec|\xe3\x10A\f\xcd\xf3\f\\\x82\xf12SPc\x1cN\xbe\"6\xbb/\xe8T_\xdf\xff|\x18+\xef\xb7\f\xce;\xd8Ȍйv\xbd\xb7\xa3\xfe\xfa|T\x10~A\x1f(\x06U.\xe7rA(y\x86\x9ds]\xa8 \x96>4tΘ^\x01&\x7f\x90Ϟa\x87`\xd2ٜÖ\xcb\r\xae=C\xc2\xf5O\xb5\x01\x0e\xed\x9a|X\xec\xf0d? \"0\x86\xcfe\x03\u05fc($r'閩KB\v\xb8?a\x9bY\xacҟ\xa3\x9f\xfaD\x0e\xf8I;ZZ\x89\xa9\x98\xcfij@\x99\xc9%\xa8k\xdf(ge\x9c\xc8\xc9ȝ\xb8 \xf7\xd2\xd8\x7f0@\xd3\xc8(?K\xd0\xf7\xd2\xe0\x97\xb3`\xd4-\xfc\x9c\xf8t3\xa0\xa0\t\xa7\xe5-\xc2\xfa9?g\xd3,\xb7E\xdc3M\ue10dW\x1cJ2\xa7\xc2\xf4\xae\x9b\xceMT\xb7\x1a\xd3uB\x8a\x05\xda\xcc\xe4L\x1e\xdfR\r\xd0\xfd\xe2I\xfd\x84_\xad\xb1p\xbf\xb8$3\xa7\x05\x94!\xb2\xc4\xec'5\xb0fE\xe6|5\xa85\x90ƪ\xf0<\x8e\xc8T\xac~7DZO\x9e\xf5\xee\xb7\xef\x8b\xe7\x98/XX\x93\xb3\xf0\x10\x8c\xac3p\xe0uw9\xbf\x9f\x85\x95ٌ^\x81\x13f\xbb\x8e$Gǻ\xe6 \xe5\x05\xe8@+\x8e.\xce,uiY\xe2\x11\x1a\xe5\x0fGX\x94#x\xe1X\xd5\xd0[\xbb3\xc15m\xacZ\xf8okiQ\x9a\xfe\x974\x94)}I\xae\xf1\xa4\x8c\xc3\xe07\x9f\x87\xeb\x81ɘ\xb2\xb1SY\xfe\xd9Pnm\xbfU\xe0\x82\x00w\x9e\x80\\\x1d\xf8E\x17d[I\xed\xcc\xf6\x8a\x01\xc7\xf3\x8a\xf7ϰ{\x7fa\xa7\x9f\x9d\xb2\xafd\xde߉\xf7·8P\x18\xd1ᐂ\xef\xc8{\xfc\xed\xfdK\\\xa9LN\xcd\xec6`њ6y\x1c*\x92\xc9\xfa\xae\r8\xa6\x9f\x9b\xef\x92\xf2\xdeɞ\xdam\x16\x8b6R\x9b\xcf\xe9\xbc\xe1\xc8z\x1e\u0088\xa1g\x9cȱ\xcdF\f>\x8f\x16\xf5\xbdu\"W\x06\x94\xcf%:\x1b\x10\xe2\x8f\x17Ff\xa9S\x99\xfebc2\x90\xc6\xfc\xaeE\xf0\f7\xb9\x83\x9b\x9c%\x1e\xe3\xb0Z\xbc\x1c\xe9\xed\xdf~\xef\xe53\xad\xe4ڿ\xfb\x1bym\x87\xba\x90uM\xf7O5\xb3\x96z\xe3F\x06\x9e\xf6\x80\x1c\xf5պEyε\xc8\x1d\x0f\xe1\xf9喙\x8a\tB\x83\xda\x00\xe5\x19\x8a\x92F\xa6rةVQM\x96\x00\"\xa6\xe8\x7f\x04W\xa2f\xe2\x0e' \x1f\xcf\xe0zDt\x9d\xd3ٽ\x894\x89\x94\x8f\x1f\x9c\xc9jdI\xb6\x15(\x180\xc6a\xde\x1d=U!M/eq\x84C\xda\xc8\xf2'MVLi\xd3_\x82&\xadΥ\xf5\x91\xe4\xb3\xeb\xfe\xcaj\x90\xad9'\x82o\xbbi\x06g\xcd5\xfd\xce\xea\xb6&\xb4\x96\xad3\xe6\x86\xd5\xf1TףwK\x99\x89\xc7V\x98\xbf1Ғ\xa0\xe1`\x80,a\x95>\xefM\xb5B\n\xcdJP\xa1J\xc1\x91\x8dI+\x98+\xcax\x9b:%J\xb5c#`q\xab\xd4I\x01\xf0\x177\xb2\x97w\xac\xe4v\x88\xa0̽\xe3A\x1a\x10\xb6\"\xcc\x10\x10\x85\xc58(\xa7\x92q\n\x8f\fD\r\xcb\xd5sy\n\xdc6\x10m\x9d\x87\x80\x05\n$\x13\x93)\xb7~\xf7O\x94\xf1s\x90\xcdr\xde'\xa9\x1e\x81\x96\xa7\xe4h~\xed\r' t\xab\xf0\xf0\xdf\xe9\x8e-\xe3yk\xb6\x94#\x9c\xb6\xa2\xa8\x00\x95\x90\x18\xea\x06\a\x9e\tm\x80\xe6\xf2\x82\xf5\x8aZ!\x98X\xe7\xd1.;\x11\xda5\x87\ua954\x1c\xe8\xf8)d\xd7,\xae\xdf@\x13\xfd\xdaM\xf3BM\xd4\x11\xc1\x1d\x9b#\x1d\xb2)j\x95\x16\xa1\xc6@\xdd8\x91\x93D\xb5\xa2o]Π\x88\x8e\t\xc3\xfd*^3\xbef\x82e\xd0v@\xd7;\xc1L\xdfy\xb4 \xce\xea<\xda\t\xa2;pJ\x86\xedn\x00\xc0\nh\x88Cp\xed\x91k\x8ep$\x97@hYB\xe9r\x97\xd6\x15\xf1a\x89+|\x1b)nH\xee\xeexO0\x8b\xb2\xa1\r\x82N\xccê\r,Z\xf1,\xe4V,0\x18\xd7G\xeb\x90\x13\xb3T/\x9dޜ\xac\x8c\xe6\xf5K\xbe\x9a\x9e\xd3BC~\xcd\xe7\xa9\xe0?\x9dA\xcbd\xf3\xcdQ\t\x8f).\x98\xd3k\xae\x00{\xe4\xc7\xd9UL\xcd?1\xd8\x1fJ߸b\xe9\x17\x95\xc5ݥA\xf5\x9c\xc2m\x05\xa6\x02\x15J\xb3\x17X\x92^N\x9e\x90v\xc1K\xac\x93\xb3L\x15\\dW\xfe\xb9W9\x87\xd1M\xcb\xf9\x85\xe5m\xda\xf2d8l$\x8a\xd8!geՏ\xa5=\x86\x9c\xea\x8bl<\xf6+-\x86\xf5\x85\xb1\n\"\x14\x18\xca0\xb3\xa7qj\xbfXX\xda;\xdf\x1f\x96S`\xfe/,\xff\x0f/=̨\x94\xc8Gcn\x95fDb\x02V\x82\xc1zh\xec\xea+|?_\xe8\xfbc\xe1\xd4@\xfd\xa5\xf1\x123\xea\xc2f\xa05\x01g\xaf\xde\x04\xadA\xab\x9d+\x10\xed\x80\xcf\x19\xda\xf1ׅ\xbb\x05\x11\xc0\xa4\xf8\xf5k\x05A|}\xf5>\xd3\xe4\x9fI%\xdbDU\xdf\x04\xcaf\xaa;\xe67<(\xf4\xf0\a\n`\xe8\xe6\xe3\xe5\xf0\x17#}\xd9\af\xd1\x12\x800(\xea2\xb3L\x94l\xc3ʖ\xf2 \xb5\xdd\x1d\x02\xc7@\x1d\x9f%\xa0IE\x04\xe3\x8e\x01\xc3\xf8\x01Ñ/\x8d;\x969Z\xc5M\xfb\xa2y\xd5!'ׄ\fk>F\xac\xe1\xb1\xc7\x17\xafR\x05\xfb\x87\xd4z\x1c_\xe1\x91\x13I\xccTs\x9cPÑY,\xf6\xe2\xf3\x96\x9c*\x8dcb\xee\xb3Ud\xbc~\x1dF\x16~\xe6k.\x8e\xc1\xce\xd9\xeb+ް\xaa\xe2mj)2+(^\xaf\x142/\xfa<\xa9\x14`>`\x19\xaf\x82\x98\xad}xQ@sҖfk\x1a\x8e\xa9d\x98\xa5N\x9e\x98\xbdY\xad\u009bU(\xbcm]\xc2$\x17M\xfexL\xe5A\x8c\x93~\xa1M\xc3\xc4\xfa\x90)rYg\x92m\xe6Y\xe6~o!\x03\x9e\xe9\x873]t8\x12\xfa\xba\xeb҉H2\xa4-\x990\xf2\x92\\\x8b\x9d\x87\x9b\x80\xd3\v\x1f\x854\a\x17\xd9첶\x8c\xf3\xfem-\x04;\r\xcaߙԴv\xab\x1a\xf3\xf6\x93t\x95j\xe0\x94\x9f\x148~ك\xd1ώ\xbe\xa5\xe7_\xb7ܰ\x86\x83\xf5\xe86\xacL\xde!3\x15\xec\"\x92\xff&\xf1\x86\xd4r\x87\x90\xbe]\xf4\x9eQ\xec\x9eq\x926\xbf\xc9\x13\xb6\x97Q\xcc~\\\x11{\x06\xcdrE\xf1\r\x8b\xd5߰H\xfd\xad\x8b\xd3g8k\xe6\xe7\xe3\x8a\xd0O>\x81\tG\xfd\xf7\xb2\x84\a\xa9\xcc\\p\xf2\xb0\xdf?q\x92\xda\v\xd8$/\x89\b]\x13\xbb\xc4\x10Ç\x17\xa7m*}\xe8\x19\xdc\xe9_di\xd76w\xc6\xf2\xb8\xd7\xfd\xe0\xae\xf2\n\x14\b\xf7\xcc\xc7\x7f>}\xb9\x8f\xf0S>\xaf\xf7\x8c\xf7\x9e\x97p\x1eL\xe9\x91\xe3\x8f\xe6|1\x93\xc3\x16\xfa\x00\xaf|.B\x1b\xf6\x1f\xf8\xaa\xdb\v\xd2A\xd7\x0fw\b#\xf8i\xf8L\\\xac\xa2\x88'\x96K\xb0\x16+\xa2jT,\xeeV\x03\x88Ê\xdf\xfe3JP\xba'\xb3\x82\xc5d\xa1\xc6\xcb\n\xdeÝ[\xc7\xd8,\x9f\xac\xd3(vD:\x8e\xac\x98*\x17\rUf\x87l\xa3/\x06k\bff*\x9d3\xaaX\x0f\x9f\x01K\xa27\xbc\xfe\x85g\x91\xbbfxڻ\x8f\xbbS\xd61~\xffd\xf6\xe6\xc9+\xaec\xdcb/\x10S\x89\xcf\xc9\x02\x93WK\x93yM\xf4\xf0\xed\xa4\xb4\xcbc\x1c=\xad\xe7l\x14\x1dRM\t0v<\xaa:-h\xa3\xabēK/\xd3u\xf8\x1a\x99\xa1\xa6}\xc9&\x1d\x80\xc1>YQ\xf5\xb4\xd5\x16\x82>\v\xdbFi\xc5a)\xddnm\xb3\xab{a\xfc\xa2\x97)x\x9b#\xe1\xcc\xe7\\N~\xc8šgD\xfd`\xf6˪\xb6CL\x9dp\x18<\xeb\xdae\x14\x19O;\xb1\x99π\xe4\x19\x8c\x13\x9e\xfe@|\xe5\xe2\x8a$_\x04\xc9|\xf5\xe3\x0fE\xf4\x84V\xd3E\x05e\xcb\xe1\xd47\xff\x9ez\xe3\xe7_\xfd\v\xb3e\xbc\xfbg\x91\xdd3\xd0\xd6g\x1e\xbe/\xe8)\xe1!\xf7)9\xe6\xf0ap\xe0\x9e\x17+\xdcK\x94E\x01Z\xafZ\x1e\xaa\x94\n\x05\xd4@\x19\xba3\x1dW|T\x9dM\xdbpIKP7R\xacX\xe2\x84d\x80\xd6\xff\x1at\xde\xe3\xd9\x02?\xb6\xaa{\xdaq\xf2Y\xbc\x17i\xae\x86*\xca9\xf0O\x8c\x83\xfeYn\x85]W\x86@>\xa4\xc6\xf5\xeee\x15\xad\xb2f}GD[/\xad\x93\vƌ\a\x8b+\xa9\xa6+\xa4\x1dޙ0\xb0\x86T|\xbdU\xcc\xc0SC\x95\x06\\Q\xc6\x0e~\xdd\x1b\xe2\xa2\xcf\x15\xa7kW\nW\xb2\x82\x1a\x88\x06\x18g\x18[>\x8e\xd7\b\x8b\xef\xb02I\x8e$\xbd\xb2\x85z\xecJƨX\x8f=/\x9a0\xd5\xc9\aF\x9dE.hc\xf0\x02\f\xd2\x11\x89h<\f|\xb4w\xef\x8d\xd1\x01\xd8qN\xf3e̾`N\x1bZ'\xa2\x84y\xbdss\b\x06\x9f\x05Ve\xaf\xee\xae\xff\xc0b,\xb0#[\xaac1u\xd2\xf7\xee`;0\xe8\xaa[\xd0P\x12\u0600 V\x14)\xe3PNq\xeaWL$\xab\r\xa8\x9ft\x84\x83\x95\x80\x96ş\fU&.\xfdЏYIUSsEJj`aG\x9f溥\x9fIU\xea\xc4\xe3@\xbc\xd9\xe6ţ\b\xd7n\xac\xf5s\xf7\xd1jК\xaeC\x10\xba\x05\x05d\r\xc2\xe2=\xe6\x16\x93\x1eS\xb8\xd2\xe7\x8dE,-\xb5(\xa4\x85i\xa9\x9f\xc0\xb9p\xf1\xf44\xbcO\x8cQ\xeczTE\xa7U\x85\xbf<\xf8\bT\xef?w}\x80\x8bO\xfd\xbe>I\xecv\xec\xceF\xa8+\xf0\xc4\a\x8f\r\x8b\x91uJ\xa6\x8dę\x8f2'\x95\x94\xcfYn\xf6\xe7رK'1\xe1X\t\xafL.ekz~\x8eGxb\x99\xf8\xfc\xe7+\xdb\x17\x84y\xed.P\x8d\xe5V\xf3<\xbd\xcf\x03H1\xbc\x95\x86\xf2`d,_\xc6\x0e\xd5\xc4\x03\x02O\xe1\xf1d\xcew\x17\xfb\x90\xf7^e\xef`W\xddS\x9e^\x13t\xd7\xc7\xc7Ҫ>\xeb\x97\x04\x12_\x01\xed|\x92\xb17\x17\xe7\xec\x1fB\xfd\x84\x8b\xca\xc0\xf1\xe7\xae\xf7\x18\x1e\xdd2\x9d\xc3\f\"\x1di\x12\f>L\x15%ㄥOx\xa9ME\xf5\x9c{\xfa`\xfbD\xb7\xa3g\xae\xa2\x13\xfa8\"\x95\xe9{\xae\vr\x0f\xdb\xc4W\x87,<\xfdB\xa9Jt\xb9\x13\x0fJ\xae\x15\xe8C\xa6[\xe0}F&֟\xa4z\xe0횉/\xe3\x95\xdfS\x9d\x1f\xa82\xcc2\xad[Ob\xecM\xb0q\x89\xdf\xe6G\x8f\xff\xc0\x04\xe5\xec\xf7\x94.\xef\xff87Ä\xbek<\xf2N\xb1P\x01\xf1s\n\xd0k\xe8\x9ft\xcf\xfc\x84y/ɽL\x8a\xb1? fC\xa0L\x93%h\xb3\x80\xd5J*\xe3\xf2\xf7\x8b\x05a\xab\xe0 Y\r\x81q\xa2{͞\xb0T\xe2=\x1e\xbd\x05\x87e\xe5S\x89\n\xad\x0e\x86\x9c5ݹ\x8c$-\n\x1b\x13\xc0\amh*6y\x91\x9e\xc6P\xd5\xcbJ\x8e\n\xb9\xeb\xf7\x8f9\xbe\xa8>\x10\x9cC\x1d^gw\x06\x9d\x8f\x9di\r^\xcb \xdab\xef\x14eB\x9c\x1a\xbb\x1b\x0f\xbb\xf3L\xcd\xd7\beL=\xfa\xfd\r\x1e\xe2\xf6\a\xac\xbe\x93%[QQ\xb1\x1e\xbd\xd0V)ٮ\xab\xc0\x9bc\x0e\x11)[\x8c\x9c\x1bT\x05:\xfc\xc7!\xa6U\xa2wh\xe7k,ƴt\\\uee0f\xf2\x02E\xad\xba\x8b-\x9d\xaa\x9a\xb0\xf9\xd9Y\xc2\x11\x88\xb3\xb6?\x01\x91\xea\x9d(&\xaf\xe0\xf8@\x9bM\xdc՝\xc2P\x12\tQ\x1b\xbf\x1a\x12\"\xc41$\xf4}\x89.\xe2\xf9a02棜\x88\x8ei'\x06\xb78\rj~\xd3}'h\xe8\xee\x1c\x87\x0e=\b\xfeNJ\xbb\r \x1c\x13\xf9\xe2\xdc\xe9\xb8\xf7ǍX7\xd1ۺ=9v\xfd\xb6\ac\xef\n\xa4\x8db\xbbiB\xbc\xf9\xf7l\x95\x92\x17\xf7\xbf3-9\xfc\xc3\xc1\xafo|\x95qK\x95`b}\x12F~\xf5c\x13\xf1\xbc\a{Έ>\xac\xfc\xd5b\xfa\xa4Y:\xf8\x88\f^\xf6\xf0\xecg\xf2_\xfe/\x00\x00\xff\xffP\a\xb5\x16Cm\x00\x00"), - []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xec=]s\x1c)\x92\xef\xfa\x15\x84\xeea?B\xdd^\xc7}ą\xde|\xb2gO\xb1\x1e[ai\xf4\xbctU\xb6\x9aQ\x15\xd4\x00\xd5r\xdf\xde\xfe\xf7\x8dL\xa0\xbe\xba\xe8\xa2Z-ygǼت\x86$\xc9L\xf2\x03\x12X,\x16g\xbc\x12\xf7\xa0\x8dP\xf2\x92\xf1J\xc0W\v\x12\xff2\xcb\xc7\xff6K\xa1\xdelߞ=\n\x99_\xb2\xab\xdaXU~\x01\xa3j\x9d\xc1{X\v)\xacP\xf2\xac\x04\xcbsn\xf9\xe5\x19c\\Je9~6\xf8'c\x99\x92V\xab\xa2\x00\xbdx\x00\xb9|\xacW\xb0\xaaE\x91\x83&\xe0\xa1\xebퟖo\xffk\xf9\x9fg\x8cI^\xc2%3\xd9\x06\xf2\xba\x00\xb3\xdcB\x01Z-\x85:3\x15d\b\xf4A\xab\xba\xbad\xed\x0f\xae\x91\xef\xd0!{\xeb\xdbӧB\x18\xfb\x97\xde\xe7\x8f\xc2X\xfa\xa9*j͋N\x7f\xf4\xd5\b\xf9P\x17\\\xb7\xdf\xcf\x183\x99\xaa\xe0\x92}®*\x9eA~Ƙǟ\xba^0\x9e\xe7D\x11^\xdch!-\xe8+U\xd4e\xa0Ă\xe5`2-*K#\xbe\xb5\xdcֆ\xa95\xb3\x1b\xe8\xf6\x83\xe5g\xa3\xe4\r\xb7\x9bK\xb64ToYm\xb8\t\xbf:\x129\x00\xfe\x93\xdd!n\xc6j!\x1f\xc6z{Ǯ\xb4\x92\f\xbeV\x1a\f\xa2\xccrb\xa0|`O\x1b\x90\xcc*\xa6kI\xa8\xfc\x0f\xcf\x1e\xebj\x04\x91\n\xb2\xe5\x00O\x8fI\xff\xe3\x14.w\x1b`\x057\x96YQ\x02\xe3\xbeC\xf6\xc4\r\xe1\xb0V\x9aٍ0\xd34A =l\x1d:\x1f\x87\x9f\x1dB9\xb7\xe0\xd1\xe9\x80\n»\xcc4\x90\xdcމ\x12\x8c\xe5e\x1f\xe6\xbb\aH\x00F$\xaaxmH8\xda\xd67\xddO\x0e\xc0J\xa9\x02\xb8\x80vX4\xb6\nu%\xa0\x80\xe6\f\xddN\x8d\x16FH\xb6\xae\xd1#]2\xd4\x12Q\x19\x11\xd2X\xe0\x11a>\x01\xef\xe0kV\xd49\xe4WEm,\xe8\xdbLU\x90\x87E\xa6Q͜\xca\xc3\x0f\a!\xfb\xf8\xa5\x10\x19 \x1f2WiA\x8b<1\xd1nC\x99]\x05n\xcd\tY\xed\x87\xd0\xc6(\x93\xbaŀņ\xe7\x7f<\xbf \t\xe8\xf7\xde\xef\xc70\xae\xa1!\xd3,\xddL\x16\x7f\xbc\x85\xb0PF\xa8;\xa9\xa3f\xf0\x9dk\xcdw\a\xb8\xde,\xa6\xbd\x00\xdfc\xb0\a\x9c\x97\xa1\xda7\xe2\xfd\xb0\xff\xdf\"\xf7O\xcboC\x8b\xce\\H\xe4s!\x8c\xed\xb1ٸU,$\xebX\b\xe9\t$\x1dLT\x93S\\\xfd'!\xe6I\xe7Nl\xb24\xb2\xe9'\xc0\xbf\x14%7J=\xa6P\xef\x7f\xb1^\xbb\x84\xc52\xda\x18a+\xd8\xf0\xadP\xda\f\x97I\xe1+d\xb5\x8dj\x16nY.\xd6k\xd0\b\x8b\x96\xf9\x9b]\x81C\xc4:\x1c\xbe\xb0\x8eʊV\x18\x8c\xabe:\xb2\x94\xa8\x11\x1b\n\x05\xa8Q\xa8\xce\xc1\xc1Ђ\x1c\x88\\lE^\xf3\x82|\t.37>\xde\xe0\x17\xd3j\x13\x02\xb1\x87\x7fT\xaa]q\x0eM\x18$2\xb1\xb7\xea\xa5$\xa0\x8f_bl\xb4_5N\x89\xb0\x94p\xb0od\xa6\xae\v0\xbe\xbb\x9c\xdc\xe4V']\xb4\xccrk\f\x05_A\xc1\f\x14\x90Y\xa5\xe3\x14J\x91\x03WR\x95n\x84\xb8#Z\xb6\x1fm\xb5\x83\x99\x00\xcb(\xc4݈l\xe3\xdcW\x144\x82\xc5r\x05\x86VExU\x15\x11\xd3ՖI\xe1\xf0\x9dM鍶$h\x90!ܘ.iK\xa2~n\xcb(\xd9۹٧\xfa\xf8:\xff(\xbe\xbf%\xa2\a\xabs\xa4\xb0Oh\x12F\xfb\x05\xc9\xf3!Jz\xa4\xb8\x00\xb3\xec\xac\xce\t\x1b\xbe\xa60\xb4\xe7?\xeem\xa5\xec\x11\xe5\xd7Ż\xe3&\xcc\f\xd6MΩ\x97e\\\xd3Ϳ\b\xdf\xc8d\xddz\x8b5\x8bg\x1f\xbb-/hW\xc03$\xbf`kQX \xa7j\nQ6\x83s\xa7$P\xaa\x05f\xb4Il\xb3͇f\xef(\xa1ŀVC\x00\xceA\x0fQ\x0e\xf1 \x01$k\\\v\xda4\x15\x1aJڌ\xa5H\xb2\xfb\x85\\\xc1w\x9f\xde\xc7c\xcfnI\x94ԽA%LZW\xde\r\x1c\xa3.\xae>T\t\xbf\x90\xbf\xd6\x04\x82n\x13\xfe\x82q\xf6\b;\xe7bqɐo)\x8b\xff|\xf8*\fv,s\xf6^\x81\xf9\xa4,}yQ*\xbbA\xbc\x06\x8d]O4A\xa5\xb3$H\xc4n\U00088ce5(\xa8\r?\x84a\xd7\x12C2G\xa2\x19\xddQ\xae\x90\xeb\xd2uVֆ\xb6Z\xa5\x92\v\xb7,6֛\xe7\x81\xd2=\x16\x9c\xa4c\xdf\xe9\x1d\x1a#\xf7\x8b\xcbZ*x\x06yآ\xa3t\x1an\xe1Ad3\xfa,A?\x00\xab\xd0,\xa4K\xcb\fE\xedG6_\xbc\xd2=\x87n\xf9\xbax\xacW\xa0%X0\v4k\v\x0fŪ2\x91.\xde&\x8c䜌\x95\x05\xce\xf5ĚAZ\x92\xaaG2r\x0eWO%\xd63\xc9D^\x04\xb9]IR\xd0Ml\x9dg\xbdf\xca\xcd1*\xa63\x16\xe7\x02\x94\x9c\xb6\xd6\xfe\x86\x96\x9ef\xe3\xdfYŅ6K\xf6\x8e2{\v\xe8\xfd\xe6\x17&;`\x12\xbb\xadh\x95\xfd\x97Zly\x81\xfe\a\x1a\bɠpވZ\xef\xf9j\x17\xeci\xa3\x8cs\x1b\x9aM\xbb\xf3Gع\x1d\xe5\xa4n\xbb\n\xeb\xfcZ\x9e;_fO\xf14\x8e\x8f\x92Ŏ\x9d\xd3o\xe7\xcfu\xeffH\xf4\x8c\xaa=Q.y\x95.ɔ7;'\xd0\xc0`=8DظI \xc5\x00a\x8a\x02ɢ\\)\x13I\x16\x89\xa0\x95 \xe87\xcaX\xb7\x0e\xd9\xf3\xf7G\x17*UX\x9cd|mA3c\x95\x0e)\x99\xa8\xf8S\x96\xe2\xbb\xe5n\x03\x06\xfc>\x94_\xf4t\x801\x8a=ou\x83\xb3*\xe7n/\x8c:\xe2\x19yOԶ\xd2*\x03\x13͋hK\xa2m\xeaQp\x9f\x0eͺ.w\xd1\xdf:Ik\xa7,J\x872ϑG\xd2\x1d\x11\x19}\xf8\xdaY\xa2F\xed\x82\x7f\xa7H\xeb182:\xafQ\x96|\x98\x0e\x9c\x8c\xee\x95k\x1d\xe6\x98\a\xe6\xc2-\xfdP\x93Ι\xe3u4\xa2\xfc\xcf\xe6ڔB^SG\xec\xed\v\xbaC^\x8b\xc7ң\xc6\xca\xf1N\xfaU\xe8\xac\xe5^\xf3\xc1\xe7\xd4)\xda\xf8\xd1\xd0c\xee\xfe\x9e\by\xd7R\xd9\xce2\xceL'\xbaR\xf9\xef\f[\vml\x17\rs \xb1j\x14\xd4\x11\xa1\xa7\xfc\xa0\xf5ё\xe7g\u05fa\xb3\xa0\xb8QO>qzN\xbc\x1dH\xba\xe1[\xf0\x99\xab 3UKZ\nC=\x80\xdd̀\xe8X\xe3\xac@\xa2\xbd\xeb4\x96u\x99N\x90\x05I\x92\x90\x93\xebf\xdd&?p\x91\xb6nŎc\xab=\x94\xc39V\x8e\x9fG!\xc1\xb3\x9bN_\U000af8acK\xc6K\xe4!\xb9\x1d\xa2\x84&\xa3ޱ\xbbI\xfb\xc4\x16d\xb4\xac\xc2YV\x15`\xc1\xa7m\xce\xc0#S҈\x1c\x1a\xd3\xefE@I\xc6ٚ\x8b\xa2\xd63\xb4\xeal\x92\xcf\r¼69}d\x95\x8eȂH\x94\xb8\xce>\xc3\v\x9e\xd6\xf8\x95\x9e\xe7Ǧ8\x8c\x1a\xe6\xfb\x8b\x95\x16\xca\x1d\x068\xbd\xcb\xe8ӎ\xb9\xdc}\xf7\x19\xbf\xfb\x8c\xdf}\xc69\x1d}\xf7\x19'\xcaw\x9f\xf1\xbb\xcfx\xb8|\xf7\x19S\xcaw\x9fq&\"\xdf\xcagL\xc1pAk\x9c\a*$a\x95\x98\n1\x85\xf6D_>\xe9ǟ\xd58I.\xf3\xf58ȑC<\x91\xe3\x171\xaf\xa35^Mr3\xce\xc00w\xdc)\xca\x04\x87\xf9\x04\xa7g\x02\x02\xa7?=s}\x10\xf2\tO\xcf\xf8!\xa4E\x18G\x9d\x9d\tD\x9a\x7fz\xe2\xc2'\x11\x95\xc0\xc3V\x8aK\xff\x88\x8d1&I\tx|\xe3\xe4\xf7\xbd\x8c\xc9\x17\x90\xa5W9\x913K\x9eFY\x7f\xfe\xc7\xf3_\a\x8bN˔(\x1b\xf6i\xeb\xd4xL?b,\xdfM\x8d\xecg\xa9\xfez\xa6\xc2Ie?\xf5DMC\xe4\b\xbc\xbeX\x0f\xa8\xfck\xd27\x16\xcaϕ\xb7\x96'8a\x7f=\x02/\xe9\x8c=7;\x99m\xb4\x92\xaa6~M\ba\xbd\xcbܽ\x03\x01dL\xd8G5\xc8\x7f\xb0\x8d\xaa#\xa76&H\x9b\x90E\x9bF\x90^R\xadO\x8c\x00˷o\x97\xfd_\xac\xf2)\xb6\xecI\xd8M\x04\x18\xddG\xc1\xf3\x1c\xe3\x82\u0381\x1e\xaf\a\xc2UIC\xa1\x8c\x00S\x9aIQ8\x89\r\x10z\xf2\xca>Wnu\xf0h\xbfiz\r+=\x11wn\xfam\x93-9\xed\xbe?#\xe9\xf6\xa4G\xa3\xbeYZ\xedqɴ\xa9+\x94\t\x89\xb3\xe9\xe9\xb2)lu%=I69BNM\x88\x9d\xbb\x02\xf1\xa2ɯ/\x93\xf2\x9aL\xb3\xb4\xf4ֹ\x14{\x95T\xd6WN`}\xbd\xb4\xd5\x19ɪ\xa7?\xf5\x92\xbe\x96~tveڲ\xcc\xe1\x84Ӥ4Ӥ\xa5\x9b\x94\x01\x1f5Ԥ\xf4ѹI\xa3I\x9cL\x9f\xae\xaf\x9a\x16\xfa\xaaɠ\xaf\x9f\x02:)m\x93\x15\xe6&y\x8e_r\x18ʴ\x03P|\v\xe1|.\x99\x94\xee\xb9\xe6ϊ;?\x0f`\xa1\xb0\x047\xf5\x15〲.\xac\xa8\x8a\xf6>\xb6X\xc0\xb9\x81]sY\xd1ϊ\x8e\xc8\xfb\x9b\xba>\x7fi$~9\x88j\xb8aOP\x14\x8c\xc7\xe6\xe6\x1e\x152w\x0fh\xa6\x16\x80\xb6\x11g\xb9\xbf\x8c\xc9_\x1ez\xe1\xa6\v\xdd\x06@\x16\xb6\x8c-\xf5qy\xf8\xa6\xaf\x83\x06,U\x8f\xedy\xe6.ޠo\xbfԠw\x8c\xee\x1dk|\xb3\xf6P\xa9\x9f\xe8\x06\x03Ӡ~\xbc:<\xb4g\xb2\x17\xe0\xb4ꁽ\x93\xce#\x18\xe2DmP\xef\xb4\x01\x1d*U\x8cӢ\xfdD@H\xd5@\x884Mq\xfe眲|\x89\xf0\xee\x14\x01^\x92\a4\xcf{\xfd\x86\xa7'\x8f=5\x99\x9e\x8c\x92tJ\xf2%½9\x01\xdf,\x7f5\xfd\x14\xe4\xfc\x8d\xe7\x17>\xf5\xf8R\xa7\x1dgP/\xf5t\xe3|ڽ\xd2i\xc6W?\xc5\xf8\x9a\xa7\x17g\x9dZLNϚ\x95q0'\xb5\xea\x19\xc7\xed\xd2r\t\xa6O!&\x9e>L\xcc4H\x1b\xfc\x91\xc3N<]8\xffTa\"\x7f\xe7L\xe9W>=\xf8ʧ\x06\xbf\xc5i\xc1\x04\tL\xa82\xffT\u0cf7\xa4\x94\xceAOn\xfb͑\xdaIyM\x8d\xe5\xfa\x88\r\xf6\xb5\xc2m\xb2X\xab\x17\x03\x90Y\xf2\x17\xf9ӣ\r\x87\xb6\xc1Q2;\x1eQo_\xb2u\xd7\xfa\x0e\xb1\x7f\xcd\xc1m]\x1a\xa88\x1a\x00\n\xdc(5+\xea*|\xe0\xd9f\xd0Æ\x1b\xb6V\xba䖝7\x9b\xc5o\\\a\xf8\xf7\xf9\x92\xb1\x1fT\x93\xabӽ/͈\xb2*v\x18\x89\xb1\xf3n\x83\xe7IIT:C\xcf7\xaa\x10Y\xc4\xe7\x1c\xbdW\xcf5ػl\x88n\xfe\xcb:\xd9\"\xb1\xc0\a\x9b\x8bp\xebb\xffJfw\x9f\xfb\x91k%\xbc\x12\x7f\xa6'\x95N\xb0\xea\xf6\xee\xe6\x9a`\x051\xa2\xb7\x9a\x9a\x04ņ\xe5+@\x97\xa1\x1d\xfb!}r\xbd\xeeA\xed\xe7\bw\x1f\xab\x80ܽL\x12\xdc\x16\xaf\x9a3\x85Z\xeb\xe6\xda\xe1r\xa8'\x94/.wL\xf9\xa7'\x84\xce\x17\x15\xd7v璉.zx\x04\xbb>\xb5jv\xd0Z\xed\xbf\xbc\xd2-=\xb2\x87GWh'{W\xf5\x93\a\x86\xf4|\x0eN\x87OUO\x9e\xa7~\x01\x9c\x0e\xbbP\v\xa2b\xe4\xa7h\x06\xe4\xc9W,\x8d\xbf\xa1\xffG\xb5\x85\xf7ѕ\xcb\xfe\xeb+\x83&#\xa9\x89\x01*]2\x1f\xa1`\x9b\x8fHw|?O\xed\xc5s\r\x03*\xfe\x8e\xf0\xe7,N\xde\xf6A\x8d?HB7\xa8\x87Nc^\x15=\xf5\xb4c7\xf7\x14\xb76\xaa\xd4O}\x1f\xb7\x86\xe5ɐ`\x10\x81%\xe4\xc17ZNEF\xab4\x7f\x80\x8fʽ\xad\x93\"&\xfd\x16\xbd\x97\x97\xbc\xe7\x16\xf2\xb5\xfd$\x8c)z?\xb6!\xc0\xf6|\xc6\xdeE\xff\x88\xed\x91O\x19X[\xba\x91ғ&\xef\xfd\xeb$\xa8\x8f\r \v\x02\x05\x1c\xb4\x15\xfew\xa3\x9e\xe8\x02\xfc\xf8\x1asx@\xa4\xf3\x86\x19\xd0A\x11J\xe1=j\x98uU(\x9e\x83\xbe\xa2GT\x12F\xfcS\xaf\xc1\xc0\x1d\xe8?\xc5\xe2\xedfd<\xa1\xe7\x17̒A\x8f\xae(\xa0\xf8A\x14`\x1c≦\xe1f\xbfec)\xear\xe5<\xd55\xfe\xd8tr\xc02\xbb\xa1\xd2\x06C\x05\x1a\xfdD\xb7\x15Q\x9b \xf9\x87\x89\xc1\x1a>\ni\xe1\x01\xc6c\xe8\t\x9b\xe0\xdeh \a (0\x8a\xf8\xfe\x12[y\xec\x11\xe4>\xdez \x03\xcdbdL\x8e\x95w\xabn\xee\xaf\f\xabeN\x1b\x00\xf7\x7f\xbe=J~\xb7\xbd\xf7e\x82NHQ\xef\xf7\xe3-;!BG;\x91O\x1fW\xe21X\xdc\x18\x95\t\x8a*\x9e\x84\xf5\xd79\xbe\xdc\x1d\xe2\x87\x02\xc4\x03\xd2Q\x1b\xf8\xfc$A\x7f\t\x16\xc8\\\xcbػ-\xd3\xda\xef\xa7=h\xd1\xf7Z\xac¾G`\f\x000\x15\xf6\xb9\x8c{\t(l\xaf\t\xd3H\x1c\xc4>\x01\xdcyG\xc8ik\x85\xb4\xe3\x9c!n\x9bVt\xd8tDCN\x8b\xed\xfd\x00\xc6 \x93\x9d\x1e}j\xaa\xb8Ӧ\x86\xfd^\x8cy\xa3\xb4c\x96\xe1@\xff\xb0\xf7kT\x83\x1f\xd4\xde1\xcd=\xaaF\xf6>\xd2CxyGr\xbc\x97\xde\xfdR\xaf\xda\a\x15\xd8\xdf\xfe~\xf6\x8f\x00\x00\x00\xff\xff)\x00\x87w>{\x00\x00"), + []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xec=]s\x1c)\x92\xef\xfa\x15\x84\xeea?B\xdd^\xc7}ą\xde|\xb2gO\xb1\x1e[ai\xf4\xbctU\xb6\x9aQ\x15\xd4\x00\xd5r\xdf\xde\xfe\xf7\x8dL\xa0\xbe\xba\xe8\xa2Z-ygǼت\x86$\xc9L\xf2\x03\x12X,\x16g\xbc\x12\xf7\xa0\x8dP\xf2\x92\xf1J\xc0W\v\x12\xff2\xcb\xc7\xff6K\xa1\xdelߞ=\n\x99_\xb2\xab\xdaXU~\x01\xa3j\x9d\xc1{X\v)\xacP\xf2\xac\x04\xcbsn\xf9\xe5\x19c\\Je9~6\xf8'c\x99\x92V\xab\xa2\x00\xbdx\x00\xb9|\xacW\xb0\xaaE\x91\x83&\xe0\xa1\xebퟖo\xffk\xf9\x9fg\x8cI^\xc2%3\xd9\x06\xf2\xba\x00\xb3\xdcB\x01Z-\x85:3\x15d\b\xf4A\xab\xba\xbad\xed\x0f\xae\x91\xef\xd0!{\xeb\xdbӧB\x18\xfb\x97\xde\xe7\x8f\xc2X\xfa\xa9*j͋N\x7f\xf4\xd5\b\xf9P\x17\\\xb7\xdf\xcf\x183\x99\xaa\xe0\x92}®*\x9eA~Ƙǟ\xba^0\x9e\xe7D\x11^\xdch!-\xe8+U\xd4e\xa0Ă\xe5`2-*K#\xbe\xb5\xdcֆ\xa95\xb3\x1b\xe8\xf6\x83\xe5g\xa3\xe4\r\xb7\x9bK\xb64ToYm\xb8\t\xbf:\x129\x00\xfe\x93\xdd!n\xc6j!\x1f\xc6z{Ǯ\xb4\x92\f\xbeV\x1a\f\xa2\xccrb\xa0|`O\x1b\x90\xcc*\xa6kI\xa8\xfc\x0f\xcf\x1e\xebj\x04\x91\n\xb2\xe5\x00O\x8fI\xff\xe3\x14.w\x1b`\x057\x96YQ\x02\xe3\xbeC\xf6\xc4\r\xe1\xb0V\x9aٍ0\xd34A =l\x1d:\x1f\x87\x9f\x1dB9\xb7\xe0\xd1\xe9\x80\n»\xcc4\x90\xdcމ\x12\x8c\xe5e\x1f\xe6\xbb\aH\x00F$\xaaxmH8\xda\xd67\xddO\x0e\xc0J\xa9\x02\xb8\xca\x04,W\xb7\xd7\x03h\x9d\xf1\xe1h\xc8s\xa7ie\x15{\xe2\u0092\x89\xb8\xba\xbdf\xf7\x18\xf2@h͜n`\xb6\xd6\x12\xcdr\xa4\xbf/\xc0\xf3ݝ\xfa\xc9\x00\xcbk\xf2(\x827~\xc1V\xb0F\xf3\xab\x01a\xe0O\xa05\x9a#CH\xa8z\xcf\xc3\v\xe5\xceI\x10\x8a\xb2wP\x84ao\xff\xc4J!k;:I\x0e\xeaa\xa2\x1e\xb7\xbcT[\xd0\xcf!\xee{n\xf9\x8f\bd@S\x04\xce\b\xba\x97o\xa2\xefj7)>4\xbb[\xa8°\xf3sT^\xe7.B>\xbfp\x10jQ\u0605\x90\xdd~\x82&Ş\x8e#\x88\xa3\xafc\xba\xb9S?\x187C\x9fE\x9f\b̑)V\xa9\x9cm\xa9\x1e[\x8b\x02\x98\xd9\x19\veP\xb2m\xa0҉\xbe\x86\x85\\\x9b\xa2\xf0`\f\xd2\xdb\x0f\xea\xc5\xe6\xea\x90h_\xc0X\x91\x9d\x92d\x0e\xe2\b\xc1\xb4\xff\xa1G\x19\x8at\xf8#0\x1e\x01\xef\xe9\x89aUQt\x88ާV\x14\xb7JC\x86.\xf7\xa5w\xe5\x05\x14\x14>H\xc5\n%\x1f@;,\x1aӊ\xaa\x1dP@s\x86^\xb2F\x83($[\xd7\xe8@/\x19j\x89\xa8\x8c\bi,\xf0\x880\x9f\x80w\xf05+\xea\x1c\xf2\xab\xa26\x16\xf4m\xa6*\xc8Úب!I\xe5ᇃ\x90}\xb8U\x88\f\x90\x0f\x99\xab\xb4\xa05\xa9\x98h\xb7\x91\u05ee\x02\xb7D\x86\xac\xf6ChC\xaaI\xddb\xc0b\xc3\xf3?\x9e_\x90\x04\xf4{\xef\xf7c\x18\xd7Аi\x96n&\ae\xbc\x85\xb0PF\xa8;\xa9\xa3f\xf0\x9dk\xcdw\a\xb8ެ\xfd\xbd\x00\xdfc\xb0\a\x9c\x97\xa1\xda7\xe2\xfd\xb0\xff\xdf\"\xf7O\xcboCk\xe4\\H\xe4s!\x8c\xed\xb1ٸE7$\xebX\xc4\xeb\t$\x1dLT\x93S\\\xfd'!\xe6I\xe7Nl\xb24\xb2\xe9'\xc0\xbf\x14%7J=\xa6P\xef\x7f\xb1^\xbb\xe2\xc62\xda\xc7a+\xd8\xf0\xadP\xda\fWu\xe1+d\xb5\x8dj\x16nY.\xd6k\xd0\b\x8bv%\x9aM\x8cC\xc4:\x1cm\xb1\x8eʊV\x18\x8c\xabe:\xb2\x94\xa8\x11\x1b\n\xc5\xd3Q\xa8\xce\xc1\xc1Ђ\x1c\x88\\lE^\xf3\x82|\t\f\xe0h|\xbc\xc1/\xa6\xd5&\x04b\x0f\xff\xa8T\xbb\xe2\x1c\x9a0Hdbo\x91NI@\x1f\xbf\xc4\xd8h\xbfj\x9c\x12a\xe5\xe3`\xdf\xc8L]\x17`|w9\xb9ɭN\xbah\x99\xe5\x96D\n\xbe\xc2\x18\x18\nȬ\xd2q\n\xa5ȁ+\xa9J7B\xdc\x11-ۏ\xb6\xda\xc1L\x80e\x14\xe2nD\xb6q\xee+\n\x1a\xc1b\xb9\x02C\x8b8\xbc\xaa\x8a\x88\xe9jˤp\xf8Φ\xf4F[\x124\xc8\x10nL\x97\xb4%Q?\xb7e\x94\xec\xed\xdc\xecS}|[b\x14\xdf\xdf\x12у\xd59R\xd8'4\t\xa3\xed\x8d\xe4\xf9\x10%=R\\\x80Yv\x16\x13\x85\r_S\x18\xda\xf3\x1f\xf7v~\xf6\x88\xf2\xeb\xe2\xddq\x13f\x06\xeb&\xe7\xd4\xcb2\xae\xe9\xe6_\x84od\xb2n\xbdŚų\x8fݖ\x17\xb4\x89\xe1\x19\x92_\xb0\xb5(,\x90S5\x85(\x9b\xc1\xb9S\x12(\xd5\x023\xdaӶ\xd9\xe6C\xb3Օ\xd0b@\xab!\x00砇(\x87x\x90\x00\x925\xae\x05\xed\xf1\n\r%\xed\x1dS$\xd9\xfdB\xae\xe0\xbbO\xef\xe3\xb1g\xb7$J\xeaޠ\x12&\xad+\xef\x06\x8eQ\x17W\x1f\xaa\x84_\xc8_k\x02A\x973p\xc18{\x84\x9ds\xb1\xb8d\xc87\x1e*'\xa2\xa0\x81\x12\x18HS<\u008e@\x8dg$\x8c\x979\xd2\xe2\xca#\x8clR\xc6J\x8f\xae\x88\x9f\xdf\xfaqt\xc3\x0fD\x98\x94\xd9Ԗ\x86\xa8~\xfa\x8c\xe4\x03\xc4\xcb\f\xbd\x14J\xe0ˑ\xc3N\x16\xa7n_\xfd\x1c\x9eG\xd8\xfd\xce8^\xe3,\xdb\b\xda#\xe3\xb4z\xa3ֳ\x18\xee\xca=/D\xdet\xe6\xe6յ\xbc`\x9f\x94\xc5\x7f>|\x15\x06;\x969{\xaf\xc0|R\x96\xbe\xbc(\x95\xdd ^\x83Ʈ'\x9a\xa0\xd2Y\x12$b7\xd7\xc5\xd9R\x14Ԇ\x1f°k\x89!\x99#ь\xee(\xb5\xc9u\xe9:+kC;\xc3RɅ[\x16\x1b\xeb\xcd\xf3@\xe9\x1e\vNұ\xef\xf4\x0e\x8d\x91\xfb\xc5%Y\x15<\x83|\xed,Q\xa3v\xc1\xbfS\xa4\xf5\x18\x1c\x19\x1d/)K>\xcc^NF\xf7ʵ\x0es\xcc\x03s\xe1\x96~\xa8I\xe7\xcc\xf1:\x1aQ\xfegsmJ!\xaf\xa9#\xf6\xf6\x05\xdd!\xaf\xc5c\xe9Qc\xe5x'\xfd*t\xd6r\xaf\xf9\xe0S\x00\x15m\xfch\xe81w\x7fO\x84\xbck\xa9lg\x19g\xa6\x13]\xa9\xfcw\x86\xad\x856\xb6\x8b\x869\x90X5\n\xea\x88\xd0S~\xd0\xfa\xe8\xc8\xf3\xb3k\xddYPܨ'\x9f\xe7='\xde\x0e$\xdd\xf0-\xf8D[\x90\x99\xaa%-\x85\xa1\x1e\xc0nf@t\xacqV \xd1\xdeu\x1a˺L'Ȃ$I\xc8\xc9u\xb3n\x93\x1f\xb8H[\xb7bDZ\xd5\x1e\xca\xe1\x1c+\xc7ϣ\x90\xe0\xd9\xcd\xfe/\xf9WQ\xd6%\xe3%\xf2\x90\xdc\x0eQBs\x00\xc0\xb1\xbbI\xfb\xc4\x16d\xb4\xac\xc2YV\x15`\xc1\xa7m\xce\xc0#S҈\x1c\x1a\xd3\xefE@I\xc6ٚ\x8b\xa2\xd63\xb4\xeal\x92\xcf\r¼69}d\x95\x8eȂH\x94\xb8\xce>\xc3\v\x9e\xd6\xf8\x95\x9e\xe7Ǧ8\x8c\x1a\xe6\xfb\x8b\x95\x16ʝ]8\xbd\xcb\xe8ӎ\xb9\xdc}\xf7\x19\xbf\xfb\x8c\xdf}\xc69\x1d}\xf7\x19'\xcaw\x9f\xf1\xbb\xcfx\xb8|\xf7\x19S\xcaw\x9fq&\"\xdf\xcagL\xc1pAk\x9c\a*$a\x95\x98\n1\x85\xf6D_>\xe9ǟ\xd58I.\xf3\xf58ȑC<\x91\xe3\x171\xaf\xa35^Mr3\xce\xc00wܡ\xcf\x04\x87\xf9\x04\xa7g\x02\x02\xa7?=s}\x10\xf2\tO\xcf\xf8!\xa4E\x18G\x9d\x9d\tD\x9a\x7fz\xe2\xc2'\x11\x95\xc0\xc3V\x8aK\xff\x88\x8d1&I\tx|\xe3\xe4\xf7\xbd\x8c\xc9\x17\x90\xa5W9\x913K\x9eFY\x7f\xfe\xc7\xf3_\a\x8bN˔(\x1b\xf6i\xeb\xd4xL?b,\xdfM\x8d\xecg\xa9\xfez\xa6\xc2Ie?\xf5DMC\xe4\b\xbc\xbeX\x0f\xa8\xfck\xd27\x16\xcaϕ\xb7\x96'8a\x7f=\x02/\xe9\x8c=7;\x99m\xb4\x92\xaa6~M\ba\xbd\xcb\xdc5\t\x01dL\xd8G5\xc8\x7f\xb0\x8d\xaa#\xa76&H\x9b\x90E\x9bF\x90^R\xadO\x8c\x00˷o\x97\xfd_\xac\xf2)\xb6\xecI\xd8M\x04\x18]\x9f\xc1\xf3\x1c\xe3\x82\u0381\x1e\xaf\a\xc2\xcdNC\xa1\x8c\x00S\x9aIQ8\x89\r\x10z\xf2\xca>Wnu\xf0h\xbfiz\r+=\x11wn\xfam\x93-9\xed\xbe?#\xe9\xf6\xa4G\xa3\xbeYZ\xedqɴ\xa9+\x94\t\x89\xb3\xe9\xe9\xb2)lu%=I69BNM\x88\x9d\xbb\x02\xf1\xa2ɯ/\x93\xf2\x9aL\xb3\xb4\xf4ֹ\x14{\x95T\xd6WN`}\xbd\xb4\xd5\x19ɪ\xa7?\xf5\x92\xbe\x96~tveڲ\xcc\xe1\x84Ӥ4Ӥ\xa5\x9b\x94\x01\x1f5Ԥ\xf4ѹI\xa3I\x9cL\x9f\xae\xaf\x9a\x16\xfa\xaaɠ\xaf\x9f\x02:)m\x93\x15\xe6&y\x8e\xdf\xc9\x18ʴ\x03P|\v\xe1|.\x99\x94\xee\xb9\xe6ϊ;?\x0f`\xa1\xb0\x047\xf5\x15〲.\xac\xa8\x8a\xf6\xfa\xb8X\xc0\xb9\x81]sY\xd1ϊ\x8e\xc8\xfb\x9b\xba>\x7fi$~9\x88j\xb8aOP\x14\x8c\xc7\xe6\xe6\x1e\x152wmi\xa6\x16\x80\xb6\x11g\xb9\xbf\x8c\xc9\xdfuz\xe1\xa6\v\xdd\x06@\x16\xb6\x8c-\xf5qy\xf8\xa6\xaf\x83\x06,U\x8f\xedy\xe6.ޠo\xbfԠw\x8c\xee\x1dk|\xb3\xf6P\xa9\x9f\xe8\x06\x03Ӡ~\xbc:<\xb4g\xb2\x17\xe0\xb4ꁽ\x93\xce#\x18\xe2DmP\xef\xb4\x01\x1d*U\x8cӢ\xfdD@H\xd5@\x884Mq\xfe眲|\x89\xf0\xee\x14\x01^\x92\a4\xcf{\xfd\x86\xa7'\x8f=5\x99\x9e\x8c\x92tJ\xf2%½9\x01\xdf,\x7f5\xfd\x14\xe4\xfc\x8d\xe7\x17>\xf5\xf8R\xa7\x1dgP/\xf5t\xe3|ڽ\xd2i\xc6W?\xc5\xf8\x9a\xa7\x17g\x9dZLNϚ\x95q0'\xb5\xea\x19\xc7\xed\xd2r\t\xa6O!&\x9e>L\xcc4H\x1b\xfc\x91\xc3N<]8\xffTa\"\x7f\xe7L\xe9W>=\xf8ʧ\x06\xbf\xc5i\xc1\x04\tL\xa82\xffT\u0cf7\xa4\x94\xceAOn\xfb͑\xdaIyM\x8d\xe5\xfa\x88\r\xf6\xb5\xc2m\xb2X\xab\x17\x03\x90Y\xf2\xef\x0e\xd0\x1b\x13\x87\xb6\xc1Q2;\x1eQo_\xb2u\xd7\xfa\x0e\xb1\x7f|\xc2m]\x1a\xa88\x1a\x00\n\xdc(5+\xea*|\xe0\xd9f\xd0Æ\x1b\xb6V\xba䖝7\x9b\xc5o\\\a\xf8\xf7\xf9\x92\xb1\x1fT\x93\xabӽ/͈\xb2*v\x18\x89\xb1\xf3n\x83\xe7IIT:C\xcf7\xaa\x10Y\xc4\xe7\x1c\xbdW\xcf5ػl\x88n\xfe\xcb:\xd9\"\xb1\xc0\a\x9b\x8bp\xebb\xffJfw\xfd\xfc\x91k%\xbc\x12\x7f\xa6\x17\xa0N\xb0\xea\xf6\xee\xe6\x9a`\x051\xa2\xa7\xa5\x9a\x04ņ\xe5+@\x97\xa1\x1d\xfb!}r\xbd\xeeA\xed\xe7\bw\xdfր\xdc=\xa4\x12\xdc\x16\xaf\x9a3\x85Z\xeb\xe6\xda\xe1r\xa8'\x94/.wL\xf9\x972\x84\xce\x17\x15\xd7v璉.zx\x04\xbb>\xb5jv\xd0Z\xed?\x14\xd3-=\xb2\x877bh'{W\xf5\x93\a\x86\xf4|\x0eN\x87OUO\x9e\xa7~\x01\x9c\x0e\xbbP\v\xa2b\xe4\xa7h\x06\xe4\xc9W,\x8d\xbf\xa1\xffG\xb5\x85\xf7ѕ\xcb\xfec1\x83&#\xa9\x89\x01*]2\x1f\xa1`\x9b\x8fHw|?O\xed\xc5s\r\x03*\xfe\x8e\xf0\xe7,N\xde\xf6A\x8d\xbf\xf5@7\xa8\x87Nc^\x15\xbdL\xb5c7\xf7\x14\xb76\xaa\xd4O}\x1f\xb7\x86\xe5ɐ`\x10\x81%\xe4\xc1'eNEF\xab4\x7f\x80\x8f\xca=\x05\x94\"&\xfd\x16\xbd\x87\xa2\xbc\xe7\x16\xf2\xb5\xfd$\x8c)z?\xb6!\xc0\xf6|\xc6\xdeE\xff\x88\xed\x91O\x19X\x9b\xf2\xdaGTF\xee\xee>\xba\x91\xd2\v,\xef\xfdc*\xa8\x8f\r \v\x02\x05\x1c\xb4\x15\xfew\xa3\x9e\xe8\x02\xfc\xf8\x1asx\xef\xa4\xf3\xe4\x1a\xd0A\x11J\xe1=j\x98uU(\x9e\x83\xbe\xa27_\x12F\xfcS\xaf\xc1\xc0\x1d\xe8\xbf\x1c\xe3\xedfd<\xa1\xe7\x17̒A\x8f\xae(\xa0\xf8A\x14`\x1c≦\xe1f\xbfec)\xear\xe5<\xd55\xfe\xd8tr\xc02\xbb\xa1\xd2\x06C\x05\x1a\xfdD\xb7\x15Q\x9b \xf9\x87\x89\xc1\x1a>\ni\xe1\x01\xc6c\xe8\t\x9b\xe0\xdeh \a (0\x8a\xf8\xfe\x12[y\xec\x11\xe4>\xdez \x03\xcdbdL\x8e\x95w\xabn\xee\xaf\f\xabeN\x1b\x00\xf7\x7f\xbe=J~\xb7\xbd\xf7e\x82NHQ\xef\xf7\xe3-;!BG;\x91O\x1fW\xe21X\xdc\x18\x95\t\x8a*\x9e\x84\xf5\xd79\xbe\xdc\x1d\xe2\x87\x02\xc4\x03\xd2Q\x1b\xf8\xfc$A\x7f\t\x16\xc8\\\xcbػ-\xd3\xda\xef\xa7=h\xd1\xf7Z\xac¾G`\f\x000\x15\xf6\xb9\x8c{\t(l\xaf\tӼŶO\xcf\t\x15\x12\xb7t\xe3\x0e\xdbb\xfc\xe9\xa8E\xf3\xc4\xd5Y\x02\xb9\xdd\xfbG}\xc0\xe3/\U000391d22^\xd9Z\a\xedZk\xbae\x1d\x81\x80\xbb\x84\xfc\xb87\xf8ڧَap\xfb6Z\xbb\xff0\xf9z\xeb\b\x9c\xe6\x15\xbd\xe8\x93\\.\xa2v\xaf\xab.\x10\xfeq<\x1e\x9d1\x88\xf3\xad{jm\x82\b\x1fۚc\x03n\x86\x81C\xf6\x8f\xb7\xbd\xeaH\xe8\xd2\xfd\x891\xdc`\x9d攫\x97#j\x18.뿍1a\xfc(\xe4\x82}\x82\xfd\x88}\xc1>H\x1c\xc4>\x01\xdcyG\xc8ik\x85\xb4\xe3\x9c!n\x9bVt\xd8tDCN\x8b\xed\xfd\x00\xc6 \x93\x9d\x1e}j\xaa\xb8Ӧ\x86\xfd^\x8cy\xa3\xb4c\x96\xe1@\xff\xb0\xf7kT\x83\x1f\xd4\xde1\xcd=\xaaF\xf6>һ}yGr\xbc\x97\xde\xfdR\xaf\xda\a\x15\xd8\xdf\xfe~\xf6\x8f\x00\x00\x00\xff\xff\xdd\xeaj\x99\xed{\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xbcV\xcfo+5\x10\xbe\xe7\xaf\x18\x89+\xbb\xa1B \x94\x1b*\x1c*\xe0\xa9j\x9ezw\xbc\x93d\xa8\xd7^f\xc6)A\xfc\xf1\xc8\xf6n\x9b\xee:\xb4\x8f\x03\xbe\xad\xed\xf9\xe6\x9bo~x\x9b\xa6Y\x99\x81\x1e\x91\x85\x82߀\x19\b\xffT\xf4\xe9Kڧ\x1f\xa4\xa5\xb0>ݬ\x9e\xc8w\x1b\xb8\x8d\xa2\xa1\x7f@\t\x91-\xfe\x84{\xf2\xa4\x14\xfc\xaaG5\x9dQ\xb3Y\x01\x18\uf0da\xb4-\xe9\x13\xc0\x06\xaf\x1c\x9cCn\x0e\xe8ۧ\xb8\xc3]$\xd7!g\xf0\xc9\xf5\xe9\x9b\xf6\xe6\xfb\xf6\xbb\x15\x807=n@\x90ә\x1a\x8d\xc2\xf8GDQiO\xe8\x90CKa%\x03ڄ\x7f\xe0\x10\x87\r\xbc\x1e\x14\xfb\xd1w\xe1\xbd\xcdP\xdb\f\xf5P\xa0\xf2\xa9#\xd1_\xae\xdd\xf8\x95\xc6[\x83\x8bl\\\x9dP\xbe \xc7\xc0\xfa\xe9\xd5i\x03\"\\N\xc8\x1f\xa23\\5^\x01\x88\r\x03n \xdb\x0e\xc6b\xb7\x02\x18\x05\xc9Xͨ\xc5\xe9\xa6\xc0\xd9#\xf6\xa68\x01\b\x03\xfa\x1f\xef\xef\x1e\xbfݾ\xd9\x06\xe8P,ӠYֿ\x9b\x97}\xa8\x85\t$``\xa4\x04\x1a\xc0X\x8b\"`#3z\x85B\x19\xc8\xef\x03\xf79\xad`v!\xea\x05\xaa\x1e\x11\x1e\xb3\xfec\x98\xed\xcb\xe1\xc0a@V\x9a\xa4)\xeb\xa2\xe2.v\xff\x8dxZ)\xd6b\x05]*=\x94\xecy\xd4\v\xbbQ\x1e\b{\xd0#\t0\x0e\x8c\x82\xbe\x14c\xda6\x1e\xc2\xeew\xb4\xdaΠ\x8b.\x922\x19]\x97*\xf6\x84\xac\xc0h\xc3\xc1\xd3_/ؒ\x04JN\x9dѬ\x9dWdo\x1c\x9c\x8c\x8b\xf85\x18\xdf͐{s\x06\xc6\xe4\x13\xa2\xbf\xc0\xcb\x062\xe7\xf1[`\xccRo\xe0\xa8:\xc8f\xbd>\x90N}hC\xdfGOz^疢]\xd4\xc0\xb2\xee\xf0\x84n-th\f\xdb#)Z\x8d\x8ck3P\x93\x03\xf1\xb9\x17۾\xfb\x8a\xc7Ε7n\xf5\x9cjP\x94\xc9\x1f.\x0er\xeb|AzR#\x95b*P%\xc4\xd7,\xa4\xad$\xdd\xc3\xcf\xdb\xcf01)\x99*Iy\xbd\xba\xd0e\xcaOR\x93\xfc\x1e\xb9\xd8\xed9\xf4\x19\x13}7\x04\xf2\x9a?\xac\xa3\\\xb8qד\xcaT\xda)us\xd8\xdb<\xab`\x87\x10\x87\xce(v\xf3\vw\x1enM\x8f\xee\xd6\b\xfeϹJY\x91&%\xe1Cٺ\x9c\xc0\xf3\xcbEދ\x83iv^ImeJl\a\xb4)\xb9I\xdfdM{\xb2\xa5\xad\xf6\x81\xc1\xd4L\xda\x0f1\xc9\x16_\xc8e\x9cH\x85\xcdlN\xa5.\x7f\x9fM},哣\x11\x9co\xce8ݧ;s\xff\x8e\xf6h\xcf\xd6a\x81(S\bߧ\x92\x16\xfa\xd8/}6\xf0\t\x9f+\xbb\xf7\x1c҄\xc6\xf9\xa8\xb9Z\x1bP\x1e\xb1\x03\xf9E\xb8\xf3\xc8ʭ\xfc0.G~\x0eh\x04\x02\x8eާ\x96\x0e~\x01Yy\x11\x16wH\xb1\xaf\xb0\xa9\xf2\xb9\xf3\xfb\x90\xff\"Lrl\xb4\xb4\x13\x8e\xc9\x1e\xfd\x14^\x15\xc0\xeb\xb9.k9\xe7>$hY\xf9y\xfeo\xc6i.\x11c\xd5w\x93YU\x0f\x92ǚ\xe2\xf5\xfe\x1aYF\xe7\xcc\xce\xe1\x06\x94\xe3Һ\xd8\x1afs\x9eW\xcdTj\x9f\xa9GQ\xd3\x0f\xef\x14\xd0\xe2UH\xeb~\x81\x92\x9a\xe7\xf9\x88\xfeZ\x8b\xc0\xb3\x91W\xe7\x15\xc8\xdd\xf9\x9a\xe9\xed\xcb\xdf\xe6\xb2\xcfJ=o \xcd\xfaF\xa9\"䇔\xaa\xa6\xb4\xd4y\xf5\xb7f\xa1\xd2\xf6\xf2\xee4H\xde\xf4\xcb\xf4W\xb3\x8c\xe1*\x85j\x05,63|w\x11\x9eh`s\x98\x02\xfe'\x00\x00\xff\xff\xef\xf8\xa6>\x10\f\x00\x00"), []byte("\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xbcVM\x8f\xdb6\x10\xbd\xfbW\f\x92kd7(Z\x14\xbe\x05\xdb\x1e\x82&\xc5\"N\xf7N\x93#{j\x8ad\x87C9.\xfa\xe3\v\x92Ү-\xcb\xc9nQT\x17\xc3\xe4\xf0q>\u07bca\xd34\v\x15\xe8\x019\x92wkP\x81\xf0\x8b\xa0\xcb\xff\xe2\xf2\xf0S\\\x92_\xf5o\x17\arf\rw)\x8a\xef>a\xf4\x895\xfe\x8c-9\x12\xf2nѡ(\xa3D\xad\x17\x00\xca9/*/\xc7\xfc\x17@{'\xec\xadEnv薇\xb4\xc5m\"k\x90\v\xf8xu\xff\xdd\xf2\xed\x8f\xcb\x1f\x16\x00Nu\xb8\x86\xde\xdb\xd4at*Ľ\x17\xebu\xc5\\\xf6h\x91\xfd\x92\xfc\"\x06\xd4\xf9\x8a\x1d\xfb\x14\xd6\xf0\xb4Q!\x86\xeb\xab\xeb\x0f\x05m3\xa0}\x18Њ\x81\xa5(\xbf~\xc5\xe8\x03E)\x86\xc1&V\xf6\xa6g\xc5&\xee=\xcboO\xb77\xd0G[w\xc8\xed\x92U|\xeb\xfc\x02 j\x1fp\r\xe5xP\x1a\xcd\x02`\xc8O\x81k\xc6Լ\xad\x88z\x8f\x9d\xaa\xf7\x00\xf8\x80\xee\xdd\xfd\xfb\x87\xef7\x17\xcb\x00\x06\xa3f\nR\xb2<\x1f\"P\x04\x05\xa3'p\xdc##<\x94|B\x14\xcf\x18\a\xa7\x1fA\x01F\xff\xe3\xf2q1\xb0\x0f\xc8Bc\xf0\xf5;\xe3\xd7\xd9\xeaį\xbf\x9b\x8b=\x80\x1cJ=\x05&\x13\r#\xc8\x1e\xc7t\xa0\x19\xa2\a߂\xec)\x02c`\x8c\xe8*\xf5\xf2\xb2r\xe0\xb7\x7f\xa0\x96\xe5\x04z\x83\x9car\xad\x925\x99\x9f=\xb2\x00\xa3\xf6;G\x7f=bG\x10_.\xb5J0\n\x90\x13d\xa7,\xf4\xca&|\x03ʙ\tr\xa7N\xc0\x98\xef\x84\xe4\xce\xf0ʁ8\xf5\xe3\xa3g\x04r\xad_\xc3^$\xc4\xf5j\xb5#\x19\xbbN\xfb\xaeK\x8e\xe4\xb4*\rD\xdb$\x9e\xe3\xca`\x8fv\x15i\xd7(\xd6{\x12Ԓ\x18W*PS\x02q\xb5K:\xf3\x9a\x87>\x8d\x17\xd7\xca)S,\n\x93\u06ddm\x94.yAyr\xc3T\xd6T\xa8\x1a\xe2S\x15\xf2RNݧ_6\x9fa\xf4\xa4V\xaa\x16\xe5\xc9\xf4*/c}r6ɵ\xc8\xf5\\˾+\x98\xe8L\xf0\xe4\xa4\xfcі\xd0\tĴ\xedH2\r\xfeL\x18%\x97n\n{W\x94\t\xb6\b)\x18%h\xa6\x06\xef\x1dܩ\x0e흊\xf8?\xd7*W%6\xb9\bϪֹ\xdeN\x8dkz\xcf\x1bu\x90\xc9\x1b\xa5\x9dW\x84M@}\xd1x\x19\x85Z\x1a\x14\xa2\xf5i\x8b\x15\x10|;ý\x17\xb9\x9c?t\xa9\x9b#\xe2\xbb^\x91U[{-\t\r\xfc\xee\xd4\xcdݛş\xad\xe7\xd5b̏=\xb3\x06\xe1T\xb1\a\x96\r+\xff\x04\x00\x00\xff\xffNy\xc1Q\xa1\x0e\x00\x00"), } diff --git a/pkg/apis/velero/v1/backup_types.go b/pkg/apis/velero/v1/backup_types.go index 5ba3b2175a..c76574fced 100644 --- a/pkg/apis/velero/v1/backup_types.go +++ b/pkg/apis/velero/v1/backup_types.go @@ -184,6 +184,11 @@ type BackupSpec struct { // +optional // +nullable UploaderConfig *UploaderConfigForBackup `json:"uploaderConfig,omitempty"` + + // Cancel specifies whether to cancel the backup. + // +optional + // +nullable + Cancel *bool `json:"cancel,omitempty"` } // UploaderConfigForBackup defines the configuration for the uploader when doing backup. @@ -288,7 +293,7 @@ const ( // BackupPhase is a string representation of the lifecycle phase // of a Velero backup. -// +kubebuilder:validation:Enum=New;FailedValidation;InProgress;WaitingForPluginOperations;WaitingForPluginOperationsPartiallyFailed;Finalizing;FinalizingPartiallyFailed;Completed;PartiallyFailed;Failed;Deleting +// +kubebuilder:validation:Enum=New;FailedValidation;InProgress;WaitingForPluginOperations;WaitingForPluginOperationsPartiallyFailed;Finalizing;FinalizingPartiallyFailed;Completed;PartiallyFailed;Failed;Deleting;Cancelling;Cancelled type BackupPhase string const ( @@ -349,6 +354,12 @@ const ( // BackupPhaseDeleting means the backup and all its associated data are being deleted. BackupPhaseDeleting BackupPhase = "Deleting" + + // BackupPhaseCancelling means the backup is in the process of being cancelled. + BackupPhaseCancelling BackupPhase = "Cancelling" + + // BackupPhaseCancelled means the backup was successfully cancelled. + BackupPhaseCancelled BackupPhase = "Cancelled" ) // BackupStatus captures the current status of a Velero backup. diff --git a/pkg/apis/velero/v1/zz_generated.deepcopy.go b/pkg/apis/velero/v1/zz_generated.deepcopy.go index c998a16564..d4d511efe7 100644 --- a/pkg/apis/velero/v1/zz_generated.deepcopy.go +++ b/pkg/apis/velero/v1/zz_generated.deepcopy.go @@ -422,6 +422,11 @@ func (in *BackupSpec) DeepCopyInto(out *BackupSpec) { *out = new(UploaderConfigForBackup) **out = **in } + if in.Cancel != nil { + in, out := &in.Cancel, &out.Cancel + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackupSpec. diff --git a/pkg/backup/backup.go b/pkg/backup/backup.go index 824c448756..e0d3f1609a 100644 --- a/pkg/backup/backup.go +++ b/pkg/backup/backup.go @@ -89,6 +89,15 @@ type Backupper interface { volumeSnapshotterGetter VolumeSnapshotterGetter, ) error + // BackupWithResolvers performs the core Kubernetes backup operation, creating a gzipped tar archive + // of selected cluster resources with plugin transformations applied. + // + // It discovers resources based on the backup spec, applies BackupItemAction and ItemBlockAction + // plugins, handles volume snapshots, executes backup hooks, and writes everything to a compressed + // tar archive. Accepts pre-resolved plugin actions for efficiency. + // + // Returns an error only for complete backup failures. Individual resource failures are logged + // but don't stop the backup process. BackupWithResolvers( log logrus.FieldLogger, backupRequest *Request, @@ -98,6 +107,13 @@ type Backupper interface { volumeSnapshotterGetter VolumeSnapshotterGetter, ) error + // FinalizeBackup completes the backup process by updating resources that were modified + // during async operations and creating the final backup archive. + // + // It reads the original backup archive, collects resources specified in PostOperationItems + // from completed async operations, re-backs up those resources with their updated state, + // and writes a new archive with the updated content. This ensures the backup contains + // the final state of resources after async operations (like volume snapshots) complete. FinalizeBackup( log logrus.FieldLogger, backupRequest *Request, @@ -129,6 +145,54 @@ func (i *itemKey) String() string { return fmt.Sprintf("resource=%s,namespace=%s,name=%s", i.resource, i.namespace, i.name) } +// checkCancelRequest periodically checks if a backup has been cancelled by fetching +// the latest backup object from the API and updating the request's Cancel field. +// It uses rate limiting to avoid excessive API calls (checks at most every 3 seconds). +// Returns true if the backup should be cancelled. +func checkCancelRequest(ctx context.Context, kbClient kbclient.Client, request *Request, log logrus.FieldLogger) bool { + log.Info("Checking if backup should be cancelled") + const cancelCheckInterval = 3 * time.Second + + now := time.Now() + + // If lastCancelCheck is zero (first call), initialize it to now + if request.LastCancelCheck.IsZero() { + request.LastCancelCheck = now + return false + } + + // Check if enough time has passed since the last check + if now.Sub(request.LastCancelCheck) < cancelCheckInterval { + // Not enough time has passed, return the current cancel state + return request.Cancel + } + + // Fetch the latest backup object from the API + latestBackup := &velerov1api.Backup{} + err := kbClient.Get(ctx, kbclient.ObjectKey{ + Namespace: request.Backup.Namespace, + Name: request.Backup.Name, + }, latestBackup) + + if err != nil { + log.WithError(err).Warn("Failed to fetch latest backup object for cancel check") + // On error, keep the current state and update the check time + request.LastCancelCheck = now + return request.Cancel + } + + // Update the cancel state based on the latest backup spec + if latestBackup.Spec.Cancel != nil && *latestBackup.Spec.Cancel { + request.Cancel = true + log.Info("Backup cancellation detected") + } + + // Update the last check time + request.LastCancelCheck = now + + return request.Cancel +} + func cohabitatingResources() map[string]*cohabitatingResource { return map[string]*cohabitatingResource{ "deployments": newCohabitatingResource("deployments", "extensions", "apps"), @@ -235,6 +299,8 @@ func (kb *kubernetesBackupper) BackupWithResolvers( itemBlockActionResolver framework.ItemBlockActionResolver, volumeSnapshotterGetter VolumeSnapshotterGetter, ) error { + + log.Info("Creating output streams") gzippedData := gzip.NewWriter(backupFile) defer gzippedData.Close() @@ -246,6 +312,7 @@ func (kb *kubernetesBackupper) BackupWithResolvers( return errors.WithStack(err) } + log.Info("Resolving namespace includes/excludes") backupRequest.NamespaceIncludesExcludes = getNamespaceIncludesExcludes(backupRequest.Backup) log.Infof("Including namespaces: %s", backupRequest.NamespaceIncludesExcludes.IncludesString()) log.Infof("Excluding namespaces: %s", backupRequest.NamespaceIncludesExcludes.ExcludesString()) @@ -262,6 +329,7 @@ func (kb *kubernetesBackupper) BackupWithResolvers( } } + log.Info("Resolving resource includes/excludes") if collections.UseOldResourceFilters(backupRequest.Spec) { backupRequest.ResourceIncludesExcludes = collections.GetGlobalResourceIncludesExcludes(kb.discoveryHelper, log, backupRequest.Spec.IncludedResources, @@ -284,6 +352,7 @@ func (kb *kubernetesBackupper) BackupWithResolvers( log.Infof("Backing up all volumes using pod volume backup: %t", boolptr.IsSetToTrue(backupRequest.Backup.Spec.DefaultVolumesToFsBackup)) + log.Info("Resolving resource hooks") var err error backupRequest.ResourceHooks, err = getResourceHooks(backupRequest.Spec.Hooks.Resources, kb.discoveryHelper) if err != nil { @@ -291,12 +360,14 @@ func (kb *kubernetesBackupper) BackupWithResolvers( return err } + log.Info("Resolving backup item actions") backupRequest.ResolvedActions, err = backupItemActionResolver.ResolveActions(kb.discoveryHelper, log) if err != nil { log.WithError(errors.WithStack(err)).Debugf("Error from backupItemActionResolver.ResolveActions") return err } + log.Info("Resolving item block actions") backupRequest.ResolvedItemBlockActions, err = itemBlockActionResolver.ResolveActions(kb.discoveryHelper, log) if err != nil { log.WithError(errors.WithStack(err)).Errorf("Error from itemBlockActionResolver.ResolveActions") @@ -317,6 +388,7 @@ func (kb *kubernetesBackupper) BackupWithResolvers( kb.podVolumeContext, podVolumeCancelFunc = context.WithTimeout(context.Background(), podVolumeTimeout) defer podVolumeCancelFunc() + log.Info("Initializing PodVolumeBackupper") var podVolumeBackupper podvolume.Backupper if kb.podVolumeBackupperFactory != nil { podVolumeBackupper, err = kb.podVolumeBackupperFactory.NewBackupper(kb.podVolumeContext, log, backupRequest.Backup, kb.uploaderType) @@ -344,9 +416,11 @@ func (kb *kubernetesBackupper) BackupWithResolvers( pageSize: kb.clientPageSize, } + // Items to backup items := collector.getAllItems() log.WithField("progress", "").Infof("Collected %d items matching the backup spec from the Kubernetes API (actual number of items backed up may be more or less depending on velero.io/exclude-from-backup annotation, plugins returning additional related items to back up, etc.)", len(items)) + log.Info("Updating backup status.progress.totalItems") updated := backupRequest.Backup.DeepCopy() if updated.Status.Progress == nil { updated.Status.Progress = &velerov1api.BackupProgress{} @@ -356,6 +430,7 @@ func (kb *kubernetesBackupper) BackupWithResolvers( if err := kube.PatchResource(backupRequest.Backup, updated, kb.kbClient); err != nil { log.WithError(errors.WithStack((err))).Warn("Got error trying to update backup's status.progress.totalItems") } + backupRequest.Status.Progress = &velerov1api.BackupProgress{TotalItems: len(items)} itemBackupper := &itemBackupper{ @@ -397,7 +472,7 @@ func (kb *kubernetesBackupper) BackupWithResolvers( // it's done sending progress updates quit := make(chan struct{}) - // This is the progress updater goroutine that receives + // GOROUTINE: This is the progress updater goroutine that receives // progress updates on the 'update' channel. It patches // the backup CR with progress updates at most every second, // but it will not issue a patch if it hasn't received a new @@ -458,28 +533,34 @@ func (kb *kubernetesBackupper) BackupWithResolvers( var itemBlock *BackupItemBlock itemBlockReturn := make(chan ItemBlockReturn, 100) wg := &sync.WaitGroup{} - // Handle returns from worker pool processing ItemBlocks + // GOROUTINE: Handle returns from worker pool processing ItemBlocks go func() { for { select { case response := <-itemBlockReturn: // process each BackupItemBlock response func() { - defer wg.Done() + defer wg.Done() // Always decrement + + // Handle different error types if response.err != nil { - log.WithError(errors.WithStack((response.err))).Error("Got error in BackupItemBlock.") + if errors.Is(response.err, context.Canceled) { + // Expected during cancellation + log.Info("ItemBlock processing cancelled") + // Don't track resources for cancelled ItemBlocks + return + } + // Unexpected error + log.WithError(errors.WithStack(response.err)).Error("Got error in BackupItemBlock.") + return } + + // Normal processing - track backed up resources for _, backedUpGR := range response.resources { backedUpGroupResources[backedUpGR] = true } - // We could eventually track which itemBlocks have finished - // using response.itemBlock - // updated total is computed as "how many items we've backed up so far, - // plus how many items are processed but not yet backed up plus how many - // we know of that are remaining to be processed" + // Update progress backedUpItems, totalItems := backupRequest.BackedUpItems.BackedUpAndTotalLen() - - // send a progress update update <- progressUpdate{ totalItems: totalItems, itemsBackedUp: backedUpItems, @@ -500,6 +581,17 @@ func (kb *kubernetesBackupper) BackupWithResolvers( } }() + // Get backup context for cancellation checks + // If not set (e.g., in tests), use background context + ctx := backupRequest.BackupContext + if ctx == nil { + ctx = context.Background() + } + + // Boolean that indicates that this backup has been cancelled + var cancelled bool + var cancellationInitiated bool // Track if we've started shutdown + for i := range items { log.WithFields(map[string]any{ "progress": "", @@ -508,6 +600,32 @@ func (kb *kubernetesBackupper) BackupWithResolvers( "name": items[i].name, }).Infof("Processing item") + // Check for cancellation (rate-limited to every 3 seconds) + cancelled = checkCancelRequest(context.Background(), kb.kbClient, backupRequest, log) + if cancelled && !cancellationInitiated { + log.Info("Backup cancellation detected - initiating two-tier shutdown") + cancellationInitiated = true + + // TIER 1: Close channel to stop workers accepting new ItemBlocks + if backupRequest.WorkerPool != nil { + log.Info("Tier 1: Closing ItemBlock channel to stop new work") + backupRequest.WorkerPool.CloseChannel() + } + + // TIER 2: Cancel backup context to interrupt in-flight processing + if backupRequest.BackupCancelFunc != nil { + log.Info("Tier 2: Cancelling backup context to interrupt active work") + backupRequest.BackupCancelFunc() + } + + // Cancel all PodVolumeBackups + log.Info("Cancelling all PodVolumeBackups") + itemBackupper.podVolumeBackupper.CancelAllPodVolumeBackups() + + // Stop queueing new items + break + } + // Skip if this item has already been processed (in a block or previously excluded) if items[i].inItemBlockOrExcluded { log.Debugf("Not creating new ItemBlock for %s %s/%s because it's already in an ItemBlock", items[i].groupResource.String(), items[i].namespace, items[i].name) @@ -542,37 +660,69 @@ func (kb *kubernetesBackupper) BackupWithResolvers( // 2) Both current and next item are ordered resources // 3) Both current and next item are for the same GroupResource addNextToBlock := i < len(items)-1 && items[i].orderedResource && items[i+1].orderedResource && items[i].groupResource == items[i+1].groupResource + + // The backupItemBlock call is now made in the processItemBlockWorker goroutine, which is spawned from the StartItemBlockWorkerPool function + // StartItemBlockWorkerPool is called in the backupReconciler.prepareBackupRequest function in the backup controller if itemBlock != nil && len(itemBlock.Items) > 0 && !addNextToBlock { log.Infof("Backing Up Item Block including %s %s/%s (%v items in block)", items[i].groupResource.String(), items[i].namespace, items[i].name, len(itemBlock.Items)) wg.Add(1) - backupRequest.ItemBlockChannel <- ItemBlockInput{ + + // Safe send - channel might be closed during cancellation + select { + case backupRequest.ItemBlockChannel <- ItemBlockInput{ itemBlock: itemBlock, returnChan: itemBlockReturn, + }: + // Successfully queued + case <-ctx.Done(): + // Context cancelled while trying to send + wg.Done() // Decrement since we won't get a response + log.Info("Context cancelled while queueing ItemBlock") } + + // Reset the itemBlock so we can create a new one for the next item itemBlock = nil } } + // Wait for all ItemBlocks to complete with timeout done := make(chan struct{}) go func() { defer close(done) wg.Wait() }() - // Wait for all the ItemBlocks to be processed + // Wait for completion or timeout + var waitTimeout bool select { case <-done: - log.Info("done processing ItemBlocks") + log.Info("All ItemBlocks completed successfully") + case <-ctx.Done(): + log.Info("Backup context cancelled") + // Give workers a grace period to finish + select { + case <-done: + log.Info("All ItemBlocks completed within grace period") + case <-time.After(10 * time.Second): + log.Error("Timeout waiting for ItemBlocks after cancellation - some work may be incomplete") + waitTimeout = true + } case <-responseCtx.Done(): - log.Info("ItemBlock processing canceled") + log.Info("Response context cancelled") } - // cancel response-processing goroutine + + // Cancel response-processing goroutine responseCancel() - // no more progress updates will be sent on the 'update' channel + // No more progress updates will be sent on the 'update' channel quit <- struct{}{} + // Log warning if we timed out + if waitTimeout { + log.Warn("Backup completed with timeout - some ItemBlocks may not have been processed") + } + // back up CRD(this is a CRD definition of the resource, it's a CRD instance) for resource if found. // We should only need to do this if we've backed up at least one item for the resource // and the CRD type(this is the CRD type itself) is neither included or excluded. @@ -584,6 +734,7 @@ func (kb *kubernetesBackupper) BackupWithResolvers( } } + // We wait here for all the PVBs in the backup to complete processedPVBs := itemBackupper.podVolumeBackupper.WaitAllPodVolumesProcessed(log) backupRequest.PodVolumeBackups = append(backupRequest.PodVolumeBackups, processedPVBs...) @@ -716,7 +867,16 @@ func (kb *kubernetesBackupper) executeItemBlockActions( } } -func (kb *kubernetesBackupper) backupItemBlock(itemBlock *BackupItemBlock) []schema.GroupResource { +func (kb *kubernetesBackupper) backupItemBlock( + ctx context.Context, // For cancellation + itemBlock *BackupItemBlock, +) []schema.GroupResource { + // CHECKPOINT: Before pre-hooks + if err := CheckCancelled(ctx); err != nil { + itemBlock.Log.Info("Backup cancelled before pre-hooks") + return nil + } + // find pods in ItemBlock // filter pods based on whether they still need to be backed up // this list will be used to run pre/post hooks @@ -747,18 +907,35 @@ func (kb *kubernetesBackupper) backupItemBlock(itemBlock *BackupItemBlock) []sch itemBlock.itemBackupper.backupRequest.BackedUpItems.AddItem(key) } + // Ensure post-hooks always run (even on cancellation) to clean up pre-hook actions + defer func() { + if len(postHookPods) > 0 { + itemBlock.Log.Debug("Executing post hooks") + kb.handleItemBlockPostHooks(itemBlock, postHookPods) + } + }() + + // CHECKPOINT: Before backing up items + if err := CheckCancelled(ctx); err != nil { + itemBlock.Log.Info("Backup cancelled before item backup") + return nil + } + itemBlock.Log.Debug("Backing up items in BackupItemBlock") var grList []schema.GroupResource for _, item := range itemBlock.Items { - if backedUp := kb.backupItem(itemBlock.Log, item.Gr, itemBlock.itemBackupper, item.Item, item.PreferredGVR, itemBlock); backedUp { + // CHECKPOINT: Before each item + if err := CheckCancelled(ctx); err != nil { + itemBlock.Log.Infof("Backup cancelled during item processing (processed %d/%d items)", len(grList), len(itemBlock.Items)) + return grList // Return what we've backed up so far + } + + if backedUp := kb.backupItem(ctx, itemBlock.Log, item.Gr, itemBlock.itemBackupper, item.Item, item.PreferredGVR, itemBlock); backedUp { grList = append(grList, item.Gr) } } - if len(postHookPods) > 0 { - itemBlock.Log.Debug("Executing post hooks") - kb.handleItemBlockPostHooks(itemBlock, postHookPods) - } + // post hooks run before exit return grList } @@ -853,8 +1030,16 @@ func (kb *kubernetesBackupper) waitUntilPVBsProcessed(ctx context.Context, log l return wait.PollUntilContextCancel(ctx, 5*time.Second, true, checkFunc) } -func (kb *kubernetesBackupper) backupItem(log logrus.FieldLogger, gr schema.GroupResource, itemBackupper *itemBackupper, unstructured *unstructured.Unstructured, preferredGVR schema.GroupVersionResource, itemBlock *BackupItemBlock) bool { - backedUpItem, _, err := itemBackupper.backupItem(log, unstructured, gr, preferredGVR, false, false, itemBlock) +func (kb *kubernetesBackupper) backupItem( + ctx context.Context, // For cancellation + log logrus.FieldLogger, + gr schema.GroupResource, + itemBackupper *itemBackupper, + unstructured *unstructured.Unstructured, + preferredGVR schema.GroupVersionResource, + itemBlock *BackupItemBlock, +) bool { + backedUpItem, _, err := itemBackupper.backupItem(ctx, log, unstructured, gr, preferredGVR, false, false, itemBlock) if aggregate, ok := err.(kubeerrs.Aggregate); ok { log.WithField("name", unstructured.GetName()).Infof("%d errors encountered backup up item", len(aggregate.Errors())) // log each error separately so we get error location info in the log, and an @@ -873,13 +1058,14 @@ func (kb *kubernetesBackupper) backupItem(log logrus.FieldLogger, gr schema.Grou } func (kb *kubernetesBackupper) finalizeItem( + ctx context.Context, // For cancellation log logrus.FieldLogger, gr schema.GroupResource, itemBackupper *itemBackupper, unstructured *unstructured.Unstructured, preferredGVR schema.GroupVersionResource, ) (bool, []FileForArchive) { - backedUpItem, updateFiles, err := itemBackupper.backupItem(log, unstructured, gr, preferredGVR, true, true, nil) + backedUpItem, updateFiles, err := itemBackupper.backupItem(ctx, log, unstructured, gr, preferredGVR, true, true, nil) if aggregate, ok := err.(kubeerrs.Aggregate); ok { log.WithField("name", unstructured.GetName()).Infof("%d errors encountered backup up item", len(aggregate.Errors())) // log each error separately so we get error location info in the log, and an @@ -933,7 +1119,9 @@ func (kb *kubernetesBackupper) backupCRD(log logrus.FieldLogger, gr schema.Group log.Infof("Found associated CRD %s to add to backup", gr.String()) - kb.backupItem(log, gvr.GroupResource(), itemBackupper, unstructured, gvr, nil) + // Get context from itemBackupper + ctx := itemBackupper.backupRequest.BackupContext + kb.backupItem(ctx, log, gvr.GroupResource(), itemBackupper, unstructured, gvr, nil) } func (kb *kubernetesBackupper) writeBackupVersion(tw tarWriter) error { @@ -1058,7 +1246,9 @@ func (kb *kubernetesBackupper) FinalizeBackup( unstructuredDataUploads = append(unstructuredDataUploads, unstructured) } - backedUp, itemFiles := kb.finalizeItem(log, item.groupResource, itemBackupper, &unstructured, item.preferredGVR) + // Get context from itemBackupper + ctx := itemBackupper.backupRequest.BackupContext + backedUp, itemFiles := kb.finalizeItem(ctx, log, item.groupResource, itemBackupper, &unstructured, item.preferredGVR) if backedUp { backedUpGroupResources[item.groupResource] = true for _, itemFile := range itemFiles { diff --git a/pkg/backup/backup_test.go b/pkg/backup/backup_test.go index eb6c2d9d40..376f3fdba6 100644 --- a/pkg/backup/backup_test.go +++ b/pkg/backup/backup_test.go @@ -4055,6 +4055,10 @@ func (b *fakePodVolumeBackupper) ListPodVolumeBackupsByPod(podNamespace, podName return pvbs, nil } +func (b *fakePodVolumeBackupper) CancelAllPodVolumeBackups() ([]*velerov1.PodVolumeBackup, error) { + return b.pvbs, nil +} + // TestBackupWithPodVolume runs backups of pods that are annotated for PodVolume backup, // and ensures that the pod volume backupper is called, that the returned PodVolumeBackups // are added to the Request object, and that when PVCs are backed up with PodVolume, the diff --git a/pkg/backup/context.go b/pkg/backup/context.go new file mode 100644 index 0000000000..3ecae34129 --- /dev/null +++ b/pkg/backup/context.go @@ -0,0 +1,48 @@ +/* +Copyright the Velero Contributors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package backup + +import "context" + +// CheckCancelled checks if the context has been cancelled. +// Returns context.Canceled if cancelled, nil otherwise. +// This provides a consistent cancellation checkpoint across the backup code. +// +// This is used at safe checkpoints throughout the backup process to enable +// fast cancellation without blocking or deadlocks. +// +// If ctx is nil (e.g., in tests), this returns nil (no cancellation). +// +// Example usage: +// +// if err := CheckCancelled(ctx); err != nil { +// log.Info("Backup cancelled") +// return partialResults +// } +func CheckCancelled(ctx context.Context) error { + // Handle nil context (e.g., in tests) + if ctx == nil { + return nil + } + + select { + case <-ctx.Done(): + return ctx.Err() + default: + return nil + } +} diff --git a/pkg/backup/item_backupper.go b/pkg/backup/item_backupper.go index 3622ac7e13..946b50f86c 100644 --- a/pkg/backup/item_backupper.go +++ b/pkg/backup/item_backupper.go @@ -88,12 +88,27 @@ type FileForArchive struct { // If finalize is true, then it returns the bytes instead of writing them to the tarWriter // In addition to the error return, backupItem also returns a bool indicating whether the item // was actually backed up. -func (ib *itemBackupper) backupItem(logger logrus.FieldLogger, obj runtime.Unstructured, groupResource schema.GroupResource, preferredGVR schema.GroupVersionResource, mustInclude, finalize bool, itemBlock *BackupItemBlock) (bool, []FileForArchive, error) { - selectedForBackup, files, err := ib.backupItemInternal(logger, obj, groupResource, preferredGVR, mustInclude, finalize, itemBlock) +func (ib *itemBackupper) backupItem( + ctx context.Context, // For cancellation + logger logrus.FieldLogger, + obj runtime.Unstructured, + groupResource schema.GroupResource, + preferredGVR schema.GroupVersionResource, + mustInclude, finalize bool, + itemBlock *BackupItemBlock, +) (bool, []FileForArchive, error) { + selectedForBackup, files, err := ib.backupItemInternal(ctx, logger, obj, groupResource, preferredGVR, mustInclude, finalize, itemBlock) // return if not selected, an error occurred, there are no files to add, or for finalize if !selectedForBackup || err != nil || len(files) == 0 || finalize { return selectedForBackup, files, err } + + // CHECKPOINT: Before tar writes + if err := CheckCancelled(ctx); err != nil { + logger.Info("Backup cancelled before tar write") + return false, nil, err + } + ib.tarWriter.Lock() defer ib.tarWriter.Unlock() for _, file := range files { @@ -150,7 +165,20 @@ func (ib *itemBackupper) itemInclusionChecks(log logrus.FieldLogger, mustInclude return true } -func (ib *itemBackupper) backupItemInternal(logger logrus.FieldLogger, obj runtime.Unstructured, groupResource schema.GroupResource, preferredGVR schema.GroupVersionResource, mustInclude, finalize bool, itemBlock *BackupItemBlock) (bool, []FileForArchive, error) { +func (ib *itemBackupper) backupItemInternal( + ctx context.Context, // For cancellation + logger logrus.FieldLogger, + obj runtime.Unstructured, + groupResource schema.GroupResource, + preferredGVR schema.GroupVersionResource, + mustInclude, finalize bool, + itemBlock *BackupItemBlock, +) (bool, []FileForArchive, error) { + // CHECKPOINT: At the beginning of item processing + if err := CheckCancelled(ctx); err != nil { + return false, nil, err + } + var itemFiles []FileForArchive metadata, err := meta.Accessor(obj) if err != nil { @@ -237,7 +265,7 @@ func (ib *itemBackupper) backupItemInternal(logger logrus.FieldLogger, obj runti // the group version of the object. versionPath := resourceVersion(obj) - updatedObj, additionalItemFiles, err := ib.executeActions(log, obj, groupResource, name, namespace, metadata, finalize, itemBlock) + updatedObj, additionalItemFiles, err := ib.executeActions(ctx, log, obj, groupResource, name, namespace, metadata, finalize, itemBlock) if err != nil { backupErrs = append(backupErrs, err) return false, itemFiles, kubeerrs.NewAggregate(backupErrs) @@ -342,6 +370,7 @@ func (ib *itemBackupper) backupPodVolumes(log logrus.FieldLogger, pod *corev1api } func (ib *itemBackupper) executeActions( + ctx context.Context, // For cancellation log logrus.FieldLogger, obj runtime.Unstructured, groupResource schema.GroupResource, @@ -489,7 +518,7 @@ func (ib *itemBackupper) executeActions( } for _, item := range itemList { - _, additionalItemFiles, err := ib.backupItem(log, item.Item, additionalItem.GroupResource, item.PreferredGVR, mustInclude, finalize, itemBlock) + _, additionalItemFiles, err := ib.backupItem(ctx, log, item.Item, additionalItem.GroupResource, item.PreferredGVR, mustInclude, finalize, itemBlock) if err != nil { return nil, itemFiles, err } diff --git a/pkg/backup/item_block_worker_pool.go b/pkg/backup/item_block_worker_pool.go index da2cdd9553..6dffd4eda9 100644 --- a/pkg/backup/item_block_worker_pool.go +++ b/pkg/backup/item_block_worker_pool.go @@ -29,6 +29,8 @@ type ItemBlockWorkerPool struct { wg *sync.WaitGroup logger logrus.FieldLogger cancelFunc context.CancelFunc + channelMu sync.Mutex // Protects channelOpen + channelOpen bool // Tracks if channel is still open } type ItemBlockInput struct { @@ -64,6 +66,7 @@ func StartItemBlockWorkerPool(ctx context.Context, workers int, log logrus.Field cancelFunc: cancelFunc, logger: log, wg: wg, + channelOpen: true, // Channel starts open } return pool } @@ -75,24 +78,84 @@ func (p *ItemBlockWorkerPool) Stop() { p.logger.Info("ItemBlock worker stopped") } +// CloseChannel safely closes the input channel to signal workers to stop accepting new work. +// This is used for Tier 1 cancellation - preventing new ItemBlocks from being queued. +// It's safe to call this multiple times (idempotent). +func (p *ItemBlockWorkerPool) CloseChannel() { + p.channelMu.Lock() + defer p.channelMu.Unlock() + + if p.channelOpen { + close(p.inputChannel) + p.channelOpen = false + p.logger.Info("ItemBlock input channel closed for cancellation") + } +} + +// processItemBlockWorker is the main worker function for the ItemBlockWorkerPool. +// Each worker runs this func in a loop, processing ItemBlocks as they are received. func processItemBlockWorker(ctx context.Context, inputChannel chan ItemBlockInput, logger logrus.FieldLogger, wg *sync.WaitGroup) { + defer wg.Done() // Ensure WaitGroup is decremented when worker exits + for { select { - case m := <-inputChannel: - logger.Infof("processing ItemBlock for backup %v", m.itemBlock.itemBackupper.backupRequest.Name) - grList := m.itemBlock.itemBackupper.kubernetesBackupper.backupItemBlock(m.itemBlock) - logger.Infof("finished processing ItemBlock for backup %v", m.itemBlock.itemBackupper.backupRequest.Name) + case m, ok := <-inputChannel: + // TIER 1: Channel closed (no more work) + if !ok { + logger.Info("ItemBlock channel closed, worker exiting") + return + } + + // Get backup context for this ItemBlock + // If not set (e.g., in tests), use background context + backupCtx := m.itemBlock.itemBackupper.backupRequest.BackupContext + if backupCtx == nil { + backupCtx = context.Background() + } + + // TIER 2: Check if backup is already cancelled before processing + select { + case <-backupCtx.Done(): + // Backup cancelled - send error result to ensure WaitGroup decrements + logger.Info("Backup cancelled, skipping ItemBlock processing") + m.returnChan <- ItemBlockReturn{ + itemBlock: m.itemBlock, + resources: nil, + err: backupCtx.Err(), // context.Canceled + } + continue // Don't process, go to next iteration + default: + // Context still valid, continue processing + } + + // Process ItemBlock with backup context + logger.Infof("Processing ItemBlock for backup %v", m.itemBlock.itemBackupper.backupRequest.Name) + grList := m.itemBlock.itemBackupper.kubernetesBackupper.backupItemBlock( + backupCtx, // Pass context for Tier 2 cancellation + m.itemBlock, + ) + logger.Infof("Finished processing ItemBlock for backup %v", m.itemBlock.itemBackupper.backupRequest.Name) + + // Check if context was cancelled during processing + var err error + if backupCtx.Err() != nil { + err = backupCtx.Err() + logger.Infof("Context was cancelled during ItemBlock processing") + } + + // Always send result (even if cancelled mid-processing) m.returnChan <- ItemBlockReturn{ itemBlock: m.itemBlock, resources: grList, - err: nil, + err: err, } + case <-ctx.Done(): - logger.Info("stopping ItemBlock worker") - wg.Done() + // Worker pool context cancelled (controller shutdown) + logger.Info("Worker pool context cancelled, exiting") return } } diff --git a/pkg/backup/request.go b/pkg/backup/request.go index c3dae48a69..5629da4a6b 100644 --- a/pkg/backup/request.go +++ b/pkg/backup/request.go @@ -17,7 +17,9 @@ limitations under the License. package backup import ( + "context" "sync" + "time" "github.com/vmware-tanzu/velero/internal/hook" "github.com/vmware-tanzu/velero/internal/resourcepolicies" @@ -70,6 +72,13 @@ type Request struct { SkippedPVTracker *skipPVTracker VolumesInformation volume.BackupVolumesInformation ItemBlockChannel chan ItemBlockInput + Cancel bool + LastCancelCheck time.Time + + // Cancellation support (two-tier cancellation system) + WorkerPool *ItemBlockWorkerPool // For Tier 1: closing channel to stop workers + BackupContext context.Context // For Tier 2: cancelling in-flight processing + BackupCancelFunc context.CancelFunc // Trigger function for Tier 2 cancellation } // BackupVolumesInformation contains the information needs by generating diff --git a/pkg/cmd/server/server.go b/pkg/cmd/server/server.go index 15c4afd950..adb8ae02a9 100644 --- a/pkg/cmd/server/server.go +++ b/pkg/cmd/server/server.go @@ -572,6 +572,7 @@ func (s *server) runControllers(defaultVolumeSnapshotLocations map[string]string constant.ControllerBackupDeletion: {}, constant.ControllerBackupFinalizer: {}, constant.ControllerBackupOperations: {}, + constant.ControllerBackupCancellation: {}, constant.ControllerBackupRepo: {}, constant.ControllerBackupSync: {}, constant.ControllerDownloadRequest: {}, @@ -590,6 +591,7 @@ func (s *server) runControllers(defaultVolumeSnapshotLocations map[string]string constant.ControllerBackupDeletion, constant.ControllerBackupFinalizer, constant.ControllerBackupOperations, + constant.ControllerBackupCancellation, constant.ControllerGarbageCollection, constant.ControllerSchedule, ) @@ -707,6 +709,21 @@ func (s *server) runControllers(defaultVolumeSnapshotLocations map[string]string } } + if _, ok := enabledRuntimeControllers[constant.ControllerBackupCancellation]; ok { + r := controller.NewBackupCancellationReconciler( + s.logger, + s.mgr.GetClient(), + newPluginManager, + backupStoreGetter, + s.metrics, + backupOpsMap, + backupTracker, + ) + if err := r.SetupWithManager(s.mgr); err != nil { + s.logger.Fatal(err, "unable to create controller", "controller", constant.ControllerBackupCancellation) + } + } + if _, ok := enabledRuntimeControllers[constant.ControllerBackupFinalizer]; ok { backupper, err := backup.NewKubernetesBackupper( s.mgr.GetClient(), diff --git a/pkg/constant/constant.go b/pkg/constant/constant.go index cfadcc5dc5..e2108aca4b 100644 --- a/pkg/constant/constant.go +++ b/pkg/constant/constant.go @@ -2,6 +2,7 @@ package constant const ( ControllerBackup = "backup" + ControllerBackupCancellation = "backup-cancellation" ControllerBackupOperations = "backup-operations" ControllerBackupDeletion = "backup-deletion" ControllerBackupFinalizer = "backup-finalizer" diff --git a/pkg/controller/backup_cancellation_controller.go b/pkg/controller/backup_cancellation_controller.go new file mode 100644 index 0000000000..9bdef72826 --- /dev/null +++ b/pkg/controller/backup_cancellation_controller.go @@ -0,0 +1,153 @@ +/* +Copyright 2020 the Velero contributors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package controller + +import ( + "context" + + "github.com/sirupsen/logrus" + velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + "github.com/vmware-tanzu/velero/pkg/constant" + "github.com/vmware-tanzu/velero/pkg/itemoperationmap" + "github.com/vmware-tanzu/velero/pkg/metrics" + "github.com/vmware-tanzu/velero/pkg/persistence" + "github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt" + kubeutil "github.com/vmware-tanzu/velero/pkg/util/kube" + apierrors "k8s.io/apimachinery/pkg/api/errors" + clocks "k8s.io/utils/clock" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type backupCancellationReconciler struct { + client.Client + logger logrus.FieldLogger + clock clocks.WithTickerAndDelayedExecution + itemOperationsMap *itemoperationmap.BackupItemOperationsMap + newPluginManager func(logger logrus.FieldLogger) clientmgmt.Manager + backupStoreGetter persistence.ObjectBackupStoreGetter + metrics *metrics.ServerMetrics + backupTracker BackupTracker +} + +func NewBackupCancellationReconciler( + logger logrus.FieldLogger, + client client.Client, + newPluginManager func(logrus.FieldLogger) clientmgmt.Manager, + backupStoreGetter persistence.ObjectBackupStoreGetter, + metrics *metrics.ServerMetrics, + itemOperationsMap *itemoperationmap.BackupItemOperationsMap, + backupTracker BackupTracker, +) *backupCancellationReconciler { + return &backupCancellationReconciler{ + Client: client, + logger: logger, + clock: clocks.RealClock{}, + itemOperationsMap: itemOperationsMap, + newPluginManager: newPluginManager, + backupStoreGetter: backupStoreGetter, + metrics: metrics, + backupTracker: backupTracker, + } +} + +func (r *backupCancellationReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&velerov1api.Backup{}). + Named(constant.ControllerBackupCancellation). + Complete(r) +} + +func (r *backupCancellationReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + log := r.logger.WithFields(logrus.Fields{ + "controller": constant.ControllerBackupCancellation, + "backuprequest": req.String(), + }) + + original := &velerov1api.Backup{} + err := r.Client.Get(ctx, req.NamespacedName, original) + if err != nil { + if apierrors.IsNotFound(err) { + log.Debug("backup not found") + return ctrl.Result{}, nil + } + log.WithError(err).Error("error getting backup") + return ctrl.Result{}, err + } + + switch original.Status.Phase { + case "", velerov1api.BackupPhaseCancelling: + // only process cancelling backups + default: + r.logger.WithFields(logrus.Fields{ + "backup": kubeutil.NamespaceAndName(original), + "phase": original.Status.Phase, + }).Debug("Backup is not handled") + return ctrl.Result{}, nil + } + + log.Info("Reconciling backup cancellation") + + log.Debug("Getting backup") + + backup := original.DeepCopy() + log.Debugf("backup: %s", backup.Name) + + log = r.logger.WithFields( + logrus.Fields{ + "backup": req.String(), + }, + ) + + switch original.Status.Phase { + case velerov1api.BackupPhaseCancelling: + // only process cancelling backups + default: + r.logger.WithFields(logrus.Fields{ + "backup": kubeutil.NamespaceAndName(original), + "phase": original.Status.Phase, + }).Debug("Backup is not handled") + return ctrl.Result{}, nil + } + + // Controller successfully catches a cancelling backup + // Retrieve all async ops for the backup + // Lets try to make the funcs in backup_operations_controller usable here + + // After line 113 in backup_cancellation_controller.go: + + // Perform cancellation cleanup + // TODO: Add cleanup logic here (subset of deletion): + // - Delete partial backup data from object storage? + // - Clean up in-progress volume snapshots? + // - Remove temporary files? + + + + //todo: remove backup from backup tracker + r.backupTracker.Delete(backup.Namespace, backup.Name) + + // Then set to cancelled + backup.Status.Phase = velerov1api.BackupPhaseCancelled + + if err := r.Client.Patch(ctx, backup, client.MergeFrom(original)); err != nil { + log.WithError(err).Errorf("error updating backup phase to %v", backup.Status.Phase) + return ctrl.Result{}, err + } + + return ctrl.Result{}, nil +} diff --git a/pkg/controller/backup_controller.go b/pkg/controller/backup_controller.go index c9728ea82a..704cbfb35c 100644 --- a/pkg/controller/backup_controller.go +++ b/pkg/controller/backup_controller.go @@ -268,6 +268,9 @@ func (b *backupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr request := b.prepareBackupRequest(original, log) if len(request.Status.ValidationErrors) > 0 { request.Status.Phase = velerov1api.BackupPhaseFailedValidation + } else if original.Spec.Cancel != nil && *original.Spec.Cancel { + log.Infof("Marking backup %s Cancelled", original.Name) + request.Status.Phase = velerov1api.BackupPhaseCancelling } else { request.Status.Phase = velerov1api.BackupPhaseInProgress request.Status.StartTimestamp = &metav1.Time{Time: b.clock.Now()} @@ -281,6 +284,11 @@ func (b *backupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr return ctrl.Result{}, errors.Wrapf(err, "error updating Backup status to %s", request.Status.Phase) } + if request.Status.Phase == velerov1api.BackupPhaseCancelling { + log.Infof("Marking backup %s Cancelled", original.Name) + return ctrl.Result{}, nil + } + backupScheduleName := request.GetLabels()[velerov1api.ScheduleNameLabel] if request.Status.Phase == velerov1api.BackupPhaseFailedValidation { @@ -332,6 +340,9 @@ func (b *backupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr case velerov1api.BackupPhaseFailedValidation: b.metrics.RegisterBackupValidationFailure(backupScheduleName) b.metrics.RegisterBackupLastStatus(backupScheduleName, metrics.BackupLastStatusFailure) + case velerov1api.BackupPhaseCancelling: + b.metrics.RegisterBackupFailed(backupScheduleName) + b.metrics.RegisterBackupLastStatus(backupScheduleName, metrics.BackupLastStatusFailure) } log.Info("Updating backup's status") // Phases were updated in runBackup() @@ -340,6 +351,7 @@ func (b *backupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr // BackupPhaseWaitingForPluginOperationsPartiallyFailed -> backup_operations_controller.go will now reconcile // BackupPhaseFinalizing -> backup_finalizer_controller.go will now reconcile // BackupPhaseFinalizingPartiallyFailed -> backup_finalizer_controller.go will now reconcile + // todo: BackupPhaseCancelling -> backup_cancellation_controller.go will now reconcile // BackupPhaseFailed if err := kubeutil.PatchResourceWithRetriesOnErrors(b.resourceTimeout, original, request.Backup, b.kbClient); err != nil { log.WithError(err).Errorf("error updating backup's status from %v to %v", original.Status.Phase, request.Backup.Status.Phase) @@ -348,11 +360,19 @@ func (b *backupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr } func (b *backupReconciler) prepareBackupRequest(backup *velerov1api.Backup, logger logrus.FieldLogger) *pkgbackup.Request { + // Create backup-specific context for Tier 2 cancellation + backupCtx, backupCancelFunc := context.WithCancel(b.ctx) + request := &pkgbackup.Request{ Backup: backup.DeepCopy(), // don't modify items in the cache SkippedPVTracker: pkgbackup.NewSkipPVTracker(), BackedUpItems: pkgbackup.NewBackedUpItemsMap(), ItemBlockChannel: b.workerPool.GetInputChannel(), + + // Cancellation support (two-tier cancellation system) + WorkerPool: b.workerPool, // For Tier 1: closing channel to stop workers + BackupContext: backupCtx, // For Tier 2: cancelling in-flight processing + BackupCancelFunc: backupCancelFunc, // Trigger function for Tier 2 cancellation } request.VolumesInformation.Init() @@ -676,6 +696,9 @@ func (b *backupReconciler) validateAndGetSnapshotLocations(backup *velerov1api.B // field is checked to see if the backup was a partial failure. func (b *backupReconciler) runBackup(backup *pkgbackup.Request) error { + // Ensure backup context is cancelled when we exit to prevent context leaks + defer backup.BackupCancelFunc() + b.logger.WithField(constant.ControllerBackup, kubeutil.NamespaceAndName(backup)).Info("Setting up backup log") // Log the backup to both a backup log file and to stdout. This will help see what happened if the upload of the @@ -732,6 +755,9 @@ func (b *backupReconciler) runBackup(backup *pkgbackup.Request) error { fatalErrs = append(fatalErrs, err) } + // Investigate how early we can transition phase to Cancelling, what we need to pass tocancel async ops + // todo: get cancel from backup request + // native snapshots phase will either be failed or completed right away // https://github.com/vmware-tanzu/velero/blob/de3ea52f0cc478e99efa7b9524c7f353514261a4/pkg/backup/item_backupper.go#L632-L639 backup.Status.VolumeSnapshotsAttempted = len(backup.VolumeSnapshots.Get()) @@ -748,7 +774,7 @@ func (b *backupReconciler) runBackup(backup *pkgbackup.Request) error { // Any errors on operations at this point should be added to backup errors. // If any operations are still not complete, then back will not be set to // Completed yet. - inProgressOperations, _, opsCompleted, opsFailed, errs := getBackupItemOperationProgress(backup.Backup, pluginManager, *backup.GetItemOperationsList()) + inProgressOperations, _, opsCompleted, opsFailed, errs := getBackupItemOperationProgress(backup.Backup, pluginManager, *backup.GetItemOperationsList(), backupLog) if len(errs) > 0 { for _, err := range errs { backupLog.Error(err) @@ -784,6 +810,9 @@ func (b *backupReconciler) runBackup(backup *pkgbackup.Request) error { } else { backup.Status.Phase = velerov1api.BackupPhaseFinalizingPartiallyFailed } + case backup.Cancel: // Check cancellation first + backupLog.Info("Marking backup as cancelling in runBackup") + backup.Status.Phase = velerov1api.BackupPhaseCancelling default: if inProgressOperations { backup.Status.Phase = velerov1api.BackupPhaseWaitingForPluginOperations @@ -795,7 +824,8 @@ func (b *backupReconciler) runBackup(backup *pkgbackup.Request) error { // Otherwise, the JSON file in object storage has a CompletionTimestamp of 'null'. if backup.Status.Phase == velerov1api.BackupPhaseFailed || backup.Status.Phase == velerov1api.BackupPhasePartiallyFailed || - backup.Status.Phase == velerov1api.BackupPhaseCompleted { + backup.Status.Phase == velerov1api.BackupPhaseCompleted || + backup.Status.Phase == velerov1api.BackupPhaseCancelling { backup.Status.CompletionTimestamp = &metav1.Time{Time: b.clock.Now()} } recordBackupMetrics(backupLog, backup.Backup, backupFile, b.metrics, false) diff --git a/pkg/controller/backup_deletion_controller.go b/pkg/controller/backup_deletion_controller.go index 5a791999c8..206d5fa5c2 100644 --- a/pkg/controller/backup_deletion_controller.go +++ b/pkg/controller/backup_deletion_controller.go @@ -123,6 +123,8 @@ func (r *backupDeletionReconciler) Reconcile(ctx context.Context, req ctrl.Reque "controller": constant.ControllerBackupDeletion, "deletebackuprequest": req.String(), }) + + // Controller works on DeleteBackupRequest objects log.Debug("Getting deletebackuprequest") dbr := &velerov1api.DeleteBackupRequest{} if err := r.Get(ctx, req.NamespacedName, dbr); err != nil { @@ -156,6 +158,7 @@ func (r *backupDeletionReconciler) Reconcile(ctx context.Context, req ctrl.Reque return ctrl.Result{}, err } + // BackupDeleteRequest has the backup name in the spec log = log.WithField("backup", dbr.Spec.BackupName) // Remove any existing deletion requests for this backup so we only have @@ -165,9 +168,16 @@ func (r *backupDeletionReconciler) Reconcile(ctx context.Context, req ctrl.Reque } // Don't allow deleting an in-progress backup + // todo: If cancellation is implented, we would set backup.Spec.Cancel to true + // how would we return here? as opposed to a user-canceled backup, where do do not delete everything + // another flag to send it back to deletion controller? if r.backupTracker.Contains(dbr.Namespace, dbr.Spec.BackupName) { err := r.patchDeleteBackupRequestWithError(ctx, dbr, errors.New("backup is still in progress")) return ctrl.Result{}, err + + // Cancellation Scenario: + // Set backup.Spec.Cancel to true + // exponential backoff; by the time it comes back, it will be removed from the backup tracker from backup_cancellation_controller } // Get the backup we're trying to delete diff --git a/pkg/controller/backup_finalizer_controller.go b/pkg/controller/backup_finalizer_controller.go index b24c132fa9..7df6421cc1 100644 --- a/pkg/controller/backup_finalizer_controller.go +++ b/pkg/controller/backup_finalizer_controller.go @@ -87,11 +87,12 @@ func NewBackupFinalizerReconciler( // +kubebuilder:rbac:groups=velero.io,resources=backups/status,verbs=get;update;patch func (r *backupFinalizerReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + + // LOG log := r.log.WithFields(logrus.Fields{ "controller": "backup-finalizer", "backup": req.NamespacedName, }) - // Fetch the Backup instance. log.Debug("Getting Backup") backup := &velerov1api.Backup{} @@ -105,6 +106,7 @@ func (r *backupFinalizerReconciler) Reconcile(ctx context.Context, req ctrl.Requ return ctrl.Result{}, errors.WithStack(err) } + // Check phase, only process if phase matches switch backup.Status.Phase { case velerov1api.BackupPhaseFinalizing, velerov1api.BackupPhaseFinalizingPartiallyFailed: // only process backups finalizing after plugin operations are complete @@ -113,6 +115,7 @@ func (r *backupFinalizerReconciler) Reconcile(ctx context.Context, req ctrl.Requ return ctrl.Result{}, nil } + // Defer func to patch backup object and status after each reconciliation original := backup.DeepCopy() defer func() { switch backup.Status.Phase { @@ -133,7 +136,9 @@ func (r *backupFinalizerReconciler) Reconcile(ctx context.Context, req ctrl.Requ return } }() - + + // Get the operations associated with the backup + // BackupLocation -> backupStore -> backupItemOperations location := &velerov1api.BackupStorageLocation{} if err := r.client.Get(ctx, kbclient.ObjectKey{ Namespace: backup.Namespace, @@ -163,8 +168,11 @@ func (r *backupFinalizerReconciler) Reconcile(ctx context.Context, req ctrl.Requ SkippedPVTracker: pkgbackup.NewSkipPVTracker(), BackedUpItems: pkgbackup.NewBackedUpItemsMap(), } + var outBackupFile *os.File if len(operations) > 0 { + + // File inits log.Info("Setting up finalized backup temp file") inBackupFile, err := downloadToTempFile(backup.Name, backupStore, log) if err != nil { @@ -178,6 +186,7 @@ func (r *backupFinalizerReconciler) Reconcile(ctx context.Context, req ctrl.Requ } defer closeAndRemoveFile(outBackupFile, log) + // Get all possible plugin actions log.Info("Getting backup item actions") actions, err := pluginManager.GetBackupItemActionsV2() if err != nil { @@ -201,6 +210,8 @@ func (r *backupFinalizerReconciler) Reconcile(ctx context.Context, req ctrl.Requ return ctrl.Result{}, errors.WithStack(err) } } + + backupScheduleName := backupRequest.GetLabels()[velerov1api.ScheduleNameLabel] switch backup.Status.Phase { case velerov1api.BackupPhaseFinalizing: diff --git a/pkg/controller/backup_operations_controller.go b/pkg/controller/backup_operations_controller.go index 1a5b49c0b2..b76bf7bb4f 100644 --- a/pkg/controller/backup_operations_controller.go +++ b/pkg/controller/backup_operations_controller.go @@ -180,7 +180,7 @@ func (c *backupOperationsReconciler) Reconcile(ctx context.Context, req ctrl.Req } return ctrl.Result{}, errors.Wrap(err, "error getting backup operations") } - stillInProgress, changes, opsCompleted, opsFailed, errs := getBackupItemOperationProgress(backup, pluginManager, operations.Operations) + stillInProgress, changes, opsCompleted, opsFailed, errs := getBackupItemOperationProgress(backup, pluginManager, operations.Operations, log) // if len(errs)>0, need to update backup errors and error log operations.ErrsSinceUpdate = append(operations.ErrsSinceUpdate, errs...) backup.Status.Errors += len(operations.ErrsSinceUpdate) @@ -203,7 +203,10 @@ func (c *backupOperationsReconciler) Reconcile(ctx context.Context, req ctrl.Req // BackupPhaseWaitingForPluginOperationsPartiallyFailed and needs update // If the only changes are incremental progress, then no write is necessary, progress can remain in memory if !stillInProgress { - if backup.Status.Phase == velerov1api.BackupPhaseWaitingForPluginOperations { + if isBackupCancelled(backup) { + log.Infof("Marking backup %s Cancelled", backup.Name) + backup.Status.Phase = velerov1api.BackupPhaseCancelling + } else if backup.Status.Phase == velerov1api.BackupPhaseWaitingForPluginOperations { log.Infof("Marking backup %s Finalizing", backup.Name) backup.Status.Phase = velerov1api.BackupPhaseFinalizing } else { @@ -289,12 +292,15 @@ func (c *backupOperationsReconciler) updateBackupAndOperationsJSON( func getBackupItemOperationProgress( backup *velerov1api.Backup, pluginManager clientmgmt.Manager, - operationsList []*itemoperation.BackupOperation) (bool, bool, int, int, []string) { + operationsList []*itemoperation.BackupOperation, + log logrus.FieldLogger) (bool, bool, int, int, []string) { inProgressOperations := false changes := false var errs []string var completedCount, failedCount int + log.Info("Getting backup item operation progress:") + log.Info("length of operationsList: %v", len(operationsList)) for _, operation := range operationsList { if operation.Status.Phase == itemoperation.OperationPhaseNew || operation.Status.Phase == itemoperation.OperationPhaseInProgress { @@ -360,10 +366,19 @@ func getBackupItemOperationProgress( continue } // cancel operation if past timeout period - if operation.Status.Created.Time.Add(backup.Spec.ItemOperationTimeout.Duration).Before(time.Now()) { + if operation.Status.Created.Time.Add(backup.Spec.ItemOperationTimeout.Duration).Before(time.Now()) || isBackupCancelled(backup) { + if isBackupCancelled(backup) { + log.Info("Cancelling operation because backup is cancelled") + } else { + log.Info("Cancelling operation because it has timed out") + } _ = bia.Cancel(operation.Spec.OperationID, backup) operation.Status.Phase = itemoperation.OperationPhaseFailed - operation.Status.Error = "Asynchronous action timed out" + if isBackupCancelled(backup) { + operation.Status.Error = "Asynchronous action cancelled" + } else { + operation.Status.Error = "Asynchronous action timed out" + } errs = append(errs, wrapErrMsg(operation.Status.Error, bia)) changes = true failedCount++ @@ -396,3 +411,7 @@ func wrapErrMsg(errMsg string, bia v2.BackupItemAction) string { } return fmt.Sprintf("%splugin: %s", errMsg, plugin) } + +func isBackupCancelled(backup *velerov1api.Backup) bool { + return backup.Spec.Cancel != nil && *backup.Spec.Cancel +} diff --git a/pkg/podvolume/backupper.go b/pkg/podvolume/backupper.go index fba3cb19a6..fb641cb4c6 100644 --- a/pkg/podvolume/backupper.go +++ b/pkg/podvolume/backupper.go @@ -55,6 +55,7 @@ type Backupper interface { WaitAllPodVolumesProcessed(log logrus.FieldLogger) []*velerov1api.PodVolumeBackup GetPodVolumeBackupByPodAndVolume(podNamespace, podName, volume string) (*velerov1api.PodVolumeBackup, error) ListPodVolumeBackupsByPod(podNamespace, podName string) ([]*velerov1api.PodVolumeBackup, error) + CancelAllPodVolumeBackups() ([]*velerov1api.PodVolumeBackup, error) } type backupper struct { @@ -557,3 +558,27 @@ func newPodVolumeBackup(backup *velerov1api.Backup, pod *corev1api.Pod, volume c return pvb } + +// CancelAllPodVolumeBackups cancels all the PVBs by setting spec.cancel to true +func (b *backupper) CancelAllPodVolumeBackups() ([]*velerov1api.PodVolumeBackup, error) { + objs := b.pvbIndexer.List() + + pvbs := make([]*velerov1api.PodVolumeBackup, len(objs)) + for i, obj := range objs { + pvb, ok := obj.(*velerov1api.PodVolumeBackup) + if !ok { + return nil, errors.Errorf("expected PodVolumeBackup, but got %T", obj) + } + pvbs[i] = pvb + } + for _, pvb := range pvbs { + pvb.Spec.Cancel = true + } + for _, pvb := range pvbs { + pvb.Spec.Cancel = true + if err := b.crClient.Update(b.ctx, pvb); err != nil { + return nil, err + } + } + return pvbs, nil +}