# mistral workflow 模板

## 虚机（server）快照创建及定期删除

### 创建虚机快照

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83  --- version: "2.0" create_vm_snapshot: type: direct input: - server_id - image_name - ttl_days - ttl_hours description: create an image(snapshot) from a server. tasks: check_vm_ttl: description: the values(ttl_days, ttl_hours) should be NUMBER, and at least zero. After this operation, the input values will convert to integers. Otherwise, the next tasks would not be executed! action: std.javascript input: context: <% $%> script: | var tag_ttl = 'ERROR'; var ttl_days = Math.round(Number($.ttl_days)); var ttl_hours = Math.round(Number($.ttl_hours)); if(ttl_days >= 0 && ttl_hours >= 0){ tag_ttl = ttl_days + '_' + ttl_hours; } else{ throw new Error('check error!'); } return tag_ttl; publish: tag_ttl: <% task(check_vm_ttl).result %> check_state: SUCCESS publish-on-error: check_state: ERROR reinput_hint: The input values are incorrect and need to input again. on-success: - create_vm_snapshot: <%$.tag_ttl != ERROR %> create_vm_snapshot: description: create an image(snapshot) from a server. action: nova.servers_create_image server=<% $.server_id %> image_name=<%$.image_name %> publish: snap_image_id: <% task(create_vm_snapshot).result %> create_state: SUCCESS publish-on-error: create_state: ERROR on-success: - update_image_workflowtag update_image_workflowtag: description: create a workflow tag for server. action: glance.image_tags_update image_id=<% $.snap_image_id %> tag_value='created_by_mistral' publish: update_workflowtag_state: SUCCESS publish-on-error: update_workflowtag_state: ERROR on-success: - update_image_ttltag update_image_ttltag: description: create a ttl tag for server. action: glance.image_tags_update image_id=<%$.snap_image_id %> tag_value=<% $.tag_ttl %> retry: delay: 10 count: 1 publish: update_ttltag_state: SUCCESS publish-on-error: update_ttltag_state: ERROR on-success: - wait_for_image wait_for_image: description: Ensure the vm snapshot was created successfully. action: glance.images_get image_id=<%$.snap_image_id %> wait-before: 5 publish: tag_value: <% task(wait_for_image).result.tags %> wait_state: SUCCESS publish-on-error: wait_state: ERROR retry: delay: 10 count: 5 

### 删除过期虚机快照

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62  --- version: '2.0' judge_expiration_vm_snapshot: type: direct description: Judge expired snapshots and delete them. tasks: list_vm_snapshots: description: List all vm snapshots created by mistral. action: glance.images_list publish: ids: <% task(list_vm_snapshots).result.where($.tags.len()=2 and$.tags.contains('created_by_mistral')).select($.id) %> created_ats: <% task(list_vm_snapshots).result.where($.tags.len()=2 and $.tags.contains('created_by_mistral')).select($.created_at) %> ttls: <% task(list_vm_snapshots).result.where($.tags.len()=2 and$.tags.contains('created_by_mistral')).select($.tags[-1]) %> list_state: SUCCESS publish-on-error: list_state: ERROR on-success: - check_expiration_vm_snapshots check_expiration_vm_snapshots: description: Find out all expired vm snapshots. with-items: - image_id in <%$.ids %> - created_at in <% $.created_ats %> - ttl in <%$.ttls %> action: std.javascript input: context: <% $%> script: | var dic = {}; var ttl =$.ttl.split('_'); var now_time = new Date(); var created_time = new Date('<% $.created_at %>'); var tmp_time = new Date(created_time.setDate(created_time.getDate() + Math.round(Number(ttl[0])))); var expire_time = tmp_time.setHours(tmp_time.getHours() + Math.round(Number(ttl[1]))); dic.enable_delete = (now_time > expire_time); dic.now_time = now_time.toISOString(); dic.expire_time = new Date(expire_time).toISOString(); dic.resource_id = '<%$.image_id %>'; return dic; retry: delay: 5 count: 10 continue-on: <% task(check_expiration_vm_snapshots).result.enable_delete = true %> publish: del_image_ids: <% task(check_expiration_vm_snapshots).result.where($.enable_delete = true).select($.resource_id) %> check_state: SUCCESS publish-on-error: check_state: ERROR on-success: - delete_vm_snapshots delete_vm_snapshots: description: Delete all expired vm snapshots. with-items: del_image_id in <% $.del_image_ids %> action: glance.images_delete image_id=<%$.del_image_id %> wait-before: 5 publish: delete_state: SUCCESS publish-on-error: delete_state: ERROR 

### 删除过期卷快照

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59  --- version: '2.0' judge_expiration_vol_snapshot: type: direct description: Judge expired snapshots and delete them. tasks: list_volume_snapshots: description: List all volume snapshots created by mistral. action: cinder.volume_snapshots_list publish: ids: <% task().result.where($.metadata.len()=2 and$.metadata.property_tag='created_by_mistral').select($.id) %> created_ats: <% task().result.where($.metadata.len()=2 and $.metadata.property_tag='created_by_mistral').select($.created_at) %> ttls: <% task().result.where($.metadata.len()=2 and$.metadata.property_tag='created_by_mistral').select($.metadata.property_ttl) %> on-success: - check_expiration_volume_snapshots check_expiration_volume_snapshots: description: Find out all expired vm snapshots. with-items: - snapshot_id in <%$.ids %> - created_at in <% $.created_ats %> - ttl in <%$.ttls %> action: std.javascript input: context: <% $%> script: | var dic = {}; var ttl =$.ttl.split('_'); var now_time = new Date(); var created_time = new Date('<% $.created_at %>'); var tmp_time = new Date(created_time.setDate(created_time.getDate() + Math.round(Number(ttl[0])))); var expire_time = tmp_time.setHours(tmp_time.getHours() + Math.round(Number(ttl[1]))); dic.enable_delete = (now_time > expire_time); dic.now_time = now_time.toISOString(); dic.expire_time = new Date(expire_time).toISOString(); dic.resource_id = '<%$.snapshot_id %>'; return dic; retry: delay: 5 count: 10 continue-on: <% task(check_expiration_volume_snapshots).result.enable_delete = true %> publish: del_vol_snapshot_ids: <% task(check_expiration_volume_snapshots).result.where($.enable_delete = true).select($.resource_id) %> check_state: SUCCESS publish-on-error: check_state: ERROR on-success: - delete_volume_snapshot delete_volume_snapshot: description: Delete all expired volume snapshots. with-items: del_vol_snapshot_id in <% $.del_vol_snapshot_ids %> action: cinder.volume_snapshots_delete snapshot=<%$.del_vol_snapshot_id %> force=false wait-before: 5 publish: delete_state: SUCCESS publish-on-error: delete_state: ERROR 

## 总结说明

1. 将创建的动作和检查到期并删除的动作逻辑写在同一个 workflow 中。

这样写的特点是：

• 当对这个 workflow 创建定时任务时，“创建”和“检查到期并删除”的执行频率是一致的。比如：用户设置定 时任务每隔 5 天执行一次这个 workflow，保留快照时间为 2 天，那么同时“检查到期并删除”也是每隔 5 天执行一次，这时快照只有 2 天的 生存周期，workflow 5 天后再一次被执行时才去“检查到期并删除”，那么这就造成了删除时间的延迟
• 这种方式只能查询单个的快照是否过期，即当前所创建的快照，过期删除，不能批量查询
2. 将创建的动作和检查到期并删除的动作逻辑分开写在两个不同的 workflow 中，比如是 wfA 和 wfB

这样写的特点是：

• 当对这个 wfA 创建定时任务时，它会定时创建快照；wfB 定时”检查到期并删除“，但是这两个 workflow 的 执行频率可以不一致，可自行根据需求来设置
• 这种方式可以批量查询所有快照是否过期，过期则删除