In [ ]:
#imports
import googleapiclient.discovery
from apiclient.discovery import build
import ipywidgets as widgets
import re
import json
#we use pandas.DataFrame for printing arrays and dictionnary nicely
from pandas import DataFrame
In [ ]:
# %load getCredentialsFromFile.py
def getCredentials():
from oauth2client import file
import httplib2
import ipywidgets as widgets
print("Getting the credentials from file...")
storage = file.Storage("oauth2.dat")
credentials=storage.get()
if credentials is None or credentials.invalid:
print( '❗')
display(widgets.Valid(
value=False,
description='Credentials are ',
disabled=False))
display(widgets.HTML('go create a credential valid file here: <a target="_blank" href="cloud.google.auth.ipynb.ipynb">gcloud authorization notebook</a> and try again'))
else:
http_auth = credentials.authorize(httplib2.Http())
print('✅ Ok')
return credentials
In [ ]:
credentials=getCredentials()
In [ ]:
compute_service = build('compute', 'v1', credentials=credentials)
resource_service = build('cloudresourcemanager', 'v1', credentials=credentials)
In [ ]:
# %load chooseProjectId.py
#projectId is the variable that will contains the projectId that will be used in the API calls
projectId=None
#list the existing projects
projects=resource_service.projects().list().execute()
#we create a dictionaray name:projectId foe a dropdown list widget
projectsList={project['name']:project['projectId'] for project in projects['projects']}
projectsList['None']='invalid'
#the dropdownlist widget
projectWidget=widgets.Dropdown(options=projectsList,description='Choose your Project',value='invalid')
#a valid widget that get valid when a project is selected
projectIdValid=widgets.Valid(value=False,description='')
display(widgets.Box([projectWidget,projectIdValid]))
def projectValueChange(sender):
if projectWidget.value!='invalid':
#when a valid project is selected ,the gloabl variable projectId is set
projectIdValid.value=True
projectIdValid.description=projectWidget.value
global projectId
projectId=projectWidget.value
else:
projectIdValid.value=False
projectIdValid.description=''
projectWidget.observe(projectValueChange, 'value')
In [ ]:
# %load chooseZone.py
#zone is the variable that will contains the zone that will be used in the API calls
zone=None
#list the existing zones
zones=compute_service.zones().list(project=projectId).execute()
#list that will contains the zones for a dropdown list
zonesList=[item['name'] for item in zones['items']]
zonesList.append('none')
#the dropdownlist widget
zoneWidget=widgets.Dropdown(options=zonesList,value='none',description='Choose your Zone:')
zoneValid=widgets.Valid(value=False,description='')
display(widgets.Box([zoneWidget,zoneValid]))
def zoneValueChange(sender):
if zoneWidget.value!='none':
#when a vail zone is slected, the variable zone is set
zoneValid.value=True
zoneValid.description=zoneWidget.value
global zone
zone=zoneWidget.value
else:
zoneValid.value=False
zoneValid.description=''
zoneWidget.observe(zoneValueChange, 'value')
In [ ]:
image_response = compute_service.images().getFromFamily(
project='debian-cloud', family='debian-8').execute()
source_disk_image = image_response['selfLink']
In [ ]:
machineType=None
machineTypes=compute_service.machineTypes().list(project=projectId,zone=zone).execute()
machineTypesList=[item['name'] for item in machineTypes['items']]
machineTypesList.append('none')
machineTypesWidget=widgets.Dropdown(options=machineTypesList,value='none',description='Choose your MachineType:')
machineTypesValid=widgets.Valid(value=False,description='')
display(widgets.Box([machineTypesWidget,machineTypesValid]))
def machineTypeValueChange(sender):
if machineTypesWidget.value!='none':
machineTypesValid.value=True
machineTypesValid.description=machineTypesWidget.value
global machineType
machineType=machineTypesWidget.value
else:
machineTypesValid.value=True
machineTypesValid.description=''
machineTypesWidget.observe(machineTypeValueChange, 'value')
In [ ]:
instanceName=None
# instanceName have to validates this regexp
instanceNameControl=re.compile(r'^(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?)$')
#the widgets
instanceNameWidget=widgets.Text(description="Name for the new instance:")
valid=widgets.Valid(value=False,description='',disabled=False)
display(widgets.Box([instanceNameWidget,valid]))
def instanceNameValueChange(sender):
if instanceNameWidget.value!="":
if instanceNameControl.match(instanceNameWidget.value):
#when the entered text valid the regexp we set the
valid.value=True
valid.description='OK'
global instanceName
instanceName=instanceNameWidget.value
else:
valid.value=False
valid.description="The instance name has to verify the regexp '(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?)'"
else:
valid.value=False
valid.description=''
instanceNameWidget.observe(instanceNameValueChange, 'value')
In [ ]:
config= {'name':instanceName,
'machineType': "zones/%(zone)s/machineTypes/%(machineType)s" %{'zone':zone,'machineType':machineType},
'disks':[
{
'boot':True,
'autoDelete':True,
'initializeParams':{
'sourceImage':source_disk_image
}
}],
'scheduling':
{
'preemptible': True
},
'networkInterfaces':[{
'network':'global/networks/default',
'accessConfigs': [
{'type':'ONE_TO_ONE_NAT','name':'ExternalNAT'}
]
}],
'serviceAccounts':[{
'email':'default',
'scopes':[
'https://www.googleapis.com/auth/devstorage.read_write',
'https://www.googleapis.com/auth/logging.write'
]
}],
"labels": {
"env": "test",
"created-by": "jupyter-notebooks-cloud-google-compute-instances"
},
}
#print(json.dumps(config, indent=2))
In [ ]:
#a progress widget will present the progress of the operation
progress=widgets.IntProgress(value=0,min=0,max=3,step=1,description=':',bar_style='warning')
display(progress)
#executing the insert operation
operation = compute_service.instances().insert(project=projectId,
zone=zone,
body=config
).execute()
def updateProgress(result,progress=progress):
#updating the progress widget with the result of the operation
if result['status']== 'PENDING':
progress.value=1
progress.bar_style='warning'
progress.description=result['status']
elif result['status']== 'RUNNING':
progress.value=2
progress.bar_style='info'
progress.description=result['status']
elif result['status']== 'DONE':
progress.value=3
if 'error' in result:
progress.description='Error'
progress.bar_style='danger'
else:
progress.description=result['status']
progress.bar_style='success'
import time
#repeat until the result is DONE
while True:
#obtain the status of the operation
result=compute_service.zoneOperations().get(project=projectId,
zone=zone,
operation=operation['name']).execute()
updateProgress(result)
if result['status']== 'DONE':
break
time.sleep(.25)
In [ ]:
result = compute_service.instances().list(project=projectId, zone=zone).execute()
if 'items' in result.keys():
display(DataFrame.from_dict({instance['name']:(instance['status'],'✅'if instance['status']=='RUNNING' else '✖'if instance['status']=='TERMINATED' else '❓')for instance in result['items']},orient='index'))
else:
print("No instance found.")
In [ ]:
# getting the current instances list
instances=compute_service.instances().list(project=projectId,zone=zone).execute()
instancesList=[item['name'] for item in instances['items']]
# none is added for the dropdownlist
instancesList.append('none')
#building and displaying the widgets
instancesWidget=widgets.Dropdown(options=instancesList,value='none')
instancesValid=widgets.Valid(value=False,description='')
instanceAction=widgets.RadioButtons(
options=[ 'Status','Start','Stop', 'Delete'],value='Status')
instanceExecute=widgets.ToggleButton(value=False,description='Execute',disabled=True)
display(widgets.Box([instancesWidget,instancesValid,instanceAction,instanceExecute]))
## execute an operation.
def execute(operation):
#exctract the method and the instancename form the operation
instanceName=operation.uri.split('?')[0].split('/')[-1]
methodId=operation.methodId.split('.')[-1]
#some widgets (action + instance + progress)
progress=widgets.IntProgress(value=0,min=0,max=3,step=1,description=':',bar_style='info')
display(widgets.Box([widgets.Label(value=methodId+"ing"),widgets.Label(value=instanceName),progress]))
#the dropdown and buttons are disabled when an operation is executing
global instanceExecute
global instancesWidget
instancesWidget.disabled=True
instanceExecute.disabled=True
#execute the operation
operation=operation.execute()
#until the operation is not DONE, we update the progress bar
while True:
result=compute_service.zoneOperations().get(project=projectId,
zone=zone,
operation=operation['name']).execute()
updateProgress(result,progress)
if result['status']== 'DONE':
if methodId==u'delete':
#when the instance is deleted, it has to be remove from the dropdownlist
global instancesList
instancesList.remove(instanceName)
instancesWidget.options=instancesList
instancesValid.value=False
#the operation is completed, the dropwdown and buttons are enabled
instancesWidget.disabled=False
instanceExecute.disabled=False
break
time.sleep(0.1)
def executeInstance(sender):
#callback when the execute button is clicked
if instancesValid.value==True:
# the correct operation is created and pass to the execute method
if instanceAction.value=='Stop':
execute(compute_service.instances().stop(project=projectId,
zone=zone,
instance=instancesWidget.value
))
elif instanceAction.value=='Start':
execute(compute_service.instances().start(project=projectId,
zone=zone,
instance=instancesWidget.value
))
elif instanceAction.value=='Delete':
execute(compute_service.instances().delete(project=projectId,
zone=zone,
instance=instancesWidget.value
))
elif instanceAction.value=='Status':
instance=compute_service.instances().get(project=projectId,
zone=zone,
instance=instancesWidget.value).execute()
display(widgets.Box([widgets.Label(value=instance['name']),
widgets.Label(value=instance['status'])
]))
def instancesValueChange(sender):
#callback when an element is selected in the dropdown list
if instancesWidget.value!=None:
#when the seleciton is correct the valid widget is valid
instancesValid.value=True
instanceExecute.disabled=False
#set up the callback on the widgets
instancesWidget.observe(instancesValueChange, 'value')
instanceExecute.observe(executeInstance,'value')
In [ ]: