Skip to content

Commit cdbc9ce

Browse files
[cuegui] Add email notifications for subscription size/burst changes
Added email notifications to track subscription modifications in the CueCommander GUI. When a subscription's size or burst value is changed, an automated email is sent to configured recipients with details about the change, including: - What was changed (size or burst) - Old and new values - Who made the change - Timestamp of the change Key features: - Configurable CC recipients via cuegui.yaml - Support for email templates with {show} and {domain} placeholders - Disabled by default (set email.subscription_change_cc to enable) - Graceful error handling - email failures don't block subscription changes Configuration: - New setting: email.subscription_change_cc in cuegui.yaml - Example: "{show}-admin@{domain},resource-team@{domain}" Files modified: - cuegui/config/cuegui.yaml: Added email.subscription_change_cc config - cuegui/Constants.py: Added SUBSCRIPTION_CHANGE_CC_TEMPLATE constant - cuegui/MenuActions.py: Implemented _sendSubscriptionChangeEmail() and updated editSize() and editBurst() methods
1 parent 55a90b3 commit cdbc9ce

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed

cuegui/cuegui/Constants.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ def __get_version_from_cmd(command):
158158
SHOW_SUPPORT_CC_TEMPLATE = [val.strip()
159159
for val
160160
in __config.get('email.show_support_cc_template', '').split(',')]
161+
SUBSCRIPTION_CHANGE_CC_TEMPLATE = [val.strip()
162+
for val
163+
in __config.get('email.subscription_change_cc', '').split(',')
164+
if val.strip()]
161165

162166
GITHUB_CREATE_ISSUE_URL = __config.get('links.issue.create')
163167
URL_USERGUIDE = __config.get('links.user_guide')

cuegui/cuegui/MenuActions.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,18 @@
2525
from builtins import filter
2626
from builtins import str
2727
from builtins import object
28+
import datetime
2829
import getpass
2930
import glob
31+
import smtplib
3032
import subprocess
3133
import time
34+
try:
35+
from email.MIMEText import MIMEText
36+
from email.Header import Header
37+
except ImportError:
38+
from email.mime.text import MIMEText
39+
from email.header import Header
3240

3341
from qtpy import QtGui
3442
from qtpy import QtWidgets
@@ -1663,6 +1671,82 @@ class SubscriptionActions(AbstractActions):
16631671
def __init__(self, *args):
16641672
AbstractActions.__init__(self, *args)
16651673

1674+
def _sendSubscriptionChangeEmail(self, subscription, change_type, old_value, new_value):
1675+
"""Sends an email notification when a subscription is changed.
1676+
1677+
@param subscription: The subscription object that was changed
1678+
@param change_type: Type of change ('size' or 'burst')
1679+
@param old_value: The previous value (in cores)
1680+
@param new_value: The new value (in cores)
1681+
"""
1682+
try:
1683+
username = getpass.getuser()
1684+
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
1685+
1686+
# Extract show name from subscription
1687+
show_name = subscription.data.show_name
1688+
subscription_name = subscription.data.name
1689+
allocation_name = subscription.data.allocation_name
1690+
1691+
# Construct email
1692+
subject = "Subscription {} Changed: {}".format(change_type.title(), subscription_name)
1693+
1694+
body = """A subscription {} has been modified.
1695+
1696+
Subscription: {}
1697+
Show: {}
1698+
Allocation: {}
1699+
1700+
Change Details:
1701+
{}: {} -> {}
1702+
1703+
Modified by: {}
1704+
Timestamp: {}
1705+
1706+
This is an automated notification from CueCommander.
1707+
""".format(change_type, subscription_name, show_name, allocation_name,
1708+
change_type.title(), old_value, new_value, username, timestamp)
1709+
1710+
# Email addresses
1711+
email_domain = cuegui.Constants.EMAIL_DOMAIN
1712+
if not email_domain:
1713+
logger.warning("EMAIL_DOMAIN not configured, skipping email notification")
1714+
return
1715+
1716+
from_addr = "cuecommander@{}".format(email_domain)
1717+
1718+
# Build CC list from configuration template
1719+
cc_list = []
1720+
for template in cuegui.Constants.SUBSCRIPTION_CHANGE_CC_TEMPLATE:
1721+
if template:
1722+
cc_addr = template.format(show=show_name, domain=email_domain)
1723+
cc_list.append(cc_addr)
1724+
1725+
# Skip sending email if no CC recipients are configured
1726+
if not cc_list:
1727+
logger.info(
1728+
"No CC recipients configured for subscription change notifications, "
1729+
"skipping email")
1730+
return
1731+
1732+
# Create email message
1733+
msg = MIMEText(body, 'plain', 'utf-8')
1734+
msg["Subject"] = Header(subject, 'utf-8', continuation_ws=' ')
1735+
msg["From"] = from_addr
1736+
msg["To"] = from_addr
1737+
msg["Cc"] = ", ".join(cc_list)
1738+
1739+
# Send email
1740+
recipient_list = [from_addr] + cc_list
1741+
server = smtplib.SMTP('smtp')
1742+
server.sendmail(from_addr, recipient_list, msg.as_string())
1743+
server.quit()
1744+
1745+
logger.info("Sent subscription change notification email for %s", subscription_name)
1746+
except Exception as e:
1747+
# Log error but don't fail the operation if email fails
1748+
logger.warning("Failed to send subscription change notification email: %s", e)
1749+
16661750
editSize_info = ["Edit Subscription Size...", None, "configure"]
16671751
def editSize(self, rpcObjects=None):
16681752
subs = self._getSelected(rpcObjects)
@@ -1688,9 +1772,17 @@ def editSize(self, rpcObjects=None):
16881772
return
16891773

16901774
for sub in subs:
1775+
# Capture old value before change
1776+
old_size = sub.data.size / 100.0
1777+
new_size = value
1778+
16911779
self.cuebotCall(sub.setSize,
16921780
"Set Size on Subscription %s Failed" % sub.data.name,
16931781
int(value*100.0))
1782+
1783+
# Send email notification
1784+
self._sendSubscriptionChangeEmail(sub, "size", old_size, new_size)
1785+
16941786
self._update()
16951787

16961788
editBurst_info = ["Edit Subscription Burst...", None, "configure"]
@@ -1708,9 +1800,17 @@ def editBurst(self, rpcObjects=None):
17081800
decimalPlaces)
17091801
if choice:
17101802
for sub in subs:
1803+
# Capture old value before change
1804+
old_burst = sub.data.burst / 100.0
1805+
new_burst = value
1806+
17111807
self.cuebotCall(sub.setBurst,
17121808
"Set Burst on Subscription %s Failed" % sub.data.name,
17131809
int(value*100.0))
1810+
1811+
# Send email notification
1812+
self._sendSubscriptionChangeEmail(sub, "burst", old_burst, new_burst)
1813+
17141814
self._update()
17151815

17161816
delete_info = ["Delete Subscription", None, "configure"]

cuegui/cuegui/config/cuegui.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,14 @@ email.domain: 'your.domain.com'
133133
# - {show} is not required and will be replaced by the job show
134134
# - Multiple addresses might be provided in a comma-separated list
135135
email.show_support_cc_template: "{show}-support@{domain}"
136+
# CC list for subscription change notifications (size/burst changes)
137+
# - {domain} will be replaced by email.domain
138+
# - {show} will be replaced by the subscription show name
139+
# - Multiple addresses might be provided in a comma-separated list
140+
# - Set to empty string ("") to disable email notifications for subscription changes
141+
# - Example: "{show}-admin@{domain},resource-team@{domain}"
142+
# - Example: "admin@example.com,team-lead@example.com"
143+
email.subscription_change_cc: ""
136144

137145
# Unix epoch timestamp. If the user last viewed the startup notice before this time, the
138146
# notice will be shown.

0 commit comments

Comments
 (0)