implement servicevm related command

Change-Id: Ib606eb3e4721ec9a255092bf4581f3b576c3714a
This commit is contained in:
Isaku Yamahata 2014-06-27 18:07:43 +09:00
parent ffa7a582e5
commit 87a2257477
12 changed files with 1260 additions and 229 deletions

View File

@ -15,7 +15,7 @@
#
"""
Command-line interface to the Neutron APIs
Command-line interface to the Tacker APIs
"""
from __future__ import print_function
@ -28,46 +28,20 @@ import sys
from cliff import app
from cliff import commandmanager
from neutronclient.common import clientmanager
from neutronclient.common import exceptions as exc
from neutronclient.common import utils
from neutronclient.neutron.v2_0 import agent
from neutronclient.neutron.v2_0 import agentscheduler
from neutronclient.neutron.v2_0 import credential
from neutronclient.neutron.v2_0 import extension
from neutronclient.neutron.v2_0 import floatingip
from neutronclient.neutron.v2_0.fw import firewall
from neutronclient.neutron.v2_0.fw import firewallpolicy
from neutronclient.neutron.v2_0.fw import firewallrule
from neutronclient.neutron.v2_0.lb import healthmonitor as lb_healthmonitor
from neutronclient.neutron.v2_0.lb import member as lb_member
from neutronclient.neutron.v2_0.lb import pool as lb_pool
from neutronclient.neutron.v2_0.lb import vip as lb_vip
from neutronclient.neutron.v2_0 import metering
from neutronclient.neutron.v2_0.nec import packetfilter
from neutronclient.neutron.v2_0 import netpartition
from neutronclient.neutron.v2_0 import network
from neutronclient.neutron.v2_0 import networkprofile
from neutronclient.neutron.v2_0.nsx import networkgateway
from neutronclient.neutron.v2_0.nsx import qos_queue
from neutronclient.neutron.v2_0 import policyprofile
from neutronclient.neutron.v2_0 import port
from neutronclient.neutron.v2_0 import quota
from neutronclient.neutron.v2_0 import router
from neutronclient.neutron.v2_0 import securitygroup
from neutronclient.neutron.v2_0 import servicetype
from neutronclient.neutron.v2_0 import subnet
from neutronclient.neutron.v2_0.vpn import ikepolicy
from neutronclient.neutron.v2_0.vpn import ipsec_site_connection
from neutronclient.neutron.v2_0.vpn import ipsecpolicy
from neutronclient.neutron.v2_0.vpn import vpnservice
from neutronclient.openstack.common.gettextutils import _
from neutronclient.openstack.common import strutils
from neutronclient.version import __version__
from tackerclient.common import clientmanager
from tackerclient.common import exceptions as exc
from tackerclient.common import utils
from tackerclient.openstack.common.gettextutils import _
from tackerclient.openstack.common import strutils
from tackerclient.tacker.v1_0 import extension
from tackerclient.tacker.v1_0.vm import device
from tackerclient.tacker.v1_0.vm import device_template
from tackerclient.tacker.v1_0.vm import service_instance
from tackerclient.version import __version__
VERSION = '2.0'
NEUTRON_API_VERSION = '2.0'
VERSION = '1.0'
TACKER_API_VERSION = '1.0'
def run_command(cmd, cmd_parser, sub_argv):
@ -97,189 +71,27 @@ def env(*_vars, **kwargs):
return kwargs.get('default', '')
COMMAND_V2 = {
'net-list': network.ListNetwork,
'net-external-list': network.ListExternalNetwork,
'net-show': network.ShowNetwork,
'net-create': network.CreateNetwork,
'net-delete': network.DeleteNetwork,
'net-update': network.UpdateNetwork,
'subnet-list': subnet.ListSubnet,
'subnet-show': subnet.ShowSubnet,
'subnet-create': subnet.CreateSubnet,
'subnet-delete': subnet.DeleteSubnet,
'subnet-update': subnet.UpdateSubnet,
'port-list': port.ListPort,
'port-show': port.ShowPort,
'port-create': port.CreatePort,
'port-delete': port.DeletePort,
'port-update': port.UpdatePort,
'quota-list': quota.ListQuota,
'quota-show': quota.ShowQuota,
'quota-delete': quota.DeleteQuota,
'quota-update': quota.UpdateQuota,
COMMAND_V1 = {
'ext-list': extension.ListExt,
'ext-show': extension.ShowExt,
'router-list': router.ListRouter,
'router-port-list': port.ListRouterPort,
'router-show': router.ShowRouter,
'router-create': router.CreateRouter,
'router-delete': router.DeleteRouter,
'router-update': router.UpdateRouter,
'router-interface-add': router.AddInterfaceRouter,
'router-interface-delete': router.RemoveInterfaceRouter,
'router-gateway-set': router.SetGatewayRouter,
'router-gateway-clear': router.RemoveGatewayRouter,
'floatingip-list': floatingip.ListFloatingIP,
'floatingip-show': floatingip.ShowFloatingIP,
'floatingip-create': floatingip.CreateFloatingIP,
'floatingip-delete': floatingip.DeleteFloatingIP,
'floatingip-associate': floatingip.AssociateFloatingIP,
'floatingip-disassociate': floatingip.DisassociateFloatingIP,
'security-group-list': securitygroup.ListSecurityGroup,
'security-group-show': securitygroup.ShowSecurityGroup,
'security-group-create': securitygroup.CreateSecurityGroup,
'security-group-delete': securitygroup.DeleteSecurityGroup,
'security-group-update': securitygroup.UpdateSecurityGroup,
'security-group-rule-list': securitygroup.ListSecurityGroupRule,
'security-group-rule-show': securitygroup.ShowSecurityGroupRule,
'security-group-rule-create': securitygroup.CreateSecurityGroupRule,
'security-group-rule-delete': securitygroup.DeleteSecurityGroupRule,
'lb-vip-list': lb_vip.ListVip,
'lb-vip-show': lb_vip.ShowVip,
'lb-vip-create': lb_vip.CreateVip,
'lb-vip-update': lb_vip.UpdateVip,
'lb-vip-delete': lb_vip.DeleteVip,
'lb-pool-list': lb_pool.ListPool,
'lb-pool-show': lb_pool.ShowPool,
'lb-pool-create': lb_pool.CreatePool,
'lb-pool-update': lb_pool.UpdatePool,
'lb-pool-delete': lb_pool.DeletePool,
'lb-pool-stats': lb_pool.RetrievePoolStats,
'lb-member-list': lb_member.ListMember,
'lb-member-show': lb_member.ShowMember,
'lb-member-create': lb_member.CreateMember,
'lb-member-update': lb_member.UpdateMember,
'lb-member-delete': lb_member.DeleteMember,
'lb-healthmonitor-list': lb_healthmonitor.ListHealthMonitor,
'lb-healthmonitor-show': lb_healthmonitor.ShowHealthMonitor,
'lb-healthmonitor-create': lb_healthmonitor.CreateHealthMonitor,
'lb-healthmonitor-update': lb_healthmonitor.UpdateHealthMonitor,
'lb-healthmonitor-delete': lb_healthmonitor.DeleteHealthMonitor,
'lb-healthmonitor-associate': lb_healthmonitor.AssociateHealthMonitor,
'lb-healthmonitor-disassociate': (
lb_healthmonitor.DisassociateHealthMonitor
),
'queue-create': qos_queue.CreateQoSQueue,
'queue-delete': qos_queue.DeleteQoSQueue,
'queue-show': qos_queue.ShowQoSQueue,
'queue-list': qos_queue.ListQoSQueue,
'agent-list': agent.ListAgent,
'agent-show': agent.ShowAgent,
'agent-delete': agent.DeleteAgent,
'agent-update': agent.UpdateAgent,
'net-gateway-create': networkgateway.CreateNetworkGateway,
'net-gateway-update': networkgateway.UpdateNetworkGateway,
'net-gateway-delete': networkgateway.DeleteNetworkGateway,
'net-gateway-show': networkgateway.ShowNetworkGateway,
'net-gateway-list': networkgateway.ListNetworkGateway,
'net-gateway-connect': networkgateway.ConnectNetworkGateway,
'net-gateway-disconnect': networkgateway.DisconnectNetworkGateway,
'gateway-device-create': networkgateway.CreateGatewayDevice,
'gateway-device-update': networkgateway.UpdateGatewayDevice,
'gateway-device-delete': networkgateway.DeleteGatewayDevice,
'gateway-device-show': networkgateway.ShowGatewayDevice,
'gateway-device-list': networkgateway.ListGatewayDevice,
'dhcp-agent-network-add': agentscheduler.AddNetworkToDhcpAgent,
'dhcp-agent-network-remove': agentscheduler.RemoveNetworkFromDhcpAgent,
'net-list-on-dhcp-agent': agentscheduler.ListNetworksOnDhcpAgent,
'dhcp-agent-list-hosting-net': agentscheduler.ListDhcpAgentsHostingNetwork,
'l3-agent-router-add': agentscheduler.AddRouterToL3Agent,
'l3-agent-router-remove': agentscheduler.RemoveRouterFromL3Agent,
'router-list-on-l3-agent': agentscheduler.ListRoutersOnL3Agent,
'l3-agent-list-hosting-router': agentscheduler.ListL3AgentsHostingRouter,
'lb-pool-list-on-agent': agentscheduler.ListPoolsOnLbaasAgent,
'lb-agent-hosting-pool': agentscheduler.GetLbaasAgentHostingPool,
'service-provider-list': servicetype.ListServiceProvider,
'firewall-rule-list': firewallrule.ListFirewallRule,
'firewall-rule-show': firewallrule.ShowFirewallRule,
'firewall-rule-create': firewallrule.CreateFirewallRule,
'firewall-rule-update': firewallrule.UpdateFirewallRule,
'firewall-rule-delete': firewallrule.DeleteFirewallRule,
'firewall-policy-list': firewallpolicy.ListFirewallPolicy,
'firewall-policy-show': firewallpolicy.ShowFirewallPolicy,
'firewall-policy-create': firewallpolicy.CreateFirewallPolicy,
'firewall-policy-update': firewallpolicy.UpdateFirewallPolicy,
'firewall-policy-delete': firewallpolicy.DeleteFirewallPolicy,
'firewall-policy-insert-rule': firewallpolicy.FirewallPolicyInsertRule,
'firewall-policy-remove-rule': firewallpolicy.FirewallPolicyRemoveRule,
'firewall-list': firewall.ListFirewall,
'firewall-show': firewall.ShowFirewall,
'firewall-create': firewall.CreateFirewall,
'firewall-update': firewall.UpdateFirewall,
'firewall-delete': firewall.DeleteFirewall,
'cisco-credential-list': credential.ListCredential,
'cisco-credential-show': credential.ShowCredential,
'cisco-credential-create': credential.CreateCredential,
'cisco-credential-delete': credential.DeleteCredential,
'cisco-network-profile-list': networkprofile.ListNetworkProfile,
'cisco-network-profile-show': networkprofile.ShowNetworkProfile,
'cisco-network-profile-create': networkprofile.CreateNetworkProfile,
'cisco-network-profile-delete': networkprofile.DeleteNetworkProfile,
'cisco-network-profile-update': networkprofile.UpdateNetworkProfile,
'cisco-policy-profile-list': policyprofile.ListPolicyProfile,
'cisco-policy-profile-show': policyprofile.ShowPolicyProfile,
'cisco-policy-profile-update': policyprofile.UpdatePolicyProfile,
'ipsec-site-connection-list': (
ipsec_site_connection.ListIPsecSiteConnection
),
'ipsec-site-connection-show': (
ipsec_site_connection.ShowIPsecSiteConnection
),
'ipsec-site-connection-create': (
ipsec_site_connection.CreateIPsecSiteConnection
),
'ipsec-site-connection-update': (
ipsec_site_connection.UpdateIPsecSiteConnection
),
'ipsec-site-connection-delete': (
ipsec_site_connection.DeleteIPsecSiteConnection
),
'vpn-service-list': vpnservice.ListVPNService,
'vpn-service-show': vpnservice.ShowVPNService,
'vpn-service-create': vpnservice.CreateVPNService,
'vpn-service-update': vpnservice.UpdateVPNService,
'vpn-service-delete': vpnservice.DeleteVPNService,
'vpn-ipsecpolicy-list': ipsecpolicy.ListIPsecPolicy,
'vpn-ipsecpolicy-show': ipsecpolicy.ShowIPsecPolicy,
'vpn-ipsecpolicy-create': ipsecpolicy.CreateIPsecPolicy,
'vpn-ipsecpolicy-update': ipsecpolicy.UpdateIPsecPolicy,
'vpn-ipsecpolicy-delete': ipsecpolicy.DeleteIPsecPolicy,
'vpn-ikepolicy-list': ikepolicy.ListIKEPolicy,
'vpn-ikepolicy-show': ikepolicy.ShowIKEPolicy,
'vpn-ikepolicy-create': ikepolicy.CreateIKEPolicy,
'vpn-ikepolicy-update': ikepolicy.UpdateIKEPolicy,
'vpn-ikepolicy-delete': ikepolicy.DeleteIKEPolicy,
'meter-label-create': metering.CreateMeteringLabel,
'meter-label-list': metering.ListMeteringLabel,
'meter-label-show': metering.ShowMeteringLabel,
'meter-label-delete': metering.DeleteMeteringLabel,
'meter-label-rule-create': metering.CreateMeteringLabelRule,
'meter-label-rule-list': metering.ListMeteringLabelRule,
'meter-label-rule-show': metering.ShowMeteringLabelRule,
'meter-label-rule-delete': metering.DeleteMeteringLabelRule,
'nuage-netpartition-list': netpartition.ListNetPartition,
'nuage-netpartition-show': netpartition.ShowNetPartition,
'nuage-netpartition-create': netpartition.CreateNetPartition,
'nuage-netpartition-delete': netpartition.DeleteNetPartition,
'nec-packet-filter-list': packetfilter.ListPacketFilter,
'nec-packet-filter-show': packetfilter.ShowPacketFilter,
'nec-packet-filter-create': packetfilter.CreatePacketFilter,
'nec-packet-filter-update': packetfilter.UpdatePacketFilter,
'nec-packet-filter-delete': packetfilter.DeletePacketFilter,
'device-template-create': device_template.CreateDeviceTemplate,
'device-template-list': device_template.ListDeviceTemplate,
'device-template-show': device_template.ShowDeviceTemplate,
'device-template-update': device_template.UpdateDeviceTemplate,
'device-template-delete': device_template.DeleteDeviceTemplate,
'service-instance-create': service_instance.CreateServiceInstance,
'service-instance-list': service_instance.ListServiceInstance,
'service-instance-show': service_instance.ShowServiceInstance,
'service-instance-update': service_instance.UpdateServiceInstance,
'service-instance-delete': service_instance.DeleteServiceInstance,
'device-create': device.CreateDevice,
'device-list': device.ListDevice,
'device-show': device.ShowDevice,
'device-update': device.UpdateDevice,
'device-delete': device.DeleteDevice,
}
COMMANDS = {'2.0': COMMAND_V2}
COMMANDS = {'1.0': COMMAND_V1}
class HelpAction(argparse.Action):
@ -307,7 +119,7 @@ class HelpAction(argparse.Action):
sys.exit(0)
class NeutronShell(app.App):
class TackerShell(app.App):
# verbose logging levels
WARNING_LEVEL = 0
@ -318,10 +130,10 @@ class NeutronShell(app.App):
log = logging.getLogger(__name__)
def __init__(self, apiversion):
super(NeutronShell, self).__init__(
super(TackerShell, self).__init__(
description=__doc__.strip(),
version=VERSION,
command_manager=commandmanager.CommandManager('neutron.cli'), )
command_manager=commandmanager.CommandManager('tacker.cli'), )
self.commands = COMMANDS
for k, v in self.commands[apiversion].items():
self.command_manager.add_command(k, v)
@ -373,8 +185,8 @@ class NeutronShell(app.App):
'--os-auth-strategy', metavar='<auth-strategy>',
default=env('OS_AUTH_STRATEGY', default='keystone'),
help=_('Authentication strategy (Env: OS_AUTH_STRATEGY'
', default keystone). For now, any other value will'
' disable the authentication'))
', default keystone). For now, any other value will'
' disable the authentication'))
parser.add_argument(
'--os_auth_strategy',
help=argparse.SUPPRESS)
@ -466,8 +278,8 @@ class NeutronShell(app.App):
parser.add_argument(
'--insecure',
action='store_true',
default=env('NEUTRONCLIENT_INSECURE', default=False),
help=_("Explicitly allow neutronclient to perform \"insecure\" "
default=env('TACKERCLIENT_INSECURE', default=False),
help=_("Explicitly allow tackerclient to perform \"insecure\" "
"SSL (https) requests. The server's certificate will "
"not be verified against any certificate authorities. "
"This option should be used with caution."))
@ -650,7 +462,7 @@ class NeutronShell(app.App):
* validate authentication info
"""
super(NeutronShell, self).initialize_app(argv)
super(TackerShell, self).initialize_app(argv)
self.api_version = {'network': self.api_version}
@ -693,9 +505,9 @@ class NeutronShell(app.App):
def main(argv=sys.argv[1:]):
try:
return NeutronShell(NEUTRON_API_VERSION).run(map(strutils.safe_decode,
argv))
except exc.NeutronClientException:
return TackerShell(TACKER_API_VERSION).run(map(strutils.safe_decode,
argv))
except exc.TackerClientException:
return 1
except Exception as e:
print(unicode(e))

View File

View File

@ -0,0 +1,137 @@
#
# Copyright 2013 Intel
# Copyright 2013 Isaku Yamahata <isaku.yamahata at intel com>
# <isaku.yamahata at gmail com>
# All Rights Reserved.
#
#
# Licensed 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.
#
# @author: Isaku Yamahata, Intel
from tackerclient.common import exceptions
from tackerclient.openstack.common.gettextutils import _
from tackerclient.tacker import v1_0 as tackerV10
_DEVICE = 'device'
class ListDevice(tackerV10.ListCommand):
"""List device that belong to a given tenant."""
resource = _DEVICE
class ShowDevice(tackerV10.ShowCommand):
"""show information of a given Device."""
resource = _DEVICE
class CreateDevice(tackerV10.CreateCommand):
"""create a Device."""
resource = _DEVICE
def add_known_arguments(self, parser):
parser.add_argument(
'--device-template-id',
required=True,
help='device template id to create device based on')
parser.add_argument(
'--kwargs',
metavar='<key>=<value>',
action='append',
dest='kwargs',
default=[],
help='instance specific argument')
parser.add_argument(
'--service-context',
metavar='<network-id=network-uuid,subnet-id=subnet-uuid,'
'port-id=port-uuid,router-id=router-uuid,'
'role=role-string,index=int>',
action='append',
dest='service_context',
default=[],
help='service context to insert service')
def args2body(self, parsed_args):
body = {
self.resource: {
'template_id': parsed_args.device_template_id,
}
}
if parsed_args.kwargs:
try:
kwargs = dict(key_value.split('=', 1)
for key_value in parsed_args.kwargs)
except ValueError:
msg = (_('invalid argument for --kwargs %s') %
parsed_args.kwargs)
raise exceptions.TackerCLIError(msg)
if kwargs:
body[self.resource]['kwargs'] = kwargs
if parsed_args.service_context:
try:
service_context = [dict(
(k.replace('-', '_'), v)
for k, v in (key_value.split('=', 1)
for key_value in entry_string.split(',')))
for entry_string in parsed_args.service_context]
except ValueError:
msg = (_('invalid argument for --service-context %s') %
parsed_args.service_context)
raise exceptions.TackerCLIError(msg)
if service_context:
body[self.resource]['service_context'] = service_context
tackerV10.update_dict(parsed_args, body[self.resource], ['tenant_id'])
return body
class UpdateDevice(tackerV10.UpdateCommand):
"""Update a given Device."""
resource = _DEVICE
def add_known_arguments(self, parser):
parser.add_argument(
'--kwargs',
metavar='<key>=<value>',
action='append',
dest='kwargs',
default=[],
help='instance specific argument')
def args2body(self, parsed_args):
body = {self.resource: {}}
if parsed_args.kwargs:
try:
kwargs = dict(key_value.split('=', 1)
for key_value in parsed_args.kwargs)
except ValueError:
msg = (_('invalid argument for --kwargs %s') %
parsed_args.kwargs)
raise exceptions.TackerCLIError(msg)
if kwargs:
body[self.resource]['kwargs'] = kwargs
tackerV10.update_dict(parsed_args, body[self.resource], ['tenant_id'])
return body
class DeleteDevice(tackerV10.DeleteCommand):
"""Delete a given Device."""
resource = _DEVICE

View File

@ -0,0 +1,94 @@
#
# Copyright 2013 Intel
# Copyright 2013 Isaku Yamahata <isaku.yamahata at intel com>
# <isaku.yamahata at gmail com>
# All Rights Reserved.
#
#
# Licensed 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.
#
# @author: Isaku Yamahata, Intel
from tackerclient.tacker import v1_0 as tackerV10
_DEVICE_TEMPLATE = "device_template"
class ListDeviceTemplate(tackerV10.ListCommand):
"""List device template that belong to a given tenant."""
resource = _DEVICE_TEMPLATE
class ShowDeviceTemplate(tackerV10.ShowCommand):
"""show information of a given DeviceTemplate."""
resource = _DEVICE_TEMPLATE
class CreateDeviceTemplate(tackerV10.CreateCommand):
"""create a DeviceTemplate."""
resource = _DEVICE_TEMPLATE
def add_known_arguments(self, parser):
parser.add_argument(
'--name',
help='Set a name for the devicetemplate')
parser.add_argument(
'--description',
help='Set a description for the devicetemplate')
parser.add_argument(
'--template-service-type',
action='append',
help='Add a servicetype for the devicetemplate')
parser.add_argument(
'--device-driver',
help='Set a device driver name for the devicetemplate')
parser.add_argument(
'--mgmt-driver',
help='Set a manegement driver name for the devicetemplate')
parser.add_argument(
'--attribute',
nargs=2,
action='append',
help='Set a servicetypes for the devicetemplate')
def args2body(self, parsed_args):
body = {
self.resource: {
'service_types': [
{'service_type': service_type}
for service_type in parsed_args.template_service_type],
'device_driver': parsed_args.device_driver,
'mgmt_driver': parsed_args.mgmt_driver,
}
}
if parsed_args.attribute:
body[self.resource]['attributes'] = dict(parsed_args.attribute)
tackerV10.update_dict(parsed_args, body[self.resource],
['tenant_id', 'name', 'description'])
return body
class UpdateDeviceTemplate(tackerV10.UpdateCommand):
"""Update a given DeviceTemplate."""
resource = _DEVICE_TEMPLATE
allow_names = False
class DeleteDeviceTemplate(tackerV10.DeleteCommand):
"""Delete a given DeviceTemplate."""
resource = _DEVICE_TEMPLATE

View File

@ -0,0 +1,164 @@
#
# Copyright 2013 Intel
# Copyright 2013 Isaku Yamahata <isaku.yamahata at intel com>
# <isaku.yamahata at gmail com>
# All Rights Reserved.
#
#
# Licensed 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.
#
# @author: Isaku Yamahata, Intel
from tackerclient.common import exceptions
from tackerclient.openstack.common.gettextutils import _
from tackerclient.tacker import v1_0 as tackerV10
_SERVICE_INSTANCE = 'service_instance'
class ListServiceInstance(tackerV10.ListCommand):
"""List service instance that belong to a given tenant."""
resource = _SERVICE_INSTANCE
class ShowServiceInstance(tackerV10.ShowCommand):
"""show information of a given ServiceInstance."""
resource = _SERVICE_INSTANCE
class CreateServiceInstance(tackerV10.CreateCommand):
"""create a ServiceInstance."""
resource = _SERVICE_INSTANCE
def add_known_arguments(self, parser):
parser.add_argument(
'--name',
default=None,
help='Set a name for the devicetemplate')
parser.add_argument(
'--service-type-id',
required=True,
help='service type id to create service instance based on')
parser.add_argument(
'--service-table-id',
required=True,
help='service type id to create service instance based on')
parser.add_argument(
'--mgmt-driver',
default=None,
help='Set a manegement driver name for the service instance')
parser.add_argument(
'--service-context',
metavar='<network-id=network-uuid,subnet-id=subnet-uuid,'
'port-id=port-uuid,router-id=router-uuid,'
'role=role-string,index=int>',
action='append',
dest='service_context',
default=[],
help='service context to insert service')
parser.add_argument(
'--device',
required=True,
help='Set a device for the service instance to create on')
parser.add_argument(
'--kwargs',
metavar='<key>=<value>',
action='append',
dest='kwargs',
default=[],
help='instance specific argument')
def args2body(self, parsed_args):
body = {
self.resource: {
'service_type_id': parsed_args.service_type_id,
'service_table_id': parsed_args.service_table_id,
'devices': [parsed_args.device],
}
}
if parsed_args.name is not None:
body[self.resource]['name'] = parsed_args.name
if parsed_args.mgmt_driver is not None:
body[self.resource]['mgmt_driver'] = parsed_args.mgmt_driver
if parsed_args.kwargs:
try:
kwargs = dict(key_value.split('=', 1)
for key_value in parsed_args.kwargs)
except ValueError:
msg = (_('invalid argument for --kwargs %s') %
parsed_args.kwargs)
raise exceptions.TackerCLIError(msg)
if kwargs:
body[self.resource]['kwargs'] = kwargs
if parsed_args.service_context:
try:
service_context = [dict(
(k.replace('-', '_'), v)
for k, v in (key_value.split('=', 1)
for key_value in entry_string.split(',')))
for entry_string in parsed_args.service_context]
except ValueError:
msg = (_('invalid argument for --service-context %s') %
parsed_args.service_context)
raise exceptions.TackerCLIError(msg)
if service_context:
body[self.resource]['service_context'] = service_context
tackerV10.update_dict(parsed_args, body[self.resource], ['tenant_id'])
return body
class UpdateServiceInstance(tackerV10.UpdateCommand):
"""Update a given ServiceInstance."""
resource = _SERVICE_INSTANCE
def add_known_arguments(self, parser):
parser.add_argument(
'--name',
help='Set a name for the devicetemplate')
parser.add_argument(
'--kwargs',
metavar='<key>=<value>',
action='append',
dest='kwargs',
default=[],
help='instance specific argument')
def args2body(self, parsed_args):
body = {self.resource: {}}
if parsed_args.name:
body[self.resource]['name'] = parsed_args.name
if parsed_args.kwargs:
try:
kwargs = dict(key_value.split('=', 1)
for key_value in parsed_args.kwargs)
except ValueError:
msg = (_('invalid argument for --kwargs %s') %
parsed_args.kwargs)
raise exceptions.TackerCLIError(msg)
if kwargs:
body[self.resource]['kwargs'] = kwargs
tackerV10.update_dict(parsed_args, body[self.resource], ['tenant_id'])
return body
class DeleteServiceInstance(tackerV10.DeleteCommand):
"""Delete a given ServiceInstance."""
resource = _SERVICE_INSTANCE

View File

View File

@ -0,0 +1,126 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2014 Intel
# Copyright 2014 Isaku Yamahata <isaku.yamahata at intel com>
# <isaku.yamahata at gmail com>
# All Rights Reserved.
#
#
# Licensed 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.
#
# @author: Isaku Yamahata, Intel
import sys
from tackerclient.tacker.v1_0.vm import device
from tackerclient.tests.unit import test_cli10
class CLITestV10VmDeviceJSON(test_cli10.CLITestV10Base):
_RESOURCE = 'device'
_RESOURCES = 'devices'
def setUp(self):
plurals = {'devices': 'device'}
super(CLITestV10VmDeviceJSON, self).setUp(plurals=plurals)
def test_create_device_all_params(self):
cmd = device.CreateDevice(test_cli10.MyApp(sys.stdout), None)
my_id = 'my-id'
template_id = 'template_id'
key = 'key'
value = 'value'
network_id = 'network_id'
subnet_id = 'subnet_id'
port_id = 'port_id'
router_id = 'router_id'
role = 'role'
index = 1
args = [
'--device-template-id', template_id,
'--kwargs', '%s=%s' % (key, value),
'--service-context',
('network-id=%s,subnet-id=%s,port-id=%s,router-id=%s,'
'role=%s,index=%s' % (network_id, subnet_id, port_id, router_id,
role, index))
]
position_names = ['template_id']
position_values = [template_id]
extra_body = {
'kwargs': {
key: value
},
'service_context': [{
'network_id': network_id,
'subnet_id': subnet_id,
'port_id': port_id,
'router_id': router_id,
'role': role,
'index': str(index),
}],
}
self._test_create_resource(self._RESOURCE, cmd, None, my_id,
args, position_names, position_values,
extra_body=extra_body)
def test_create_device_with_mandatory_params(self):
cmd = device.CreateDevice(test_cli10.MyApp(sys.stdout), None)
my_id = 'my-id'
template_id = 'template_id'
args = [
'--device-template-id', template_id,
]
position_names = ['template_id']
position_values = [template_id]
self._test_create_resource(self._RESOURCE, cmd, None, my_id,
args, position_names, position_values)
def test_list_devices(self):
cmd = device.ListDevice(test_cli10.MyApp(sys.stdout), None)
self._test_list_resources(self._RESOURCES, cmd, True)
def test_list_devices_pagenation(self):
cmd = device.ListDevice(test_cli10.MyApp(sys.stdout), None)
self._test_list_resources(self._RESOURCES, cmd, True)
def test_show_device_id(self):
cmd = device.ShowDevice(test_cli10.MyApp(sys.stdout), None)
args = ['--fields', 'id', self.test_id]
self._test_show_resource(self._RESOURCE, cmd, self.test_id, args,
['id'])
def test_show_device_id_name(self):
cmd = device.ShowDevice(test_cli10.MyApp(sys.stdout), None)
args = ['--fields', 'id', '--fields', 'name', self.test_id]
self._test_show_resource(self._RESOURCE, cmd, self.test_id,
args, ['id', 'name'])
def test_update_device(self):
cmd = device.UpdateDevice(test_cli10.MyApp(sys.stdout), None)
my_id = 'my-id'
key = 'new-key'
value = 'new-value'
self._test_update_resource(self._RESOURCE, cmd, my_id,
[my_id, '--kwargs', '%s=%s' % (key, value)],
{'kwargs': {key: value}})
def test_delete_device(self):
cmd = device.DeleteDevice(test_cli10.MyApp(sys.stdout), None)
my_id = 'my-id'
args = [my_id]
self._test_delete_resource(self._RESOURCE, cmd, my_id, args)
class CLITestV10VmDeviceXML(CLITestV10VmDeviceJSON):
format = 'xml'

View File

@ -0,0 +1,132 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2014 Intel
# Copyright 2014 Isaku Yamahata <isaku.yamahata at intel com>
# <isaku.yamahata at gmail com>
# All Rights Reserved.
#
#
# Licensed 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.
#
# @author: Isaku Yamahata, Intel
import sys
from tackerclient.tacker.v1_0.vm import device_template
from tackerclient.tests.unit import test_cli10
class CLITestV10VmDeviceTemplateJSON(test_cli10.CLITestV10Base):
_RESOURCE = 'device_template'
_RESOURCES = 'device_templates'
def setUp(self):
plurals = {'device_templates': 'device_template'}
super(CLITestV10VmDeviceTemplateJSON, self).setUp(plurals=plurals)
def test_create_device_template_all_params(self):
cmd = device_template.CreateDeviceTemplate(
test_cli10.MyApp(sys.stdout), None)
my_id = 'my-id'
name = 'my-name'
description = 'my-description'
service_type = 'MY-SERVICE'
device_driver = 'device-driver'
mgmt_driver = 'mgmt-driver'
attr_key = 'attr-key'
attr_val = 'attr-val'
args = [
'--name', name,
'--description', description,
'--template-service-type', service_type,
'--device-driver', device_driver,
'--mgmt-driver', mgmt_driver,
'--attribute', attr_key, attr_val,
]
position_names = ['name', 'description',
'device_driver', 'mgmt_driver']
position_values = [name, description, device_driver, mgmt_driver]
extra_body = {
'service_types': [{'service_type': service_type}],
'attributes': {attr_key: attr_val},
}
self._test_create_resource(self._RESOURCE, cmd, None, my_id,
args, position_names, position_values,
extra_body=extra_body)
def test_create_device_template_with_mandatory_params(self):
cmd = device_template.CreateDeviceTemplate(
test_cli10.MyApp(sys.stdout), None)
my_id = 'my-id'
service_type = 'MY-SERVICE'
device_driver = 'device-driver'
mgmt_driver = 'mgmt-driver'
args = [
'--template-service-type', service_type,
'--device-driver', device_driver,
'--mgmt-driver', mgmt_driver,
]
position_names = ['device_driver', 'mgmt_driver']
position_values = [device_driver, mgmt_driver]
extra_body = {
'service_types': [{'service_type': service_type}],
}
self._test_create_resource(self._RESOURCE, cmd, None, my_id,
args, position_names, position_values,
extra_body=extra_body)
def test_list_device_templates(self):
cmd = device_template.ListDeviceTemplate(test_cli10.MyApp(sys.stdout),
None)
self._test_list_resources(self._RESOURCES, cmd, True)
def test_list_device_templates_pagenation(self):
cmd = device_template.ListDeviceTemplate(test_cli10.MyApp(sys.stdout),
None)
self._test_list_resources(self._RESOURCES, cmd, True)
def test_show_device_template_id(self):
cmd = device_template.ShowDeviceTemplate(test_cli10.MyApp(sys.stdout),
None)
args = ['--fields', 'id', self.test_id]
self._test_show_resource(self._RESOURCE, cmd, self.test_id, args,
['id'])
def test_show_device_template_id_name(self):
cmd = device_template.ShowDeviceTemplate(test_cli10.MyApp(sys.stdout),
None)
args = ['--fields', 'id', '--fields', 'name', self.test_id]
self._test_show_resource(self._RESOURCE, cmd, self.test_id,
args, ['id', 'name'])
def test_update_device_template(self):
cmd = device_template.UpdateDeviceTemplate(
test_cli10.MyApp(sys.stdout), None)
my_id = 'my-id'
name = 'new-name'
description = 'new-description'
self._test_update_resource(self._RESOURCE, cmd, my_id,
[my_id, '--name', name,
'--description', description],
{'name': name, 'description': description})
def test_delete_device_tempalte(self):
cmd = device_template.DeleteDeviceTemplate(
test_cli10.MyApp(sys.stdout), None)
my_id = 'my-id'
args = [my_id]
self._test_delete_resource(self._RESOURCE, cmd, my_id, args)
class CLITestV10VmDeviceTemplateXML(CLITestV10VmDeviceTemplateJSON):
format = 'xml'

View File

@ -0,0 +1,155 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright 2014 Intel
# Copyright 2014 Isaku Yamahata <isaku.yamahata at intel com>
# <isaku.yamahata at gmail com>
# All Rights Reserved.
#
#
# Licensed 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.
#
# @author: Isaku Yamahata, Intel
import sys
from tackerclient.tacker.v1_0.vm import service_instance
from tackerclient.tests.unit import test_cli10
class CLITestV10VmServiceInstanceJSON(test_cli10.CLITestV10Base):
_RESOURCE = 'service_instance'
_RESOURCES = 'service_instances'
def setUp(self):
plurals = {'service_instances': 'service_instance'}
super(CLITestV10VmServiceInstanceJSON, self).setUp(plurals=plurals)
def test_create_service_instance_all_params(self):
cmd = service_instance.CreateServiceInstance(
test_cli10.MyApp(sys.stdout), None)
my_id = 'my-id'
name = 'my-name'
service_type_id = 'service-type-id'
service_table_id = 'service-table-id'
mgmt_driver = 'mgmt-driver'
network_id = 'network_id'
subnet_id = 'subnet_id'
port_id = 'port_id'
router_id = 'router_id'
role = 'role'
index = 1
device = 'my-device'
key = 'key'
value = 'value'
args = [
'--name', name,
'--service-type-id', service_type_id,
'--service-table-id', service_table_id,
'--mgmt-driver', mgmt_driver,
'--service-context',
('network-id=%s,subnet-id=%s,port-id=%s,router-id=%s,'
'role=%s,index=%s' % (network_id, subnet_id, port_id, router_id,
role, index)),
'--device', device,
'--kwargs', '%s=%s' % (key, value),
]
position_names = ['name', 'service_type_id', 'service_table_id',
'mgmt_driver']
position_values = [name, service_type_id, service_table_id,
mgmt_driver]
extra_body = {
'devices': [device],
'service_context': [{
'network_id': network_id,
'subnet_id': subnet_id,
'port_id': port_id,
'router_id': router_id,
'role': role,
'index': str(index),
}],
'kwargs': {
key: value
},
}
self._test_create_resource(self._RESOURCE, cmd, None, my_id,
args, position_names, position_values,
extra_body=extra_body)
def test_create_service_instance_with_mandatory_params(self):
cmd = service_instance.CreateServiceInstance(
test_cli10.MyApp(sys.stdout), None)
my_id = 'my-id'
service_type_id = 'service-type-id'
service_table_id = 'service-table-id'
device = 'my-device'
args = [
'--service-type-id', service_type_id,
'--service-table-id', service_table_id,
'--device', device,
]
position_names = ['service_type_id', 'service_table_id']
position_values = [service_type_id, service_table_id]
extra_body = {
'devices': [device],
}
self._test_create_resource(self._RESOURCE, cmd, None, my_id,
args, position_names, position_values,
extra_body=extra_body)
def test_list_service_instances(self):
cmd = service_instance.ListServiceInstance(
test_cli10.MyApp(sys.stdout), None)
self._test_list_resources(self._RESOURCES, cmd, True)
def test_list_service_instances_pagenation(self):
cmd = service_instance.ListServiceInstance(
test_cli10.MyApp(sys.stdout), None)
self._test_list_resources(self._RESOURCES, cmd, True)
def test_show_service_instance_id(self):
cmd = service_instance.ShowServiceInstance(
test_cli10.MyApp(sys.stdout), None)
args = ['--fields', 'id', self.test_id]
self._test_show_resource(self._RESOURCE, cmd, self.test_id, args,
['id'])
def test_show_service_instance_id_name(self):
cmd = service_instance.ShowServiceInstance(
test_cli10.MyApp(sys.stdout), None)
args = ['--fields', 'id', '--fields', 'name', self.test_id]
self._test_show_resource(self._RESOURCE, cmd, self.test_id,
args, ['id', 'name'])
def test_update_service_instance(self):
cmd = service_instance.UpdateServiceInstance(
test_cli10.MyApp(sys.stdout), None)
my_id = 'my-id'
key = 'new-key'
value = 'new-value'
self._test_update_resource(self._RESOURCE, cmd, my_id,
[my_id, '--kwargs', '%s=%s' % (key, value)],
{'kwargs': {key: value}})
def test_delete_service_instance(self):
cmd = service_instance.DeleteServiceInstance(
test_cli10.MyApp(sys.stdout), None)
my_id = 'my-id'
args = [my_id]
self._test_delete_resource(self._RESOURCE, cmd, my_id, args)
class CLITestV10VmServiceInstanceXML(CLITestV10VmServiceInstanceJSON):
format = 'xml'

411
tackerclient/v1_0/client.py Normal file
View File

@ -0,0 +1,411 @@
# Copyright 2012 OpenStack Foundation.
# All Rights Reserved
#
# Licensed 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 logging
import time
import urllib
import requests
import six.moves.urllib.parse as urlparse
from tackerclient import client
from tackerclient.common import _
from tackerclient.common import constants
from tackerclient.common import exceptions
from tackerclient.common import serializer
from tackerclient.common import utils
_logger = logging.getLogger(__name__)
def exception_handler_v10(status_code, error_content):
"""Exception handler for API v1.0 client
This routine generates the appropriate
Tacker exception according to the contents of the
response body
:param status_code: HTTP error status code
:param error_content: deserialized body of error response
"""
error_dict = None
if isinstance(error_content, dict):
error_dict = error_content.get('TackerError')
# Find real error type
bad_tacker_error_flag = False
if error_dict:
# If Tacker key is found, it will definitely contain
# a 'message' and 'type' keys?
try:
error_type = error_dict['type']
error_message = error_dict['message']
if error_dict['detail']:
error_message += "\n" + error_dict['detail']
except Exception:
bad_tacker_error_flag = True
if not bad_tacker_error_flag:
# If corresponding exception is defined, use it.
client_exc = getattr(exceptions, '%sClient' % error_type, None)
# Otherwise look up per status-code client exception
if not client_exc:
client_exc = exceptions.HTTP_EXCEPTION_MAP.get(status_code)
if client_exc:
raise client_exc(message=error_message,
status_code=status_code)
else:
raise exceptions.TackerClientException(
status_code=status_code, message=error_message)
else:
raise exceptions.TackerClientException(status_code=status_code,
message=error_dict)
else:
message = None
if isinstance(error_content, dict):
message = error_content.get('message')
if message:
raise exceptions.TackerClientException(status_code=status_code,
message=message)
# If we end up here the exception was not a tacker error
msg = "%s-%s" % (status_code, error_content)
raise exceptions.TackerClientException(status_code=status_code,
message=msg)
class APIParamsCall(object):
"""A Decorator to add support for format and tenant overriding
and filters
"""
def __init__(self, function):
self.function = function
def __get__(self, instance, owner):
def with_params(*args, **kwargs):
_format = instance.format
if 'format' in kwargs:
instance.format = kwargs['format']
ret = self.function(instance, *args, **kwargs)
instance.format = _format
return ret
return with_params
class Client(object):
"""Client for the OpenStack Tacker v1.0 API.
:param string username: Username for authentication. (optional)
:param string user_id: User ID for authentication. (optional)
:param string password: Password for authentication. (optional)
:param string token: Token for authentication. (optional)
:param string tenant_name: Tenant name. (optional)
:param string tenant_id: Tenant id. (optional)
:param string auth_url: Keystone service endpoint for authorization.
:param string service_type: Network service type to pull from the
keystone catalog (e.g. 'network') (optional)
:param string endpoint_type: Network service endpoint type to pull from the
keystone catalog (e.g. 'publicURL',
'internalURL', or 'adminURL') (optional)
:param string region_name: Name of a region to select when choosing an
endpoint from the service catalog.
:param string endpoint_url: A user-supplied endpoint URL for the tacker
service. Lazy-authentication is possible for API
service calls if endpoint is set at
instantiation.(optional)
:param integer timeout: Allows customization of the timeout for client
http requests. (optional)
:param bool insecure: SSL certificate validation. (optional)
:param string ca_cert: SSL CA bundle file to use. (optional)
Example::
from tackerclient.v1_0 import client
tacker = client.Client(username=USER,
password=PASS,
tenant_name=TENANT_NAME,
auth_url=KEYSTONE_URL)
nets = tacker.list_networks()
...
"""
extensions_path = "/extensions"
extension_path = "/extensions/%s"
device_templates_path = '/device-templates'
device_template_path = '/device-templates/%s'
service_instances_path = '/service-instances'
service_instance_path = '/service-instances/%s'
devices_path = '/devices'
device_path = '/devices/%s'
# API has no way to report plurals, so we have to hard code them
EXTED_PLURALS = {}
# 8192 Is the default max URI len for eventlet.wsgi.server
MAX_URI_LEN = 8192
def get_attr_metadata(self):
if self.format == 'json':
return {}
old_request_format = self.format
self.format = 'json'
exts = self.list_extensions()['extensions']
self.format = old_request_format
ns = dict([(ext['alias'], ext['namespace']) for ext in exts])
self.EXTED_PLURALS.update(constants.PLURALS)
return {'plurals': self.EXTED_PLURALS,
'xmlns': constants.XML_NS_V10,
constants.EXT_NS: ns}
@APIParamsCall
def list_extensions(self, **_params):
"""Fetch a list of all exts on server side."""
return self.get(self.extensions_path, params=_params)
@APIParamsCall
def show_extension(self, ext_alias, **_params):
"""Fetch a list of all exts on server side."""
return self.get(self.extension_path % ext_alias, params=_params)
def list_device_templates(self, retrieve_all=True, **_params):
return self.list('device_templates', self.device_templates_path,
retrieve_all, **_params)
@APIParamsCall
def show_device_template(self, device_template, **_params):
return self.get(self.device_template_path % device_template,
params=_params)
@APIParamsCall
def update_device_template(self, device_template, body=None):
return self.put(self.device_template_path % device_template, body=body)
@APIParamsCall
def create_device_template(self, body=None):
return self.post(self.device_templates_path, body=body)
@APIParamsCall
def delete_device_template(self, device_template):
return self.delete(self.device_template_path % device_template)
@APIParamsCall
def list_service_instances(self, retrieve_all=True, **_params):
return self.list('service_instances', self.service_instances_path,
retrieve_all, **_params)
@APIParamsCall
def show_service_instance(self, service_instance, **_params):
return self.get(self.service_instance_path % service_instance,
params=_params)
@APIParamsCall
def update_service_instance(self, service_instance, body=None):
return self.put(self.service_instance_path % service_instance,
body=body)
@APIParamsCall
def create_service_instance(self, body=None):
return self.post(self.service_instances_path, body=body)
@APIParamsCall
def delete_service_instance(self, service_instance):
return self.delete(self.service_instance_path % service_instance)
@APIParamsCall
def list_devices(self, retrieve_all=True, **_params):
return self.list('devices', self.devices_path, retrieve_all, **_params)
@APIParamsCall
def show_device(self, device, **_params):
return self.get(self.device_path % device, params=_params)
@APIParamsCall
def update_device(self, device, body=None):
return self.put(self.device_path % device, body=body)
@APIParamsCall
def create_device(self, body=None):
return self.post(self.devices_path, body=body)
@APIParamsCall
def delete_device(self, device):
return self.delete(self.device_path % device)
def __init__(self, **kwargs):
"""Initialize a new client for the Tacker v1.0 API."""
super(Client, self).__init__()
self.httpclient = client.HTTPClient(**kwargs)
self.version = '1.0'
self.format = 'json'
self.action_prefix = "/v%s" % (self.version)
self.retries = 0
self.retry_interval = 1
def _handle_fault_response(self, status_code, response_body):
# Create exception with HTTP status code and message
_logger.debug(_("Error message: %s"), response_body)
# Add deserialized error message to exception arguments
try:
des_error_body = self.deserialize(response_body, status_code)
except Exception:
# If unable to deserialized body it is probably not a
# Tacker error
des_error_body = {'message': response_body}
# Raise the appropriate exception
exception_handler_v10(status_code, des_error_body)
def _check_uri_length(self, action):
uri_len = len(self.httpclient.endpoint_url) + len(action)
if uri_len > self.MAX_URI_LEN:
raise exceptions.RequestURITooLong(
excess=uri_len - self.MAX_URI_LEN)
def do_request(self, method, action, body=None, headers=None, params=None):
# Add format and tenant_id
action += ".%s" % self.format
action = self.action_prefix + action
if type(params) is dict and params:
params = utils.safe_encode_dict(params)
action += '?' + urllib.urlencode(params, doseq=1)
# Ensure client always has correct uri - do not guesstimate anything
self.httpclient.authenticate_and_fetch_endpoint_url()
self._check_uri_length(action)
if body:
body = self.serialize(body)
self.httpclient.content_type = self.content_type()
resp, replybody = self.httpclient.do_request(action, method, body=body)
status_code = self.get_status_code(resp)
if status_code in (requests.codes.ok,
requests.codes.created,
requests.codes.accepted,
requests.codes.no_content):
return self.deserialize(replybody, status_code)
else:
if not replybody:
replybody = resp.reason
self._handle_fault_response(status_code, replybody)
def get_auth_info(self):
return self.httpclient.get_auth_info()
def get_status_code(self, response):
"""Returns the integer status code from the response.
Either a Webob.Response (used in testing) or requests.Response
is returned.
"""
if hasattr(response, 'status_int'):
return response.status_int
else:
return response.status_code
def serialize(self, data):
"""Serializes a dictionary into either xml or json.
A dictionary with a single key can be passed and
it can contain any structure.
"""
if data is None:
return None
elif type(data) is dict:
return serializer.Serializer(
self.get_attr_metadata()).serialize(data, self.content_type())
else:
raise Exception(_("Unable to serialize object of type = '%s'") %
type(data))
def deserialize(self, data, status_code):
"""Deserializes an xml or json string into a dictionary."""
if status_code == 204:
return data
return serializer.Serializer(self.get_attr_metadata()).deserialize(
data, self.content_type())['body']
def content_type(self, _format=None):
"""Returns the mime-type for either 'xml' or 'json'.
Defaults to the currently set format.
"""
_format = _format or self.format
return "application/%s" % (_format)
def retry_request(self, method, action, body=None,
headers=None, params=None):
"""Call do_request with the default retry configuration.
Only idempotent requests should retry failed connection attempts.
:raises: ConnectionFailed if the maximum # of retries is exceeded
"""
max_attempts = self.retries + 1
for i in range(max_attempts):
try:
return self.do_request(method, action, body=body,
headers=headers, params=params)
except exceptions.ConnectionFailed:
# Exception has already been logged by do_request()
if i < self.retries:
_logger.debug(_('Retrying connection to Tacker service'))
time.sleep(self.retry_interval)
raise exceptions.ConnectionFailed(reason=_("Maximum attempts reached"))
def delete(self, action, body=None, headers=None, params=None):
return self.retry_request("DELETE", action, body=body,
headers=headers, params=params)
def get(self, action, body=None, headers=None, params=None):
return self.retry_request("GET", action, body=body,
headers=headers, params=params)
def post(self, action, body=None, headers=None, params=None):
# Do not retry POST requests to avoid the orphan objects problem.
return self.do_request("POST", action, body=body,
headers=headers, params=params)
def put(self, action, body=None, headers=None, params=None):
return self.retry_request("PUT", action, body=body,
headers=headers, params=params)
def list(self, collection, path, retrieve_all=True, **params):
if retrieve_all:
res = []
for r in self._pagination(collection, path, **params):
res.extend(r[collection])
return {collection: res}
else:
return self._pagination(collection, path, **params)
def _pagination(self, collection, path, **params):
if params.get('page_reverse', False):
linkrel = 'previous'
else:
linkrel = 'next'
next = True
while next:
res = self.get(path, params=params)
yield res
next = False
try:
for link in res['%s_links' % collection]:
if link['rel'] == linkrel:
query_str = urlparse.urlparse(link['href']).query
params = urlparse.parse_qs(query_str)
next = True
break
except KeyError:
break