The functionality of this script to shutdown GCP VM's based on some logic. Currently we are trying shut it down at night, but the scripts are failing before it could shutdown the VM. We shutdown based on time. At evenings and night the VM are shutdown using these scripts
Script to turn off instances overnight
Environment: Runs in Google Cloud Functions (Python3.7)
import datetime
import json
from pprint import pformat
import pytz
import re
import modules.common.cfcommon as cfcommon
import modules.utilities.dateutilities as dateutilities
from modules.compute.instances import InstanceList, Instance
from modules.compute.compute_service import ComputeServiceContext
from modules.utilities.printutilities import print_message, debug_message
from modules.pubsub.topic import PublishMessage
from modules.common.labels import VMAUTOSHUTDOWN_LABEL, VMAUTOSHUTDOWN_DEFER_LABEL, ShutdownDeferLabelValueIsValid, ShutdownLabelValueIsValid
from templates.renderer import render_template
# Takes a list in the following format and checks if the 'Instance' object is within it
# list must contain dictionaries in the following format:
# {"name": "instancename", "zone": "zonename"}
# Example: {"name": "test-01", "zone": "us-east4-c"}
#
# Parameters:
# inputList - list of dictionary objects
# instance - Instance object
def isInstanceInList(inputList, instance):
if not isinstance(inputList, list):
raise TypeError("Provided inputList is not a list")
if not isinstance(instance, Instance):
raise TypeError("Provided instance is not of type 'Instance'")
# Iterate over every item in inputList and check if the name and zone match
for cItem in inputList:
if cItem["name"].lower() == instance.properties["name"].lower() and cItem["zone"].lower() == instance.GetShortZoneName().lower():
return True
# No match found
return False
# Takes a list of Instance objects and sees if their shutdown timezone is within the graceperiod of the shutdownHour
#
# Example: is shutdown hour is 23 and the gracePeriodMin is 15 then if the function is called at 23:12, the instance will be included in the shutdown list
#
# Parameters:
# instanceList - List of Instance objects
# shutdownHour - number (0-23) 0 = Midnight, 23 = 11PM
# gracePeriodMin - number
def getInstancesToStop(instanceList, gracePeriodMin):
instancesToStop = []
debug_message("Entering getInstancesToStop")
for cInstance in instanceList:
debug_message("Instance: %s (ID: %s, Zone: %s, Project: %s)" % (cInstance.GetName(), cInstance.GetId(), cInstance.GetShortZoneName(), cInstance.project))
labels = cInstance.GetLabels()
if VMAUTOSHUTDOWN_LABEL in labels.keys():
labelValue = labels.get(VMAUTOSHUTDOWN_LABEL, '')
pattern = '\d\d-\d\d-\d\d'
match = re.match(pattern, labelValue)
if not match or not ShutdownLabelValueIsValid(labelValue):
debug_message(f'Label {labelValue} does not match the correct format')
instancesToStop.append(cInstance)
continue
else:
debug_message(f'Label {VMAUTOSHUTDOWN_LABEL} not found. Adding to shutdown list')
instancesToStop.append(cInstance)
continue
shutdown_deferred_utc_datetime = None
if VMAUTOSHUTDOWN_DEFER_LABEL in labels.keys():
labelValue = labels.get(VMAUTOSHUTDOWN_DEFER_LABEL, '')
pattern = '\d\d\d\d-\d\d-\d\dt\d\d-\d\d-\d\d'
match = re.match(pattern, labelValue)
if match and ShutdownDeferLabelValueIsValid(labelValue):
shutdown_deferred_utc_date, shutdown_deferred_utc_time = labelValue.split('t')
year, month, day = shutdown_deferred_utc_date.split('-')
hour, minute, second = shutdown_deferred_utc_time.split('-')
shutdown_deferred_utc_datetime = datetime.datetime.now(pytz.timezone('GMT')).replace(
year=int(year), month=int(month), day=int(day), hour=int(hour), minute=int(minute), second=int(second)
)
else:
debug_message(f'Label {labels[VMAUTOSHUTDOWN_DEFER_LABEL]} does not match the correct format')
instancesToStop.append(cInstance)
continue
current_utc_time = dateutilities.get_current_datetime()
# If defer date is in the future, and not in grace window time, skip shutting down
if shutdown_deferred_utc_datetime is not None and shutdown_deferred_utc_datetime > current_utc_time:
debug_message(f'Instance {cInstance.GetName()} shutdown deferred until after {labels[VMAUTOSHUTDOWN_DEFER_LABEL]}')
continue
# If defer time is in past, continue with the vm hour shutdown
shutdown_utc_hour = labels[VMAUTOSHUTDOWN_LABEL].split('-')[0]
# Convert shutdown UTC hour into datetime object
shutdown_utc_time = datetime.datetime.now(pytz.timezone('GMT')).replace(hour=int(shutdown_utc_hour), minute=0, second=0)
shutdown_utc_grace_time = shutdown_utc_time + datetime.timedelta(minutes=gracePeriodMin)
debug_message(f"Shutdown UTC time {shutdown_utc_time}")
debug_message(f"Shutdown UTC grace time {shutdown_utc_grace_time}")
# Check if shutdown is within time window
if current_utc_time >= shutdown_utc_time and current_utc_time <= shutdown_utc_grace_time:
debug_message("We're in the time window")
instancesToStop.append(cInstance)
else:
debug_message("We're outside the time window. Not adding to stop list")
return instancesToStop
# This is the main entry point that cloud functions calls
def AutoStopVMInstances(config, policy=None, payload=None, generate_local_report=False):
FUNCTION_NAME = "AutoStopVMInstances"
# Populated by config later...
QUERY_PROJECT_IDS = None # List of project IDs
INSTANCE_WHITELIST = None # List of dictionaries in format {"name": "instancename", "zone": "zonename", "project": "projectid"}
PREVIEW_MODE = True
SHUTDOWN_GRACEPERIOD_MIN = 30
# Start
startTime = datetime.datetime.now()
print_message("Started %s within Cloud Function %s [%s]" % (FUNCTION_NAME, cfcommon.CLOUD_FUNCTION_NAME, startTime))
debug_message("")
# For ease of access, assign from config values
debug_message("Processing Configuration...")
QUERY_PROJECT_IDS = config.get("QueryProjectIDs", []) # Required field
INSTANCE_WHITELIST = config.get("InstanceWhiteList", []) # Optional Field
PREVIEW_MODE = config.get("PreviewMode", True) # Required field
SHUTDOWN_GRACEPERIOD_MIN = config.get("ShutdownGracePeriodMin", None) # Required field
SKIP_INSTANCE_GROUPS = config.get("SkipInstanceGroups", False) # Optional
EMAIL_PUB_SUB_PROJECT = config.get("EmailPubSubProject", None) # Optional
EMAIL_PUB_SUB_TOPIC = config.get("EmailPubSubTopic", None) # Optional
EMAIL_TO = config.get("EmailTo", []) # Optional
EMAIL_CC = config.get("EmailCC", None) # Optional
EMAIL_BCC = config.get("EmailBCC", None) # Optional
EMAIL_FROM = config.get("EmailFrom", "noreply-ei-cs-cloudops-resource-administration#ei-cs-cloudops.local") # Optional
EMAIL_SUBJECT = config.get("EmailSubject", "Nightly VM Instance Shutdown Summary") # Optional
cfLogger = cfcommon.CloudFunctionLog()
# Validate whitelist
if INSTANCE_WHITELIST is None:
raise Exception("Unable to get whitelist")
debug_message("Whitelist loaded:")
debug_message(pformat((INSTANCE_WHITELIST)))
# Re-init Compute service - execution environment in cloud functions can be shared among each other. Let's re-init our connection every execution.
ComputeServiceContext.InitComputeService()
# Build the service object.
allRunningInstances = []
for cProjectId in QUERY_PROJECT_IDS:
debug_message("Checking Project: %s" % (cProjectId))
# Main Loop - Let's get and analyze all instances from our project
# Paginated within the 'request' object
runningInstances = []
allInstances = []
debug_message("Building Instance List...", end="")
instances = InstanceList(cProjectId)
instances.PopulateInstances()
debug_message("Done")
for cInstance in instances.GetAllInstances():
debug_message("Found Instance %s in %s [%s - %s]" % (cInstance.GetName(), cInstance.GetZone(), cInstance.GetId(), cInstance.GetStatus()))
# Check if whitelisted. If it is, skip it
if isInstanceInList(INSTANCE_WHITELIST, cInstance):
debug_message(" Instance is whitelisted. Skipping.")
continue
# Check if we should skip instance groups
if SKIP_INSTANCE_GROUPS and cInstance.IsWithinInstanceGroup():
debug_message(" Instance is within an instance group. Skipping.")
continue
debug_message(" Is Running: %s" % (cInstance.IsRunning()))
owner = cInstance.GetOwner()
if owner in ("devops", "ei devops", "eicsdevopseng"):
debug_message("Skipping instance owned by devops")
continue
# # TODO: FOR USE WHEN TESTING
# if VMAUTOSHUTDOWN_LABEL not in labels.keys():
# continue
# Keep track of this instance
allInstances.append(cInstance)
# If it's running, it's a candidate to stop
if cInstance.IsRunning():
runningInstances.append(cInstance)
# Handle no instances found
if len(allInstances) == 0:
debug_message("INFO: No Instances found.")
# Summarize for user
debug_message("")
if len(runningInstances) > 0:
debug_message("Found %s/%s non-whitelisted instances are running (project: %s)" % (len(runningInstances), len(allInstances), cProjectId))
else:
debug_message("All %s non-whitelisted instances are good (project: %s)" % (len(allInstances), cProjectId))
# Main loop to stop
debug_message("")
allRunningInstances = allRunningInstances + runningInstances
instancesToBeStopped = getInstancesToStop(allRunningInstances, SHUTDOWN_GRACEPERIOD_MIN)
stoppedCount = 0
instanceSummary = []
if len(instancesToBeStopped) == 0:
print_message("No instances are due to be stopped")
else:
for cInstance in instancesToBeStopped:
summaryEntry = {
"Name": cInstance.GetName(),
"ID": cInstance.GetId(),
"Zone": cInstance.GetShortZoneName(),
"Project": cInstance.GetProject(),
"Preview": PREVIEW_MODE,
"Stopped": False,
"InstanceLink": cInstance.GetSelfLinkToConsole()
}
logMessage = "Stopping Instance: {name} (ID: {id}, Zone: {zone}, Project: {project})".format(
name=summaryEntry.get("Name"),
id=summaryEntry.get("ID"),
zone=summaryEntry.get("Zone"),
project=summaryEntry.get("Project")
)
if PREVIEW_MODE:
print_message("(PREVIEW) " + logMessage )
else:
print_message(logMessage)
cInstance.Stop()
summaryEntry["Stopped"] = True
stoppedCount += 1
instanceSummary.append(summaryEntry)
if EMAIL_PUB_SUB_PROJECT is not None and EMAIL_PUB_SUB_TOPIC is not None:
debug_message("It looks like we have an email config. Attempting to send email")
emailBody = render_template(
'shutdown_report',
instance_summary=instanceSummary,
config=json.dumps(config, indent=4, sort_keys=True),
preview_mode=PREVIEW_MODE,
generation_time=datetime.datetime.now().astimezone(pytz.utc)
)
emailPayload = {
"To": EMAIL_TO,
"From": EMAIL_FROM,
"Subject": EMAIL_SUBJECT,
"BodyHtml": emailBody
}
if EMAIL_CC is not None:
emailPayload["CC"] = EMAIL_CC
if EMAIL_BCC is not None:
emailPayload["BCC"] = EMAIL_BCC
if not generate_local_report:
print_message("Sending email...", end="")
PublishMessage(EMAIL_PUB_SUB_PROJECT, EMAIL_PUB_SUB_TOPIC, json.dumps(emailPayload))
else:
print_message('Generating local HTML report')
with open('./html_reports/shutdown_report.html', 'w') as r:
r.write(emailBody)
print_message("Done")
# We want to log a nice structured json line to stackdriver for easy reporting.
cfLogger.log({
"StartTime": startTime.isoformat(),
"InstancesStoppedCount": stoppedCount,
"PreviewMode": PREVIEW_MODE,
"Instances": instanceSummary,
"Whitelist": INSTANCE_WHITELIST,
"EndTime": datetime.datetime.now().isoformat(),
"LogLine": "Summary"
})
print_message("DONE [%s]" % (datetime.datetime.now()))
The error I'm getting when trying to run a VM shutdown script:
Caught exception while running VMNightlyShutdown. Exception Text: Traceback (most recent call last):
File "/workspace/main.py", line 248, in StartCloudFunction
policy=policy_config)
File "/workspace/vm_nightly_shutdown.py", line 256, in AutoStopVMInstances
cInstance.Stop()
File "/workspace/modules/compute/instances.py", line 729, in Stop
stop_instance(self.project, self.GetShortZoneName(), self.GetName(), waitForCompletion=waitForCompletion)
File "/workspace/modules/compute/instances.py", line 45, in stop_instance
return wait_for_operation(project, zone, response["name"])
File "/workspace/modules/compute/instances.py", line 27, in wait_for_operation
operation=operation
File "/layers/google.python.pip/pip/lib/python3.7/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "/layers/google.python.pip/pip/lib/python3.7/site-packages/googleapiclient/http.py", line 932, in execute
headers=self.headers,
File "/layers/google.python.pip/pip/lib/python3.7/site-packages/googleapiclient/http.py", line 222, in _retry_request
raise exception
File "/layers/google.python.pip/pip/lib/python3.7/site-packages/googleapiclient/http.py", line 191, in _retry_request
resp, content = http.request(uri, method, *args, **kwargs)
File "/layers/google.python.pip/pip/lib/python3.7/site-packages/google_auth_httplib2.py", line 225, in request
**kwargs
File "/layers/google.python.pip/pip/lib/python3.7/site-packages/httplib2/__init__.py", line 1721, in request
conn, authority, uri, request_uri, method, body, headers, redirections, cachekey,
File "/layers/google.python.pip/pip/lib/python3.7/site-packages/httplib2/__init__.py", line 1440, in _request
(response, content) = self._conn_request(conn, request_uri, method, body, headers)
File "/layers/google.python.pip/pip/lib/python3.7/site-packages/httplib2/__init__.py", line 1392, in _conn_request
response = conn.getresponse()
File "/layers/google.python.runtime/python/lib/python3.7/http/client.py", line 1373, in getresponse
response.begin()
File "/layers/google.python.runtime/python/lib/python3.7/http/client.py", line 319, in begin
version, status, reason = self._read_status()
File "/layers/google.python.runtime/python/lib/python3.7/http/client.py", line 280, in _read_status
line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
File "/layers/google.python.runtime/python/lib/python3.7/socket.py", line 589, in readinto
return self._sock.recv_into(b)
File "/layers/google.python.runtime/python/lib/python3.7/ssl.py", line 1071, in recv_into
return self.read(nbytes, buffer)
File "/layers/google.python.runtime/python/lib/python3.7/ssl.py", line 929, in read
return self._sslobj.read(len, buffer)
ssl.SSLError: [SSL: DECRYPTION_FAILED_OR_BAD_RECORD_MAC] decryption failed or bad record mac (_ssl.c:2570)",
}
I was supposed to create a python code to take items in a list and turn them into a bar graph. In my code, I have a create graph method that works in the first time I run my code, but then when I opt to enter a different data set in, it causes errors, specifically when creategraph is called in a while loop.
def creategraph():
bar = turtle.Turtle()
bar.speed(100)
bar.color("black")
bar.fillcolor("green")
bar.pensize(3)
bar.setposition(-200, 0)
xs = [top(text), eighties(text), seventies(text), sixties(text), belowsixties(text)]
#creates list withthe heights ^^
for i in xs:
draw_bar(bar, i)
bar.penup()
bar.setposition(-200, -50)
bar.forward(40)
bar.write(str("90s"))
bar.forward(40)
bar.forward(40)
bar.write(str("80s"))
bar.forward(40)
bar.forward(40)
bar.write(str("70s"))
bar.forward(40)
bar.forward(40)
bar.write(str("60s"))
bar.forward(40)
bar.forward(40)
bar.write(str("<60"))
bar.forward(40)
bar.hideturtle()
turtle.done()
this causes me to get error messages like this:
exception was:
Traceback (most recent call last):
File "C:\Users\bwoo2\OneDrive\Desktop\CS\Python\__Project2_ScoreAnalysis_Bwoo.py", line 160, in <module>
creategraph()
File "C:\Users\bwoo2\OneDrive\Desktop\CS\Python\__Project2_ScoreAnalysis_Bwoo.py", line 102, in creategraph
bar = turtle.Turtle()
File "C:\Users\bwoo2\AppData\Local\Programs\Thonny\lib\turtle.py", line 3816, in __init__
visible=visible)
File "C:\Users\bwoo2\AppData\Local\Programs\Thonny\lib\turtle.py", line 2557, in __init__
self._update()
File "C:\Users\bwoo2\AppData\Local\Programs\Thonny\lib\turtle.py", line 2660, in _update
self._update_data()
File "C:\Users\bwoo2\AppData\Local\Programs\Thonny\lib\turtle.py", line 2646, in _update_data
self.screen._incrementudc()
File "C:\Users\bwoo2\AppData\Local\Programs\Thonny\lib\turtle.py", line 1292, in _incrementudc
raise Terminator
turtle.Terminator
and my loop that calls the graph is
codebreaker = 0
while codebreaker == 0:
breaker = False
text = input("Please enter the file name: ")
f = open(text)
lineList = [line.rstrip('\n') for line in f]
f.close()
text = lineList
print("Results for", text[0])
print("Number of scores:", findscores(text))
print("High score:", findmax(text))
print("Low score:", findmin(text))
print("Avg:", findavg(text))
print("Check other screen for graph of data")
print("Make sure to close out of graph before processing another file")
creategraph()
print("")
y_n = input("Process another file? y/n :")
if y_n == "y":
breaker = False
elif y_n == "n":
breaker = True
if breaker == True:
codebreaker = 1
Any idea what's wrong with the creategraph function?
Your primary problem is that the turtle.done() function is only meant to be called once, when you are turning control over to the event handler and all future interaction with the code will be through events (mouse clicks, key presses, etc.) If you are calling creategraph() multiple times, then turtle.done() has no business being called from it.
Your secondary problem is that you are trying to combine console input with turtle events. You really should be using turtle's event model only. That is, instead of input() you should be using turtle's textinput() method to pop up a dialog based on an event (i.e. pushing a 'new data' pseudo button).
I am trying to run a function every 2 minutes, and I use apscheduler for this. However, when I run this I get the following error:
Traceback (most recent call last):
File "main_forecast.py", line 7, in <module>
scheduler.add_job(get_warnings(), 'interval', seconds = 120)
File "/home/anastasispap/.local/lib/python3.6/site-packages/apscheduler/schedulers/base.py", line 434, in add_job
job = Job(self, **job_kwargs)
File "/home/anastasispap/.local/lib/python3.6/site-packages/apscheduler/job.py", line 49, in __init__
self._modify(id=id or uuid4().hex, **kwargs)
File "/home/anastasispap/.local/lib/python3.6/site-packages/apscheduler/job.py", line 170, in _modify
raise TypeError('func must be a callable or a textual reference to one')
TypeError: func must be a callable or a textual reference to one
And here's the code:
from apscheduler.schedulers.background import BackgroundScheduler
from enemies_info import get_warnings
import time
scheduler = BackgroundScheduler()
scheduler.add_job(get_warnings(), 'interval', seconds = 120)
scheduler.start()
while True:
time.sleep(120)
The function I want to run every 2 minutes is get_warnings.
def get_warnings():
print('get_warning has been run')
names = []
types = []
number_of_threats = 0
forecast_weather()
for i in range(0, number_of_enemies):
enemies = info["enemies"][i]
name = enemies["name"]
type = enemies["type"]
temperature = enemies["temperature"]
temperature = temperature.split("-")
min_temp = temperature[0]
max_temp = temperature[1]
for i in range(len(temperatures)):
if avg_temps[i] <= str(max_temp):
names.append(name)
types.append(type)
number_of_threats += 1
break
os.chdir('..')
write_data(number_of_threats, names, types)
move_to_github()
You are calling the function get_warnings, instead of providing it as a callable. Try:
scheduler.add_job(get_warnings, 'interval', seconds = 120)
Error
Traceback (most recent call last):
File "C:/Users/RCS/Desktop/Project/SHM.py", line 435, in <module>
app = SHM()
File "C:/Users/RCS/Desktop/Project/SHM.py", line 34, in __init__
frame = F(container, self)
File "C:/Users/RCS/Desktop/Project/SHM.py", line 384, in __init__
if "3202" in q:
TypeError: argument of type 'method' is not iterable
code
some part of code, initialisation and all
while 1:
q = variable1.get
if "3202" in q:
variable2.set("NI NODE3202")
try:
switch(labelframe2, labelframe1)
except:
switch(labelframe3, labelframe1)
elif "3212" in q:
variable2.set("NI NODE3212")
try:
switch(labelframe1, labelframe2)
except:
switch(labelframe3, labelframe2)
elif "3214" in q:
variable2.set("NI NODE3214")
try:
switch(labelframe1, labelframe3)
except:
switch(labelframe2, labelframe3)
else:
None
some other part of code
def switch(x, y):
if x.isGridded:
x.isGridded = False
x.grid_forget()
y.isGridded = True
y.grid(row=0, column=0)
else:
return False
I am trying to create a switch between three labelframes which are inside another labelframe, and outside this labelframe are other labelframes that are not changing.
I have read some similar answers but I don't want to use __iter__() in my code. Can anybody provide any other suggestions?
You forgot to call the Entry.get() method:
q = variable1.get()
# ^^ call the method
Because the method object itself doesn't support containment testing directly, Python is instead trying to iterate over the object to see if there are any elements contained in it that match your string.
If you call the method, you get a string value instead. Strings do support containment testing.
The reason you got that error was because you did not add "()" after.get query hence the error to fix this change q = variable1.get to q = variable.get()
I'm working on a project and this error keeps showing up:
class PRNG:
def __init__(self):
# parameters
# P-256 prime
self.p=115792089210356248762697446949407573530086143415290314195533631308867097853951
self.a=self.p-3
self.b=41058363725152142129326129780047268409114441015993725554835256314039467401291
self.E=curve(self.a,self.b,self.p)
self.E.n=115792089210356248762697446949407573529996955224135760342422259061068512044369
self.P=point(0,46263761741508638697010950048709651021688891777877937875096931459006746039284)
self.k=183521403747637560534595403690771364941493702673414885451510208165414833985
self.Q=mult(self.k,self.P,self.E)
self.t=bytes_to_int(os.urandom(32)) # initial seed
#print self.t
self.output_length=240
self.truncate_length=16
def function_attack(self, nbytes, predicted_state):
calls = ((nbytes*8-1)/self.output_length)+1
out = ''
for i in xrange(calls):
tP=mult(predicted_state,self.P,self.E)
s=tP.x
sQ=mult(s,self.Q,self.E)
r=sQ.x
r_out=r % (2**self.output_length)
self.t=s
out = out + int_to_bytes(r_out, self.output_length/8)
return out[:nbytes]
def function(self, nbytes):
calls = ((nbytes*8-1)/self.output_length)+1
out = ''
for i in xrange(calls):
tP=mult(self.t,self.P,self.E)
s=tP.x
sQ=mult(s,self.Q,self.E)
r=sQ.x
r_out=r % (2**self.output_length)
self.t=s
out = out + int_to_bytes(r_out, self.output_length/8)
return out[:nbytes]
The first method is being called in a separate file and the output is always the following(regardless if I change the name of the local variable calls):
File "C:\file1.py", line 32, in <module>
prng = PRNG()
File "C:\file_where_error_occurs.py", line 286, in __init__
for i in xrange(calls):
NameError: global name 'calls' is not defined
What is python doing?
you have indentation errors ... this is typically caused by mixing tabs and spaces ... most decent editors can fix this for you easily ... to see your indentation errors run your program as
python -tt my_program.py