python-watcher 14.1.0__py3-none-any.whl → 14.1.1__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.
Files changed (21) hide show
  1. {python_watcher-14.1.0.dist-info → python_watcher-14.1.1.dist-info}/METADATA +57 -48
  2. {python_watcher-14.1.0.dist-info → python_watcher-14.1.1.dist-info}/RECORD +20 -20
  3. {python_watcher-14.1.0.dist-info → python_watcher-14.1.1.dist-info}/WHEEL +1 -1
  4. python_watcher-14.1.1.dist-info/pbr.json +1 -0
  5. watcher/common/service.py +2 -2
  6. watcher/conf/grafana_client.py +1 -0
  7. watcher/conf/maas_client.py +1 -0
  8. watcher/decision_engine/strategy/strategies/workload_balance.py +29 -9
  9. watcher/tests/common/test_service.py +22 -0
  10. watcher/tests/decision_engine/model/gnocchi_metrics.py +2 -2
  11. watcher/tests/decision_engine/strategy/strategies/test_workload_balance.py +40 -2
  12. python_watcher-14.1.0.dist-info/pbr.json +0 -1
  13. {python_watcher-14.1.0.data → python_watcher-14.1.1.data}/data/etc/apache2/watcher +0 -0
  14. {python_watcher-14.1.0.data → python_watcher-14.1.1.data}/data/etc/watcher/README-watcher.conf.txt +0 -0
  15. {python_watcher-14.1.0.data → python_watcher-14.1.1.data}/data/etc/watcher/oslo-config-generator/watcher.conf +0 -0
  16. {python_watcher-14.1.0.data → python_watcher-14.1.1.data}/data/etc/watcher/oslo-policy-generator/watcher-policy-generator.conf +0 -0
  17. {python_watcher-14.1.0.data → python_watcher-14.1.1.data}/scripts/watcher-api-wsgi +0 -0
  18. {python_watcher-14.1.0.dist-info → python_watcher-14.1.1.dist-info}/entry_points.txt +0 -0
  19. {python_watcher-14.1.0.dist-info → python_watcher-14.1.1.dist-info/licenses}/AUTHORS +0 -0
  20. {python_watcher-14.1.0.dist-info → python_watcher-14.1.1.dist-info/licenses}/LICENSE +0 -0
  21. {python_watcher-14.1.0.dist-info → python_watcher-14.1.1.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: python-watcher
3
- Version: 14.1.0
3
+ Version: 14.1.1
4
4
  Summary: OpenStack Watcher provides a flexible and scalable resource optimization service for multi-tenant OpenStack-based clouds.
5
5
  Home-page: https://docs.openstack.org/watcher/latest/
6
6
  Author: OpenStack
@@ -20,52 +20,61 @@ Classifier: Programming Language :: Python :: 3.12
20
20
  Requires-Python: >=3.9
21
21
  License-File: LICENSE
22
22
  License-File: AUTHORS
23
- Requires-Dist: apscheduler >=3.5.1
24
- Requires-Dist: eventlet >=0.27.0
25
- Requires-Dist: jsonpatch >=1.21
26
- Requires-Dist: keystoneauth1 >=3.4.0
27
- Requires-Dist: jsonschema >=3.2.0
28
- Requires-Dist: keystonemiddleware >=4.21.0
29
- Requires-Dist: lxml >=4.5.1
30
- Requires-Dist: croniter >=0.3.20
31
- Requires-Dist: os-resource-classes >=0.4.0
32
- Requires-Dist: oslo.concurrency >=3.26.0
33
- Requires-Dist: oslo.cache >=1.29.0
34
- Requires-Dist: oslo.config >=6.8.0
35
- Requires-Dist: oslo.context >=2.21.0
36
- Requires-Dist: oslo.db >=4.44.0
37
- Requires-Dist: oslo.i18n >=3.20.0
38
- Requires-Dist: oslo.log >=3.37.0
39
- Requires-Dist: oslo.messaging >=14.1.0
40
- Requires-Dist: oslo.policy >=4.5.0
41
- Requires-Dist: oslo.reports >=1.27.0
42
- Requires-Dist: oslo.serialization >=2.25.0
43
- Requires-Dist: oslo.service >=1.30.0
44
- Requires-Dist: oslo.upgradecheck >=1.3.0
45
- Requires-Dist: oslo.utils >=7.0.0
46
- Requires-Dist: oslo.versionedobjects >=1.32.0
47
- Requires-Dist: PasteDeploy >=1.5.2
48
- Requires-Dist: pbr >=3.1.1
49
- Requires-Dist: pecan >=1.3.2
50
- Requires-Dist: PrettyTable >=0.7.2
51
- Requires-Dist: gnocchiclient >=7.0.1
52
- Requires-Dist: python-cinderclient >=3.5.0
53
- Requires-Dist: python-glanceclient >=2.9.1
54
- Requires-Dist: python-keystoneclient >=3.15.0
55
- Requires-Dist: python-monascaclient >=1.12.0
56
- Requires-Dist: python-neutronclient >=6.7.0
57
- Requires-Dist: python-novaclient >=14.1.0
58
- Requires-Dist: python-observabilityclient >=0.3.0
59
- Requires-Dist: python-openstackclient >=3.14.0
60
- Requires-Dist: python-ironicclient >=2.5.0
61
- Requires-Dist: SQLAlchemy >=1.2.5
62
- Requires-Dist: stevedore >=1.28.0
63
- Requires-Dist: taskflow >=3.8.0
64
- Requires-Dist: WebOb >=1.8.5
65
- Requires-Dist: WSME >=0.9.2
66
- Requires-Dist: networkx >=2.4
67
- Requires-Dist: microversion-parse >=0.2.1
68
- Requires-Dist: futurist >=1.8.0
23
+ Requires-Dist: apscheduler>=3.5.1
24
+ Requires-Dist: eventlet>=0.27.0
25
+ Requires-Dist: jsonpatch>=1.21
26
+ Requires-Dist: keystoneauth1>=3.4.0
27
+ Requires-Dist: jsonschema>=3.2.0
28
+ Requires-Dist: keystonemiddleware>=4.21.0
29
+ Requires-Dist: lxml>=4.5.1
30
+ Requires-Dist: croniter>=0.3.20
31
+ Requires-Dist: os-resource-classes>=0.4.0
32
+ Requires-Dist: oslo.concurrency>=3.26.0
33
+ Requires-Dist: oslo.cache>=1.29.0
34
+ Requires-Dist: oslo.config>=6.8.0
35
+ Requires-Dist: oslo.context>=2.21.0
36
+ Requires-Dist: oslo.db>=4.44.0
37
+ Requires-Dist: oslo.i18n>=3.20.0
38
+ Requires-Dist: oslo.log>=3.37.0
39
+ Requires-Dist: oslo.messaging>=14.1.0
40
+ Requires-Dist: oslo.policy>=4.5.0
41
+ Requires-Dist: oslo.reports>=1.27.0
42
+ Requires-Dist: oslo.serialization>=2.25.0
43
+ Requires-Dist: oslo.service>=1.30.0
44
+ Requires-Dist: oslo.upgradecheck>=1.3.0
45
+ Requires-Dist: oslo.utils>=7.0.0
46
+ Requires-Dist: oslo.versionedobjects>=1.32.0
47
+ Requires-Dist: PasteDeploy>=1.5.2
48
+ Requires-Dist: pbr>=3.1.1
49
+ Requires-Dist: pecan>=1.3.2
50
+ Requires-Dist: PrettyTable>=0.7.2
51
+ Requires-Dist: gnocchiclient>=7.0.1
52
+ Requires-Dist: python-cinderclient>=3.5.0
53
+ Requires-Dist: python-glanceclient>=2.9.1
54
+ Requires-Dist: python-keystoneclient>=3.15.0
55
+ Requires-Dist: python-monascaclient>=1.12.0
56
+ Requires-Dist: python-neutronclient>=6.7.0
57
+ Requires-Dist: python-novaclient>=14.1.0
58
+ Requires-Dist: python-observabilityclient>=0.3.0
59
+ Requires-Dist: python-openstackclient>=3.14.0
60
+ Requires-Dist: python-ironicclient>=2.5.0
61
+ Requires-Dist: SQLAlchemy>=1.2.5
62
+ Requires-Dist: stevedore>=1.28.0
63
+ Requires-Dist: taskflow>=3.8.0
64
+ Requires-Dist: WebOb>=1.8.5
65
+ Requires-Dist: WSME>=0.9.2
66
+ Requires-Dist: networkx>=2.4
67
+ Requires-Dist: microversion-parse>=0.2.1
68
+ Requires-Dist: futurist>=1.8.0
69
+ Dynamic: author
70
+ Dynamic: author-email
71
+ Dynamic: classifier
72
+ Dynamic: description
73
+ Dynamic: home-page
74
+ Dynamic: license-file
75
+ Dynamic: requires-dist
76
+ Dynamic: requires-python
77
+ Dynamic: summary
69
78
 
70
79
  =======
71
80
  Watcher
@@ -1,8 +1,10 @@
1
- python_watcher-14.1.0.data/data/etc/apache2/watcher,sha256=urybYUTb0kAVIvbm4WK5oDfXR82QSK2lyMl4Z9dCz4Q,1190
2
- python_watcher-14.1.0.data/data/etc/watcher/README-watcher.conf.txt,sha256=EIa_sjXDyl1XSg0ovsFwUjqw0euS0N2PYn4HtyBGJME,131
3
- python_watcher-14.1.0.data/data/etc/watcher/oslo-config-generator/watcher.conf,sha256=O7g1DZqgXvbQgkBfot0dR1ar1d-3SBkOU_ZK4Dz7SFc,406
4
- python_watcher-14.1.0.data/data/etc/watcher/oslo-policy-generator/watcher-policy-generator.conf,sha256=ZfIuVdtrj7IZm2BrRQvAW3JOL_kqCiILf-vBmwX3ufw,76
5
- python_watcher-14.1.0.data/scripts/watcher-api-wsgi,sha256=YcIpUO3iRVW6Fu3Md_ooAeHkmJJasG031naMdf8cv2A,1829
1
+ python_watcher-14.1.1.data/data/etc/apache2/watcher,sha256=urybYUTb0kAVIvbm4WK5oDfXR82QSK2lyMl4Z9dCz4Q,1190
2
+ python_watcher-14.1.1.data/data/etc/watcher/README-watcher.conf.txt,sha256=EIa_sjXDyl1XSg0ovsFwUjqw0euS0N2PYn4HtyBGJME,131
3
+ python_watcher-14.1.1.data/data/etc/watcher/oslo-config-generator/watcher.conf,sha256=O7g1DZqgXvbQgkBfot0dR1ar1d-3SBkOU_ZK4Dz7SFc,406
4
+ python_watcher-14.1.1.data/data/etc/watcher/oslo-policy-generator/watcher-policy-generator.conf,sha256=ZfIuVdtrj7IZm2BrRQvAW3JOL_kqCiILf-vBmwX3ufw,76
5
+ python_watcher-14.1.1.data/scripts/watcher-api-wsgi,sha256=YcIpUO3iRVW6Fu3Md_ooAeHkmJJasG031naMdf8cv2A,1829
6
+ python_watcher-14.1.1.dist-info/licenses/AUTHORS,sha256=9d2KSouBWGvHRnwW5J5wzVLYye0DXA0miYTgIytR-X0,7961
7
+ python_watcher-14.1.1.dist-info/licenses/LICENSE,sha256=XfKg2H1sVi8OoRxoisUlMqoo10TKvHmU_wU39ks7MyA,10143
6
8
  watcher/__init__.py,sha256=Vs2olXPZ_IAV1rukHYRl3ITzYFBNXX9mIUtFXkMWYwg,640
7
9
  watcher/_i18n.py,sha256=-25OcpwjDCiYdFIUJh86S7Sg0fs3wMIIjEreaGUyCyY,1295
8
10
  watcher/eventlet.py,sha256=W4qOoDisSJSax28o30p3_w5QRjy_zdE3vNdRUkegXu4,1365
@@ -86,7 +88,7 @@ watcher/common/placement_helper.py,sha256=jo9Ksofh7AGd8rLFsib-cF1kRocP05-trpJOxd
86
88
  watcher/common/policy.py,sha256=8WGBY79RJItBN4RphBEacYj7JKtSHJLoVw3WW7oM5oA,4893
87
89
  watcher/common/rpc.py,sha256=X1ZEohTH6Maw_iZaj9JBDAD_sfUPzV35W4lCeJhRITc,4415
88
90
  watcher/common/scheduling.py,sha256=EDlbXf86tgjzHN_qdTpk_JhfaZI5varD9-meThH7ync,2619
89
- watcher/common/service.py,sha256=E7zX4m-nskz-ODbhsKoYhfKHB9-Sbj-FntikvUflFes,9740
91
+ watcher/common/service.py,sha256=nFyaWGiCrlJawrR73EKNe10jfLQbNjp47qSRiwz6gD0,9730
90
92
  watcher/common/service_manager.py,sha256=PQwa-58CTLD0bWS_5i9KigSTp9OGeP7m7D1oMg3f50A,1421
91
93
  watcher/common/utils.py,sha256=PCPgzMtVfZR9613P7guKv1DJljK_4e0TbW7LgMXmwcg,6038
92
94
  watcher/common/loader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -122,11 +124,11 @@ watcher/conf/decision_engine.py,sha256=eptqMmeCTEw0g6JJw-rLhHB3pb-gHlnS12rW1HPjC
122
124
  watcher/conf/exception.py,sha256=_VAlIawyQZGHbn8zFzXsNaOiCv5miZD9VGR3HJn2Y1Q,989
123
125
  watcher/conf/glance_client.py,sha256=4Z_8qz6tNSBIO6McnyYs6w8OlyntXaLWGomLh4A7JrY,1593
124
126
  watcher/conf/gnocchi_client.py,sha256=oFbFgpA9dbQcA5pW4-gBBYuuvrIkm4ucRwZ67UopvJ0,1581
125
- watcher/conf/grafana_client.py,sha256=JMalRmtMpRwpMMr8EkkV_maUcbEw4PGzPSv8Z4DTDpc,6908
127
+ watcher/conf/grafana_client.py,sha256=FOG9dDck_PYptoX6cGsyTXdzewIoHO3kbbxLHrgjIXA,6936
126
128
  watcher/conf/grafana_translators.py,sha256=5mqq-ZUYpiOaOtm7GRbxiyiJQFw_GFb8JynGhCMAwyE,1651
127
129
  watcher/conf/ironic_client.py,sha256=Ux2gvBHlHBrrnfR8vDlwHrCWJLgileiaL6xSgqXkOxw,1589
128
130
  watcher/conf/keystone_client.py,sha256=V7PKGylRSrw9zwMw_xuehxmpqXM7up9y_DIdYJBJFdg,1349
129
- watcher/conf/maas_client.py,sha256=7KGb3yIKWDvCdYA5Kc22uszkFEOp9rcJQHpQFES2dfA,1277
131
+ watcher/conf/maas_client.py,sha256=99UaXMNg_1GPyfU2q4TjjHpRmI6zAStcrYzvo6lDyyg,1305
130
132
  watcher/conf/monasca_client.py,sha256=LcUhyHOZ-VgAY2p3dhuvNeNsmITBhHaoKJxGYD7-Q5w,1596
131
133
  watcher/conf/neutron_client.py,sha256=VyLPAeKSJ6hy-eL_a-DhRLUrLCPQ2TBsb7eBIrAB8Ws,1608
132
134
  watcher/conf/nova_client.py,sha256=hEYsV5j5TzvK1iAl9JA-ESZ2AT2HXtJ_F7qGTqvr0nk,1923
@@ -261,7 +263,7 @@ watcher/decision_engine/strategy/strategies/saving_energy.py,sha256=gzjv0Uk3bEV6
261
263
  watcher/decision_engine/strategy/strategies/storage_capacity_balance.py,sha256=a2C12V3LfISTJLEVFsjvrXWCXmv9knhmU5smzG0N-XE,15669
262
264
  watcher/decision_engine/strategy/strategies/uniform_airflow.py,sha256=MzCCmXirahFlzbPCR8_E8Bek1iB0sqVKamzIhEwi3NY,13391
263
265
  watcher/decision_engine/strategy/strategies/vm_workload_consolidation.py,sha256=-usWMjqFcbTSWbGKNmsSlZ-0wnMNwLv2w22Fu6nIqyw,27190
264
- watcher/decision_engine/strategy/strategies/workload_balance.py,sha256=MMJZkfi8kFJDT4Hcp-NTCclN1MMKj02t88OdMinWYnI,14333
266
+ watcher/decision_engine/strategy/strategies/workload_balance.py,sha256=Q0S8niQ0paVG7QDVPVSRcK8wsQH-oric0It1xYSBQLo,15629
265
267
  watcher/decision_engine/strategy/strategies/workload_stabilization.py,sha256=xKnjDeSAkGxvAuUKlxRGuaHVyBjSy-1nFcgI4ni8pnk,24902
266
268
  watcher/decision_engine/strategy/strategies/zone_migration.py,sha256=Dt82_SkERBm-GyoGxsdS4cAFlzUQjGEMEoE9x_5B_hE,32798
267
269
  watcher/hacking/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -357,7 +359,7 @@ watcher/tests/common/test_ironic_helper.py,sha256=Ut-bpvPBQJWdu9xWPvzQ0sFEimuHU0
357
359
  watcher/tests/common/test_nova_helper.py,sha256=BaJ4Gfn1hGG5sho2QZ7btCvzrvzbIpR6PI6kAejr6Yw,28524
358
360
  watcher/tests/common/test_placement_helper.py,sha256=Y4P2YbWhC0itWGJbaDkoua9ot0XknXuM8disvceIXQQ,11761
359
361
  watcher/tests/common/test_scheduling.py,sha256=nWmLBoRwNZCSRRW_3DtlgWC0zpY9jfbb1wIkYY47_aE,2494
360
- watcher/tests/common/test_service.py,sha256=C7i4Pdawc_XKpqZuklJqQd3unztgiVpvkwwjUujGRK0,3535
362
+ watcher/tests/common/test_service.py,sha256=zQ4kKVr6BsP-4cvlGS3GL2GyWzt2Zu0UhLmz2W97R_g,4401
361
363
  watcher/tests/common/test_utils.py,sha256=Mq-51gFQv2EPdGaO44_py8ewdbObvnhwE4fpnzPTQPM,1697
362
364
  watcher/tests/common/loader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
363
365
  watcher/tests/common/loader/test_loader.py,sha256=mBnhe2apSmqpEL-8QZUlRDhDuWEEGo7iZQxpZIuGCWM,3612
@@ -418,7 +420,7 @@ watcher/tests/decision_engine/messaging/test_data_model_endpoint.py,sha256=6wj90
418
420
  watcher/tests/decision_engine/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
419
421
  watcher/tests/decision_engine/model/faker_cluster_and_metrics.py,sha256=jJ53BoXal8Vr516Mc60PgWMClIGVpck3yoDNe07Aw6g,7038
420
422
  watcher/tests/decision_engine/model/faker_cluster_state.py,sha256=whaEpzD8zt7BVnqsBrWcbugDOeyChAyn74d1YwO0P1o,12405
421
- watcher/tests/decision_engine/model/gnocchi_metrics.py,sha256=LoKRVLPPwi_BIJgRlPRZ_gG87Nqkfd0_4e0DcmonSu8,9358
423
+ watcher/tests/decision_engine/model/gnocchi_metrics.py,sha256=Fs5gGrAgxHA2eENzJbWCMDEUNMZPxy2qUwhLFNWTS-M,9357
422
424
  watcher/tests/decision_engine/model/monasca_metrics.py,sha256=s-voe8Cu7Su2_Tn_sp3dSxWTPI3zgFd9Wtrf9CZ7Wu4,4121
423
425
  watcher/tests/decision_engine/model/test_element.py,sha256=m0Bti4A6DRsZbYvWbobowBF_CsBTHhXr2nmFmJuM0rU,5637
424
426
  watcher/tests/decision_engine/model/test_model.py,sha256=UwqHkRyo9puoWjZaRto90HE3k_ycwveUYvg_a3jGNlY,20671
@@ -523,7 +525,7 @@ watcher/tests/decision_engine/strategy/strategies/test_storage_capacity_balance.
523
525
  watcher/tests/decision_engine/strategy/strategies/test_strategy_endpoint.py,sha256=mw2CFX-JfWwaNM3EYFLoZzHZxJXpEh5YD7JPrZz0ggI,2886
524
526
  watcher/tests/decision_engine/strategy/strategies/test_uniform_airflow.py,sha256=ChNt74enUScPZFFrDLa9Xqnq4O1nU2CAg7KnyNl3JOM,7265
525
527
  watcher/tests/decision_engine/strategy/strategies/test_vm_workload_consolidation.py,sha256=AXY55dBg_8w37qpy0BT89ScUo81BUCZXwZO957jTgEE,19203
526
- watcher/tests/decision_engine/strategy/strategies/test_workload_balance.py,sha256=utqnw1rUNTFfdBhuNsxY8Q81Lr7SNhfYSyHCVxUL-BA,6074
528
+ watcher/tests/decision_engine/strategy/strategies/test_workload_balance.py,sha256=m2VljGe-9IJBBRyJwkseDiRxLB1z510tQL3orGyG470,8380
527
529
  watcher/tests/decision_engine/strategy/strategies/test_workload_stabilization.py,sha256=eGr_PX8dpM4oTlC-GFrimDN1kQbKpNFzA_C5c4mo250,14313
528
530
  watcher/tests/decision_engine/strategy/strategies/test_zone_migration.py,sha256=eEkK66H_nnhghDEuBXo8dvdifhN6N_9CO5mlVdN-ytM,30871
529
531
  watcher/tests/notifications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -547,11 +549,9 @@ watcher/tests/objects/test_strategy.py,sha256=WoJYFQD0LU7vkUT2MMy1bx3S6eY458aTIC
547
549
  watcher/tests/objects/utils.py,sha256=WtBFlXWIBRvl1keAjz1GtrkUWppil2pFIA-RngcqA5c,8058
548
550
  watcher/wsgi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
549
551
  watcher/wsgi/api.py,sha256=F1s1Q_CMuRdgS_f7Gl3XzavjZqdxqO9IHLxSWl6NOO4,789
550
- python_watcher-14.1.0.dist-info/AUTHORS,sha256=9d2KSouBWGvHRnwW5J5wzVLYye0DXA0miYTgIytR-X0,7961
551
- python_watcher-14.1.0.dist-info/LICENSE,sha256=XfKg2H1sVi8OoRxoisUlMqoo10TKvHmU_wU39ks7MyA,10143
552
- python_watcher-14.1.0.dist-info/METADATA,sha256=bpNI_tPLjPM568PVe3YLFl8uXnDwDhDB-vs_ywg8iOQ,3880
553
- python_watcher-14.1.0.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
554
- python_watcher-14.1.0.dist-info/entry_points.txt,sha256=PN53WKewBT3McXxlv--kAOX-3NWeJqYVy8wkeCR0orc,4396
555
- python_watcher-14.1.0.dist-info/pbr.json,sha256=VdP5H0whv1sbxfhXfL9UYnztLRuOH2xlRrkMU-YtJfk,47
556
- python_watcher-14.1.0.dist-info/top_level.txt,sha256=O2B7Sbzshq5s-tZxb2a7VETvMDiJItSYieAiJ6Jm5yY,8
557
- python_watcher-14.1.0.dist-info/RECORD,,
552
+ python_watcher-14.1.1.dist-info/METADATA,sha256=WySMYxnHrs_uuDWG55W5RxGJenw3h6IjXvG-zViKKHg,4019
553
+ python_watcher-14.1.1.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
554
+ python_watcher-14.1.1.dist-info/entry_points.txt,sha256=PN53WKewBT3McXxlv--kAOX-3NWeJqYVy8wkeCR0orc,4396
555
+ python_watcher-14.1.1.dist-info/pbr.json,sha256=879o55rPCg0i2X1_4q2X756BVg5rlJIWWpR0FtSH_ZU,47
556
+ python_watcher-14.1.1.dist-info/top_level.txt,sha256=O2B7Sbzshq5s-tZxb2a7VETvMDiJItSYieAiJ6Jm5yY,8
557
+ python_watcher-14.1.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.3.2)
2
+ Generator: setuptools (83.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -0,0 +1 @@
1
+ {"git_version": "f3ed6d60", "is_release": true}
watcher/common/service.py CHANGED
@@ -241,7 +241,7 @@ class Service(service.ServiceBase):
241
241
  )
242
242
 
243
243
  def start(self):
244
- LOG.debug("Connecting to '%s'", CONF.transport_url)
244
+ LOG.debug("Connecting to messaging transport")
245
245
  if self.conductor_topic_handler:
246
246
  self.conductor_topic_handler.start()
247
247
  if self.notification_handler:
@@ -250,7 +250,7 @@ class Service(service.ServiceBase):
250
250
  self.heartbeat.start()
251
251
 
252
252
  def stop(self):
253
- LOG.debug("Disconnecting from '%s'", CONF.transport_url)
253
+ LOG.debug("Disconnecting from messaging transport")
254
254
  if self.conductor_topic_handler:
255
255
  self.conductor_topic_handler.stop()
256
256
  if self.notification_handler:
@@ -29,6 +29,7 @@ GRAFANA_CLIENT_OPTS = [
29
29
  # A similar structure to the database_map would solve this.
30
30
  cfg.StrOpt('token',
31
31
  default=None,
32
+ secret=True,
32
33
  help="Authentication token to gain access"),
33
34
  # TODO(Dantali0n) each individual metric could have its own base url.
34
35
  # A similar structure to the database_map would solve this.
@@ -23,6 +23,7 @@ MAAS_CLIENT_OPTS = [
23
23
  cfg.StrOpt('url',
24
24
  help='MaaS URL, example: http://1.2.3.4:5240/MAAS'),
25
25
  cfg.StrOpt('api_key',
26
+ secret=True,
26
27
  help='MaaS API authentication key.'),
27
28
  cfg.IntOpt('timeout',
28
29
  default=60,
@@ -192,15 +192,30 @@ class WorkloadBalance(base.WorkloadStabilizationBaseStrategy):
192
192
  if (free_res['vcpu'] >= required_cores and
193
193
  free_res['memory'] >= required_mem and
194
194
  free_res['disk'] >= required_disk):
195
- if (self._meter == 'instance_cpu_usage' and
196
- ((src_instance_workload + workload) <
197
- self.threshold / 100 * host.vcpus)):
198
- destination_hosts.append(instance_data)
199
- if (self._meter == 'instance_ram_usage' and
200
- ((src_instance_workload + workload) <
201
- self.threshold / 100 * host.memory)):
202
- destination_hosts.append(instance_data)
203
-
195
+ if self._meter == 'instance_cpu_usage':
196
+ usage = src_instance_workload + workload
197
+ usage_percent = usage / host.vcpus * 100
198
+ limit = self.threshold / 100 * host.vcpus
199
+ if usage < limit:
200
+ destination_hosts.append(instance_data)
201
+ LOG.debug(f"Host {host.hostname} evaluated as destination "
202
+ f"for {instance_to_migrate.uuid}. Host usage "
203
+ f"for cpu would be {usage_percent}."
204
+ f"The threshold is: {self.threshold}. "
205
+ f"selected: {usage < limit}"
206
+ )
207
+ if self._meter == 'instance_ram_usage':
208
+ usage = src_instance_workload + workload
209
+ usage_percent = usage / host.memory * 100
210
+ limit = self.threshold / 100 * host.memory
211
+ if usage < limit:
212
+ destination_hosts.append(instance_data)
213
+ LOG.debug(f"Host {host.hostname} evaluated as destination "
214
+ f"for {instance_to_migrate.uuid}. Host usage "
215
+ f"for ram would be {usage_percent}."
216
+ f"The threshold is: {self.threshold}. "
217
+ f"selected: {usage < limit}"
218
+ )
204
219
  return destination_hosts
205
220
 
206
221
  def group_hosts_by_cpu_or_ram_util(self):
@@ -251,8 +266,10 @@ class WorkloadBalance(base.WorkloadStabilizationBaseStrategy):
251
266
  cluster_workload += node_workload
252
267
  if self._meter == 'instance_cpu_usage':
253
268
  node_util = node_workload / node.vcpus * 100
269
+ host_metric = 'host_cpu_usage_percent'
254
270
  else:
255
271
  node_util = node_workload / node.memory * 100
272
+ host_metric = 'host_ram_usage_percent'
256
273
 
257
274
  instance_data = {
258
275
  'compute_node': node, self._meter: node_util,
@@ -262,6 +279,9 @@ class WorkloadBalance(base.WorkloadStabilizationBaseStrategy):
262
279
  overload_hosts.append(instance_data)
263
280
  else:
264
281
  nonoverload_hosts.append(instance_data)
282
+ LOG.debug(f"Host usage for {node_id}: {host_metric} is "
283
+ f"{node_util}. Higher than threshold {self.threshold}: "
284
+ f"{node_util >= self.threshold}")
265
285
 
266
286
  avg_workload = 0
267
287
  if cluster_size != 0:
@@ -104,3 +104,25 @@ class TestService(base.TestCase):
104
104
  self.assertIsInstance(
105
105
  dummy_service.conductor_topic_handler,
106
106
  om.rpc.server.RPCServer)
107
+
108
+ @mock.patch.object(service.LOG, 'debug', autospec=True)
109
+ def test_transport_url_not_logged(self, mock_debug):
110
+ transport_url = 'rabbit://api:secret-pass@example.com:5672/'
111
+ CONF.set_override('transport_url', transport_url)
112
+
113
+ dummy_service = service.Service(DummyManager)
114
+ dummy_service.conductor_topic_handler = None
115
+ dummy_service.notification_handler = None
116
+ dummy_service.heartbeat = None
117
+
118
+ dummy_service.start()
119
+ dummy_service.stop()
120
+
121
+ logged = ' '.join(
122
+ str(arg) for call in mock_debug.call_args_list for arg in call.args
123
+ )
124
+
125
+ self.assertNotIn(transport_url, logged)
126
+ self.assertNotIn('secret-pass', logged)
127
+ mock_debug.assert_any_call("Connecting to messaging transport")
128
+ mock_debug.assert_any_call("Disconnecting from messaging transport")
@@ -304,8 +304,8 @@ class FakeGnocchiMetrics(object):
304
304
  mock = {}
305
305
 
306
306
  # node 0
307
- mock['INSTANCE_1'] = 30
308
- mock['73b09e16-35b7-4922-804e-e8f5d9b740fc'] = 12
307
+ mock['INSTANCE_1'] = 40
308
+ mock['73b09e16-35b7-4922-804e-e8f5d9b740fc'] = 9
309
309
  # node 1
310
310
  mock['INSTANCE_3'] = 12
311
311
  mock['INSTANCE_4'] = 12
@@ -22,6 +22,7 @@ from unittest import mock
22
22
  from watcher.applier.loading import default
23
23
  from watcher.common import utils
24
24
  from watcher.decision_engine.strategy import strategies
25
+ from watcher.decision_engine.strategy.strategies import workload_balance
25
26
  from watcher.tests.decision_engine.model import gnocchi_metrics
26
27
  from watcher.tests.decision_engine.strategy.strategies.test_base \
27
28
  import TestBaseStrategy
@@ -77,7 +78,7 @@ class TestWorkloadBalance(TestBaseStrategy):
77
78
  n1, n2, avg, w_map = self.strategy.group_hosts_by_cpu_or_ram_util()
78
79
  self.assertEqual(n1[0]['compute_node'].uuid, 'Node_0')
79
80
  self.assertEqual(n2[0]['compute_node'].uuid, 'Node_1')
80
- self.assertEqual(avg, 33.0)
81
+ self.assertEqual(avg, 36.5)
81
82
 
82
83
  def test_choose_instance_to_migrate(self):
83
84
  model = self.fake_c_cluster.generate_scenario_6_with_2_nodes()
@@ -99,7 +100,8 @@ class TestWorkloadBalance(TestBaseStrategy):
99
100
  n1, avg, w_map)
100
101
  self.assertIsNone(instance_to_mig)
101
102
 
102
- def test_filter_destination_hosts(self):
103
+ @mock.patch.object(workload_balance.LOG, 'debug', autospec=True)
104
+ def test_filter_destination_hosts_cpu(self, mock_debug):
103
105
  model = self.fake_c_cluster.generate_scenario_6_with_2_nodes()
104
106
  self.m_c_model.return_value = model
105
107
  self.strategy.datasource = mock.MagicMock(
@@ -111,6 +113,42 @@ class TestWorkloadBalance(TestBaseStrategy):
111
113
  n2, instance_to_mig[1], avg, w_map)
112
114
  self.assertEqual(len(dest_hosts), 1)
113
115
  self.assertEqual(dest_hosts[0]['compute_node'].uuid, 'Node_1')
116
+ expected_calls = [
117
+ mock.call('Host usage for Node_0: host_cpu_usage_percent is 32.5. '
118
+ 'Higher than threshold 25.0: True'),
119
+ mock.call('Host usage for Node_1: host_cpu_usage_percent is 7.5. '
120
+ 'Higher than threshold 25.0: False'),
121
+ mock.call('Host hostname_1 evaluated as destination for '
122
+ '73b09e16-35b7-4922-804e-e8f5d9b740fc. Host usage for '
123
+ 'cpu would be 20.0.The threshold is: 25.0. selected: '
124
+ 'True')]
125
+ mock_debug.assert_has_calls(expected_calls, any_order=True)
126
+
127
+ @mock.patch.object(workload_balance.LOG, 'debug', autospec=True)
128
+ def test_filter_destination_hosts_ram(self, mock_debug):
129
+ model = self.fake_c_cluster.generate_scenario_6_with_2_nodes()
130
+ self.m_c_model.return_value = model
131
+ self.strategy._meter = 'instance_ram_usage'
132
+ self.strategy.threshold = 30.0
133
+ self.strategy.datasource = mock.MagicMock(
134
+ statistic_aggregation=self.fake_metrics.mock_get_statistics_wb)
135
+ n1, n2, avg, w_map = self.strategy.group_hosts_by_cpu_or_ram_util()
136
+ instance_to_mig = self.strategy.choose_instance_to_migrate(
137
+ n1, avg, w_map)
138
+ dest_hosts = self.strategy.filter_destination_hosts(
139
+ n2, instance_to_mig[1], avg, w_map)
140
+ self.assertEqual(len(dest_hosts), 1)
141
+ self.assertEqual(dest_hosts[0]['compute_node'].uuid, 'Node_1')
142
+ expected_calls = [
143
+ mock.call('Host usage for Node_0: host_ram_usage_percent is '
144
+ '37.121212121212125. Higher than threshold 30.0: True'),
145
+ mock.call('Host usage for Node_1: host_ram_usage_percent is '
146
+ '18.181818181818183. Higher than threshold 30.0: False'),
147
+ mock.call('Host hostname_1 evaluated as destination for '
148
+ '73b09e16-35b7-4922-804e-e8f5d9b740fc. Host usage for '
149
+ 'ram would be 25.0.The threshold is: 30.0. selected: '
150
+ 'True')]
151
+ mock_debug.assert_has_calls(expected_calls, any_order=True)
114
152
 
115
153
  def test_execute_no_workload(self):
116
154
  model = self.fake_c_cluster.\
@@ -1 +0,0 @@
1
- {"git_version": "024815af", "is_release": true}