blob: 8bb0e14c5e04ff970ecfa605ac57ccfdb8ed5564 [file] [log] [blame]
#!/usr/bin/env python
# encoding: utf-8
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import json
import urllib
from flask import request, url_for
from gstack import app, authentication
from gstack.services import requester
from gstack.controllers import zones, helper, operations, images, errors, machine_type, networks
def _get_virtual_machines(authorization, args=None):
command = 'listVirtualMachines'
if not args:
args = {}
cloudstack_response = requester.make_request(
command,
args,
authorization.client_id,
authorization.client_secret
)
return cloudstack_response
def _deploy_virtual_machine(authorization, args, projectid):
command = 'deployVirtualMachine'
converted_args = {}
template = images.get_template_by_name(
authorization=authorization,
image=args['template']
)
converted_args['templateid'] = template['id']
zone = zones.get_zone_by_name(
authorization=authorization,
zone=args['zone']
)
converted_args['zoneid'] = zone['id']
serviceoffering = machine_type.get_machinetype_by_name(
authorization=authorization,
machinetype=args['serviceoffering']
)
converted_args['serviceofferingid'] = serviceoffering['id']
if 'network' in args:
network = networks.get_network_by_name(
authorization=authorization,
securitygroup=args['network']
)
converted_args['securitygroupids'] = network['id']
converted_args['displayname'] = args['name']
converted_args['name'] = args['name']
converted_args['keypair'] = projectid
cloudstack_response = requester.make_request(
command,
converted_args,
authorization.client_id,
authorization.client_secret
)
return cloudstack_response
def _destroy_virtual_machine(authorization, instance):
virtual_machine_id = _get_virtual_machine_by_name(
authorization,
instance)['id']
if virtual_machine_id is None:
func_route = url_for('_destroy_virtual_machine', instance=instance)
return errors.resource_not_found(func_route)
args = {
'id': virtual_machine_id
}
return requester.make_request(
'destroyVirtualMachine',
args,
authorization.client_id,
authorization.client_secret
)
def _cloudstack_virtual_machine_to_gce(cloudstack_response, zone, projectid):
response = {}
response['kind'] = 'compute#instance'
response['id'] = cloudstack_response['id']
response['creationTimestamp'] = cloudstack_response['created']
response['status'] = cloudstack_response['state'].upper()
response['name'] = cloudstack_response['name']
response['description'] = cloudstack_response['name']
response['machineType'] = cloudstack_response['serviceofferingname']
response['image'] = cloudstack_response['templatename']
response['canIpForward'] = 'true'
response['networkInterfaces'] = []
response['disks'] = []
networking = {}
accessconfig = {}
if 'securitygroup' in cloudstack_response:
networking['network'] = cloudstack_response['securitygroup'][0]['name']
networking['networkIP'] = cloudstack_response['nic'][0]['ipaddress']
networking['name'] = cloudstack_response['nic'][0]['id']
accessconfig['natIP'] = cloudstack_response['nic'][0]['ipaddress']
networking['accessConfigs'] = []
accessconfig['kind'] = 'compute#accessConfig'
accessconfig['type'] = 'ONE_TO_ONE_NAT'
accessconfig['name'] = 'External NAT'
networking['accessConfigs'] = accessconfig
response['networkInterfaces'].append(networking)
response['selfLink'] = urllib.unquote_plus(helper.get_root_url() + url_for(
'getinstance',
projectid=projectid,
instance=cloudstack_response['name'],
zone=zone
))
response['zone'] = zone
return response
def _get_virtual_machine_by_name(authorization, instance):
virtual_machine_list = _get_virtual_machines(
authorization=authorization,
args={
'keyword': instance
}
)
if virtual_machine_list['listvirtualmachinesresponse']:
response = helper.filter_by_name(
data=virtual_machine_list['listvirtualmachinesresponse']['virtualmachine'],
name=instance
)
return response
else:
return None
@app.route('/compute/v1/projects/<projectid>/aggregated/instances', methods=['GET'])
@authentication.required
def aggregatedlistinstances(authorization, projectid):
zone_list = zones.get_zone_names(authorization=authorization)
virtual_machine_list = _get_virtual_machines(authorization=authorization)
instance = None
filter = helper.get_filter(request.args)
if 'name' in filter:
instance = filter['name']
items = {}
for zone in zone_list:
zone_instances = []
if instance:
virtual_machine = _get_virtual_machine_by_name(
authorization=authorization,
instance=instance
)
if virtual_machine:
zone_instances.append(
_cloudstack_virtual_machine_to_gce(
cloudstack_response=virtual_machine,
projectid=projectid,
zone=zone
)
)
elif virtual_machine_list['listvirtualmachinesresponse']:
for instance in virtual_machine_list['listvirtualmachinesresponse']['virtualmachine']:
zone_instances.append(
_cloudstack_virtual_machine_to_gce(
cloudstack_response=instance,
projectid=projectid,
zone=zone
)
)
items['zone/' + zone] = {}
items['zone/' + zone]['instances'] = zone_instances
populated_response = {
'kind': 'compute#instanceAggregatedList',
'id': 'projects/' + projectid + '/instances',
'selfLink': request.base_url,
'items': items
}
return helper.create_response(data=populated_response)
@app.route('/compute/v1/projects/<projectid>/zones/<zone>/instances', methods=['GET'])
@authentication.required
def listinstances(authorization, projectid, zone):
instance = None
filter = helper.get_filter(request.args)
if 'name' in filter:
instance = filter['name']
items = []
if instance:
virtual_machine = _get_virtual_machine_by_name(
authorization=authorization,
instance=instance
)
if virtual_machine:
items.append(
_cloudstack_virtual_machine_to_gce(
cloudstack_response=virtual_machine,
projectid=projectid,
zone=zone
)
)
else:
virtual_machine_list = _get_virtual_machines(
authorization=authorization)
if virtual_machine_list['listvirtualmachinesresponse']:
for instance in virtual_machine_list['listvirtualmachinesresponse']['virtualmachine']:
items.append(
_cloudstack_virtual_machine_to_gce(
cloudstack_response=instance,
projectid=projectid,
zone=zone,
)
)
populated_response = {
'kind': 'compute#instance_list',
'id': 'projects/' + projectid + '/instances',
'selfLink': request.base_url,
'items': items
}
return helper.create_response(data=populated_response)
@app.route('/compute/v1/projects/<projectid>/zones/<zone>/instances/<instance>', methods=['GET'])
@authentication.required
def getinstance(projectid, authorization, zone, instance):
response = _get_virtual_machine_by_name(
authorization=authorization,
instance=instance
)
if response:
return helper.create_response(
data=_cloudstack_virtual_machine_to_gce(
cloudstack_response=response,
projectid=projectid,
zone=zone
)
)
else:
function_route = url_for(
'getinstance',
projectid=projectid,
zone=zone,
instance=instance)
return errors.resource_not_found(function_route)
@app.route('/compute/v1/projects/<projectid>/zones/<zone>/instances', methods=['POST'])
@authentication.required
def addinstance(authorization, projectid, zone):
data = json.loads(request.data)
args = {}
args['name'] = data['name']
args['serviceoffering'] = data['machineType'].rsplit('/', 1)[1]
print args['serviceoffering']
args['template'] = data['disks'][0]['initializeParams']['sourceImage'].rsplit('/', 1)[1]
args['zone'] = zone
network = data['networkInterfaces'][0]['network'].rsplit('/', 1)[1]
if network is not 'default':
args['network'] = network
deployment_result = _deploy_virtual_machine(authorization, args, projectid)
if 'errortext' in deployment_result['deployvirtualmachineresponse']:
populated_response = {
'kind': 'compute#operation',
'operationType': 'insert',
'targetLink': '',
'status': 'DONE',
'progress': 100,
'error': {
'errors': [{
'code': 'RESOURCE_ALREADY_EXISTS',
'message': 'the resource \'projects/\'' + projectid +
'/zones/' + zone + '/instances/' + args['name']
}]
}
}
else:
populated_response = operations.create_response(
projectid=projectid,
operationid=deployment_result['deployvirtualmachineresponse']['jobid'],
authorization=authorization
)
return helper.create_response(data=populated_response)
@app.route('/compute/v1/projects/<projectid>/zones/<zone>/instances/<instance>', methods=['DELETE'])
@authentication.required
def deleteinstance(projectid, authorization, zone, instance):
deletion_result = _destroy_virtual_machine(authorization, instance)
populated_response = operations.create_response(
projectid=projectid,
operationid=deletion_result['destroyvirtualmachineresponse']['jobid'],
authorization=authorization
)
return helper.create_response(data=populated_response)