hcs-cli 0.1.321__py3-none-any.whl → 0.1.323__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,10 +8,123 @@ from hcs_cli.support.scm.html_util import show_html
8
8
 
9
9
 
10
10
  def _timestamp_to_date(timestamp: int):
11
- return datetime.fromtimestamp(timestamp / 1000).strftime("%Y-%m-%dT%H:%M")
11
+ return datetime.utcfromtimestamp(timestamp / 1000).strftime("%Y-%m-%dT%H:%M")
12
12
 
13
13
 
14
- def edit_plan(plan: dict, template_name: str):
14
+ def _process_usage_data(usage_api: dict, template_name: str):
15
+ """Process usage API data for the usage chart."""
16
+ if not usage_api:
17
+ return None
18
+
19
+ x_axis = []
20
+ consumed_capacity = []
21
+ spare_capacity = []
22
+ no_spare_error = []
23
+ powered_on_vms = []
24
+ consumed_capacity_predicated = []
25
+ spare_capacity_predicated = []
26
+ no_spare_error_predicated = []
27
+ optimized_capacity = []
28
+
29
+ history = usage_api.get("history", {})
30
+ prediction = usage_api.get("prediction", {})
31
+ timeslot_ms = usage_api.get("timeslotMs", 0)
32
+
33
+ start_timestamp = history.get("startTimestamp", 0)
34
+ for i in range(len(history.get("maxCapacity", []))):
35
+ t = start_timestamp + i * timeslot_ms
36
+ x_axis.append(_timestamp_to_date(t))
37
+ max_capacity = history["maxCapacity"][i]
38
+ min_free = history["minFree"][i]
39
+ consumed_capacity.append(history["poweredOnAssignedVms"][i])
40
+ spare_capacity.append(max_capacity - consumed_capacity[-1])
41
+ no_spare_error.append(history["noSpare"][i])
42
+ # Calculate poweredOnVms = poweredOnAssignedVms + poweredOnUnassignedVms
43
+ assigned = history.get("poweredOnAssignedVms", [0])[i] if i < len(history.get("poweredOnAssignedVms", [])) else 0
44
+ unassigned = history.get("poweredOnUnassignedVms", [0])[i] if i < len(history.get("poweredOnUnassignedVms", [])) else 0
45
+ powered_on_vms.append(assigned + unassigned)
46
+
47
+ start_timestamp = prediction.get("startTimestamp", 0)
48
+ for i in range(len(prediction.get("maxCapacity", []))):
49
+ t = start_timestamp + i * timeslot_ms
50
+ x_axis.append(_timestamp_to_date(t))
51
+ max_capacity = prediction["maxCapacity"][i]
52
+ min_free = prediction["minFree"][i]
53
+ ideal_capacity = prediction["idealCapacity"][i]
54
+ consumed_capacity_predicated.append(ideal_capacity)
55
+ spare_capacity_predicated.append(min_free)
56
+ optimized_capacity.append(ideal_capacity)
57
+ no_spare_error_predicated.append(prediction["noSpare"][i])
58
+
59
+ # split_index marks where real data ends and predicted data begins
60
+ split_index = len(consumed_capacity)
61
+
62
+ n = len(consumed_capacity) - 1
63
+ consumed_capacity_predicated = [0] * n + [consumed_capacity[-1]] + consumed_capacity_predicated
64
+ spare_capacity_predicated = [0] * n + [0] + spare_capacity_predicated
65
+ optimized_capacity = [0] * n + [0] + optimized_capacity
66
+ no_spare_error_predicated = [0] * n + [no_spare_error[-1]] + no_spare_error_predicated
67
+
68
+ # Calculate predicated powered on vms based on historical data
69
+ # Structure: [zeros for historical period] + [predictions for 7 days (336 slots)]
70
+ # Each week is 336 time slots (48 slots/day * 7 days)
71
+ # Formula: slot[N] = 0.85 * slot[N-336] + 0.15 * (slot[N-336*2] + slot[N-336*3] + slot[N-336*4]) / 3
72
+ powered_on_vms_predicated = []
73
+ total_historical_slots = len(powered_on_vms)
74
+
75
+ # First part: zeros for the historical period
76
+ powered_on_vms_predicated.extend([0] * total_historical_slots)
77
+
78
+ # Second part: 7 days of predictions (336 slots)
79
+ for day_offset in range(7): # 7 days
80
+ for slot_in_day in range(48): # 48 slots per day
81
+ slot_index = day_offset * 48 + slot_in_day
82
+
83
+ # Calculate which slot in the future we're predicting
84
+ # This is relative to the end of historical data
85
+ predict_slot = total_historical_slots + slot_index
86
+
87
+ # Look back to find corresponding slots from previous weeks
88
+ weeks_ago_1 = predict_slot - 336
89
+
90
+ # Get the value from 1 week ago if available
91
+ value_1_week = 0
92
+ if weeks_ago_1 >= 0 and weeks_ago_1 < total_historical_slots:
93
+ value_1_week = powered_on_vms[weeks_ago_1]
94
+
95
+ # Collect values from 2, 3, 4 weeks ago for averaging
96
+ secondary_values = []
97
+ for weeks in [2, 3, 4]:
98
+ weeks_ago = predict_slot - 336 * weeks
99
+ if weeks_ago >= 0 and weeks_ago < total_historical_slots:
100
+ secondary_values.append(powered_on_vms[weeks_ago])
101
+
102
+ # Calculate the average of secondary values
103
+ if secondary_values:
104
+ avg_secondary = sum(secondary_values) / len(secondary_values)
105
+ else:
106
+ avg_secondary = value_1_week
107
+
108
+ # Apply formula: 0.85 * week_1_ago + 0.15 * avg(weeks_2_3_4_ago)
109
+ value = 0.85 * value_1_week + 0.15 * avg_secondary
110
+ powered_on_vms_predicated.append(value)
111
+
112
+ return {
113
+ "x_axis": x_axis,
114
+ "consumed_capacity": consumed_capacity,
115
+ "spare_capacity": spare_capacity,
116
+ "no_spare_error": no_spare_error,
117
+ "powered_on_vms": powered_on_vms,
118
+ "powered_on_vms_predicated": powered_on_vms_predicated,
119
+ "consumed_capacity_predicated": consumed_capacity_predicated,
120
+ "spare_capacity_predicated": spare_capacity_predicated,
121
+ "no_spare_error_predicated": no_spare_error_predicated,
122
+ "optimized_capacity": optimized_capacity,
123
+ "split_index": split_index,
124
+ }
125
+
126
+
127
+ def edit_plan(plan: dict, template_name: str, usage_api: dict = None, template_id: str = None, org_id: str = None):
15
128
  # Start a local server to host plan-editor3.
16
129
  file_path = path.join(path.dirname(__file__), "plan-editor.html.template")
17
130
  with open(file_path, "r") as f:
@@ -61,19 +174,31 @@ def edit_plan(plan: dict, template_name: str):
61
174
  del usage["prediction"]
62
175
  del usage["timeslotMs"]
63
176
 
177
+ # Process usage API data for the usage chart
178
+ usage_chart_data = _process_usage_data(usage_api, template_name)
179
+
180
+ # Format the template ID path
181
+ template_id_path = ""
182
+ if org_id and template_id:
183
+ template_id_path = f"org/{org_id}/pool/{template_id}"
184
+ elif template_id:
185
+ template_id_path = template_id
186
+
64
187
  html_template = template.replace(
65
188
  html_template,
66
189
  {
67
190
  "PLAN_DATA": json.dumps(plan),
191
+ "TEMPLATE_NAME": template_name,
192
+ "TEMPLATE_ID_PATH": template_id_path,
68
193
  "x_axis": x_axis,
69
194
  "template_name": template_name,
70
- "consumed_capacity": consumed_capacity,
71
195
  "spare_capacity": spare_capacity,
72
196
  "no_spare_error": no_spare_error,
73
197
  "consumed_capacity_predicated": consumed_capacity_predicated,
74
198
  "spare_capacity_predicated": spare_capacity_predicated,
75
199
  "no_spare_error_predicated": no_spare_error_predicated,
76
200
  "optimized_capacity": optimized_capacity,
201
+ "USAGE_CHART_DATA": json.dumps(usage_chart_data) if usage_chart_data else "null",
77
202
  },
78
203
  True,
79
204
  False,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hcs-cli
3
- Version: 0.1.321
3
+ Version: 0.1.323
4
4
  Summary: Horizon Cloud Service CLI.
5
5
  Project-URL: Homepage, https://github.com/euc-eng/hcs-cli
6
6
  Project-URL: Bug Tracker, https://github.com/euc-eng/hcs-cli/issues
@@ -14,7 +14,7 @@ Classifier: License :: OSI Approved :: MIT License
14
14
  Classifier: Operating System :: OS Independent
15
15
  Classifier: Programming Language :: Python :: 3
16
16
  Requires-Python: >=3.9
17
- Requires-Dist: hcs-core>=0.1.321
17
+ Requires-Dist: hcs-core>=0.1.323
18
18
  Requires-Dist: inquirerpy>=0.3.4
19
19
  Requires-Dist: matplotlib>=3.8.0
20
20
  Requires-Dist: paho-mqtt>=2.1.0
@@ -1,13 +1,13 @@
1
- hcs_cli/__init__.py,sha256=dX6e1kri6Gcqjvlr5u1l5USUlOgjbOKPHS5vP_FG78Y,72
1
+ hcs_cli/__init__.py,sha256=7KW1VRAYQU035f2jaLhiQJVZNuy6DZMC5son4DF-wQQ,72
2
2
  hcs_cli/__main__.py,sha256=lwPXLjh1OpOs4doVLJJ6_3XHtC-VqDOXiw45hvAQorM,684
3
3
  hcs_cli/main.py,sha256=0NmRcidxNxtJatS_prEKQ4_6bqu-l8UkLhAPOXW3uyc,3537
4
4
  hcs_cli/cmds/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- hcs_cli/cmds/api.py,sha256=IIz-vORyL5EzDOSCOSgdP_6MIjGG6KvinnCkyg8JUpg,7015
5
+ hcs_cli/cmds/api.py,sha256=HhIR3_09twsGvIx861XgGR_GuEQV8pUCtXiJrp2QuUA,6312
6
6
  hcs_cli/cmds/inspect.py,sha256=QBhBOkf2mHlGhgAhY9FXCfvViL2p4D3BudoKjyADdfE,659
7
7
  hcs_cli/cmds/login.py,sha256=dj42jDrKktt4bUqSD0Xj6Jo9ZSI7M9v9R280YavWpuc,11165
8
8
  hcs_cli/cmds/logout.py,sha256=BxU-K1cIkdBpAAp6SGuwEqECL6g20l9CqEcSX-3pZag,744
9
9
  hcs_cli/cmds/query.py,sha256=hh1TVeSkvRiB07fqIA3GGpEBtP3XMz5XCmAGTXD7FOM,9302
10
- hcs_cli/cmds/task.py,sha256=YIZUjDzHZaNCbmAt589Nzp8s7NMsBI7w_a33l109iy8,19564
10
+ hcs_cli/cmds/task.py,sha256=Jup7VS2sNLz98Zc3o-WhZA7HM5RWadvUKiwIOkjWM0s,21572
11
11
  hcs_cli/cmds/test.py,sha256=Kkpe3wV3ViRRAKeMO5IBwjTysEsKzZXP46OXNb-GhxE,1309
12
12
  hcs_cli/cmds/upgrade.py,sha256=iJYSyxyNBhiss0u605nD6jpYUdoDhjfIeJP98zSeDf4,931
13
13
  hcs_cli/cmds/ad/__init__.py,sha256=wC4uftNZRN3bo9SrRHNNE1tzE0x3B1mCXcIzARm73gI,636
@@ -43,7 +43,7 @@ hcs_cli/cmds/auth/user/__init__.py,sha256=a0hkNUCmxpMRnEf0iDRrW0oI2G2S1oCQmMeuqC
43
43
  hcs_cli/cmds/auth/user/list.py,sha256=-r-xMjZLrCteXlDgqTZU0F2Uutj1iE72y_LSlp4q9po,1444
44
44
  hcs_cli/cmds/clouddriver/__init__.py,sha256=CXJ0wWXJkL89XMNXYkHH7TXkq10TH5JBy8Yhs48PCis,639
45
45
  hcs_cli/cmds/clouddriver/provider.py,sha256=EOsJrxnNZwdfHGuUsjDBWOWDj0bR-0ekCAJ4clHZZFw,1373
46
- hcs_cli/cmds/clouddriver/summary.py,sha256=VbVVTeo4zPjEJhEeWtNpcpcozbRm2gplMpSR3GL_8io,757
46
+ hcs_cli/cmds/clouddriver/service.py,sha256=idNx8ESPTddGL-XDSTeHbBIEJd14UDonr-wbVfAxJQ0,913
47
47
  hcs_cli/cmds/clouddriver/task.py,sha256=OWlBvGmwKjveB4Wa7yL13r-EAy4TLU_OGU8mr4Gm6us,1440
48
48
  hcs_cli/cmds/credential/__init__.py,sha256=CJEt8JL1o3Iaj8Boq213gTGlpw8_jh9yWyKyKCL6o9M,638
49
49
  hcs_cli/cmds/credential/get.py,sha256=IAiYaw5zqQc4WqkKijgabyV8MpXxrZkgY_Cwm5gJ5W4,1079
@@ -235,7 +235,7 @@ hcs_cli/cmds/scm/__init__.py,sha256=qOaaE1aCoIxeA7nRxhI0ZasMEE-KZ9PAfEkTSWdWcHw,
235
235
  hcs_cli/cmds/scm/health.py,sha256=c_0wOh3S4sHBLpAbcjvZGOToRjaEQHlyBD44Ry7pmsI,1277
236
236
  hcs_cli/cmds/scm/operator.py,sha256=9RQPgx0zHUIJLrJnNEu0rUw2VTD73lY-91iYVJ77Pck,3891
237
237
  hcs_cli/cmds/scm/plan.py,sha256=1DauYaO9D8bhBIERNS8WK9k0-BarYN8M8xldGdaHwFQ,16802
238
- hcs_cli/cmds/scm/template.py,sha256=X33WJPrVCY0P_SRL4BFjNDH8Ax863Fn_uRQdG-1wsTA,1546
238
+ hcs_cli/cmds/scm/template.py,sha256=MkKumBTpWoSz9a-wJMz5TK1wkGO4IDUkSHIxvDacZZM,1717
239
239
  hcs_cli/cmds/site/__init__.py,sha256=f5ZuflhKsBw-8TAJ8xWzlw5lnIU8Imba70GIYSzgz-Q,624
240
240
  hcs_cli/cmds/site/create.py,sha256=jf3g0h7EBf5AW1Di1Qbl62yt6A_sMXGrcKpiZh0gJAQ,1171
241
241
  hcs_cli/cmds/site/delete.py,sha256=7Tq1HaqfsoJxva-XSOa3PKFUKusBUpmg8OkYjwyLlwY,1159
@@ -393,12 +393,13 @@ hcs_cli/provider/hcs/runtime/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
393
393
  hcs_cli/provider/hcs/runtime/password.py,sha256=_MmoKPUKXUJFjyDv6gSwKOX67XCSZ1DABwSE2HPEEfA,944
394
394
  hcs_cli/provider/hcs/runtime/wait_for.py,sha256=uWPQnG3Lb0yEt5DN7TFgQpmxasBLclA15PYFMV5bfds,2320
395
395
  hcs_cli/service/__init__.py,sha256=6G9yVufTdwMISCx6OJQQvS14nF9carw6vEmXqHpQmIY,2812
396
+ hcs_cli/service/api.py,sha256=RundRlezi5Z8Id3trTakdsqezVnUEYDWF-MRSVFMBHY,4219
396
397
  hcs_cli/service/csp.py,sha256=SkBCcQ3bKETKuc-vs_VtCUu5CRc3FmjauoWIh3uUMB8,954
397
398
  hcs_cli/service/edge.py,sha256=KhePkqeSqpumlR0Je_O_8Y-gSnnDEpBd-78aYb3PzLQ,4268
398
399
  hcs_cli/service/graphql.py,sha256=Vqt4wMeRSPV_2YhGvb9vs0vlac0_fMAhg1BijKX6reg,468
399
400
  hcs_cli/service/pool.py,sha256=EjTENTX5wSZ-YhP8ON_tonB54-OhjWCluzIHVR7ed04,1266
400
401
  hcs_cli/service/site.py,sha256=th23Ucm8HgU96Rbt2m8ww2YrISj2Oksojc4atkdjRNM,1568
401
- hcs_cli/service/task.py,sha256=qqAQPqIS66cBp-f_4zsLm2-iEsWwB6rkBgczDVAlo-Y,9565
402
+ hcs_cli/service/task.py,sha256=F8NsjF2ZJbInmOvp8YzowlampQPU3KvQHlJKxdQ_uHs,9781
402
403
  hcs_cli/service/template.py,sha256=pCHmMX8zSdq0RX7bCftVog0_hNQU5gIe2o0FevxpKeg,2796
403
404
  hcs_cli/service/uag.py,sha256=5TMt6lqxMVOlp6d49aOZsKFfcgGRdE03Ew4yVWwbw7Q,3747
404
405
  hcs_cli/service/vm.py,sha256=9yfG_B8omd6lkXEvLbOd1tpFc_j-P40Y5aZG-_-TeC4,5398
@@ -420,8 +421,9 @@ hcs_cli/service/av/app.py,sha256=VmUvBzTLoGzpW8G_M40MTcdEnNPXlUW33YLjZHpE9Pg,184
420
421
  hcs_cli/service/av/avimport.py,sha256=TImptsWHgo1MIv-S7UJCCZANd7kSsx_vzF8cnugORd4,2313
421
422
  hcs_cli/service/av/entitlements.py,sha256=BqM3HxQayUOEegKPhHytBUsD8OMyIIFx-L7KzxQSFLY,1550
422
423
  hcs_cli/service/av/fileshare.py,sha256=i8YpFevp8no-JZP9dqK8y1feGdwWZR8KelZqM-G7pEo,1753
423
- hcs_cli/service/clouddriver/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
424
+ hcs_cli/service/clouddriver/__init__.py,sha256=WXsp49ivOll5PqIVKYbBVJmK3S5giiMoCm08J1UuTNQ,76
424
425
  hcs_cli/service/clouddriver/provider.py,sha256=PgAqYdZe-mlsE6iZ2lJuNTxkwxhhL4DE5q36X09rqVI,1344
426
+ hcs_cli/service/clouddriver/service.py,sha256=QF-ScexqS1zgpKiw4Oa_CBLZnZIwytr0uU9FaOAA9lQ,899
425
427
  hcs_cli/service/credential/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
426
428
  hcs_cli/service/credential/credential.py,sha256=MINXDWGJJ9k_BNixpJGC1uGWhADLCSQuFdGLUPA1Rio,798
427
429
  hcs_cli/service/credential/nls.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -493,9 +495,9 @@ hcs_cli/support/test_utils2.py,sha256=g321d4lNbJfy8VaSfwWjlj4_ZJe9NW6B16S8GOT3rE
493
495
  hcs_cli/support/use_util.py,sha256=QBrcNIW-k0g41euTc7-oU1WKEmACJx3YGQflyC3YeFs,2970
494
496
  hcs_cli/support/vm_table.py,sha256=hqNUKLVUuBiuDwlqcAQ7uAT1-4z6ZYOIGRcFWn8lnAo,2329
495
497
  hcs_cli/support/scm/html_util.py,sha256=clgMpM90HxRRs3D9ORYYNB57AYh7y_-UzJrB4KX3dsY,458
496
- hcs_cli/support/scm/plan-editor.html.template,sha256=qXhHYjBsG8uaVlMkc0gnCePoSV3w5NyTkaLhXV9jlC0,26874
497
- hcs_cli/support/scm/plan_editor.py,sha256=pZtm9X_R-vs2JxJ_NX7-wTAoY-nhI-gFqhcyVDdEZVM,3108
498
- hcs_cli-0.1.321.dist-info/METADATA,sha256=llYPP2ShA7g1sBAPChU2L8BaF62Yq0ozSKHZ0xFVieQ,3614
499
- hcs_cli-0.1.321.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
500
- hcs_cli-0.1.321.dist-info/entry_points.txt,sha256=5uH-af1WUETSBSer2bu4YMGQNY5RriJHsjepb8ACiX8,42
501
- hcs_cli-0.1.321.dist-info/RECORD,,
498
+ hcs_cli/support/scm/plan-editor.html.template,sha256=HtXMmvIvTixVEYN1gblCeqFTt_F8JF6ltDC11Eb_GMw,46975
499
+ hcs_cli/support/scm/plan_editor.py,sha256=TxfHyyozoQ_DCyaPrYXFG9n8AnBuUD8753009FUD0GU,8722
500
+ hcs_cli-0.1.323.dist-info/METADATA,sha256=b-2W82xpVCj8-96cj5dRQJYZuRH3zlCnqPQru2H9hJU,3614
501
+ hcs_cli-0.1.323.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
502
+ hcs_cli-0.1.323.dist-info/entry_points.txt,sha256=5uH-af1WUETSBSer2bu4YMGQNY5RriJHsjepb8ACiX8,42
503
+ hcs_cli-0.1.323.dist-info/RECORD,,