Removing old provider code to make room for new provider code
This patch clears out all of the old provider code from this directory to make room for the new, maintained tree that will be imported into this project. Depends-On: I38e2168e311536cc63932d906a46e1b1cf3ac4bf Change-Id: I0d3b2c3805cc47edbb2aac14f757d5bdc114899a
This commit is contained in:
parent
965e34806d
commit
f7756c89de
5
.gitreview
Normal file
5
.gitreview
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[gerrit]
|
||||||
|
host=review.openstack.org
|
||||||
|
port=29418
|
||||||
|
project=openstack/k8s-cloud-provider
|
||||||
|
|
191
LICENSE
191
LICENSE
@ -1,191 +0,0 @@
|
|||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
Copyright 2014 Docker, Inc.
|
|
||||||
|
|
||||||
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.
|
|
107
Makefile
107
Makefile
@ -1,107 +0,0 @@
|
|||||||
# golang-client Makefile
|
|
||||||
# Follows the interface defined in the Golang CTI proposed
|
|
||||||
# in https://review.openstack.org/410355
|
|
||||||
|
|
||||||
#REPO_VERSION?=$(shell git describe --tags)
|
|
||||||
|
|
||||||
GIT_HOST = git.openstack.org
|
|
||||||
|
|
||||||
PWD := $(shell pwd)
|
|
||||||
BASE_DIR := $(shell basename $(PWD))
|
|
||||||
# Keep an existing GOPATH, make a private one if it is undefined
|
|
||||||
GOPATH_DEFAULT := $(PWD)/.go
|
|
||||||
export GOPATH ?= $(GOPATH_DEFAULT)
|
|
||||||
PKG := $(shell awk '/^package: / { print $$2 }' glide.yaml)
|
|
||||||
DEST := $(GOPATH)/src/$(GIT_HOST)/openstack/$(BASE_DIR)
|
|
||||||
DEST := $(GOPATH)/src/$(PKG)
|
|
||||||
|
|
||||||
# CTI targets
|
|
||||||
|
|
||||||
depend: work
|
|
||||||
cd $(DEST) && glide install --strip-vendor
|
|
||||||
|
|
||||||
depend-update: work
|
|
||||||
cd $(DEST) && glide update
|
|
||||||
|
|
||||||
build: work
|
|
||||||
cd $(DEST) && go build -o openstack-controller-manager main.go
|
|
||||||
|
|
||||||
test: unit functional
|
|
||||||
|
|
||||||
unit: depend
|
|
||||||
cd $(DEST) && go test -tags=unit $(shell glide novendor)
|
|
||||||
|
|
||||||
functional:
|
|
||||||
@echo "$@ not yet implemented"
|
|
||||||
|
|
||||||
fmt: work
|
|
||||||
cd $(DEST) && CGO_ENABLED=0 go fmt ./...
|
|
||||||
|
|
||||||
lint:
|
|
||||||
@echo "$@ not yet implemented"
|
|
||||||
|
|
||||||
cover:
|
|
||||||
@echo "$@ not yet implemented"
|
|
||||||
|
|
||||||
docs:
|
|
||||||
@echo "$@ not yet implemented"
|
|
||||||
|
|
||||||
godoc:
|
|
||||||
@echo "$@ not yet implemented"
|
|
||||||
|
|
||||||
releasenotes:
|
|
||||||
@echo "Reno not yet implemented for this repo"
|
|
||||||
|
|
||||||
translation:
|
|
||||||
@echo "$@ not yet implemented"
|
|
||||||
|
|
||||||
# Do the work here
|
|
||||||
|
|
||||||
# Set up the development environment
|
|
||||||
env:
|
|
||||||
@echo "PWD: $(PWD)"
|
|
||||||
@echo "BASE_DIR: $(BASE_DIR)"
|
|
||||||
@echo "GOPATH: $(GOPATH)"
|
|
||||||
@echo "GOROOT: $(GOROOT)"
|
|
||||||
@echo "DEST: $(DEST)"
|
|
||||||
@echo "PKG: $(PKG)"
|
|
||||||
go version
|
|
||||||
go env
|
|
||||||
|
|
||||||
# Get our dev/test dependencies in place
|
|
||||||
bootstrap:
|
|
||||||
tools/test-setup.sh
|
|
||||||
|
|
||||||
work: $(GOPATH) $(DEST)
|
|
||||||
|
|
||||||
$(GOPATH):
|
|
||||||
mkdir -p $(GOPATH)
|
|
||||||
|
|
||||||
$(DEST): $(GOPATH)
|
|
||||||
mkdir -p $(shell dirname $(DEST))
|
|
||||||
ln -s $(PWD) $(DEST)
|
|
||||||
|
|
||||||
.bindep:
|
|
||||||
virtualenv .bindep
|
|
||||||
.bindep/bin/pip install -i https://pypi.python.org/simple bindep
|
|
||||||
|
|
||||||
bindep: .bindep
|
|
||||||
@.bindep/bin/bindep -b -f bindep.txt || true
|
|
||||||
|
|
||||||
install-distro-packages:
|
|
||||||
tools/install-distro-packages.sh
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf .bindep openstack-controller-manager
|
|
||||||
|
|
||||||
realclean: clean
|
|
||||||
rm -rf vendor
|
|
||||||
if [ "$(GOPATH)" = "$(GOPATH_DEFAULT)" ]; then \
|
|
||||||
rm -rf $(GOPATH); \
|
|
||||||
fi
|
|
||||||
|
|
||||||
shell: work
|
|
||||||
cd $(DEST) && $(SHELL) -i
|
|
||||||
|
|
||||||
.PHONY: bindep build clean cover depend docs fmt functional lint realclean \
|
|
||||||
relnotes test translation
|
|
@ -1,6 +0,0 @@
|
|||||||
pkg-config
|
|
||||||
build-essential
|
|
||||||
mercurial
|
|
||||||
golang-go
|
|
||||||
golint
|
|
||||||
make
|
|
@ -1,18 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
echo "In gate_test_hook"
|
|
||||||
$BASE/new/devstack-gate/devstack-vm-gate.sh
|
|
@ -1,176 +0,0 @@
|
|||||||
#!/bin/bash -xe
|
|
||||||
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
# This script is executed inside post_test_hook function in devstack gate.
|
|
||||||
|
|
||||||
BASE_DIR=$(cd $(dirname $BASH_SOURCE)/.. && pwd)
|
|
||||||
|
|
||||||
|
|
||||||
TESTS_LIST_REGEX=(
|
|
||||||
'\[Slow\]'
|
|
||||||
'\[Serial\]'
|
|
||||||
'\[Disruptive\]'
|
|
||||||
'\[Flaky\]'
|
|
||||||
'\[Feature:.+\]'
|
|
||||||
'\[HPA\]'
|
|
||||||
)
|
|
||||||
|
|
||||||
FLAKY_TESTS_LIST=(
|
|
||||||
# https://github.com/kubernetes/kubernetes/issues/44226
|
|
||||||
'Downward API volume [It] should update labels on modification [Conformance] [Volume]'
|
|
||||||
'Downward API volume [It] should update annotations on modification [Conformance] [Volume]'
|
|
||||||
'Projected [It] should update labels on modification [Conformance] [Volume]'
|
|
||||||
'Secrets [It] should be consumable from pods in volume with mappings [Conformance] [Volume]'
|
|
||||||
)
|
|
||||||
|
|
||||||
FAILING_TESTS_LIST=(
|
|
||||||
'Services [It] should be able to create a functioning NodePort service'
|
|
||||||
'Services [It] should serve multiport endpoints from pods [Conformance]'
|
|
||||||
)
|
|
||||||
|
|
||||||
function escape_test_name() {
|
|
||||||
sed 's/\[[^]]*\]//g' <<< "$1" | sed "s/[^[:alnum:]]/ /g" | tr -s " " | sed "s/^\s\+//" | sed "s/\s/.*/g"
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_names () {
|
|
||||||
local first=y
|
|
||||||
for name in "${TESTS_LIST_REGEX[@]}"; do
|
|
||||||
if [ -z "${first}" ]; then
|
|
||||||
echo -n "|"
|
|
||||||
else
|
|
||||||
first=
|
|
||||||
fi
|
|
||||||
echo -n "${name}"
|
|
||||||
done
|
|
||||||
for name in "${FLAKY_TESTS_LIST[@]}"; do
|
|
||||||
if [ -z "${first}" ]; then
|
|
||||||
echo -n "|"
|
|
||||||
else
|
|
||||||
first=
|
|
||||||
fi
|
|
||||||
echo -n "$(escape_test_name "${name}")"
|
|
||||||
done
|
|
||||||
for name in "${FAILING_TESTS_LIST[@]}"; do
|
|
||||||
if [ -z "${first}" ]; then
|
|
||||||
echo -n "|"
|
|
||||||
else
|
|
||||||
first=
|
|
||||||
fi
|
|
||||||
echo -n "$(escape_test_name "${name}")"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
cd $BASE/new/devstack
|
|
||||||
source openrc admin admin
|
|
||||||
|
|
||||||
echo "In post_test_hook"
|
|
||||||
|
|
||||||
# Get the latest stable version of kubernetes
|
|
||||||
export K8S_VERSION=$(curl -sS https://storage.googleapis.com/kubernetes-release/release/stable.txt)
|
|
||||||
echo "K8S_VERSION : ${K8S_VERSION}"
|
|
||||||
|
|
||||||
echo "Download Kubernetes CLI"
|
|
||||||
sudo wget -O kubectl "http://storage.googleapis.com/kubernetes-release/release/${K8S_VERSION}/bin/linux/amd64/kubectl"
|
|
||||||
sudo chmod 755 kubectl
|
|
||||||
|
|
||||||
export KUBECONFIG=/var/run/kubernetes/admin.kubeconfig
|
|
||||||
|
|
||||||
echo "Waiting for kubernetes service to start..."
|
|
||||||
for i in {1..600}
|
|
||||||
do
|
|
||||||
if [[ -f $KUBECONFIG ]]; then
|
|
||||||
running_count=$(./kubectl get nodes --no-headers 2>/dev/null | grep "Ready" | wc -l)
|
|
||||||
if [ "$running_count" -ge 1 ]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
echo -n "."
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Cluster created!"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
sudo journalctl -u devstack@kubernetes.service
|
|
||||||
|
|
||||||
echo "Dump Kubernetes Objects..."
|
|
||||||
./kubectl get componentstatuses
|
|
||||||
./kubectl get configmaps
|
|
||||||
./kubectl get daemonsets
|
|
||||||
./kubectl get deployments
|
|
||||||
./kubectl get events
|
|
||||||
./kubectl get endpoints
|
|
||||||
./kubectl get horizontalpodautoscalers
|
|
||||||
./kubectl get ingress
|
|
||||||
./kubectl get jobs
|
|
||||||
./kubectl get limitranges
|
|
||||||
./kubectl get nodes
|
|
||||||
./kubectl get namespaces
|
|
||||||
./kubectl get pods
|
|
||||||
./kubectl get persistentvolumes
|
|
||||||
./kubectl get persistentvolumeclaims
|
|
||||||
./kubectl get quota
|
|
||||||
./kubectl get resourcequotas
|
|
||||||
./kubectl get replicasets
|
|
||||||
./kubectl get replicationcontrollers
|
|
||||||
./kubectl get secrets
|
|
||||||
./kubectl get serviceaccounts
|
|
||||||
./kubectl get services
|
|
||||||
|
|
||||||
echo "Clear the taint to make sure we can schedule jobs to the master node"
|
|
||||||
./kubectl taint nodes --all node.cloudprovider.kubernetes.io/uninitialized-
|
|
||||||
|
|
||||||
./kubectl get node -o json
|
|
||||||
|
|
||||||
echo "Create a default StorageClass since we do not have a cloud provider"
|
|
||||||
./kubectl create -f - <<EOF || true
|
|
||||||
kind: StorageClass
|
|
||||||
apiVersion: storage.k8s.io/v1
|
|
||||||
metadata:
|
|
||||||
namespace: kube-system
|
|
||||||
name: standard
|
|
||||||
annotations:
|
|
||||||
storageclass.beta.kubernetes.io/is-default-class: "true"
|
|
||||||
labels:
|
|
||||||
addonmanager.kubernetes.io/mode: Reconcile
|
|
||||||
|
|
||||||
provisioner: kubernetes.io/host-path
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo "Running tests..."
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
export GOPATH=${BASE_DIR}/go
|
|
||||||
export KUBE_MASTER=local
|
|
||||||
export KUBERNETES_PROVIDER=skeleton
|
|
||||||
export KUBERNETES_CONFORMANCE_TEST=y
|
|
||||||
export GINKGO_PARALLEL=y
|
|
||||||
export GINKGO_PARALLELISM=5
|
|
||||||
export GINKGO_NO_COLOR=y
|
|
||||||
export KUBE_MASTER_IP=https://127.0.0.1:6443/
|
|
||||||
|
|
||||||
pushd $GOPATH/src/k8s.io/kubernetes >/dev/null
|
|
||||||
sudo -E PATH=$GOPATH/bin:$PATH make all WHAT=cmd/kubectl
|
|
||||||
sudo -E PATH=$GOPATH/bin:$PATH make all WHAT=vendor/github.com/onsi/ginkgo/ginkgo
|
|
||||||
|
|
||||||
# open up access for containers
|
|
||||||
sudo ifconfig -a
|
|
||||||
export HOST_INTERFACE=$(ip -f inet route | awk '/default/ {print $5}')
|
|
||||||
sudo iptables -t nat -A POSTROUTING -o $HOST_INTERFACE -s 10.0.0.0/24 -j MASQUERADE
|
|
||||||
sudo iptables -t nat -A POSTROUTING -o $HOST_INTERFACE -s 172.17.0.0/24 -j MASQUERADE
|
|
||||||
|
|
||||||
|
|
||||||
sudo -E PATH=$GOPATH/bin:$PATH make all WHAT=test/e2e/e2e.test
|
|
||||||
sudo -E PATH=$GOPATH/bin:$PATH go run hack/e2e.go -- -v --test --test_args="--ginkgo.trace=true --ginkgo.seed=1378936983 --logtostderr --v 4 --provider=local --report-dir=/opt/stack/logs/ --ginkgo.v --ginkgo.skip=$(test_names)"
|
|
||||||
popd >/dev/null
|
|
@ -1,19 +0,0 @@
|
|||||||
#!/bin/bash -xe
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
# This script is executed inside pre_test_hook function in devstack gate.
|
|
||||||
|
|
||||||
export localconf=$BASE/new/devstack/local.conf
|
|
||||||
|
|
||||||
echo "In pre_test_hook"
|
|
@ -1,193 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
# lib/dlm
|
|
||||||
#
|
|
||||||
# Functions to control the installation and configuration of kubernetes with the
|
|
||||||
# external OpenStack cloud provider enabled.
|
|
||||||
|
|
||||||
# Save trace setting
|
|
||||||
_XTRACE_K8S_PROVIDER=$(set +o | grep xtrace)
|
|
||||||
set -o xtrace
|
|
||||||
|
|
||||||
|
|
||||||
BASE_DIR=$(cd $(dirname $BASH_SOURCE)/.. && pwd)
|
|
||||||
|
|
||||||
# Defaults
|
|
||||||
# --------
|
|
||||||
|
|
||||||
export GOPATH=${BASE_DIR}/go
|
|
||||||
|
|
||||||
CONFORMANCE_REPO=${CONFORMANCE_REPO:-github.com/kubernetes/kubernetes}
|
|
||||||
K8S_SRC=${GOPATH}/src/k8s.io/kubernetes
|
|
||||||
|
|
||||||
function install_prereqs {
|
|
||||||
# Install pre-reqs
|
|
||||||
$BASE_DIR/tools/install-distro-packages.sh
|
|
||||||
$BASE_DIR/tools/test-setup.sh
|
|
||||||
|
|
||||||
install_package nfs-common
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function install_docker {
|
|
||||||
# Install docker if needed
|
|
||||||
if ! is_package_installed docker-engine; then
|
|
||||||
sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D || true
|
|
||||||
sudo apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D || true
|
|
||||||
sudo apt-add-repository 'deb http://apt.dockerproject.org/repo ubuntu-xenial main'
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-cache policy docker-engine
|
|
||||||
sudo apt-get install -y docker-engine=1.12.6-0~ubuntu-xenial
|
|
||||||
sudo cat /lib/systemd/system/docker.service
|
|
||||||
sudo sed -r -i "s|(ExecStart)=(.+)|\1=\2 --iptables=false|" /lib/systemd/system/docker.service
|
|
||||||
sudo cat /lib/systemd/system/docker.service
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
sudo systemctl restart docker
|
|
||||||
sudo systemctl status docker
|
|
||||||
sudo ifconfig -a
|
|
||||||
fi
|
|
||||||
docker --version
|
|
||||||
|
|
||||||
# Get the latest stable version of kubernetes
|
|
||||||
export K8S_VERSION=$(curl -sS https://storage.googleapis.com/kubernetes-release/release/stable.txt)
|
|
||||||
echo "K8S_VERSION : ${K8S_VERSION}"
|
|
||||||
|
|
||||||
echo "Starting docker service"
|
|
||||||
sudo systemctl enable docker.service
|
|
||||||
sudo systemctl start docker.service --ignore-dependencies
|
|
||||||
echo "Checking docker service"
|
|
||||||
sudo docker ps
|
|
||||||
}
|
|
||||||
|
|
||||||
function install_k8s_cloud_provider {
|
|
||||||
echo_summary "Installing Devstack Plugin for k8s-cloud-provider"
|
|
||||||
|
|
||||||
# golang env details
|
|
||||||
go env
|
|
||||||
go version
|
|
||||||
|
|
||||||
go get -u github.com/jteeuwen/go-bindata/go-bindata || true
|
|
||||||
go get -u github.com/cloudflare/cfssl/cmd/... || true
|
|
||||||
|
|
||||||
# Get Kubernetes from source
|
|
||||||
mkdir -p ${GOPATH}/src/k8s.io/
|
|
||||||
if [ ! -d "${K8S_SRC}" ]; then
|
|
||||||
git clone https://${CONFORMANCE_REPO} ${K8S_SRC}
|
|
||||||
pushd ${K8S_SRC} >/dev/null
|
|
||||||
git remote update
|
|
||||||
git fetch --all --tags --prune
|
|
||||||
|
|
||||||
popd >/dev/null
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Run the script that builds kubernetes from source and starts the processes
|
|
||||||
pushd ${K8S_SRC} >/dev/null
|
|
||||||
|
|
||||||
# local-up-cluster needs the etcd path and the GOPATH bin as cf-ssl
|
|
||||||
# and go-bindata are located there
|
|
||||||
export PATH=$DEST/bin:$GOPATH/bin:${PATH}
|
|
||||||
|
|
||||||
# Seed the log files so devstack-gate can capture the logs
|
|
||||||
export LOG_DIR=${SCREEN_LOGDIR:-/opt/stack/logs}
|
|
||||||
sudo mkdir -p $LOG_DIR
|
|
||||||
sudo touch $LOG_DIR/kube-apiserver.log;sudo ln -s $LOG_DIR/kube-apiserver.log $LOG_DIR/screen-kube-apiserver.log
|
|
||||||
sudo touch $LOG_DIR/kube-controller-manager.log;sudo ln -s $LOG_DIR/kube-controller-manager.log $LOG_DIR/screen-kube-controller-manager.log
|
|
||||||
sudo touch $LOG_DIR/kube-proxy.log;sudo ln -s $LOG_DIR/kube-proxy.log $LOG_DIR/screen-kube-proxy.log
|
|
||||||
sudo touch $LOG_DIR/kube-scheduler.log;sudo ln -s $LOG_DIR/kube-scheduler.log $LOG_DIR/screen-kube-scheduler.log
|
|
||||||
sudo touch $LOG_DIR/kubelet.log;sudo ln -s $LOG_DIR/kubelet.log $LOG_DIR/screen-kubelet.log
|
|
||||||
|
|
||||||
echo "Stopping firewall and allow all traffic..."
|
|
||||||
sudo iptables -F
|
|
||||||
sudo iptables -X
|
|
||||||
sudo iptables -t nat -F
|
|
||||||
sudo iptables -t nat -X
|
|
||||||
sudo iptables -t mangle -F
|
|
||||||
sudo iptables -t mangle -X
|
|
||||||
sudo iptables -P INPUT ACCEPT
|
|
||||||
sudo iptables -P FORWARD ACCEPT
|
|
||||||
sudo iptables -P OUTPUT ACCEPT
|
|
||||||
|
|
||||||
# Turn on/off a few things in local-up-cluster.sh
|
|
||||||
export ALLOW_PRIVILEGED=true
|
|
||||||
export ALLOW_SECURITY_CONTEXT=true
|
|
||||||
export CLOUD_PROVIDER=external
|
|
||||||
export ENABLE_CRI=false
|
|
||||||
export ENABLE_DAEMON=true
|
|
||||||
export ENABLE_HOSTPATH_PROVISIONER=true
|
|
||||||
export ENABLE_SINGLE_CA_SIGNER=true
|
|
||||||
export HOSTNAME_OVERRIDE=$(ip route get 1.1.1.1 | awk '{print $7}')
|
|
||||||
export KUBE_ENABLE_CLUSTER_DASHBOARD=true
|
|
||||||
export KUBE_ENABLE_CLUSTER_DNS=true
|
|
||||||
export LOG_LEVEL=10
|
|
||||||
|
|
||||||
# Listen on all interfaces
|
|
||||||
export KUBELET_HOST="0.0.0.0"
|
|
||||||
|
|
||||||
# Use the docker0's ip address for kubedns to work
|
|
||||||
export API_HOST_IP="172.17.0.1"
|
|
||||||
|
|
||||||
# kill etcd and let local-up-cluster start it up
|
|
||||||
$SYSTEMCTL stop $ETCD_SYSTEMD_SERVICE
|
|
||||||
|
|
||||||
# local-up-cluster.sh compiles everything from source and starts the services.
|
|
||||||
sudo -E PATH=$PATH ./hack/local-up-cluster.sh
|
|
||||||
|
|
||||||
popd >/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
# cleanup_k8s_cloud_provider() - Remove residual data files, anything left over from previous
|
|
||||||
# runs that a clean run would need to clean up
|
|
||||||
function cleanup_k8s_cloud_provider {
|
|
||||||
echo_summary "Cleaning up Devstack Plugin for k8s-cloud-provider"
|
|
||||||
# Kill the k8s processes
|
|
||||||
ps -ef | grep -e hyperkube | grep -v grep | awk '{print $2}' | xargs sudo kill -9
|
|
||||||
|
|
||||||
# Cleanup docker images and containers
|
|
||||||
sudo docker rm -f $(docker ps -a -q) || true
|
|
||||||
sudo docker rmi -f $(docker images -q -a) || true
|
|
||||||
|
|
||||||
# Stop docker
|
|
||||||
sudo systemctl stop docker.service
|
|
||||||
sudo rm -rf "$K8S_SRC"
|
|
||||||
}
|
|
||||||
|
|
||||||
function stop_k8s_cloud_provider {
|
|
||||||
echo_summary "Stop Devstack Plugin for k8s-cloud-provider"
|
|
||||||
stop_process kubernetes
|
|
||||||
}
|
|
||||||
|
|
||||||
# check for service enabled
|
|
||||||
if is_service_enabled k8s-cloud-provider; then
|
|
||||||
|
|
||||||
if [[ "$1" == "stack" && "$2" == "pre-install" ]]; then
|
|
||||||
# no-op
|
|
||||||
:
|
|
||||||
|
|
||||||
elif [[ "$1" == "stack" && "$2" == "install" ]]; then
|
|
||||||
install_docker
|
|
||||||
install_prereqs
|
|
||||||
|
|
||||||
elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
|
|
||||||
install_k8s_cloud_provider
|
|
||||||
|
|
||||||
elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
|
|
||||||
# no-op
|
|
||||||
:
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$1" == "unstack" ]]; then
|
|
||||||
stop_k8s_cloud_provider
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$1" == "clean" ]]; then
|
|
||||||
cleanup_k8s_cloud_provider
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Restore xtrace
|
|
||||||
$_XTRACE_K8S_PROVIDER
|
|
||||||
|
|
||||||
# Tell emacs to use shell-script-mode
|
|
||||||
## Local variables:
|
|
||||||
## mode: shell-script
|
|
||||||
## End:
|
|
@ -1,4 +0,0 @@
|
|||||||
# settings file for devstack plugin
|
|
||||||
|
|
||||||
enable_service k8s-cloud-provider
|
|
||||||
enable_service kubernetes
|
|
677
glide.lock
generated
677
glide.lock
generated
@ -1,677 +0,0 @@
|
|||||||
hash: 55acf1401fca2a0eef9461c95e0e16b2fcf37239abb1894ff965b7c001f84517
|
|
||||||
updated: 2017-03-24T09:48:00.184737937-04:00
|
|
||||||
imports:
|
|
||||||
- name: bitbucket.org/ww/goautoneg
|
|
||||||
version: 75cd24fc2f2c2a2088577d12123ddee5f54e0675
|
|
||||||
- name: cloud.google.com/go
|
|
||||||
version: 3b1ae45394a234c385be014e9a488f2bb6eef821
|
|
||||||
subpackages:
|
|
||||||
- compute/metadata
|
|
||||||
- internal
|
|
||||||
- name: github.com/aws/aws-sdk-go
|
|
||||||
version: 63ce630574a5ec05ecd8e8de5cea16332a5a684d
|
|
||||||
subpackages:
|
|
||||||
- aws
|
|
||||||
- aws/awserr
|
|
||||||
- aws/awsutil
|
|
||||||
- aws/client
|
|
||||||
- aws/client/metadata
|
|
||||||
- aws/corehandlers
|
|
||||||
- aws/credentials
|
|
||||||
- aws/credentials/ec2rolecreds
|
|
||||||
- aws/credentials/endpointcreds
|
|
||||||
- aws/credentials/stscreds
|
|
||||||
- aws/defaults
|
|
||||||
- aws/ec2metadata
|
|
||||||
- aws/endpoints
|
|
||||||
- aws/request
|
|
||||||
- aws/session
|
|
||||||
- aws/signer/v4
|
|
||||||
- private/protocol
|
|
||||||
- private/protocol/ec2query
|
|
||||||
- private/protocol/json/jsonutil
|
|
||||||
- private/protocol/jsonrpc
|
|
||||||
- private/protocol/query
|
|
||||||
- private/protocol/query/queryutil
|
|
||||||
- private/protocol/rest
|
|
||||||
- private/protocol/restxml
|
|
||||||
- private/protocol/xml/xmlutil
|
|
||||||
- private/waiter
|
|
||||||
- service/autoscaling
|
|
||||||
- service/ec2
|
|
||||||
- service/ecr
|
|
||||||
- service/elb
|
|
||||||
- service/route53
|
|
||||||
- service/sts
|
|
||||||
- name: github.com/Azure/azure-sdk-for-go
|
|
||||||
version: 0984e0641ae43b89283223034574d6465be93bf4
|
|
||||||
subpackages:
|
|
||||||
- arm/compute
|
|
||||||
- arm/containerregistry
|
|
||||||
- arm/network
|
|
||||||
- arm/storage
|
|
||||||
- storage
|
|
||||||
- name: github.com/Azure/go-autorest
|
|
||||||
version: d7c034a8af24eda120dd6460bfcd6d9ed14e43ca
|
|
||||||
subpackages:
|
|
||||||
- autorest
|
|
||||||
- autorest/azure
|
|
||||||
- autorest/date
|
|
||||||
- autorest/to
|
|
||||||
- autorest/validation
|
|
||||||
- name: github.com/beorn7/perks
|
|
||||||
version: 3ac7bf7a47d159a033b107610db8a1b6575507a4
|
|
||||||
subpackages:
|
|
||||||
- quantile
|
|
||||||
- name: github.com/davecgh/go-spew
|
|
||||||
version: 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d
|
|
||||||
subpackages:
|
|
||||||
- spew
|
|
||||||
- name: github.com/dgrijalva/jwt-go
|
|
||||||
version: 01aeca54ebda6e0fbfafd0a524d234159c05ec20
|
|
||||||
- name: github.com/docker/distribution
|
|
||||||
version: cd27f179f2c10c5d300e6d09025b538c475b0d51
|
|
||||||
subpackages:
|
|
||||||
- digest
|
|
||||||
- reference
|
|
||||||
- name: github.com/docker/engine-api
|
|
||||||
version: dea108d3aa0c67d7162a3fd8aa65f38a430019fd
|
|
||||||
subpackages:
|
|
||||||
- client
|
|
||||||
- client/transport
|
|
||||||
- client/transport/cancellable
|
|
||||||
- types
|
|
||||||
- types/blkiodev
|
|
||||||
- types/container
|
|
||||||
- types/filters
|
|
||||||
- types/network
|
|
||||||
- types/reference
|
|
||||||
- types/registry
|
|
||||||
- types/strslice
|
|
||||||
- types/time
|
|
||||||
- types/versions
|
|
||||||
- name: github.com/docker/go-connections
|
|
||||||
version: f549a9393d05688dff0992ef3efd8bbe6c628aeb
|
|
||||||
subpackages:
|
|
||||||
- nat
|
|
||||||
- sockets
|
|
||||||
- tlsconfig
|
|
||||||
- name: github.com/docker/go-units
|
|
||||||
version: e30f1e79f3cd72542f2026ceec18d3bd67ab859c
|
|
||||||
- name: github.com/emicklei/go-restful
|
|
||||||
version: 09691a3b6378b740595c1002f40c34dd5f218a22
|
|
||||||
subpackages:
|
|
||||||
- log
|
|
||||||
- swagger
|
|
||||||
- name: github.com/exponent-io/jsonpath
|
|
||||||
version: d6023ce2651d8eafb5c75bb0c7167536102ec9f5
|
|
||||||
- name: github.com/ghodss/yaml
|
|
||||||
version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee
|
|
||||||
- name: github.com/go-ini/ini
|
|
||||||
version: 2e44421e256d82ebbf3d4d4fcabe8930b905eff3
|
|
||||||
- name: github.com/go-openapi/analysis
|
|
||||||
version: b44dc874b601d9e4e2f6e19140e794ba24bead3b
|
|
||||||
- name: github.com/go-openapi/jsonpointer
|
|
||||||
version: 46af16f9f7b149af66e5d1bd010e3574dc06de98
|
|
||||||
- name: github.com/go-openapi/jsonreference
|
|
||||||
version: 13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272
|
|
||||||
- name: github.com/go-openapi/loads
|
|
||||||
version: 18441dfa706d924a39a030ee2c3b1d8d81917b38
|
|
||||||
- name: github.com/go-openapi/spec
|
|
||||||
version: 6aced65f8501fe1217321abf0749d354824ba2ff
|
|
||||||
- name: github.com/go-openapi/swag
|
|
||||||
version: 1d0bd113de87027671077d3c71eb3ac5d7dbba72
|
|
||||||
- name: github.com/gogo/protobuf
|
|
||||||
version: c0656edd0d9eab7c66d1eb0c568f9039345796f7
|
|
||||||
subpackages:
|
|
||||||
- proto
|
|
||||||
- sortkeys
|
|
||||||
- name: github.com/golang/glog
|
|
||||||
version: 23def4e6c14b4da8ac2ed8007337bc5eb5007998
|
|
||||||
- name: github.com/golang/groupcache
|
|
||||||
version: 02826c3e79038b59d737d3b1c0a1d937f71a4433
|
|
||||||
subpackages:
|
|
||||||
- lru
|
|
||||||
- name: github.com/golang/protobuf
|
|
||||||
version: 4bd1920723d7b7c925de087aa32e2187708897f7
|
|
||||||
subpackages:
|
|
||||||
- jsonpb
|
|
||||||
- proto
|
|
||||||
- name: github.com/google/gofuzz
|
|
||||||
version: 44d81051d367757e1c7c6a5a86423ece9afcf63c
|
|
||||||
- name: github.com/gophercloud/gophercloud
|
|
||||||
version: b06120d13e262ceaf890ef38ee30898813696af0
|
|
||||||
subpackages:
|
|
||||||
- openstack
|
|
||||||
- openstack/blockstorage/v1/apiversions
|
|
||||||
- openstack/blockstorage/v1/volumes
|
|
||||||
- openstack/blockstorage/v2/volumes
|
|
||||||
- openstack/common/extensions
|
|
||||||
- openstack/compute/v2/extensions/volumeattach
|
|
||||||
- openstack/compute/v2/flavors
|
|
||||||
- openstack/compute/v2/images
|
|
||||||
- openstack/compute/v2/servers
|
|
||||||
- openstack/identity/v2/tenants
|
|
||||||
- openstack/identity/v2/tokens
|
|
||||||
- openstack/identity/v3/extensions/trusts
|
|
||||||
- openstack/identity/v3/tokens
|
|
||||||
- openstack/networking/v2/extensions
|
|
||||||
- openstack/networking/v2/extensions/layer3/floatingips
|
|
||||||
- openstack/networking/v2/extensions/layer3/routers
|
|
||||||
- openstack/networking/v2/extensions/lbaas/members
|
|
||||||
- openstack/networking/v2/extensions/lbaas/monitors
|
|
||||||
- openstack/networking/v2/extensions/lbaas/pools
|
|
||||||
- openstack/networking/v2/extensions/lbaas/vips
|
|
||||||
- openstack/networking/v2/extensions/lbaas_v2/listeners
|
|
||||||
- openstack/networking/v2/extensions/lbaas_v2/loadbalancers
|
|
||||||
- openstack/networking/v2/extensions/lbaas_v2/monitors
|
|
||||||
- openstack/networking/v2/extensions/lbaas_v2/pools
|
|
||||||
- openstack/networking/v2/extensions/security/groups
|
|
||||||
- openstack/networking/v2/extensions/security/rules
|
|
||||||
- openstack/networking/v2/ports
|
|
||||||
- openstack/utils
|
|
||||||
- pagination
|
|
||||||
- name: github.com/howeyc/gopass
|
|
||||||
version: 3ca23474a7c7203e0a0a070fd33508f6efdb9b3d
|
|
||||||
- name: github.com/imdario/mergo
|
|
||||||
version: 6633656539c1639d9d78127b7d47c622b5d7b6dc
|
|
||||||
- name: github.com/inconshreveable/mousetrap
|
|
||||||
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
|
|
||||||
- name: github.com/jmespath/go-jmespath
|
|
||||||
version: 3433f3ea46d9f8019119e7dd41274e112a2359a9
|
|
||||||
- name: github.com/juju/ratelimit
|
|
||||||
version: 77ed1c8a01217656d2080ad51981f6e99adaa177
|
|
||||||
- name: github.com/mailru/easyjson
|
|
||||||
version: d5b7844b561a7bc640052f1b935f7b800330d7e0
|
|
||||||
subpackages:
|
|
||||||
- buffer
|
|
||||||
- jlexer
|
|
||||||
- jwriter
|
|
||||||
- name: github.com/matttproud/golang_protobuf_extensions
|
|
||||||
version: fc2b8d3a73c4867e51861bbdd5ae3c1f0869dd6a
|
|
||||||
subpackages:
|
|
||||||
- pbutil
|
|
||||||
- name: github.com/mesos/mesos-go
|
|
||||||
version: 45c8b08e9af666add36a6f93ff8c1c75812367b0
|
|
||||||
subpackages:
|
|
||||||
- detector
|
|
||||||
- detector/zoo
|
|
||||||
- mesosproto
|
|
||||||
- mesosutil
|
|
||||||
- upid
|
|
||||||
- name: github.com/mitchellh/mapstructure
|
|
||||||
version: cc8532a8e9a55ea36402aa21efdf403a60d34096
|
|
||||||
- name: github.com/prometheus/client_golang
|
|
||||||
version: e51041b3fa41cece0dca035740ba6411905be473
|
|
||||||
subpackages:
|
|
||||||
- prometheus
|
|
||||||
- name: github.com/prometheus/client_model
|
|
||||||
version: fa8ad6fec33561be4280a8f0514318c79d7f6cb6
|
|
||||||
subpackages:
|
|
||||||
- go
|
|
||||||
- name: github.com/prometheus/common
|
|
||||||
version: ffe929a3f4c4faeaa10f2b9535c2b1be3ad15650
|
|
||||||
subpackages:
|
|
||||||
- expfmt
|
|
||||||
- model
|
|
||||||
- name: github.com/prometheus/procfs
|
|
||||||
version: 454a56f35412459b5e684fd5ec0f9211b94f002a
|
|
||||||
- name: github.com/PuerkitoBio/purell
|
|
||||||
version: 8a290539e2e8629dbc4e6bad948158f790ec31f4
|
|
||||||
- name: github.com/PuerkitoBio/urlesc
|
|
||||||
version: 5bd2802263f21d8788851d5305584c82a5c75d7e
|
|
||||||
- name: github.com/rackspace/gophercloud
|
|
||||||
version: e00690e87603abe613e9f02c816c7c4bef82e063
|
|
||||||
subpackages:
|
|
||||||
- openstack
|
|
||||||
- openstack/blockstorage/v1/volumes
|
|
||||||
- openstack/compute/v2/extensions/bootfromvolume
|
|
||||||
- openstack/compute/v2/extensions/diskconfig
|
|
||||||
- openstack/compute/v2/extensions/volumeattach
|
|
||||||
- openstack/compute/v2/flavors
|
|
||||||
- openstack/compute/v2/images
|
|
||||||
- openstack/compute/v2/servers
|
|
||||||
- openstack/identity/v2/tenants
|
|
||||||
- openstack/identity/v2/tokens
|
|
||||||
- openstack/identity/v3/tokens
|
|
||||||
- openstack/utils
|
|
||||||
- pagination
|
|
||||||
- rackspace
|
|
||||||
- rackspace/blockstorage/v1/volumes
|
|
||||||
- rackspace/compute/v2/servers
|
|
||||||
- rackspace/compute/v2/volumeattach
|
|
||||||
- rackspace/identity/v2/tokens
|
|
||||||
- testhelper
|
|
||||||
- testhelper/client
|
|
||||||
- name: github.com/rubiojr/go-vhd
|
|
||||||
version: 0bfd3b39853cdde5762efda92289f14b0ac0491b
|
|
||||||
subpackages:
|
|
||||||
- vhd
|
|
||||||
- name: github.com/samuel/go-zookeeper
|
|
||||||
version: 177002e16a0061912f02377e2dd8951a8b3551bc
|
|
||||||
subpackages:
|
|
||||||
- zk
|
|
||||||
- name: github.com/spf13/cobra
|
|
||||||
version: f62e98d28ab7ad31d707ba837a966378465c7b57
|
|
||||||
subpackages:
|
|
||||||
- doc
|
|
||||||
- name: github.com/spf13/pflag
|
|
||||||
version: c990990ab4981d84da820b7b00c85139ca150b5f
|
|
||||||
- name: github.com/ugorji/go
|
|
||||||
version: ded73eae5db7e7a0ef6f55aace87a2873c5d2b74
|
|
||||||
subpackages:
|
|
||||||
- codec
|
|
||||||
- name: github.com/vmware/govmomi
|
|
||||||
version: 0a28e595c8e9e99879e8d2f796e82c5a68202ff0
|
|
||||||
subpackages:
|
|
||||||
- find
|
|
||||||
- list
|
|
||||||
- object
|
|
||||||
- property
|
|
||||||
- session
|
|
||||||
- task
|
|
||||||
- vim25
|
|
||||||
- vim25/debug
|
|
||||||
- vim25/methods
|
|
||||||
- vim25/mo
|
|
||||||
- vim25/progress
|
|
||||||
- vim25/soap
|
|
||||||
- vim25/types
|
|
||||||
- vim25/xml
|
|
||||||
- name: github.com/vmware/photon-controller-go-sdk
|
|
||||||
version: 4a435daef6ccd3d0edaac1161e76f51a70c2589a
|
|
||||||
subpackages:
|
|
||||||
- SSPI
|
|
||||||
- photon
|
|
||||||
- photon/lightwave
|
|
||||||
- name: github.com/xanzy/go-cloudstack
|
|
||||||
version: 1e2cbf647e57fa90353612074fdfc42faf5073bf
|
|
||||||
subpackages:
|
|
||||||
- cloudstack
|
|
||||||
- name: golang.org/x/crypto
|
|
||||||
version: d172538b2cfce0c13cee31e647d0367aa8cd2486
|
|
||||||
subpackages:
|
|
||||||
- bcrypt
|
|
||||||
- blowfish
|
|
||||||
- ssh/terminal
|
|
||||||
- name: golang.org/x/net
|
|
||||||
version: f2499483f923065a842d38eb4c7f1927e6fc6e6d
|
|
||||||
subpackages:
|
|
||||||
- context
|
|
||||||
- context/ctxhttp
|
|
||||||
- html
|
|
||||||
- html/atom
|
|
||||||
- http2
|
|
||||||
- http2/hpack
|
|
||||||
- idna
|
|
||||||
- internal/timeseries
|
|
||||||
- lex/httplex
|
|
||||||
- trace
|
|
||||||
- websocket
|
|
||||||
- name: golang.org/x/oauth2
|
|
||||||
version: 3c3a985cb79f52a3190fbc056984415ca6763d01
|
|
||||||
subpackages:
|
|
||||||
- google
|
|
||||||
- internal
|
|
||||||
- jws
|
|
||||||
- jwt
|
|
||||||
- name: golang.org/x/sys
|
|
||||||
version: 8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9
|
|
||||||
subpackages:
|
|
||||||
- unix
|
|
||||||
- name: golang.org/x/text
|
|
||||||
version: 2910a502d2bf9e43193af9d68ca516529614eed3
|
|
||||||
subpackages:
|
|
||||||
- cases
|
|
||||||
- internal/tag
|
|
||||||
- language
|
|
||||||
- runes
|
|
||||||
- secure/bidirule
|
|
||||||
- secure/precis
|
|
||||||
- transform
|
|
||||||
- unicode/bidi
|
|
||||||
- unicode/norm
|
|
||||||
- width
|
|
||||||
- name: google.golang.org/api
|
|
||||||
version: 64485db7e8c8be51e572801d06cdbcfadd3546c1
|
|
||||||
subpackages:
|
|
||||||
- cloudmonitoring/v2beta2
|
|
||||||
- compute/v0.alpha
|
|
||||||
- compute/v1
|
|
||||||
- container/v1
|
|
||||||
- dns/v1
|
|
||||||
- gensupport
|
|
||||||
- googleapi
|
|
||||||
- googleapi/internal/uritemplates
|
|
||||||
- logging/v2beta1
|
|
||||||
- monitoring/v3
|
|
||||||
- name: google.golang.org/appengine
|
|
||||||
version: 4f7eeb5305a4ba1966344836ba4af9996b7b4e05
|
|
||||||
subpackages:
|
|
||||||
- internal
|
|
||||||
- internal/app_identity
|
|
||||||
- internal/base
|
|
||||||
- internal/datastore
|
|
||||||
- internal/log
|
|
||||||
- internal/modules
|
|
||||||
- internal/remote_api
|
|
||||||
- internal/urlfetch
|
|
||||||
- urlfetch
|
|
||||||
- name: gopkg.in/gcfg.v1
|
|
||||||
version: 083575c3955c85df16fe9590cceab64d03f5eb6e
|
|
||||||
subpackages:
|
|
||||||
- scanner
|
|
||||||
- token
|
|
||||||
- types
|
|
||||||
- name: gopkg.in/inf.v0
|
|
||||||
version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
|
|
||||||
- name: gopkg.in/yaml.v2
|
|
||||||
version: 53feefa2559fb8dfa8d81baad31be332c97d6c77
|
|
||||||
- name: k8s.io/apimachinery
|
|
||||||
version: 592382eb7243e2379169a0ced0fb71a8353a5653
|
|
||||||
subpackages:
|
|
||||||
- pkg/api/equality
|
|
||||||
- pkg/api/errors
|
|
||||||
- pkg/api/meta
|
|
||||||
- pkg/api/resource
|
|
||||||
- pkg/api/validation
|
|
||||||
- pkg/apimachinery
|
|
||||||
- pkg/apimachinery/announced
|
|
||||||
- pkg/apimachinery/registered
|
|
||||||
- pkg/apis/meta/v1
|
|
||||||
- pkg/apis/meta/v1/unstructured
|
|
||||||
- pkg/apis/meta/v1/validation
|
|
||||||
- pkg/conversion
|
|
||||||
- pkg/conversion/queryparams
|
|
||||||
- pkg/fields
|
|
||||||
- pkg/labels
|
|
||||||
- pkg/openapi
|
|
||||||
- pkg/runtime
|
|
||||||
- pkg/runtime/schema
|
|
||||||
- pkg/runtime/serializer
|
|
||||||
- pkg/runtime/serializer/json
|
|
||||||
- pkg/runtime/serializer/protobuf
|
|
||||||
- pkg/runtime/serializer/recognizer
|
|
||||||
- pkg/runtime/serializer/streaming
|
|
||||||
- pkg/runtime/serializer/versioning
|
|
||||||
- pkg/selection
|
|
||||||
- pkg/types
|
|
||||||
- pkg/util/diff
|
|
||||||
- pkg/util/errors
|
|
||||||
- pkg/util/framer
|
|
||||||
- pkg/util/intstr
|
|
||||||
- pkg/util/json
|
|
||||||
- pkg/util/mergepatch
|
|
||||||
- pkg/util/net
|
|
||||||
- pkg/util/rand
|
|
||||||
- pkg/util/runtime
|
|
||||||
- pkg/util/sets
|
|
||||||
- pkg/util/strategicpatch
|
|
||||||
- pkg/util/validation
|
|
||||||
- pkg/util/validation/field
|
|
||||||
- pkg/util/wait
|
|
||||||
- pkg/util/yaml
|
|
||||||
- pkg/version
|
|
||||||
- pkg/watch
|
|
||||||
- third_party/forked/golang/json
|
|
||||||
- third_party/forked/golang/reflect
|
|
||||||
- name: k8s.io/apiserver
|
|
||||||
version: 6eb4e56e7999d0faa4ab9ecffa3d118c628e84aa
|
|
||||||
subpackages:
|
|
||||||
- pkg/authentication/authenticator
|
|
||||||
- pkg/authentication/serviceaccount
|
|
||||||
- pkg/authentication/user
|
|
||||||
- pkg/features
|
|
||||||
- pkg/server/healthz
|
|
||||||
- pkg/util/feature
|
|
||||||
- pkg/util/flag
|
|
||||||
- pkg/util/logs
|
|
||||||
- name: k8s.io/client-go
|
|
||||||
version: f1cb94b672d5cdaf5107430eab7cac84e54b8133
|
|
||||||
subpackages:
|
|
||||||
- discovery
|
|
||||||
- kubernetes
|
|
||||||
- kubernetes/scheme
|
|
||||||
- kubernetes/typed/apps/v1beta1
|
|
||||||
- kubernetes/typed/authentication/v1
|
|
||||||
- kubernetes/typed/authentication/v1beta1
|
|
||||||
- kubernetes/typed/authorization/v1
|
|
||||||
- kubernetes/typed/authorization/v1beta1
|
|
||||||
- kubernetes/typed/autoscaling/v1
|
|
||||||
- kubernetes/typed/autoscaling/v2alpha1
|
|
||||||
- kubernetes/typed/batch/v1
|
|
||||||
- kubernetes/typed/batch/v2alpha1
|
|
||||||
- kubernetes/typed/certificates/v1beta1
|
|
||||||
- kubernetes/typed/core/v1
|
|
||||||
- kubernetes/typed/extensions/v1beta1
|
|
||||||
- kubernetes/typed/policy/v1beta1
|
|
||||||
- kubernetes/typed/rbac/v1alpha1
|
|
||||||
- kubernetes/typed/rbac/v1beta1
|
|
||||||
- kubernetes/typed/settings/v1alpha1
|
|
||||||
- kubernetes/typed/storage/v1
|
|
||||||
- kubernetes/typed/storage/v1beta1
|
|
||||||
- pkg/api
|
|
||||||
- pkg/api/install
|
|
||||||
- pkg/api/v1
|
|
||||||
- pkg/api/v1/ref
|
|
||||||
- pkg/apis/apps
|
|
||||||
- pkg/apis/apps/install
|
|
||||||
- pkg/apis/apps/v1beta1
|
|
||||||
- pkg/apis/authentication
|
|
||||||
- pkg/apis/authentication/install
|
|
||||||
- pkg/apis/authentication/v1
|
|
||||||
- pkg/apis/authentication/v1beta1
|
|
||||||
- pkg/apis/authorization
|
|
||||||
- pkg/apis/authorization/install
|
|
||||||
- pkg/apis/authorization/v1
|
|
||||||
- pkg/apis/authorization/v1beta1
|
|
||||||
- pkg/apis/autoscaling
|
|
||||||
- pkg/apis/autoscaling/install
|
|
||||||
- pkg/apis/autoscaling/v1
|
|
||||||
- pkg/apis/autoscaling/v2alpha1
|
|
||||||
- pkg/apis/batch
|
|
||||||
- pkg/apis/batch/install
|
|
||||||
- pkg/apis/batch/v1
|
|
||||||
- pkg/apis/batch/v2alpha1
|
|
||||||
- pkg/apis/certificates
|
|
||||||
- pkg/apis/certificates/install
|
|
||||||
- pkg/apis/certificates/v1beta1
|
|
||||||
- pkg/apis/extensions
|
|
||||||
- pkg/apis/extensions/install
|
|
||||||
- pkg/apis/extensions/v1beta1
|
|
||||||
- pkg/apis/policy
|
|
||||||
- pkg/apis/policy/install
|
|
||||||
- pkg/apis/policy/v1beta1
|
|
||||||
- pkg/apis/rbac
|
|
||||||
- pkg/apis/rbac/install
|
|
||||||
- pkg/apis/rbac/v1alpha1
|
|
||||||
- pkg/apis/rbac/v1beta1
|
|
||||||
- pkg/apis/settings
|
|
||||||
- pkg/apis/settings/install
|
|
||||||
- pkg/apis/settings/v1alpha1
|
|
||||||
- pkg/apis/storage
|
|
||||||
- pkg/apis/storage/install
|
|
||||||
- pkg/apis/storage/v1
|
|
||||||
- pkg/apis/storage/v1beta1
|
|
||||||
- pkg/util
|
|
||||||
- pkg/util/parsers
|
|
||||||
- pkg/version
|
|
||||||
- rest
|
|
||||||
- rest/watch
|
|
||||||
- tools/auth
|
|
||||||
- tools/cache
|
|
||||||
- tools/clientcmd
|
|
||||||
- tools/clientcmd/api
|
|
||||||
- tools/clientcmd/api/latest
|
|
||||||
- tools/clientcmd/api/v1
|
|
||||||
- tools/metrics
|
|
||||||
- tools/record
|
|
||||||
- transport
|
|
||||||
- util/cert
|
|
||||||
- util/clock
|
|
||||||
- util/flowcontrol
|
|
||||||
- util/homedir
|
|
||||||
- util/integer
|
|
||||||
- util/workqueue
|
|
||||||
- name: k8s.io/kubernetes
|
|
||||||
version: 868da1e08b38d5d7ebd3cfc3a1974063ce41109f
|
|
||||||
subpackages:
|
|
||||||
- cmd/cloud-controller-manager/app
|
|
||||||
- cmd/cloud-controller-manager/app/options
|
|
||||||
- cmd/kubeadm/app/constants
|
|
||||||
- pkg/api
|
|
||||||
- pkg/api/helper
|
|
||||||
- pkg/api/install
|
|
||||||
- pkg/api/service
|
|
||||||
- pkg/api/util
|
|
||||||
- pkg/api/v1
|
|
||||||
- pkg/api/v1/helper
|
|
||||||
- pkg/api/v1/node
|
|
||||||
- pkg/api/v1/pod
|
|
||||||
- pkg/api/v1/ref
|
|
||||||
- pkg/api/v1/service
|
|
||||||
- pkg/api/validation
|
|
||||||
- pkg/apis/apps
|
|
||||||
- pkg/apis/apps/install
|
|
||||||
- pkg/apis/apps/v1beta1
|
|
||||||
- pkg/apis/authentication
|
|
||||||
- pkg/apis/authentication/install
|
|
||||||
- pkg/apis/authentication/v1
|
|
||||||
- pkg/apis/authentication/v1beta1
|
|
||||||
- pkg/apis/authorization
|
|
||||||
- pkg/apis/authorization/install
|
|
||||||
- pkg/apis/authorization/v1
|
|
||||||
- pkg/apis/authorization/v1beta1
|
|
||||||
- pkg/apis/autoscaling
|
|
||||||
- pkg/apis/autoscaling/install
|
|
||||||
- pkg/apis/autoscaling/v1
|
|
||||||
- pkg/apis/autoscaling/v2alpha1
|
|
||||||
- pkg/apis/batch
|
|
||||||
- pkg/apis/batch/install
|
|
||||||
- pkg/apis/batch/v1
|
|
||||||
- pkg/apis/batch/v2alpha1
|
|
||||||
- pkg/apis/certificates
|
|
||||||
- pkg/apis/certificates/install
|
|
||||||
- pkg/apis/certificates/v1beta1
|
|
||||||
- pkg/apis/componentconfig
|
|
||||||
- pkg/apis/extensions
|
|
||||||
- pkg/apis/extensions/install
|
|
||||||
- pkg/apis/extensions/v1beta1
|
|
||||||
- pkg/apis/policy
|
|
||||||
- pkg/apis/policy/install
|
|
||||||
- pkg/apis/policy/v1beta1
|
|
||||||
- pkg/apis/rbac
|
|
||||||
- pkg/apis/rbac/install
|
|
||||||
- pkg/apis/rbac/v1alpha1
|
|
||||||
- pkg/apis/rbac/v1beta1
|
|
||||||
- pkg/apis/settings
|
|
||||||
- pkg/apis/settings/install
|
|
||||||
- pkg/apis/settings/v1alpha1
|
|
||||||
- pkg/apis/storage
|
|
||||||
- pkg/apis/storage/install
|
|
||||||
- pkg/apis/storage/v1
|
|
||||||
- pkg/apis/storage/v1beta1
|
|
||||||
- pkg/capabilities
|
|
||||||
- pkg/client/clientset_generated/clientset
|
|
||||||
- pkg/client/clientset_generated/clientset/scheme
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/apps/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/authentication/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/authentication/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/authorization/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/authorization/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/autoscaling/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/autoscaling/v2alpha1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/batch/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/batch/v2alpha1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/certificates/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/core/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/extensions/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/policy/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/rbac/v1alpha1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/rbac/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/settings/v1alpha1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/storage/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/storage/v1beta1
|
|
||||||
- pkg/client/informers/informers_generated/externalversions
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/apps
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/apps/v1beta1
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/autoscaling
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/autoscaling/v1
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/autoscaling/v2alpha1
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/batch
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/batch/v1
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/batch/v2alpha1
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/certificates
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/certificates/v1beta1
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/core
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/core/v1
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/extensions
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/extensions/v1beta1
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/internalinterfaces
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/policy
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/policy/v1beta1
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/rbac
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/rbac/v1alpha1
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/rbac/v1beta1
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/settings
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/settings/v1alpha1
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/storage
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/storage/v1
|
|
||||||
- pkg/client/informers/informers_generated/externalversions/storage/v1beta1
|
|
||||||
- pkg/client/leaderelection
|
|
||||||
- pkg/client/leaderelection/resourcelock
|
|
||||||
- pkg/client/listers/apps/v1beta1
|
|
||||||
- pkg/client/listers/autoscaling/v1
|
|
||||||
- pkg/client/listers/autoscaling/v2alpha1
|
|
||||||
- pkg/client/listers/batch/v1
|
|
||||||
- pkg/client/listers/batch/v2alpha1
|
|
||||||
- pkg/client/listers/certificates/v1beta1
|
|
||||||
- pkg/client/listers/core/v1
|
|
||||||
- pkg/client/listers/extensions/v1beta1
|
|
||||||
- pkg/client/listers/policy/v1beta1
|
|
||||||
- pkg/client/listers/rbac/v1alpha1
|
|
||||||
- pkg/client/listers/rbac/v1beta1
|
|
||||||
- pkg/client/listers/settings/v1alpha1
|
|
||||||
- pkg/client/listers/storage/v1
|
|
||||||
- pkg/client/listers/storage/v1beta1
|
|
||||||
- pkg/client/metrics
|
|
||||||
- pkg/client/metrics/prometheus
|
|
||||||
- pkg/client/retry
|
|
||||||
- pkg/cloudprovider
|
|
||||||
- pkg/cloudprovider/providers
|
|
||||||
- pkg/cloudprovider/providers/aws
|
|
||||||
- pkg/cloudprovider/providers/azure
|
|
||||||
- pkg/cloudprovider/providers/cloudstack
|
|
||||||
- pkg/cloudprovider/providers/gce
|
|
||||||
- pkg/cloudprovider/providers/mesos
|
|
||||||
- pkg/cloudprovider/providers/openstack
|
|
||||||
- pkg/cloudprovider/providers/ovirt
|
|
||||||
- pkg/cloudprovider/providers/photon
|
|
||||||
- pkg/cloudprovider/providers/rackspace
|
|
||||||
- pkg/cloudprovider/providers/vsphere
|
|
||||||
- pkg/controller
|
|
||||||
- pkg/controller/cloud
|
|
||||||
- pkg/controller/route
|
|
||||||
- pkg/controller/service
|
|
||||||
- pkg/credentialprovider
|
|
||||||
- pkg/credentialprovider/aws
|
|
||||||
- pkg/features
|
|
||||||
- pkg/master/ports
|
|
||||||
- pkg/security/apparmor
|
|
||||||
- pkg/serviceaccount
|
|
||||||
- pkg/util
|
|
||||||
- pkg/util/configz
|
|
||||||
- pkg/util/exec
|
|
||||||
- pkg/util/hash
|
|
||||||
- pkg/util/io
|
|
||||||
- pkg/util/metrics
|
|
||||||
- pkg/util/mount
|
|
||||||
- pkg/util/net/sets
|
|
||||||
- pkg/util/node
|
|
||||||
- pkg/util/parsers
|
|
||||||
- pkg/version
|
|
||||||
- pkg/version/prometheus
|
|
||||||
- pkg/version/verflag
|
|
||||||
- pkg/volume
|
|
||||||
- pkg/volume/util
|
|
||||||
testImports: []
|
|
61
glide.yaml
61
glide.yaml
@ -1,61 +0,0 @@
|
|||||||
package: git.openstack.org/openstack/k8s-cloud-provider
|
|
||||||
import:
|
|
||||||
- package: github.com/golang/glog
|
|
||||||
- package: github.com/gophercloud/gophercloud
|
|
||||||
subpackages:
|
|
||||||
- openstack
|
|
||||||
- openstack/blockstorage/v1/apiversions
|
|
||||||
- openstack/blockstorage/v1/volumes
|
|
||||||
- openstack/blockstorage/v2/volumes
|
|
||||||
- openstack/compute/v2/extensions/volumeattach
|
|
||||||
- openstack/compute/v2/flavors
|
|
||||||
- openstack/compute/v2/servers
|
|
||||||
- openstack/identity/v3/extensions/trusts
|
|
||||||
- openstack/identity/v3/tokens
|
|
||||||
- openstack/networking/v2/extensions
|
|
||||||
- openstack/networking/v2/extensions/layer3/floatingips
|
|
||||||
- openstack/networking/v2/extensions/layer3/routers
|
|
||||||
- openstack/networking/v2/extensions/lbaas/members
|
|
||||||
- openstack/networking/v2/extensions/lbaas/monitors
|
|
||||||
- openstack/networking/v2/extensions/lbaas/pools
|
|
||||||
- openstack/networking/v2/extensions/lbaas/vips
|
|
||||||
- openstack/networking/v2/extensions/lbaas_v2/listeners
|
|
||||||
- openstack/networking/v2/extensions/lbaas_v2/loadbalancers
|
|
||||||
- openstack/networking/v2/extensions/lbaas_v2/monitors
|
|
||||||
- openstack/networking/v2/extensions/lbaas_v2/pools
|
|
||||||
- openstack/networking/v2/extensions/security/groups
|
|
||||||
- openstack/networking/v2/extensions/security/rules
|
|
||||||
- openstack/networking/v2/ports
|
|
||||||
- pagination
|
|
||||||
- package: github.com/mitchellh/mapstructure
|
|
||||||
- package: github.com/spf13/pflag
|
|
||||||
- package: gopkg.in/gcfg.v1
|
|
||||||
- package: k8s.io/apimachinery
|
|
||||||
subpackages:
|
|
||||||
- pkg/api/resource
|
|
||||||
- pkg/types
|
|
||||||
- pkg/util/net
|
|
||||||
- package: k8s.io/apiserver
|
|
||||||
subpackages:
|
|
||||||
- pkg/server/healthz
|
|
||||||
- pkg/util/flag
|
|
||||||
- pkg/util/logs
|
|
||||||
- package: k8s.io/client-go
|
|
||||||
subpackages:
|
|
||||||
- util/cert
|
|
||||||
- package: k8s.io/kubernetes
|
|
||||||
subpackages:
|
|
||||||
- cmd/cloud-controller-manager/app
|
|
||||||
- cmd/cloud-controller-manager/app/options
|
|
||||||
- pkg/api/v1
|
|
||||||
- pkg/api/v1/service
|
|
||||||
- pkg/client/metrics/prometheus
|
|
||||||
- pkg/cloudprovider
|
|
||||||
- pkg/cloudprovider/providers
|
|
||||||
- pkg/util/exec
|
|
||||||
- pkg/util/mount
|
|
||||||
- pkg/version/prometheus
|
|
||||||
- pkg/version/verflag
|
|
||||||
- pkg/volume
|
|
||||||
ignore:
|
|
||||||
- git.openstack.org/openstack/k8s-cloud-provider/openstack
|
|
64
main.go
64
main.go
@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2016 The Kubernetes Authors.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// The external controller manager is responsible for running controller loops that
|
|
||||||
// are cloud provider dependent. It uses the API to listen to new events on resources.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"k8s.io/apiserver/pkg/server/healthz"
|
|
||||||
"k8s.io/apiserver/pkg/util/flag"
|
|
||||||
"k8s.io/apiserver/pkg/util/logs"
|
|
||||||
"k8s.io/kubernetes/cmd/cloud-controller-manager/app"
|
|
||||||
"k8s.io/kubernetes/cmd/cloud-controller-manager/app/options"
|
|
||||||
_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
|
|
||||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
|
||||||
_ "k8s.io/kubernetes/pkg/cloudprovider/providers"
|
|
||||||
_ "k8s.io/kubernetes/pkg/version/prometheus" // for version metric registration
|
|
||||||
"k8s.io/kubernetes/pkg/version/verflag"
|
|
||||||
|
|
||||||
"github.com/golang/glog"
|
|
||||||
"github.com/spf13/pflag"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
healthz.DefaultHealthz()
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
s := options.NewCloudControllerManagerServer()
|
|
||||||
s.AddFlags(pflag.CommandLine)
|
|
||||||
|
|
||||||
flag.InitFlags()
|
|
||||||
logs.InitLogs()
|
|
||||||
defer logs.FlushLogs()
|
|
||||||
|
|
||||||
verflag.PrintAndExitIfRequested()
|
|
||||||
|
|
||||||
cloud, err := cloudprovider.InitCloudProvider("openstack", s.CloudConfigFile)
|
|
||||||
if err != nil {
|
|
||||||
glog.Fatalf("Cloud provider could not be initialized: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := app.Run(s, cloud); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,96 +0,0 @@
|
|||||||
package(default_visibility = ["//visibility:public"])
|
|
||||||
|
|
||||||
licenses(["notice"])
|
|
||||||
|
|
||||||
load(
|
|
||||||
"@io_bazel_rules_go//go:def.bzl",
|
|
||||||
"go_library",
|
|
||||||
"go_test",
|
|
||||||
)
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = [
|
|
||||||
"metadata.go",
|
|
||||||
"openstack.go",
|
|
||||||
"openstack_instances.go",
|
|
||||||
"openstack_loadbalancer.go",
|
|
||||||
"openstack_routes.go",
|
|
||||||
"openstack_volumes.go",
|
|
||||||
],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
deps = [
|
|
||||||
"//pkg/api/v1:go_default_library",
|
|
||||||
"//pkg/api/v1/service:go_default_library",
|
|
||||||
"//pkg/cloudprovider:go_default_library",
|
|
||||||
"//pkg/util/exec:go_default_library",
|
|
||||||
"//pkg/util/mount:go_default_library",
|
|
||||||
"//pkg/volume:go_default_library",
|
|
||||||
"//vendor:github.com/golang/glog",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/blockstorage/v1/apiversions",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/compute/v2/flavors",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/compute/v2/servers",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/identity/v3/tokens",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/members",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/monitors",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/pools",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/vips",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/loadbalancers",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/monitors",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas_v2/pools",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/networking/v2/ports",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/pagination",
|
|
||||||
"//vendor:github.com/mitchellh/mapstructure",
|
|
||||||
"//vendor:gopkg.in/gcfg.v1",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/api/resource",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/types",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/net",
|
|
||||||
"//vendor:k8s.io/client-go/util/cert",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
go_test(
|
|
||||||
name = "go_default_test",
|
|
||||||
srcs = [
|
|
||||||
"metadata_test.go",
|
|
||||||
"openstack_routes_test.go",
|
|
||||||
"openstack_test.go",
|
|
||||||
],
|
|
||||||
library = ":go_default_library",
|
|
||||||
tags = ["automanaged"],
|
|
||||||
deps = [
|
|
||||||
"//pkg/api/v1:go_default_library",
|
|
||||||
"//pkg/cloudprovider:go_default_library",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/blockstorage/v1/apiversions",
|
|
||||||
"//vendor:github.com/gophercloud/gophercloud/openstack/compute/v2/servers",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/types",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/rand",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [":package-srcs"],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
)
|
|
@ -1,6 +0,0 @@
|
|||||||
# Maintainers
|
|
||||||
|
|
||||||
* [Angus Lees](https://github.com/anguslees)
|
|
||||||
|
|
||||||
|
|
||||||
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/pkg/cloudprovider/providers/openstack/MAINTAINERS.md?pixel)]()
|
|
@ -1,2 +0,0 @@
|
|||||||
approvers:
|
|
||||||
- anguslees
|
|
254
openstack/glide.lock
generated
254
openstack/glide.lock
generated
@ -1,254 +0,0 @@
|
|||||||
hash: dc2cb42b652f4df3a539065b9c5709386e88277587c0ea2ba0efc37bafe32e37
|
|
||||||
updated: 2017-03-24T08:33:36.565832163-04:00
|
|
||||||
imports:
|
|
||||||
- name: github.com/davecgh/go-spew
|
|
||||||
version: 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d
|
|
||||||
subpackages:
|
|
||||||
- spew
|
|
||||||
- name: github.com/docker/distribution
|
|
||||||
version: cd27f179f2c10c5d300e6d09025b538c475b0d51
|
|
||||||
subpackages:
|
|
||||||
- digest
|
|
||||||
- reference
|
|
||||||
- name: github.com/emicklei/go-restful
|
|
||||||
version: 09691a3b6378b740595c1002f40c34dd5f218a22
|
|
||||||
subpackages:
|
|
||||||
- log
|
|
||||||
- swagger
|
|
||||||
- name: github.com/ghodss/yaml
|
|
||||||
version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee
|
|
||||||
- name: github.com/go-openapi/jsonpointer
|
|
||||||
version: 46af16f9f7b149af66e5d1bd010e3574dc06de98
|
|
||||||
- name: github.com/go-openapi/jsonreference
|
|
||||||
version: 13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272
|
|
||||||
- name: github.com/go-openapi/spec
|
|
||||||
version: 6aced65f8501fe1217321abf0749d354824ba2ff
|
|
||||||
- name: github.com/go-openapi/swag
|
|
||||||
version: 1d0bd113de87027671077d3c71eb3ac5d7dbba72
|
|
||||||
- name: github.com/gogo/protobuf
|
|
||||||
version: e18d7aa8f8c624c915db340349aad4c49b10d173
|
|
||||||
subpackages:
|
|
||||||
- proto
|
|
||||||
- sortkeys
|
|
||||||
- name: github.com/golang/glog
|
|
||||||
version: 44145f04b68cf362d9c4df2182967c2275eaefed
|
|
||||||
- name: github.com/google/gofuzz
|
|
||||||
version: 44d81051d367757e1c7c6a5a86423ece9afcf63c
|
|
||||||
- name: github.com/gophercloud/gophercloud
|
|
||||||
version: 12f19e5e04d617182cffa5c11f189ef0013b9791
|
|
||||||
subpackages:
|
|
||||||
- openstack
|
|
||||||
- openstack/blockstorage/v1/volumes
|
|
||||||
- openstack/common/extensions
|
|
||||||
- openstack/compute/v2/extensions/volumeattach
|
|
||||||
- openstack/compute/v2/flavors
|
|
||||||
- openstack/compute/v2/images
|
|
||||||
- openstack/compute/v2/servers
|
|
||||||
- openstack/identity/v2/tenants
|
|
||||||
- openstack/identity/v2/tokens
|
|
||||||
- openstack/identity/v3/extensions/trusts
|
|
||||||
- openstack/identity/v3/tokens
|
|
||||||
- openstack/networking/v2/extensions
|
|
||||||
- openstack/networking/v2/extensions/layer3/floatingips
|
|
||||||
- openstack/networking/v2/extensions/layer3/routers
|
|
||||||
- openstack/networking/v2/extensions/lbaas/members
|
|
||||||
- openstack/networking/v2/extensions/lbaas/monitors
|
|
||||||
- openstack/networking/v2/extensions/lbaas/pools
|
|
||||||
- openstack/networking/v2/extensions/lbaas/vips
|
|
||||||
- openstack/networking/v2/extensions/lbaas_v2/listeners
|
|
||||||
- openstack/networking/v2/extensions/lbaas_v2/loadbalancers
|
|
||||||
- openstack/networking/v2/extensions/lbaas_v2/monitors
|
|
||||||
- openstack/networking/v2/extensions/lbaas_v2/pools
|
|
||||||
- openstack/networking/v2/extensions/security/groups
|
|
||||||
- openstack/networking/v2/extensions/security/rules
|
|
||||||
- openstack/networking/v2/ports
|
|
||||||
- openstack/utils
|
|
||||||
- pagination
|
|
||||||
- name: github.com/juju/ratelimit
|
|
||||||
version: 77ed1c8a01217656d2080ad51981f6e99adaa177
|
|
||||||
- name: github.com/mailru/easyjson
|
|
||||||
version: d5b7844b561a7bc640052f1b935f7b800330d7e0
|
|
||||||
subpackages:
|
|
||||||
- buffer
|
|
||||||
- jlexer
|
|
||||||
- jwriter
|
|
||||||
- name: github.com/mitchellh/mapstructure
|
|
||||||
version: 740c764bc6149d3f1806231418adb9f52c11bcbf
|
|
||||||
- name: github.com/PuerkitoBio/purell
|
|
||||||
version: 8a290539e2e8629dbc4e6bad948158f790ec31f4
|
|
||||||
- name: github.com/PuerkitoBio/urlesc
|
|
||||||
version: 5bd2802263f21d8788851d5305584c82a5c75d7e
|
|
||||||
- name: github.com/spf13/pflag
|
|
||||||
version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7
|
|
||||||
- name: github.com/ugorji/go
|
|
||||||
version: ded73eae5db7e7a0ef6f55aace87a2873c5d2b74
|
|
||||||
subpackages:
|
|
||||||
- codec
|
|
||||||
- name: golang.org/x/net
|
|
||||||
version: e90d6d0afc4c315a0d87a568ae68577cc15149a0
|
|
||||||
subpackages:
|
|
||||||
- http2
|
|
||||||
- http2/hpack
|
|
||||||
- idna
|
|
||||||
- lex/httplex
|
|
||||||
- name: golang.org/x/text
|
|
||||||
version: 2910a502d2bf9e43193af9d68ca516529614eed3
|
|
||||||
subpackages:
|
|
||||||
- cases
|
|
||||||
- internal/tag
|
|
||||||
- language
|
|
||||||
- runes
|
|
||||||
- secure/bidirule
|
|
||||||
- secure/precis
|
|
||||||
- transform
|
|
||||||
- unicode/bidi
|
|
||||||
- unicode/norm
|
|
||||||
- width
|
|
||||||
- name: gopkg.in/gcfg.v1
|
|
||||||
version: 083575c3955c85df16fe9590cceab64d03f5eb6e
|
|
||||||
subpackages:
|
|
||||||
- scanner
|
|
||||||
- token
|
|
||||||
- types
|
|
||||||
- name: gopkg.in/inf.v0
|
|
||||||
version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
|
|
||||||
- name: gopkg.in/yaml.v2
|
|
||||||
version: 53feefa2559fb8dfa8d81baad31be332c97d6c77
|
|
||||||
- name: k8s.io/apimachinery
|
|
||||||
version: c1c4a7fe832857c75cc1d79c8e40d71d5da15fc6
|
|
||||||
subpackages:
|
|
||||||
- pkg/api/errors
|
|
||||||
- pkg/api/meta
|
|
||||||
- pkg/api/resource
|
|
||||||
- pkg/apimachinery
|
|
||||||
- pkg/apimachinery/announced
|
|
||||||
- pkg/apimachinery/registered
|
|
||||||
- pkg/apis/meta/v1
|
|
||||||
- pkg/apis/meta/v1/unstructured
|
|
||||||
- pkg/conversion
|
|
||||||
- pkg/conversion/queryparams
|
|
||||||
- pkg/fields
|
|
||||||
- pkg/labels
|
|
||||||
- pkg/openapi
|
|
||||||
- pkg/runtime
|
|
||||||
- pkg/runtime/schema
|
|
||||||
- pkg/runtime/serializer
|
|
||||||
- pkg/runtime/serializer/json
|
|
||||||
- pkg/runtime/serializer/protobuf
|
|
||||||
- pkg/runtime/serializer/recognizer
|
|
||||||
- pkg/runtime/serializer/streaming
|
|
||||||
- pkg/runtime/serializer/versioning
|
|
||||||
- pkg/selection
|
|
||||||
- pkg/types
|
|
||||||
- pkg/util/errors
|
|
||||||
- pkg/util/framer
|
|
||||||
- pkg/util/intstr
|
|
||||||
- pkg/util/json
|
|
||||||
- pkg/util/net
|
|
||||||
- pkg/util/rand
|
|
||||||
- pkg/util/runtime
|
|
||||||
- pkg/util/sets
|
|
||||||
- pkg/util/validation
|
|
||||||
- pkg/util/validation/field
|
|
||||||
- pkg/util/wait
|
|
||||||
- pkg/util/yaml
|
|
||||||
- pkg/version
|
|
||||||
- pkg/watch
|
|
||||||
- third_party/forked/golang/reflect
|
|
||||||
- name: k8s.io/client-go
|
|
||||||
version: 76153773eaa3a268131d3d993290a194a1370585
|
|
||||||
subpackages:
|
|
||||||
- discovery
|
|
||||||
- pkg/api
|
|
||||||
- pkg/api/v1
|
|
||||||
- pkg/apis/extensions
|
|
||||||
- pkg/util
|
|
||||||
- pkg/util/parsers
|
|
||||||
- pkg/version
|
|
||||||
- rest
|
|
||||||
- rest/watch
|
|
||||||
- tools/clientcmd/api
|
|
||||||
- tools/metrics
|
|
||||||
- transport
|
|
||||||
- util/cert
|
|
||||||
- util/clock
|
|
||||||
- util/flowcontrol
|
|
||||||
- util/integer
|
|
||||||
- name: k8s.io/kubernetes
|
|
||||||
version: a845e3e936e91cd14c4c5b462631233716d5839b
|
|
||||||
subpackages:
|
|
||||||
- pkg/api
|
|
||||||
- pkg/api/install
|
|
||||||
- pkg/api/v1
|
|
||||||
- pkg/api/v1/service
|
|
||||||
- pkg/apis/apps
|
|
||||||
- pkg/apis/apps/install
|
|
||||||
- pkg/apis/apps/v1beta1
|
|
||||||
- pkg/apis/authentication
|
|
||||||
- pkg/apis/authentication/install
|
|
||||||
- pkg/apis/authentication/v1
|
|
||||||
- pkg/apis/authentication/v1beta1
|
|
||||||
- pkg/apis/authorization
|
|
||||||
- pkg/apis/authorization/install
|
|
||||||
- pkg/apis/authorization/v1
|
|
||||||
- pkg/apis/authorization/v1beta1
|
|
||||||
- pkg/apis/autoscaling
|
|
||||||
- pkg/apis/autoscaling/install
|
|
||||||
- pkg/apis/autoscaling/v1
|
|
||||||
- pkg/apis/autoscaling/v2alpha1
|
|
||||||
- pkg/apis/batch
|
|
||||||
- pkg/apis/batch/install
|
|
||||||
- pkg/apis/batch/v1
|
|
||||||
- pkg/apis/batch/v2alpha1
|
|
||||||
- pkg/apis/certificates
|
|
||||||
- pkg/apis/certificates/install
|
|
||||||
- pkg/apis/certificates/v1beta1
|
|
||||||
- pkg/apis/extensions
|
|
||||||
- pkg/apis/extensions/install
|
|
||||||
- pkg/apis/extensions/v1beta1
|
|
||||||
- pkg/apis/policy
|
|
||||||
- pkg/apis/policy/install
|
|
||||||
- pkg/apis/policy/v1beta1
|
|
||||||
- pkg/apis/rbac
|
|
||||||
- pkg/apis/rbac/install
|
|
||||||
- pkg/apis/rbac/v1alpha1
|
|
||||||
- pkg/apis/rbac/v1beta1
|
|
||||||
- pkg/apis/settings
|
|
||||||
- pkg/apis/settings/install
|
|
||||||
- pkg/apis/settings/v1alpha1
|
|
||||||
- pkg/apis/storage
|
|
||||||
- pkg/apis/storage/install
|
|
||||||
- pkg/apis/storage/v1
|
|
||||||
- pkg/apis/storage/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset
|
|
||||||
- pkg/client/clientset_generated/clientset/scheme
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/apps/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/authentication/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/authentication/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/authorization/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/authorization/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/autoscaling/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/autoscaling/v2alpha1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/batch/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/batch/v2alpha1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/certificates/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/core/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/extensions/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/policy/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/rbac/v1alpha1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/rbac/v1beta1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/settings/v1alpha1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/storage/v1
|
|
||||||
- pkg/client/clientset_generated/clientset/typed/storage/v1beta1
|
|
||||||
- pkg/cloudprovider
|
|
||||||
- pkg/util
|
|
||||||
- pkg/util/chmod
|
|
||||||
- pkg/util/chown
|
|
||||||
- pkg/util/exec
|
|
||||||
- pkg/util/io
|
|
||||||
- pkg/util/mount
|
|
||||||
- pkg/util/net/sets
|
|
||||||
- pkg/util/parsers
|
|
||||||
- pkg/volume
|
|
||||||
- pkg/volume/util
|
|
||||||
testImports: []
|
|
@ -1,156 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2016 The Kubernetes Authors.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package openstack
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/golang/glog"
|
|
||||||
"k8s.io/kubernetes/pkg/util/exec"
|
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
|
||||||
)
|
|
||||||
|
|
||||||
// metadataUrl is URL to OpenStack metadata server. It's hardcoded IPv4
|
|
||||||
// link-local address as documented in "OpenStack Cloud Administrator Guide",
|
|
||||||
// chapter Compute - Networking with nova-network.
|
|
||||||
// http://docs.openstack.org/admin-guide-cloud/compute-networking-nova.html#metadata-service
|
|
||||||
const metadataUrl = "http://169.254.169.254/openstack/2012-08-10/meta_data.json"
|
|
||||||
|
|
||||||
// Config drive is defined as an iso9660 or vfat (deprecated) drive
|
|
||||||
// with the "config-2" label.
|
|
||||||
// http://docs.openstack.org/user-guide/cli-config-drive.html
|
|
||||||
const configDriveLabel = "config-2"
|
|
||||||
const configDrivePath = "openstack/2012-08-10/meta_data.json"
|
|
||||||
|
|
||||||
var ErrBadMetadata = errors.New("Invalid OpenStack metadata, got empty uuid")
|
|
||||||
|
|
||||||
// Assumes the "2012-08-10" meta_data.json format.
|
|
||||||
// See http://docs.openstack.org/user-guide/cli_config_drive.html
|
|
||||||
type Metadata struct {
|
|
||||||
Uuid string `json:"uuid"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
AvailabilityZone string `json:"availability_zone"`
|
|
||||||
// .. and other fields we don't care about. Expand as necessary.
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseMetadataUUID reads JSON from OpenStack metadata server and parses
|
|
||||||
// instance ID out of it.
|
|
||||||
func parseMetadata(r io.Reader) (*Metadata, error) {
|
|
||||||
var metadata Metadata
|
|
||||||
json := json.NewDecoder(r)
|
|
||||||
if err := json.Decode(&metadata); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if metadata.Uuid == "" {
|
|
||||||
return nil, ErrBadMetadata
|
|
||||||
}
|
|
||||||
|
|
||||||
return &metadata, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getMetadataFromConfigDrive() (*Metadata, error) {
|
|
||||||
// Try to read instance UUID from config drive.
|
|
||||||
dev := "/dev/disk/by-label/" + configDriveLabel
|
|
||||||
if _, err := os.Stat(dev); os.IsNotExist(err) {
|
|
||||||
out, err := exec.New().Command(
|
|
||||||
"blkid", "-l",
|
|
||||||
"-t", "LABEL="+configDriveLabel,
|
|
||||||
"-o", "device",
|
|
||||||
).CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
glog.V(2).Infof("Unable to run blkid: %v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
dev = strings.TrimSpace(string(out))
|
|
||||||
}
|
|
||||||
|
|
||||||
mntdir, err := ioutil.TempDir("", "configdrive")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer os.Remove(mntdir)
|
|
||||||
|
|
||||||
glog.V(4).Infof("Attempting to mount configdrive %s on %s", dev, mntdir)
|
|
||||||
|
|
||||||
mounter := mount.New("" /* default mount path */)
|
|
||||||
err = mounter.Mount(dev, mntdir, "iso9660", []string{"ro"})
|
|
||||||
if err != nil {
|
|
||||||
err = mounter.Mount(dev, mntdir, "vfat", []string{"ro"})
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Error mounting configdrive %s: %v", dev, err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer mounter.Unmount(mntdir)
|
|
||||||
|
|
||||||
glog.V(4).Infof("Configdrive mounted on %s", mntdir)
|
|
||||||
|
|
||||||
f, err := os.Open(
|
|
||||||
filepath.Join(mntdir, configDrivePath))
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Error reading %s on config drive: %v", configDrivePath, err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
return parseMetadata(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getMetadataFromMetadataService() (*Metadata, error) {
|
|
||||||
// Try to get JSON from metdata server.
|
|
||||||
glog.V(4).Infof("Attempting to fetch metadata from %s", metadataUrl)
|
|
||||||
resp, err := http.Get(metadataUrl)
|
|
||||||
if err != nil {
|
|
||||||
glog.V(3).Infof("Cannot read %s: %v", metadataUrl, err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
err = fmt.Errorf("Unexpected status code when reading metadata from %s: %s", metadataUrl, resp.Status)
|
|
||||||
glog.V(3).Infof("%v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return parseMetadata(resp.Body)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Metadata is fixed for the current host, so cache the value process-wide
|
|
||||||
var metadataCache *Metadata
|
|
||||||
|
|
||||||
func getMetadata() (*Metadata, error) {
|
|
||||||
if metadataCache == nil {
|
|
||||||
md, err := getMetadataFromConfigDrive()
|
|
||||||
if err != nil {
|
|
||||||
md, err = getMetadataFromMetadataService()
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
metadataCache = md
|
|
||||||
}
|
|
||||||
return metadataCache, nil
|
|
||||||
}
|
|
@ -1,86 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2016 The Kubernetes Authors.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package openstack
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var FakeMetadata = Metadata{
|
|
||||||
Uuid: "83679162-1378-4288-a2d4-70e13ec132aa",
|
|
||||||
Name: "test",
|
|
||||||
AvailabilityZone: "nova",
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetMetadataFixture(value *Metadata) {
|
|
||||||
metadataCache = value
|
|
||||||
}
|
|
||||||
|
|
||||||
func ClearMetadata() {
|
|
||||||
metadataCache = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseMetadata(t *testing.T) {
|
|
||||||
_, err := parseMetadata(strings.NewReader("bogus"))
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("Should fail when bad data is provided: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
data := strings.NewReader(`
|
|
||||||
{
|
|
||||||
"availability_zone": "nova",
|
|
||||||
"files": [
|
|
||||||
{
|
|
||||||
"content_path": "/content/0000",
|
|
||||||
"path": "/etc/network/interfaces"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"content_path": "/content/0001",
|
|
||||||
"path": "known_hosts"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"hostname": "test.novalocal",
|
|
||||||
"launch_index": 0,
|
|
||||||
"name": "test",
|
|
||||||
"meta": {
|
|
||||||
"role": "webservers",
|
|
||||||
"essential": "false"
|
|
||||||
},
|
|
||||||
"public_keys": {
|
|
||||||
"mykey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDBqUfVvCSez0/Wfpd8dLLgZXV9GtXQ7hnMN+Z0OWQUyebVEHey1CXuin0uY1cAJMhUq8j98SiW+cU0sU4J3x5l2+xi1bodDm1BtFWVeLIOQINpfV1n8fKjHB+ynPpe1F6tMDvrFGUlJs44t30BrujMXBe8Rq44cCk6wqyjATA3rQ== Generated by Nova\n"
|
|
||||||
},
|
|
||||||
"uuid": "83679162-1378-4288-a2d4-70e13ec132aa"
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
md, err := parseMetadata(data)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Should succeed when provided with valid data: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if md.Name != "test" {
|
|
||||||
t.Errorf("incorrect name: %s", md.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if md.Uuid != "83679162-1378-4288-a2d4-70e13ec132aa" {
|
|
||||||
t.Errorf("incorrect uuid: %s", md.Uuid)
|
|
||||||
}
|
|
||||||
|
|
||||||
if md.AvailabilityZone != "nova" {
|
|
||||||
t.Errorf("incorrect az: %s", md.AvailabilityZone)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,650 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2014 The Kubernetes Authors.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package openstack
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"regexp"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gophercloud/gophercloud"
|
|
||||||
"github.com/gophercloud/gophercloud/openstack"
|
|
||||||
apiversions_v1 "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/apiversions"
|
|
||||||
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
|
|
||||||
"github.com/gophercloud/gophercloud/openstack/identity/v3/extensions/trusts"
|
|
||||||
tokens3 "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
|
|
||||||
"github.com/gophercloud/gophercloud/pagination"
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
"gopkg.in/gcfg.v1"
|
|
||||||
|
|
||||||
"github.com/golang/glog"
|
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
netutil "k8s.io/apimachinery/pkg/util/net"
|
|
||||||
certutil "k8s.io/client-go/util/cert"
|
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
|
||||||
v1helper "k8s.io/kubernetes/pkg/api/v1/helper"
|
|
||||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
|
||||||
)
|
|
||||||
|
|
||||||
const ProviderName = "openstack"
|
|
||||||
|
|
||||||
var ErrNotFound = errors.New("Failed to find object")
|
|
||||||
var ErrMultipleResults = errors.New("Multiple results where only one expected")
|
|
||||||
var ErrNoAddressFound = errors.New("No address found for host")
|
|
||||||
|
|
||||||
const (
|
|
||||||
MiB = 1024 * 1024
|
|
||||||
GB = 1000 * 1000 * 1000
|
|
||||||
)
|
|
||||||
|
|
||||||
// encoding.TextUnmarshaler interface for time.Duration
|
|
||||||
type MyDuration struct {
|
|
||||||
time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *MyDuration) UnmarshalText(text []byte) error {
|
|
||||||
res, err := time.ParseDuration(string(text))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
d.Duration = res
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type LoadBalancer struct {
|
|
||||||
network *gophercloud.ServiceClient
|
|
||||||
compute *gophercloud.ServiceClient
|
|
||||||
opts LoadBalancerOpts
|
|
||||||
}
|
|
||||||
|
|
||||||
type LoadBalancerOpts struct {
|
|
||||||
LBVersion string `gcfg:"lb-version"` // overrides autodetection. v1 or v2
|
|
||||||
SubnetId string `gcfg:"subnet-id"` // required
|
|
||||||
FloatingNetworkId string `gcfg:"floating-network-id"`
|
|
||||||
LBMethod string `gcfg:"lb-method"`
|
|
||||||
CreateMonitor bool `gcfg:"create-monitor"`
|
|
||||||
MonitorDelay MyDuration `gcfg:"monitor-delay"`
|
|
||||||
MonitorTimeout MyDuration `gcfg:"monitor-timeout"`
|
|
||||||
MonitorMaxRetries uint `gcfg:"monitor-max-retries"`
|
|
||||||
ManageSecurityGroups bool `gcfg:"manage-security-groups"`
|
|
||||||
NodeSecurityGroupID string `gcfg:"node-security-group"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type BlockStorageOpts struct {
|
|
||||||
BSVersion string `gcfg:"bs-version"` // overrides autodetection. v1 or v2. Defaults to auto
|
|
||||||
TrustDevicePath bool `gcfg:"trust-device-path"` // See Issue #33128
|
|
||||||
}
|
|
||||||
|
|
||||||
type RouterOpts struct {
|
|
||||||
RouterId string `gcfg:"router-id"` // required
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpenStack is an implementation of cloud provider Interface for OpenStack.
|
|
||||||
type OpenStack struct {
|
|
||||||
provider *gophercloud.ProviderClient
|
|
||||||
region string
|
|
||||||
lbOpts LoadBalancerOpts
|
|
||||||
bsOpts BlockStorageOpts
|
|
||||||
routeOpts RouterOpts
|
|
||||||
// InstanceID of the server where this OpenStack object is instantiated.
|
|
||||||
localInstanceID string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
Global struct {
|
|
||||||
AuthUrl string `gcfg:"auth-url"`
|
|
||||||
Username string
|
|
||||||
UserId string `gcfg:"user-id"`
|
|
||||||
Password string
|
|
||||||
TenantId string `gcfg:"tenant-id"`
|
|
||||||
TenantName string `gcfg:"tenant-name"`
|
|
||||||
TrustId string `gcfg:"trust-id"`
|
|
||||||
DomainId string `gcfg:"domain-id"`
|
|
||||||
DomainName string `gcfg:"domain-name"`
|
|
||||||
Region string
|
|
||||||
CAFile string `gcfg:"ca-file"`
|
|
||||||
}
|
|
||||||
LoadBalancer LoadBalancerOpts
|
|
||||||
BlockStorage BlockStorageOpts
|
|
||||||
Route RouterOpts
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cloudprovider.RegisterCloudProvider(ProviderName, func(config io.Reader) (cloudprovider.Interface, error) {
|
|
||||||
cfg, err := readConfig(config)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return newOpenStack(cfg)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cfg Config) toAuthOptions() gophercloud.AuthOptions {
|
|
||||||
return gophercloud.AuthOptions{
|
|
||||||
IdentityEndpoint: cfg.Global.AuthUrl,
|
|
||||||
Username: cfg.Global.Username,
|
|
||||||
UserID: cfg.Global.UserId,
|
|
||||||
Password: cfg.Global.Password,
|
|
||||||
TenantID: cfg.Global.TenantId,
|
|
||||||
TenantName: cfg.Global.TenantName,
|
|
||||||
DomainID: cfg.Global.DomainId,
|
|
||||||
DomainName: cfg.Global.DomainName,
|
|
||||||
|
|
||||||
// Persistent service, so we need to be able to renew tokens.
|
|
||||||
AllowReauth: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cfg Config) toAuth3Options() tokens3.AuthOptions {
|
|
||||||
return tokens3.AuthOptions{
|
|
||||||
IdentityEndpoint: cfg.Global.AuthUrl,
|
|
||||||
Username: cfg.Global.Username,
|
|
||||||
UserID: cfg.Global.UserId,
|
|
||||||
Password: cfg.Global.Password,
|
|
||||||
DomainID: cfg.Global.DomainId,
|
|
||||||
DomainName: cfg.Global.DomainName,
|
|
||||||
AllowReauth: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func readConfig(config io.Reader) (Config, error) {
|
|
||||||
if config == nil {
|
|
||||||
err := fmt.Errorf("no OpenStack cloud provider config file given")
|
|
||||||
return Config{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var cfg Config
|
|
||||||
|
|
||||||
// Set default values for config params
|
|
||||||
cfg.BlockStorage.BSVersion = "auto"
|
|
||||||
cfg.BlockStorage.TrustDevicePath = false
|
|
||||||
|
|
||||||
err := gcfg.ReadInto(&cfg, config)
|
|
||||||
return cfg, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tiny helper for conditional unwind logic
|
|
||||||
type Caller bool
|
|
||||||
|
|
||||||
func NewCaller() Caller { return Caller(true) }
|
|
||||||
func (c *Caller) Disarm() { *c = false }
|
|
||||||
|
|
||||||
func (c *Caller) Call(f func()) {
|
|
||||||
if *c {
|
|
||||||
f()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func readInstanceID() (string, error) {
|
|
||||||
// Try to find instance ID on the local filesystem (created by cloud-init)
|
|
||||||
const instanceIDFile = "/var/lib/cloud/data/instance-id"
|
|
||||||
idBytes, err := ioutil.ReadFile(instanceIDFile)
|
|
||||||
if err == nil {
|
|
||||||
instanceID := string(idBytes)
|
|
||||||
instanceID = strings.TrimSpace(instanceID)
|
|
||||||
glog.V(3).Infof("Got instance id from %s: %s", instanceIDFile, instanceID)
|
|
||||||
if instanceID != "" {
|
|
||||||
return instanceID, nil
|
|
||||||
}
|
|
||||||
// Fall through to metadata server lookup
|
|
||||||
}
|
|
||||||
|
|
||||||
md, err := getMetadata()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return md.Uuid, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func newOpenStack(cfg Config) (*OpenStack, error) {
|
|
||||||
provider, err := openstack.NewClient(cfg.Global.AuthUrl)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if cfg.Global.CAFile != "" {
|
|
||||||
roots, err := certutil.NewPool(cfg.Global.CAFile)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
config := &tls.Config{}
|
|
||||||
config.RootCAs = roots
|
|
||||||
provider.HTTPClient.Transport = netutil.SetOldTransportDefaults(&http.Transport{TLSClientConfig: config})
|
|
||||||
|
|
||||||
}
|
|
||||||
if cfg.Global.TrustId != "" {
|
|
||||||
opts := cfg.toAuth3Options()
|
|
||||||
authOptsExt := trusts.AuthOptsExt{
|
|
||||||
TrustID: cfg.Global.TrustId,
|
|
||||||
AuthOptionsBuilder: &opts,
|
|
||||||
}
|
|
||||||
err = openstack.AuthenticateV3(provider, authOptsExt, gophercloud.EndpointOpts{})
|
|
||||||
} else {
|
|
||||||
err = openstack.Authenticate(provider, cfg.toAuthOptions())
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
id, err := readInstanceID()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
os := OpenStack{
|
|
||||||
provider: provider,
|
|
||||||
region: cfg.Global.Region,
|
|
||||||
lbOpts: cfg.LoadBalancer,
|
|
||||||
bsOpts: cfg.BlockStorage,
|
|
||||||
routeOpts: cfg.Route,
|
|
||||||
localInstanceID: id,
|
|
||||||
}
|
|
||||||
|
|
||||||
return &os, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// mapNodeNameToServerName maps a k8s NodeName to an OpenStack Server Name
|
|
||||||
// This is a simple string cast.
|
|
||||||
func mapNodeNameToServerName(nodeName types.NodeName) string {
|
|
||||||
return string(nodeName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// mapServerToNodeName maps an OpenStack Server to a k8s NodeName
|
|
||||||
func mapServerToNodeName(server *servers.Server) types.NodeName {
|
|
||||||
// Node names are always lowercase, and (at least)
|
|
||||||
// routecontroller does case-sensitive string comparisons
|
|
||||||
// assuming this
|
|
||||||
return types.NodeName(strings.ToLower(server.Name))
|
|
||||||
}
|
|
||||||
|
|
||||||
func foreachServer(client *gophercloud.ServiceClient, opts servers.ListOptsBuilder, handler func(*servers.Server) (bool, error)) error {
|
|
||||||
pager := servers.List(client, opts)
|
|
||||||
|
|
||||||
err := pager.EachPage(func(page pagination.Page) (bool, error) {
|
|
||||||
s, err := servers.ExtractServers(page)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
for _, server := range s {
|
|
||||||
ok, err := handler(&server)
|
|
||||||
if !ok || err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
})
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func getServerByName(client *gophercloud.ServiceClient, name types.NodeName) (*servers.Server, error) {
|
|
||||||
opts := servers.ListOpts{
|
|
||||||
Name: fmt.Sprintf("^%s$", regexp.QuoteMeta(mapNodeNameToServerName(name))),
|
|
||||||
Status: "ACTIVE",
|
|
||||||
}
|
|
||||||
pager := servers.List(client, opts)
|
|
||||||
|
|
||||||
serverList := make([]servers.Server, 0, 1)
|
|
||||||
|
|
||||||
err := pager.EachPage(func(page pagination.Page) (bool, error) {
|
|
||||||
s, err := servers.ExtractServers(page)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
serverList = append(serverList, s...)
|
|
||||||
if len(serverList) > 1 {
|
|
||||||
return false, ErrMultipleResults
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(serverList) == 0 {
|
|
||||||
return nil, ErrNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
return &serverList[0], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func nodeAddresses(srv *servers.Server) ([]v1.NodeAddress, error) {
|
|
||||||
addrs := []v1.NodeAddress{}
|
|
||||||
|
|
||||||
type Address struct {
|
|
||||||
IpType string `mapstructure:"OS-EXT-IPS:type"`
|
|
||||||
Addr string
|
|
||||||
}
|
|
||||||
|
|
||||||
var addresses map[string][]Address
|
|
||||||
err := mapstructure.Decode(srv.Addresses, &addresses)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for network, addrList := range addresses {
|
|
||||||
for _, props := range addrList {
|
|
||||||
var addressType v1.NodeAddressType
|
|
||||||
if props.IpType == "floating" || network == "public" {
|
|
||||||
addressType = v1.NodeExternalIP
|
|
||||||
} else {
|
|
||||||
addressType = v1.NodeInternalIP
|
|
||||||
}
|
|
||||||
|
|
||||||
v1helper.AddToNodeAddresses(&addrs,
|
|
||||||
v1.NodeAddress{
|
|
||||||
Type: addressType,
|
|
||||||
Address: props.Addr,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AccessIPs are usually duplicates of "public" addresses.
|
|
||||||
if srv.AccessIPv4 != "" {
|
|
||||||
v1helper.AddToNodeAddresses(&addrs,
|
|
||||||
v1.NodeAddress{
|
|
||||||
Type: v1.NodeExternalIP,
|
|
||||||
Address: srv.AccessIPv4,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if srv.AccessIPv6 != "" {
|
|
||||||
v1helper.AddToNodeAddresses(&addrs,
|
|
||||||
v1.NodeAddress{
|
|
||||||
Type: v1.NodeExternalIP,
|
|
||||||
Address: srv.AccessIPv6,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return addrs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAddressesByName(client *gophercloud.ServiceClient, name types.NodeName) ([]v1.NodeAddress, error) {
|
|
||||||
srv, err := getServerByName(client, name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nodeAddresses(srv)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAddressByName(client *gophercloud.ServiceClient, name types.NodeName) (string, error) {
|
|
||||||
addrs, err := getAddressesByName(client, name)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
} else if len(addrs) == 0 {
|
|
||||||
return "", ErrNoAddressFound
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, addr := range addrs {
|
|
||||||
if addr.Type == v1.NodeInternalIP {
|
|
||||||
return addr.Address, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return addrs[0].Address, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (os *OpenStack) Clusters() (cloudprovider.Clusters, bool) {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProviderName returns the cloud provider ID.
|
|
||||||
func (os *OpenStack) ProviderName() string {
|
|
||||||
return ProviderName
|
|
||||||
}
|
|
||||||
|
|
||||||
// ScrubDNS filters DNS settings for pods.
|
|
||||||
func (os *OpenStack) ScrubDNS(nameServers, searches []string) ([]string, []string) {
|
|
||||||
return nameServers, searches
|
|
||||||
}
|
|
||||||
|
|
||||||
func (os *OpenStack) LoadBalancer() (cloudprovider.LoadBalancer, bool) {
|
|
||||||
glog.V(4).Info("openstack.LoadBalancer() called")
|
|
||||||
|
|
||||||
// TODO: Search for and support Rackspace loadbalancer API, and others.
|
|
||||||
network, err := openstack.NewNetworkV2(os.provider, gophercloud.EndpointOpts{
|
|
||||||
Region: os.region,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
glog.Warningf("Failed to find network endpoint: %v", err)
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
compute, err := openstack.NewComputeV2(os.provider, gophercloud.EndpointOpts{
|
|
||||||
Region: os.region,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
glog.Warningf("Failed to find compute endpoint: %v", err)
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
lbVersion := os.lbOpts.LBVersion
|
|
||||||
if lbVersion == "" {
|
|
||||||
// No version specified, try newest supported by server
|
|
||||||
netExts, err := networkExtensions(network)
|
|
||||||
if err != nil {
|
|
||||||
glog.Warningf("Failed to list neutron extensions: %v", err)
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
if netExts["lbaasv2"] {
|
|
||||||
lbVersion = "v2"
|
|
||||||
} else if netExts["lbaas"] {
|
|
||||||
lbVersion = "v1"
|
|
||||||
} else {
|
|
||||||
glog.Warningf("Failed to find neutron LBaaS extension (v1 or v2)")
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
glog.V(3).Infof("Using LBaaS extension %v", lbVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
glog.V(1).Info("Claiming to support LoadBalancer")
|
|
||||||
|
|
||||||
if lbVersion == "v2" {
|
|
||||||
return &LbaasV2{LoadBalancer{network, compute, os.lbOpts}}, true
|
|
||||||
} else if lbVersion == "v1" {
|
|
||||||
return &LbaasV1{LoadBalancer{network, compute, os.lbOpts}}, true
|
|
||||||
} else {
|
|
||||||
glog.Warningf("Config error: unrecognised lb-version \"%v\"", lbVersion)
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isNotFound(err error) bool {
|
|
||||||
e, ok := err.(*gophercloud.ErrUnexpectedResponseCode)
|
|
||||||
return ok && e.Actual == http.StatusNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
func (os *OpenStack) Zones() (cloudprovider.Zones, bool) {
|
|
||||||
glog.V(1).Info("Claiming to support Zones")
|
|
||||||
|
|
||||||
return os, true
|
|
||||||
}
|
|
||||||
func (os *OpenStack) GetZone() (cloudprovider.Zone, error) {
|
|
||||||
md, err := getMetadata()
|
|
||||||
if err != nil {
|
|
||||||
return cloudprovider.Zone{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
zone := cloudprovider.Zone{
|
|
||||||
FailureDomain: md.AvailabilityZone,
|
|
||||||
Region: os.region,
|
|
||||||
}
|
|
||||||
glog.V(1).Infof("Current zone is %v", zone)
|
|
||||||
|
|
||||||
return zone, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (os *OpenStack) Routes() (cloudprovider.Routes, bool) {
|
|
||||||
glog.V(4).Info("openstack.Routes() called")
|
|
||||||
|
|
||||||
network, err := openstack.NewNetworkV2(os.provider, gophercloud.EndpointOpts{
|
|
||||||
Region: os.region,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
glog.Warningf("Failed to find network endpoint: %v", err)
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
netExts, err := networkExtensions(network)
|
|
||||||
if err != nil {
|
|
||||||
glog.Warningf("Failed to list neutron extensions: %v", err)
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
if !netExts["extraroute"] {
|
|
||||||
glog.V(3).Infof("Neutron extraroute extension not found, required for Routes support")
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
compute, err := openstack.NewComputeV2(os.provider, gophercloud.EndpointOpts{
|
|
||||||
Region: os.region,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
glog.Warningf("Failed to find compute endpoint: %v", err)
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err := NewRoutes(compute, network, os.routeOpts)
|
|
||||||
if err != nil {
|
|
||||||
glog.Warningf("Error initialising Routes support: %v", err)
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
glog.V(1).Info("Claiming to support Routes")
|
|
||||||
|
|
||||||
return r, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implementation of sort interface for blockstorage version probing
|
|
||||||
type APIVersionsByID []apiversions_v1.APIVersion
|
|
||||||
|
|
||||||
func (apiVersions APIVersionsByID) Len() int {
|
|
||||||
return len(apiVersions)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (apiVersions APIVersionsByID) Swap(i, j int) {
|
|
||||||
apiVersions[i], apiVersions[j] = apiVersions[j], apiVersions[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (apiVersions APIVersionsByID) Less(i, j int) bool {
|
|
||||||
return apiVersions[i].ID > apiVersions[j].ID
|
|
||||||
}
|
|
||||||
|
|
||||||
func autoVersionSelector(apiVersion *apiversions_v1.APIVersion) string {
|
|
||||||
switch strings.ToLower(apiVersion.ID) {
|
|
||||||
case "v2.0":
|
|
||||||
return "v2"
|
|
||||||
case "v1.0":
|
|
||||||
return "v1"
|
|
||||||
default:
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func doBsApiVersionAutodetect(availableApiVersions []apiversions_v1.APIVersion) string {
|
|
||||||
sort.Sort(APIVersionsByID(availableApiVersions))
|
|
||||||
for _, status := range []string{"CURRENT", "SUPPORTED"} {
|
|
||||||
for _, version := range availableApiVersions {
|
|
||||||
if strings.ToUpper(version.Status) == status {
|
|
||||||
if detectedApiVersion := autoVersionSelector(&version); detectedApiVersion != "" {
|
|
||||||
glog.V(3).Infof("Blockstorage API version probing has found a suitable %s api version: %s", status, detectedApiVersion)
|
|
||||||
return detectedApiVersion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (os *OpenStack) volumeService(forceVersion string) (volumeService, error) {
|
|
||||||
bsVersion := ""
|
|
||||||
if forceVersion == "" {
|
|
||||||
bsVersion = os.bsOpts.BSVersion
|
|
||||||
} else {
|
|
||||||
bsVersion = forceVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
switch bsVersion {
|
|
||||||
case "v1":
|
|
||||||
sClient, err := openstack.NewBlockStorageV1(os.provider, gophercloud.EndpointOpts{
|
|
||||||
Region: os.region,
|
|
||||||
})
|
|
||||||
if err != nil || sClient == nil {
|
|
||||||
glog.Errorf("Unable to initialize cinder client for region: %s", os.region)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &VolumesV1{sClient, os.bsOpts}, nil
|
|
||||||
case "v2":
|
|
||||||
sClient, err := openstack.NewBlockStorageV2(os.provider, gophercloud.EndpointOpts{
|
|
||||||
Region: os.region,
|
|
||||||
})
|
|
||||||
if err != nil || sClient == nil {
|
|
||||||
glog.Errorf("Unable to initialize cinder v2 client for region: %s", os.region)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &VolumesV2{sClient, os.bsOpts}, nil
|
|
||||||
case "auto":
|
|
||||||
sClient, err := openstack.NewBlockStorageV1(os.provider, gophercloud.EndpointOpts{
|
|
||||||
Region: os.region,
|
|
||||||
})
|
|
||||||
if err != nil || sClient == nil {
|
|
||||||
glog.Errorf("Unable to initialize cinder client for region: %s", os.region)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
availableApiVersions := []apiversions_v1.APIVersion{}
|
|
||||||
err = apiversions_v1.List(sClient).EachPage(func(page pagination.Page) (bool, error) {
|
|
||||||
// returning false from this handler stops page iteration, error is propagated to the upper function
|
|
||||||
apiversions, err := apiversions_v1.ExtractAPIVersions(page)
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Unable to extract api versions from page: %v", err)
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
availableApiVersions = append(availableApiVersions, apiversions...)
|
|
||||||
return true, nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Error when retrieving list of supported blockstorage api versions: %v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if autodetectedVersion := doBsApiVersionAutodetect(availableApiVersions); autodetectedVersion != "" {
|
|
||||||
return os.volumeService(autodetectedVersion)
|
|
||||||
} else {
|
|
||||||
// Nothing suitable found, failed autodetection
|
|
||||||
return nil, errors.New("BS API version autodetection failed.")
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
err_txt := fmt.Sprintf("Config error: unrecognised bs-version \"%v\"", os.bsOpts.BSVersion)
|
|
||||||
glog.Warningf(err_txt)
|
|
||||||
return nil, errors.New(err_txt)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,155 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2016 The Kubernetes Authors.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package openstack
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/golang/glog"
|
|
||||||
"github.com/gophercloud/gophercloud"
|
|
||||||
"github.com/gophercloud/gophercloud/openstack"
|
|
||||||
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
|
|
||||||
"github.com/gophercloud/gophercloud/pagination"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
|
||||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Instances struct {
|
|
||||||
compute *gophercloud.ServiceClient
|
|
||||||
}
|
|
||||||
|
|
||||||
// Instances returns an implementation of Instances for OpenStack.
|
|
||||||
func (os *OpenStack) Instances() (cloudprovider.Instances, bool) {
|
|
||||||
glog.V(4).Info("openstack.Instances() called")
|
|
||||||
|
|
||||||
compute, err := openstack.NewComputeV2(os.provider, gophercloud.EndpointOpts{
|
|
||||||
Region: os.region,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
glog.Warningf("Failed to find compute endpoint: %v", err)
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
glog.V(1).Info("Claiming to support Instances")
|
|
||||||
|
|
||||||
return &Instances{compute}, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *Instances) List(name_filter string) ([]types.NodeName, error) {
|
|
||||||
glog.V(4).Infof("openstack List(%v) called", name_filter)
|
|
||||||
|
|
||||||
opts := servers.ListOpts{
|
|
||||||
Name: name_filter,
|
|
||||||
Status: "ACTIVE",
|
|
||||||
}
|
|
||||||
pager := servers.List(i.compute, opts)
|
|
||||||
|
|
||||||
ret := make([]types.NodeName, 0)
|
|
||||||
err := pager.EachPage(func(page pagination.Page) (bool, error) {
|
|
||||||
sList, err := servers.ExtractServers(page)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
for i := range sList {
|
|
||||||
ret = append(ret, mapServerToNodeName(&sList[i]))
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
glog.V(3).Infof("Found %v instances matching %v: %v",
|
|
||||||
len(ret), name_filter, ret)
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implementation of Instances.CurrentNodeName
|
|
||||||
// Note this is *not* necessarily the same as hostname.
|
|
||||||
func (i *Instances) CurrentNodeName(hostname string) (types.NodeName, error) {
|
|
||||||
md, err := getMetadata()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return types.NodeName(md.Name), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *Instances) AddSSHKeyToAllInstances(user string, keyData []byte) error {
|
|
||||||
return errors.New("unimplemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *Instances) NodeAddresses(name types.NodeName) ([]v1.NodeAddress, error) {
|
|
||||||
glog.V(4).Infof("NodeAddresses(%v) called", name)
|
|
||||||
|
|
||||||
addrs, err := getAddressesByName(i.compute, name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
glog.V(4).Infof("NodeAddresses(%v) => %v", name, addrs)
|
|
||||||
return addrs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NodeAddressesByProviderID returns the node addresses of an instances with the specified unique providerID
|
|
||||||
// This method will not be called from the node that is requesting this ID. i.e. metadata service
|
|
||||||
// and other local methods cannot be used here
|
|
||||||
func (i *Instances) NodeAddressesByProviderID(providerID string) ([]v1.NodeAddress, error) {
|
|
||||||
return []v1.NodeAddress{}, errors.New("unimplemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExternalID returns the cloud provider ID of the specified instance (deprecated).
|
|
||||||
func (i *Instances) ExternalID(name types.NodeName) (string, error) {
|
|
||||||
srv, err := getServerByName(i.compute, name)
|
|
||||||
if err != nil {
|
|
||||||
if err == ErrNotFound {
|
|
||||||
return "", cloudprovider.InstanceNotFound
|
|
||||||
}
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return srv.ID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstanceID returns the kubelet's cloud provider ID.
|
|
||||||
func (os *OpenStack) InstanceID() (string, error) {
|
|
||||||
return os.localInstanceID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstanceID returns the cloud provider ID of the specified instance.
|
|
||||||
func (i *Instances) InstanceID(name types.NodeName) (string, error) {
|
|
||||||
srv, err := getServerByName(i.compute, name)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
// In the future it is possible to also return an endpoint as:
|
|
||||||
// <endpoint>/<instanceid>
|
|
||||||
return "/" + srv.ID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstanceTypeByProviderID returns the cloudprovider instance type of the node with the specified unique providerID
|
|
||||||
// This method will not be called from the node that is requesting this ID. i.e. metadata service
|
|
||||||
// and other local methods cannot be used here
|
|
||||||
func (i *Instances) InstanceTypeByProviderID(providerID string) (string, error) {
|
|
||||||
return "", errors.New("unimplemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
// InstanceType returns the type of the specified instance.
|
|
||||||
func (i *Instances) InstanceType(name types.NodeName) (string, error) {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,278 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2016 The Kubernetes Authors.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package openstack
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/gophercloud/gophercloud"
|
|
||||||
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
|
|
||||||
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
|
|
||||||
neutronports "github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
|
|
||||||
|
|
||||||
"github.com/golang/glog"
|
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ErrNoRouterId = errors.New("router-id not set in cloud provider config")
|
|
||||||
|
|
||||||
type Routes struct {
|
|
||||||
compute *gophercloud.ServiceClient
|
|
||||||
network *gophercloud.ServiceClient
|
|
||||||
opts RouterOpts
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRoutes(compute *gophercloud.ServiceClient, network *gophercloud.ServiceClient, opts RouterOpts) (cloudprovider.Routes, error) {
|
|
||||||
if opts.RouterId == "" {
|
|
||||||
return nil, ErrNoRouterId
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Routes{
|
|
||||||
compute: compute,
|
|
||||||
network: network,
|
|
||||||
opts: opts,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Routes) ListRoutes(clusterName string) ([]*cloudprovider.Route, error) {
|
|
||||||
glog.V(4).Infof("ListRoutes(%v)", clusterName)
|
|
||||||
|
|
||||||
nodeNamesByAddr := make(map[string]types.NodeName)
|
|
||||||
err := foreachServer(r.compute, servers.ListOpts{Status: "ACTIVE"}, func(srv *servers.Server) (bool, error) {
|
|
||||||
addrs, err := nodeAddresses(srv)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
name := mapServerToNodeName(srv)
|
|
||||||
for _, addr := range addrs {
|
|
||||||
nodeNamesByAddr[addr.Address] = name
|
|
||||||
}
|
|
||||||
|
|
||||||
return true, nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
router, err := routers.Get(r.network, r.opts.RouterId).Extract()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var routes []*cloudprovider.Route
|
|
||||||
for _, item := range router.Routes {
|
|
||||||
nodeName, ok := nodeNamesByAddr[item.NextHop]
|
|
||||||
if !ok {
|
|
||||||
// Not one of our routes?
|
|
||||||
glog.V(4).Infof("Skipping route with unknown nexthop %v", item.NextHop)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
route := cloudprovider.Route{
|
|
||||||
Name: item.DestinationCIDR,
|
|
||||||
TargetNode: nodeName,
|
|
||||||
DestinationCIDR: item.DestinationCIDR,
|
|
||||||
}
|
|
||||||
routes = append(routes, &route)
|
|
||||||
}
|
|
||||||
|
|
||||||
return routes, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateRoutes(network *gophercloud.ServiceClient, router *routers.Router, newRoutes []routers.Route) (func(), error) {
|
|
||||||
origRoutes := router.Routes // shallow copy
|
|
||||||
|
|
||||||
_, err := routers.Update(network, router.ID, routers.UpdateOpts{
|
|
||||||
Routes: newRoutes,
|
|
||||||
}).Extract()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
unwinder := func() {
|
|
||||||
glog.V(4).Info("Reverting routes change to router ", router.ID)
|
|
||||||
_, err := routers.Update(network, router.ID, routers.UpdateOpts{
|
|
||||||
Routes: origRoutes,
|
|
||||||
}).Extract()
|
|
||||||
if err != nil {
|
|
||||||
glog.Warning("Unable to reset routes during error unwind: ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return unwinder, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateAllowedAddressPairs(network *gophercloud.ServiceClient, port *neutronports.Port, newPairs []neutronports.AddressPair) (func(), error) {
|
|
||||||
origPairs := port.AllowedAddressPairs // shallow copy
|
|
||||||
|
|
||||||
_, err := neutronports.Update(network, port.ID, neutronports.UpdateOpts{
|
|
||||||
AllowedAddressPairs: newPairs,
|
|
||||||
}).Extract()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
unwinder := func() {
|
|
||||||
glog.V(4).Info("Reverting allowed-address-pairs change to port ", port.ID)
|
|
||||||
_, err := neutronports.Update(network, port.ID, neutronports.UpdateOpts{
|
|
||||||
AllowedAddressPairs: origPairs,
|
|
||||||
}).Extract()
|
|
||||||
if err != nil {
|
|
||||||
glog.Warning("Unable to reset allowed-address-pairs during error unwind: ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return unwinder, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Routes) CreateRoute(clusterName string, nameHint string, route *cloudprovider.Route) error {
|
|
||||||
glog.V(4).Infof("CreateRoute(%v, %v, %v)", clusterName, nameHint, route)
|
|
||||||
|
|
||||||
onFailure := NewCaller()
|
|
||||||
|
|
||||||
addr, err := getAddressByName(r.compute, route.TargetNode)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
glog.V(4).Infof("Using nexthop %v for node %v", addr, route.TargetNode)
|
|
||||||
|
|
||||||
router, err := routers.Get(r.network, r.opts.RouterId).Extract()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
routes := router.Routes
|
|
||||||
|
|
||||||
for _, item := range routes {
|
|
||||||
if item.DestinationCIDR == route.DestinationCIDR && item.NextHop == addr {
|
|
||||||
glog.V(4).Infof("Skipping existing route: %v", route)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
routes = append(routes, routers.Route{
|
|
||||||
DestinationCIDR: route.DestinationCIDR,
|
|
||||||
NextHop: addr,
|
|
||||||
})
|
|
||||||
|
|
||||||
unwind, err := updateRoutes(r.network, router, routes)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer onFailure.Call(unwind)
|
|
||||||
|
|
||||||
port, err := getPortByIP(r.network, addr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
found := false
|
|
||||||
for _, item := range port.AllowedAddressPairs {
|
|
||||||
if item.IPAddress == route.DestinationCIDR {
|
|
||||||
glog.V(4).Info("Found existing allowed-address-pair: ", item)
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
newPairs := append(port.AllowedAddressPairs, neutronports.AddressPair{
|
|
||||||
IPAddress: route.DestinationCIDR,
|
|
||||||
})
|
|
||||||
unwind, err := updateAllowedAddressPairs(r.network, &port, newPairs)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer onFailure.Call(unwind)
|
|
||||||
}
|
|
||||||
|
|
||||||
glog.V(4).Infof("Route created: %v", route)
|
|
||||||
onFailure.Disarm()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Routes) DeleteRoute(clusterName string, route *cloudprovider.Route) error {
|
|
||||||
glog.V(4).Infof("DeleteRoute(%v, %v)", clusterName, route)
|
|
||||||
|
|
||||||
onFailure := NewCaller()
|
|
||||||
|
|
||||||
addr, err := getAddressByName(r.compute, route.TargetNode)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
router, err := routers.Get(r.network, r.opts.RouterId).Extract()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
routes := router.Routes
|
|
||||||
index := -1
|
|
||||||
for i, item := range routes {
|
|
||||||
if item.DestinationCIDR == route.DestinationCIDR && item.NextHop == addr {
|
|
||||||
index = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if index == -1 {
|
|
||||||
glog.V(4).Infof("Skipping non-existent route: %v", route)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete element `index`
|
|
||||||
routes[index] = routes[len(routes)-1]
|
|
||||||
routes = routes[:len(routes)-1]
|
|
||||||
|
|
||||||
unwind, err := updateRoutes(r.network, router, routes)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer onFailure.Call(unwind)
|
|
||||||
|
|
||||||
port, err := getPortByIP(r.network, addr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
addr_pairs := port.AllowedAddressPairs
|
|
||||||
index = -1
|
|
||||||
for i, item := range addr_pairs {
|
|
||||||
if item.IPAddress == route.DestinationCIDR {
|
|
||||||
index = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if index != -1 {
|
|
||||||
// Delete element `index`
|
|
||||||
addr_pairs[index] = addr_pairs[len(routes)-1]
|
|
||||||
addr_pairs = addr_pairs[:len(routes)-1]
|
|
||||||
|
|
||||||
unwind, err := updateAllowedAddressPairs(r.network, &port, addr_pairs)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer onFailure.Call(unwind)
|
|
||||||
}
|
|
||||||
|
|
||||||
glog.V(4).Infof("Route deleted: %v", route)
|
|
||||||
onFailure.Disarm()
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2016 The Kubernetes Authors.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package openstack
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRoutes(t *testing.T) {
|
|
||||||
const clusterName = "ignored"
|
|
||||||
|
|
||||||
cfg, ok := configFromEnv()
|
|
||||||
if !ok {
|
|
||||||
t.Skipf("No config found in environment")
|
|
||||||
}
|
|
||||||
|
|
||||||
os, err := newOpenStack(cfg)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to construct/authenticate OpenStack: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
r, ok := os.Routes()
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("Routes() returned false - perhaps your stack doens't support Neutron?")
|
|
||||||
}
|
|
||||||
|
|
||||||
newroute := cloudprovider.Route{
|
|
||||||
DestinationCIDR: "10.164.2.0/24",
|
|
||||||
TargetNode: types.NodeName("testinstance"),
|
|
||||||
}
|
|
||||||
err = r.CreateRoute(clusterName, "myhint", &newroute)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("CreateRoute error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
routelist, err := r.ListRoutes(clusterName)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ListRoutes() error: %v", err)
|
|
||||||
}
|
|
||||||
for _, route := range routelist {
|
|
||||||
_, cidr, err := net.ParseCIDR(route.DestinationCIDR)
|
|
||||||
if err != nil {
|
|
||||||
t.Logf("Ignoring route %s, unparsable CIDR: %v", route.Name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
t.Logf("%s via %s", cidr, route.TargetNode)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = r.DeleteRoute(clusterName, &newroute)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("DeleteRoute error: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,435 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2014 The Kubernetes Authors.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package openstack
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/gophercloud/gophercloud"
|
|
||||||
"github.com/gophercloud/gophercloud/openstack/blockstorage/v1/apiversions"
|
|
||||||
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/util/rand"
|
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
const volumeAvailableStatus = "available"
|
|
||||||
const volumeInUseStatus = "in-use"
|
|
||||||
const volumeCreateTimeoutSeconds = 30
|
|
||||||
const testClusterName = "testCluster"
|
|
||||||
|
|
||||||
func WaitForVolumeStatus(t *testing.T, os *OpenStack, volumeName string, status string, timeoutSeconds int) {
|
|
||||||
timeout := timeoutSeconds
|
|
||||||
start := time.Now().Second()
|
|
||||||
for {
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
|
|
||||||
if timeout >= 0 && time.Now().Second()-start >= timeout {
|
|
||||||
t.Logf("Volume (%s) status did not change to %s after %v seconds\n",
|
|
||||||
volumeName,
|
|
||||||
status,
|
|
||||||
timeout)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
getVol, err := os.getVolume(volumeName)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Cannot get existing Cinder volume (%s): %v", volumeName, err)
|
|
||||||
}
|
|
||||||
if getVol.Status == status {
|
|
||||||
t.Logf("Volume (%s) status changed to %s after %v seconds\n",
|
|
||||||
volumeName,
|
|
||||||
status,
|
|
||||||
timeout)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReadConfig(t *testing.T) {
|
|
||||||
_, err := readConfig(nil)
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("Should fail when no config is provided: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg, err := readConfig(strings.NewReader(`
|
|
||||||
[Global]
|
|
||||||
auth-url = http://auth.url
|
|
||||||
username = user
|
|
||||||
[LoadBalancer]
|
|
||||||
create-monitor = yes
|
|
||||||
monitor-delay = 1m
|
|
||||||
monitor-timeout = 30s
|
|
||||||
monitor-max-retries = 3
|
|
||||||
[BlockStorage]
|
|
||||||
bs-version = auto
|
|
||||||
trust-device-path = yes
|
|
||||||
|
|
||||||
`))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Should succeed when a valid config is provided: %s", err)
|
|
||||||
}
|
|
||||||
if cfg.Global.AuthUrl != "http://auth.url" {
|
|
||||||
t.Errorf("incorrect authurl: %s", cfg.Global.AuthUrl)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !cfg.LoadBalancer.CreateMonitor {
|
|
||||||
t.Errorf("incorrect lb.createmonitor: %t", cfg.LoadBalancer.CreateMonitor)
|
|
||||||
}
|
|
||||||
if cfg.LoadBalancer.MonitorDelay.Duration != 1*time.Minute {
|
|
||||||
t.Errorf("incorrect lb.monitordelay: %s", cfg.LoadBalancer.MonitorDelay)
|
|
||||||
}
|
|
||||||
if cfg.LoadBalancer.MonitorTimeout.Duration != 30*time.Second {
|
|
||||||
t.Errorf("incorrect lb.monitortimeout: %s", cfg.LoadBalancer.MonitorTimeout)
|
|
||||||
}
|
|
||||||
if cfg.LoadBalancer.MonitorMaxRetries != 3 {
|
|
||||||
t.Errorf("incorrect lb.monitormaxretries: %d", cfg.LoadBalancer.MonitorMaxRetries)
|
|
||||||
}
|
|
||||||
if cfg.BlockStorage.TrustDevicePath != true {
|
|
||||||
t.Errorf("incorrect bs.trustdevicepath: %v", cfg.BlockStorage.TrustDevicePath)
|
|
||||||
}
|
|
||||||
if cfg.BlockStorage.BSVersion != "auto" {
|
|
||||||
t.Errorf("incorrect bs.bs-version: %v", cfg.BlockStorage.BSVersion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestToAuthOptions(t *testing.T) {
|
|
||||||
cfg := Config{}
|
|
||||||
cfg.Global.Username = "user"
|
|
||||||
// etc.
|
|
||||||
|
|
||||||
ao := cfg.toAuthOptions()
|
|
||||||
|
|
||||||
if !ao.AllowReauth {
|
|
||||||
t.Errorf("Will need to be able to reauthenticate")
|
|
||||||
}
|
|
||||||
if ao.Username != cfg.Global.Username {
|
|
||||||
t.Errorf("Username %s != %s", ao.Username, cfg.Global.Username)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCaller(t *testing.T) {
|
|
||||||
called := false
|
|
||||||
myFunc := func() { called = true }
|
|
||||||
|
|
||||||
c := NewCaller()
|
|
||||||
c.Call(myFunc)
|
|
||||||
|
|
||||||
if !called {
|
|
||||||
t.Errorf("Caller failed to call function in default case")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Disarm()
|
|
||||||
called = false
|
|
||||||
c.Call(myFunc)
|
|
||||||
|
|
||||||
if called {
|
|
||||||
t.Error("Caller still called function when disarmed")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Confirm the "usual" deferred Caller pattern works as expected
|
|
||||||
|
|
||||||
called = false
|
|
||||||
success_case := func() {
|
|
||||||
c := NewCaller()
|
|
||||||
defer c.Call(func() { called = true })
|
|
||||||
c.Disarm()
|
|
||||||
}
|
|
||||||
if success_case(); called {
|
|
||||||
t.Error("Deferred success case still invoked unwind")
|
|
||||||
}
|
|
||||||
|
|
||||||
called = false
|
|
||||||
failure_case := func() {
|
|
||||||
c := NewCaller()
|
|
||||||
defer c.Call(func() { called = true })
|
|
||||||
}
|
|
||||||
if failure_case(); !called {
|
|
||||||
t.Error("Deferred failure case failed to invoke unwind")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// An arbitrary sort.Interface, just for easier comparison
|
|
||||||
type AddressSlice []v1.NodeAddress
|
|
||||||
|
|
||||||
func (a AddressSlice) Len() int { return len(a) }
|
|
||||||
func (a AddressSlice) Less(i, j int) bool { return a[i].Address < a[j].Address }
|
|
||||||
func (a AddressSlice) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|
||||||
|
|
||||||
func TestNodeAddresses(t *testing.T) {
|
|
||||||
srv := servers.Server{
|
|
||||||
Status: "ACTIVE",
|
|
||||||
HostID: "29d3c8c896a45aa4c34e52247875d7fefc3d94bbcc9f622b5d204362",
|
|
||||||
AccessIPv4: "50.56.176.99",
|
|
||||||
AccessIPv6: "2001:4800:790e:510:be76:4eff:fe04:82a8",
|
|
||||||
Addresses: map[string]interface{}{
|
|
||||||
"private": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:7c:1b:2b",
|
|
||||||
"version": float64(4),
|
|
||||||
"addr": "10.0.0.32",
|
|
||||||
"OS-EXT-IPS:type": "fixed",
|
|
||||||
},
|
|
||||||
map[string]interface{}{
|
|
||||||
"version": float64(4),
|
|
||||||
"addr": "50.56.176.36",
|
|
||||||
"OS-EXT-IPS:type": "floating",
|
|
||||||
},
|
|
||||||
map[string]interface{}{
|
|
||||||
"version": float64(4),
|
|
||||||
"addr": "10.0.0.31",
|
|
||||||
// No OS-EXT-IPS:type
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"public": []interface{}{
|
|
||||||
map[string]interface{}{
|
|
||||||
"version": float64(4),
|
|
||||||
"addr": "50.56.176.35",
|
|
||||||
},
|
|
||||||
map[string]interface{}{
|
|
||||||
"version": float64(6),
|
|
||||||
"addr": "2001:4800:780e:510:be76:4eff:fe04:84a8",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
addrs, err := nodeAddresses(&srv)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("nodeAddresses returned error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Sort(AddressSlice(addrs))
|
|
||||||
t.Logf("addresses is %v", addrs)
|
|
||||||
|
|
||||||
want := []v1.NodeAddress{
|
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.0.31"},
|
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.0.32"},
|
|
||||||
{Type: v1.NodeExternalIP, Address: "2001:4800:780e:510:be76:4eff:fe04:84a8"},
|
|
||||||
{Type: v1.NodeExternalIP, Address: "2001:4800:790e:510:be76:4eff:fe04:82a8"},
|
|
||||||
{Type: v1.NodeExternalIP, Address: "50.56.176.35"},
|
|
||||||
{Type: v1.NodeExternalIP, Address: "50.56.176.36"},
|
|
||||||
{Type: v1.NodeExternalIP, Address: "50.56.176.99"},
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(want, addrs) {
|
|
||||||
t.Errorf("nodeAddresses returned incorrect value %v", addrs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This allows acceptance testing against an existing OpenStack
|
|
||||||
// install, using the standard OS_* OpenStack client environment
|
|
||||||
// variables.
|
|
||||||
// FIXME: it would be better to hermetically test against canned JSON
|
|
||||||
// requests/responses.
|
|
||||||
func configFromEnv() (cfg Config, ok bool) {
|
|
||||||
cfg.Global.AuthUrl = os.Getenv("OS_AUTH_URL")
|
|
||||||
|
|
||||||
cfg.Global.TenantId = os.Getenv("OS_TENANT_ID")
|
|
||||||
// Rax/nova _insists_ that we don't specify both tenant ID and name
|
|
||||||
if cfg.Global.TenantId == "" {
|
|
||||||
cfg.Global.TenantName = os.Getenv("OS_TENANT_NAME")
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.Global.Username = os.Getenv("OS_USERNAME")
|
|
||||||
cfg.Global.Password = os.Getenv("OS_PASSWORD")
|
|
||||||
cfg.Global.Region = os.Getenv("OS_REGION_NAME")
|
|
||||||
cfg.Global.DomainId = os.Getenv("OS_DOMAIN_ID")
|
|
||||||
cfg.Global.DomainName = os.Getenv("OS_DOMAIN_NAME")
|
|
||||||
|
|
||||||
ok = (cfg.Global.AuthUrl != "" &&
|
|
||||||
cfg.Global.Username != "" &&
|
|
||||||
cfg.Global.Password != "" &&
|
|
||||||
(cfg.Global.TenantId != "" || cfg.Global.TenantName != "" ||
|
|
||||||
cfg.Global.DomainId != "" || cfg.Global.DomainName != ""))
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewOpenStack(t *testing.T) {
|
|
||||||
cfg, ok := configFromEnv()
|
|
||||||
if !ok {
|
|
||||||
t.Skipf("No config found in environment")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := newOpenStack(cfg)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to construct/authenticate OpenStack: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLoadBalancer(t *testing.T) {
|
|
||||||
cfg, ok := configFromEnv()
|
|
||||||
if !ok {
|
|
||||||
t.Skipf("No config found in environment")
|
|
||||||
}
|
|
||||||
|
|
||||||
versions := []string{"v1", "v2", ""}
|
|
||||||
|
|
||||||
for _, v := range versions {
|
|
||||||
t.Logf("Trying LBVersion = '%s'\n", v)
|
|
||||||
cfg.LoadBalancer.LBVersion = v
|
|
||||||
|
|
||||||
os, err := newOpenStack(cfg)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to construct/authenticate OpenStack: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
lb, ok := os.LoadBalancer()
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("LoadBalancer() returned false - perhaps your stack doesn't support Neutron?")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, exists, err := lb.GetLoadBalancer(testClusterName, &v1.Service{ObjectMeta: metav1.ObjectMeta{Name: "noexist"}})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("GetLoadBalancer(\"noexist\") returned error: %s", err)
|
|
||||||
}
|
|
||||||
if exists {
|
|
||||||
t.Fatalf("GetLoadBalancer(\"noexist\") returned exists")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestZones(t *testing.T) {
|
|
||||||
SetMetadataFixture(&FakeMetadata)
|
|
||||||
defer ClearMetadata()
|
|
||||||
|
|
||||||
os := OpenStack{
|
|
||||||
provider: &gophercloud.ProviderClient{
|
|
||||||
IdentityBase: "http://auth.url/",
|
|
||||||
},
|
|
||||||
region: "myRegion",
|
|
||||||
}
|
|
||||||
|
|
||||||
z, ok := os.Zones()
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("Zones() returned false")
|
|
||||||
}
|
|
||||||
|
|
||||||
zone, err := z.GetZone()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("GetZone() returned error: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if zone.Region != "myRegion" {
|
|
||||||
t.Fatalf("GetZone() returned wrong region (%s)", zone.Region)
|
|
||||||
}
|
|
||||||
|
|
||||||
if zone.FailureDomain != "nova" {
|
|
||||||
t.Fatalf("GetZone() returned wrong failure domain (%s)", zone.FailureDomain)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestVolumes(t *testing.T) {
|
|
||||||
cfg, ok := configFromEnv()
|
|
||||||
if !ok {
|
|
||||||
t.Skipf("No config found in environment")
|
|
||||||
}
|
|
||||||
|
|
||||||
os, err := newOpenStack(cfg)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to construct/authenticate OpenStack: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tags := map[string]string{
|
|
||||||
"test": "value",
|
|
||||||
}
|
|
||||||
vol, err := os.CreateVolume("kubernetes-test-volume-"+rand.String(10), 1, "", "", &tags)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Cannot create a new Cinder volume: %v", err)
|
|
||||||
}
|
|
||||||
t.Logf("Volume (%s) created\n", vol)
|
|
||||||
|
|
||||||
WaitForVolumeStatus(t, os, vol, volumeAvailableStatus, volumeCreateTimeoutSeconds)
|
|
||||||
|
|
||||||
diskId, err := os.AttachDisk(os.localInstanceID, vol)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Cannot AttachDisk Cinder volume %s: %v", vol, err)
|
|
||||||
}
|
|
||||||
t.Logf("Volume (%s) attached, disk ID: %s\n", vol, diskId)
|
|
||||||
|
|
||||||
WaitForVolumeStatus(t, os, vol, volumeInUseStatus, volumeCreateTimeoutSeconds)
|
|
||||||
|
|
||||||
devicePath := os.GetDevicePath(diskId)
|
|
||||||
if !strings.HasPrefix(devicePath, "/dev/disk/by-id/") {
|
|
||||||
t.Fatalf("GetDevicePath returned and unexpected path for Cinder volume %s, returned %s", vol, devicePath)
|
|
||||||
}
|
|
||||||
t.Logf("Volume (%s) found at path: %s\n", vol, devicePath)
|
|
||||||
|
|
||||||
err = os.DetachDisk(os.localInstanceID, vol)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Cannot DetachDisk Cinder volume %s: %v", vol, err)
|
|
||||||
}
|
|
||||||
t.Logf("Volume (%s) detached\n", vol)
|
|
||||||
|
|
||||||
WaitForVolumeStatus(t, os, vol, volumeAvailableStatus, volumeCreateTimeoutSeconds)
|
|
||||||
|
|
||||||
err = os.DeleteVolume(vol)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Cannot delete Cinder volume %s: %v", vol, err)
|
|
||||||
}
|
|
||||||
t.Logf("Volume (%s) deleted\n", vol)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCinderAutoDetectApiVersion(t *testing.T) {
|
|
||||||
updated := "" // not relevant to this test, can be set to any value
|
|
||||||
status_current := "CURRENT"
|
|
||||||
status_supported := "SUPpORTED" // lowercase to test regression resitance if api returns different case
|
|
||||||
status_deprecated := "DEPRECATED"
|
|
||||||
|
|
||||||
var result_version, api_version [4]string
|
|
||||||
|
|
||||||
for ver := 0; ver <= 3; ver++ {
|
|
||||||
api_version[ver] = fmt.Sprintf("v%d.0", ver)
|
|
||||||
result_version[ver] = fmt.Sprintf("v%d", ver)
|
|
||||||
}
|
|
||||||
result_version[0] = ""
|
|
||||||
api_current_v1 := apiversions.APIVersion{ID: api_version[1], Status: status_current, Updated: updated}
|
|
||||||
api_current_v2 := apiversions.APIVersion{ID: api_version[2], Status: status_current, Updated: updated}
|
|
||||||
api_current_v3 := apiversions.APIVersion{ID: api_version[3], Status: status_current, Updated: updated}
|
|
||||||
|
|
||||||
api_supported_v1 := apiversions.APIVersion{ID: api_version[1], Status: status_supported, Updated: updated}
|
|
||||||
api_supported_v2 := apiversions.APIVersion{ID: api_version[2], Status: status_supported, Updated: updated}
|
|
||||||
|
|
||||||
api_deprecated_v1 := apiversions.APIVersion{ID: api_version[1], Status: status_deprecated, Updated: updated}
|
|
||||||
api_deprecated_v2 := apiversions.APIVersion{ID: api_version[2], Status: status_deprecated, Updated: updated}
|
|
||||||
|
|
||||||
var testCases = []struct {
|
|
||||||
test_case []apiversions.APIVersion
|
|
||||||
wanted_result string
|
|
||||||
}{
|
|
||||||
{[]apiversions.APIVersion{api_current_v1}, result_version[1]},
|
|
||||||
{[]apiversions.APIVersion{api_current_v2}, result_version[2]},
|
|
||||||
{[]apiversions.APIVersion{api_supported_v1, api_current_v2}, result_version[2]}, // current always selected
|
|
||||||
{[]apiversions.APIVersion{api_current_v1, api_supported_v2}, result_version[1]}, // current always selected
|
|
||||||
{[]apiversions.APIVersion{api_current_v3, api_supported_v2, api_deprecated_v1}, result_version[2]}, // with current v3, but should fall back to v2
|
|
||||||
{[]apiversions.APIVersion{api_current_v3, api_deprecated_v2, api_deprecated_v1}, result_version[0]}, // v3 is not supported
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, suite := range testCases {
|
|
||||||
if autodetectedVersion := doBsApiVersionAutodetect(suite.test_case); autodetectedVersion != suite.wanted_result {
|
|
||||||
t.Fatalf("Autodetect for suite: %s, failed with result: '%s', wanted '%s'", suite.test_case, autodetectedVersion, suite.wanted_result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,422 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2016 The Kubernetes Authors.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package openstack
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
k8s_volume "k8s.io/kubernetes/pkg/volume"
|
|
||||||
|
|
||||||
"github.com/gophercloud/gophercloud"
|
|
||||||
"github.com/gophercloud/gophercloud/openstack"
|
|
||||||
volumes_v1 "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes"
|
|
||||||
volumes_v2 "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes"
|
|
||||||
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach"
|
|
||||||
"github.com/gophercloud/gophercloud/pagination"
|
|
||||||
|
|
||||||
"github.com/golang/glog"
|
|
||||||
)
|
|
||||||
|
|
||||||
type volumeService interface {
|
|
||||||
createVolume(opts VolumeCreateOpts) (string, error)
|
|
||||||
getVolume(diskName string) (Volume, error)
|
|
||||||
deleteVolume(volumeName string) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Volumes implementation for v1
|
|
||||||
type VolumesV1 struct {
|
|
||||||
blockstorage *gophercloud.ServiceClient
|
|
||||||
opts BlockStorageOpts
|
|
||||||
}
|
|
||||||
|
|
||||||
// Volumes implementation for v2
|
|
||||||
type VolumesV2 struct {
|
|
||||||
blockstorage *gophercloud.ServiceClient
|
|
||||||
opts BlockStorageOpts
|
|
||||||
}
|
|
||||||
|
|
||||||
type Volume struct {
|
|
||||||
// ID of the instance, to which this volume is attached. "" if not attached
|
|
||||||
AttachedServerId string
|
|
||||||
// Device file path
|
|
||||||
AttachedDevice string
|
|
||||||
// Unique identifier for the volume.
|
|
||||||
ID string
|
|
||||||
// Human-readable display name for the volume.
|
|
||||||
Name string
|
|
||||||
// Current status of the volume.
|
|
||||||
Status string
|
|
||||||
}
|
|
||||||
|
|
||||||
type VolumeCreateOpts struct {
|
|
||||||
Size int
|
|
||||||
Availability string
|
|
||||||
Name string
|
|
||||||
VolumeType string
|
|
||||||
Metadata map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (volumes *VolumesV1) createVolume(opts VolumeCreateOpts) (string, error) {
|
|
||||||
|
|
||||||
create_opts := volumes_v1.CreateOpts{
|
|
||||||
Name: opts.Name,
|
|
||||||
Size: opts.Size,
|
|
||||||
VolumeType: opts.VolumeType,
|
|
||||||
AvailabilityZone: opts.Availability,
|
|
||||||
Metadata: opts.Metadata,
|
|
||||||
}
|
|
||||||
|
|
||||||
vol, err := volumes_v1.Create(volumes.blockstorage, create_opts).Extract()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return vol.ID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (volumes *VolumesV2) createVolume(opts VolumeCreateOpts) (string, error) {
|
|
||||||
|
|
||||||
create_opts := volumes_v2.CreateOpts{
|
|
||||||
Name: opts.Name,
|
|
||||||
Size: opts.Size,
|
|
||||||
VolumeType: opts.VolumeType,
|
|
||||||
AvailabilityZone: opts.Availability,
|
|
||||||
Metadata: opts.Metadata,
|
|
||||||
}
|
|
||||||
|
|
||||||
vol, err := volumes_v2.Create(volumes.blockstorage, create_opts).Extract()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return vol.ID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (volumes *VolumesV1) getVolume(diskName string) (Volume, error) {
|
|
||||||
var volume_v1 volumes_v1.Volume
|
|
||||||
var volume Volume
|
|
||||||
err := volumes_v1.List(volumes.blockstorage, nil).EachPage(func(page pagination.Page) (bool, error) {
|
|
||||||
vols, err := volumes_v1.ExtractVolumes(page)
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Failed to extract volumes: %v", err)
|
|
||||||
return false, err
|
|
||||||
} else {
|
|
||||||
for _, v := range vols {
|
|
||||||
glog.V(4).Infof("%s %s %v", v.ID, v.Name, v.Attachments)
|
|
||||||
if v.Name == diskName || strings.Contains(v.ID, diskName) {
|
|
||||||
volume_v1 = v
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if it reached here then no disk with the given name was found.
|
|
||||||
errmsg := fmt.Sprintf("Unable to find disk: %s", diskName)
|
|
||||||
return false, errors.New(errmsg)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Error occurred getting volume: %s", diskName)
|
|
||||||
return volume, err
|
|
||||||
}
|
|
||||||
|
|
||||||
volume.ID = volume_v1.ID
|
|
||||||
volume.Name = volume_v1.Name
|
|
||||||
volume.Status = volume_v1.Status
|
|
||||||
|
|
||||||
if len(volume_v1.Attachments) > 0 && volume_v1.Attachments[0]["server_id"] != nil {
|
|
||||||
volume.AttachedServerId = volume_v1.Attachments[0]["server_id"].(string)
|
|
||||||
volume.AttachedDevice = volume_v1.Attachments[0]["device"].(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
return volume, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (volumes *VolumesV2) getVolume(diskName string) (Volume, error) {
|
|
||||||
var volume_v2 volumes_v2.Volume
|
|
||||||
var volume Volume
|
|
||||||
err := volumes_v2.List(volumes.blockstorage, nil).EachPage(func(page pagination.Page) (bool, error) {
|
|
||||||
vols, err := volumes_v2.ExtractVolumes(page)
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Failed to extract volumes: %v", err)
|
|
||||||
return false, err
|
|
||||||
} else {
|
|
||||||
for _, v := range vols {
|
|
||||||
glog.V(4).Infof("%s %s %v", v.ID, v.Name, v.Attachments)
|
|
||||||
if v.Name == diskName || strings.Contains(v.ID, diskName) {
|
|
||||||
volume_v2 = v
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if it reached here then no disk with the given name was found.
|
|
||||||
errmsg := fmt.Sprintf("Unable to find disk: %s", diskName)
|
|
||||||
return false, errors.New(errmsg)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Error occurred getting volume: %s", diskName)
|
|
||||||
return volume, err
|
|
||||||
}
|
|
||||||
|
|
||||||
volume.ID = volume_v2.ID
|
|
||||||
volume.Name = volume_v2.Name
|
|
||||||
volume.Status = volume_v2.Status
|
|
||||||
|
|
||||||
if len(volume_v2.Attachments) > 0 {
|
|
||||||
volume.AttachedServerId = volume_v2.Attachments[0].ServerID
|
|
||||||
volume.AttachedDevice = volume_v2.Attachments[0].Device
|
|
||||||
}
|
|
||||||
|
|
||||||
return volume, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (volumes *VolumesV1) deleteVolume(volumeName string) error {
|
|
||||||
|
|
||||||
err := volumes_v1.Delete(volumes.blockstorage, volumeName).ExtractErr()
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Cannot delete volume %s: %v", volumeName, err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (volumes *VolumesV2) deleteVolume(volumeName string) error {
|
|
||||||
err := volumes_v2.Delete(volumes.blockstorage, volumeName).ExtractErr()
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Cannot delete volume %s: %v", volumeName, err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attaches given cinder volume to the compute running kubelet
|
|
||||||
func (os *OpenStack) AttachDisk(instanceID string, diskName string) (string, error) {
|
|
||||||
volume, err := os.getVolume(diskName)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
cClient, err := openstack.NewComputeV2(os.provider, gophercloud.EndpointOpts{
|
|
||||||
Region: os.region,
|
|
||||||
})
|
|
||||||
if err != nil || cClient == nil {
|
|
||||||
glog.Errorf("Unable to initialize nova client for region: %s", os.region)
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if volume.AttachedServerId != "" {
|
|
||||||
if instanceID == volume.AttachedServerId {
|
|
||||||
glog.V(4).Infof("Disk: %q is already attached to compute: %q", diskName, instanceID)
|
|
||||||
return volume.ID, nil
|
|
||||||
}
|
|
||||||
glog.V(2).Infof("Disk %q is attached to a different compute (%q), detaching", diskName, volume.AttachedServerId)
|
|
||||||
err = os.DetachDisk(volume.AttachedServerId, diskName)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add read only flag here if possible spothanis
|
|
||||||
_, err = volumeattach.Create(cClient, instanceID, &volumeattach.CreateOpts{
|
|
||||||
VolumeID: volume.ID,
|
|
||||||
}).Extract()
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Failed to attach %s volume to %s compute: %v", diskName, instanceID, err)
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
glog.V(2).Infof("Successfully attached %s volume to %s compute", diskName, instanceID)
|
|
||||||
return volume.ID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detaches given cinder volume from the compute running kubelet
|
|
||||||
func (os *OpenStack) DetachDisk(instanceID string, partialDiskId string) error {
|
|
||||||
volume, err := os.getVolume(partialDiskId)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
cClient, err := openstack.NewComputeV2(os.provider, gophercloud.EndpointOpts{
|
|
||||||
Region: os.region,
|
|
||||||
})
|
|
||||||
if err != nil || cClient == nil {
|
|
||||||
glog.Errorf("Unable to initialize nova client for region: %s", os.region)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if volume.AttachedServerId != instanceID {
|
|
||||||
errMsg := fmt.Sprintf("Disk: %s has no attachments or is not attached to compute: %s", volume.Name, instanceID)
|
|
||||||
glog.Errorf(errMsg)
|
|
||||||
return errors.New(errMsg)
|
|
||||||
} else {
|
|
||||||
// This is a blocking call and effects kubelet's performance directly.
|
|
||||||
// We should consider kicking it out into a separate routine, if it is bad.
|
|
||||||
err = volumeattach.Delete(cClient, instanceID, volume.ID).ExtractErr()
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Failed to delete volume %s from compute %s attached %v", volume.ID, instanceID, err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
glog.V(2).Infof("Successfully detached volume: %s from compute: %s", volume.ID, instanceID)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Takes a partial/full disk id or diskname
|
|
||||||
func (os *OpenStack) getVolume(diskName string) (Volume, error) {
|
|
||||||
|
|
||||||
volumes, err := os.volumeService("")
|
|
||||||
if err != nil || volumes == nil {
|
|
||||||
glog.Errorf("Unable to initialize cinder client for region: %s", os.region)
|
|
||||||
return Volume{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return volumes.getVolume(diskName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a volume of given size (in GiB)
|
|
||||||
func (os *OpenStack) CreateVolume(name string, size int, vtype, availability string, tags *map[string]string) (volumeName string, err error) {
|
|
||||||
|
|
||||||
volumes, err := os.volumeService("")
|
|
||||||
if err != nil || volumes == nil {
|
|
||||||
glog.Errorf("Unable to initialize cinder client for region: %s", os.region)
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
opts := VolumeCreateOpts{
|
|
||||||
Name: name,
|
|
||||||
Size: size,
|
|
||||||
VolumeType: vtype,
|
|
||||||
Availability: availability,
|
|
||||||
}
|
|
||||||
if tags != nil {
|
|
||||||
opts.Metadata = *tags
|
|
||||||
}
|
|
||||||
volume_id, err := volumes.createVolume(opts)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Failed to create a %d GB volume: %v", size, err)
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
glog.Infof("Created volume %v", volume_id)
|
|
||||||
return volume_id, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetDevicePath returns the path of an attached block storage volume, specified by its id.
|
|
||||||
func (os *OpenStack) GetDevicePath(diskId string) string {
|
|
||||||
// Build a list of candidate device paths
|
|
||||||
candidateDeviceNodes := []string{
|
|
||||||
// KVM
|
|
||||||
fmt.Sprintf("virtio-%s", diskId[:20]),
|
|
||||||
// ESXi
|
|
||||||
fmt.Sprintf("wwn-0x%s", strings.Replace(diskId, "-", "", -1)),
|
|
||||||
}
|
|
||||||
|
|
||||||
files, _ := ioutil.ReadDir("/dev/disk/by-id/")
|
|
||||||
|
|
||||||
for _, f := range files {
|
|
||||||
for _, c := range candidateDeviceNodes {
|
|
||||||
if c == f.Name() {
|
|
||||||
glog.V(4).Infof("Found disk attached as %q; full devicepath: %s\n", f.Name(), path.Join("/dev/disk/by-id/", f.Name()))
|
|
||||||
return path.Join("/dev/disk/by-id/", f.Name())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glog.Warningf("Failed to find device for the diskid: %q\n", diskId)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (os *OpenStack) DeleteVolume(volumeName string) error {
|
|
||||||
used, err := os.diskIsUsed(volumeName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if used {
|
|
||||||
msg := fmt.Sprintf("Cannot delete the volume %q, it's still attached to a node", volumeName)
|
|
||||||
return k8s_volume.NewDeletedVolumeInUseError(msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
volumes, err := os.volumeService("")
|
|
||||||
if err != nil || volumes == nil {
|
|
||||||
glog.Errorf("Unable to initialize cinder client for region: %s", os.region)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = volumes.deleteVolume(volumeName)
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("Cannot delete volume %s: %v", volumeName, err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get device path of attached volume to the compute running kubelet, as known by cinder
|
|
||||||
func (os *OpenStack) GetAttachmentDiskPath(instanceID string, diskName string) (string, error) {
|
|
||||||
// See issue #33128 - Cinder does not always tell you the right device path, as such
|
|
||||||
// we must only use this value as a last resort.
|
|
||||||
volume, err := os.getVolume(diskName)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if volume.AttachedServerId != "" {
|
|
||||||
if instanceID == volume.AttachedServerId {
|
|
||||||
// Attachment[0]["device"] points to the device path
|
|
||||||
// see http://developer.openstack.org/api-ref-blockstorage-v1.html
|
|
||||||
return volume.AttachedDevice, nil
|
|
||||||
} else {
|
|
||||||
errMsg := fmt.Sprintf("Disk %q is attached to a different compute: %q, should be detached before proceeding", diskName, volume.AttachedServerId)
|
|
||||||
glog.Errorf(errMsg)
|
|
||||||
return "", errors.New(errMsg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", fmt.Errorf("volume %s is not attached to %s", diskName, instanceID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// query if a volume is attached to a compute instance
|
|
||||||
func (os *OpenStack) DiskIsAttached(diskName, instanceID string) (bool, error) {
|
|
||||||
volume, err := os.getVolume(diskName)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if instanceID == volume.AttachedServerId {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// query if a list of volumes are attached to a compute instance
|
|
||||||
func (os *OpenStack) DisksAreAttached(diskNames []string, instanceID string) (map[string]bool, error) {
|
|
||||||
attached := make(map[string]bool)
|
|
||||||
for _, diskName := range diskNames {
|
|
||||||
is_attached, _ := os.DiskIsAttached(diskName, instanceID)
|
|
||||||
attached[diskName] = is_attached
|
|
||||||
}
|
|
||||||
return attached, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// diskIsUsed returns true a disk is attached to any node.
|
|
||||||
func (os *OpenStack) diskIsUsed(diskName string) (bool, error) {
|
|
||||||
volume, err := os.getVolume(diskName)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if volume.AttachedServerId != "" {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// query if we should trust the cinder provide deviceName, See issue #33128
|
|
||||||
func (os *OpenStack) ShouldTrustDevicePath() bool {
|
|
||||||
return os.bsOpts.TrustDevicePath
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
#!/bin/bash -xe
|
|
||||||
|
|
||||||
BASE_DIR=$(cd $(dirname $BASH_SOURCE)/.. && pwd)
|
|
||||||
|
|
||||||
# Local version to install bindep packages
|
|
||||||
# Suitable for use for development
|
|
||||||
|
|
||||||
function is_fedora {
|
|
||||||
[ -f /usr/bin/yum ] && cat /etc/*release | grep -q -e "Fedora"
|
|
||||||
}
|
|
||||||
|
|
||||||
PACKAGES=""
|
|
||||||
if ! which virtualenv; then
|
|
||||||
PACKAGES="$PACKAGES virtualenv"
|
|
||||||
fi
|
|
||||||
if ! which make; then
|
|
||||||
PACKAGES="$PACKAGES make"
|
|
||||||
fi
|
|
||||||
if [[ -n $PACKAGES ]]; then
|
|
||||||
sudo apt-get -q --assume-yes install virtualenv
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for bindep
|
|
||||||
if ! which bindep; then
|
|
||||||
pushd $BASE_DIR >/dev/null
|
|
||||||
make bindep
|
|
||||||
popd >/dev/null
|
|
||||||
fi
|
|
||||||
|
|
||||||
PACKAGES=$(make bindep || true)
|
|
||||||
|
|
||||||
# inspired from project-config install-distro-packages.sh
|
|
||||||
if apt-get -v >/dev/null 2>&1 ; then
|
|
||||||
sudo apt-get -qq update
|
|
||||||
sudo PATH=/usr/sbin:/sbin:$PATH DEBIAN_FRONTEND=noninteractive \
|
|
||||||
apt-get -q --option "Dpkg::Options::=--force-confold" \
|
|
||||||
--assume-yes install $PACKAGES
|
|
||||||
elif emerge --version >/dev/null 2>&1 ; then
|
|
||||||
sudo emerge -uDNq --jobs=4 @world
|
|
||||||
sudo PATH=/usr/sbin:/sbin:$PATH emerge -q --jobs=4 $PACKAGES
|
|
||||||
else
|
|
||||||
is_fedora && YUM=dnf || YUM=yum
|
|
||||||
sudo PATH=/usr/sbin:/sbin:$PATH $YUM install -y $PACKAGES
|
|
||||||
fi
|
|
@ -1,55 +0,0 @@
|
|||||||
#!/bin/bash -xe
|
|
||||||
# test-setup.sh - Install required stuffs
|
|
||||||
# Used in both CI jobs and locally
|
|
||||||
#
|
|
||||||
# Install the following tools:
|
|
||||||
# * glide
|
|
||||||
|
|
||||||
# Get OS
|
|
||||||
case $(uname -s) in
|
|
||||||
Darwin)
|
|
||||||
OS=darwin
|
|
||||||
;;
|
|
||||||
Linux)
|
|
||||||
if LSB_RELEASE=$(which lsb_release); then
|
|
||||||
OS=$($LSB_RELEASE -s -c)
|
|
||||||
else
|
|
||||||
# No lsb-release, trya hack or two
|
|
||||||
if which dpkg 1>/dev/null; then
|
|
||||||
OS=debian
|
|
||||||
elif which yum 1>/dev/null || which dnf 1>/dev/null; then
|
|
||||||
OS=redhat
|
|
||||||
else
|
|
||||||
echo "Linux distro not yet supported"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unsupported OS"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
case $OS in
|
|
||||||
darwin)
|
|
||||||
if which brew 1>/dev/null; then
|
|
||||||
if ! which glide 1>/dev/null; then
|
|
||||||
brew install glide
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Homebrew not found, install Glide from source?"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
xenial)
|
|
||||||
APT_GET="DEBIAN_FRONTEND=noninteractive \
|
|
||||||
apt-get -q --option "Dpkg::Options::=--force-confold" \
|
|
||||||
--assume-yes"
|
|
||||||
if ! which add-apt-repository 1>/dev/null; then
|
|
||||||
sudo $APT_GET install software-properties-common
|
|
||||||
fi
|
|
||||||
sudo add-apt-repository --yes ppa:longsleep/golang-backports
|
|
||||||
sudo add-apt-repository --yes ppa:masterminds/glide
|
|
||||||
sudo apt-get update && sudo $APT_GET install golang-go glide
|
|
||||||
;;
|
|
||||||
esac
|
|
Loading…
Reference in New Issue
Block a user