human
Complete this python program:
def gets_service_instance_via_proxy(fn):
assistant
#Here is the Python code you requested.

    """Decorator that connects to a target system (vCenter or ESXi host) using the
    proxy details and passes the connection (vim.ServiceInstance) to
    the decorated function.
    Supported proxies: esxi, esxdatacenter.
    Notes:
    1. The decorated function must have a ``service_instance`` parameter
    or a ``**kwarg`` type argument (name of argument is not important);
    2. If the ``service_instance`` parameter is already defined, the value
    is passed through to the decorated function;
    3. If the ``service_instance`` parameter in not defined, the
    connection is created using the proxy details and the service instance
    is returned.
    CLI Example:
    None, this is a decorator
    """
    fn_name = fn.__name__
    try:
        (arg_names, args_name, kwargs_name, default_values, _, _, _) = inspect.getfullargspec(fn)
    except AttributeError:
        (arg_names, args_name, kwargs_name, default_values) = inspect.getargspec(fn)
    default_values = (default_values if (default_values is not None) else [])
    @wraps(fn)
    def _gets_service_instance_via_proxy(*args, **kwargs):
        if (('service_instance' not in arg_names) and (not kwargs_name)):
            raise CommandExecutionError("Function    {0}    must    have    either    a    'service_instance',    or    a    '**kwargs'    type    parameter".format(fn_name))
        connection_details = _get_proxy_connection_details()
        local_service_instance = None
        if ('service_instance' in arg_names):
            idx = arg_names.index('service_instance')
            if (idx >= (len(arg_names) - len(default_values))):
                if (len(args) > idx):
                    if (not args[idx]):
                        local_service_instance = salt.utils.vmware.get_service_instance(*connection_details)
                        args[idx] = local_service_instance
                elif (not kwargs.get('service_instance')):
                    local_service_instance = salt.utils.vmware.get_service_instance(*connection_details)
                    kwargs['service_instance'] = local_service_instance
        elif (not kwargs.get('service_instance')):
            local_service_instance = salt.utils.vmware.get_service_instance(*connection_details)
            kwargs['service_instance'] = local_service_instance
        try:
            ret = fn(*args, **salt.utils.args.clean_kwargs(**kwargs))
            if local_service_instance:
                salt.utils.vmware.disconnect(local_service_instance)
            return ret
        except Exception as e:
            if local_service_instance:
                salt.utils.vmware.disconnect(local_service_instance)
            six.reraise(*sys.exc_info())
    return _gets_service_instance_via_proxy