Merge branch 'master' into add_remove_nics

This commit is contained in:
Marcus Sorensen 2013-01-30 13:55:29 -07:00
commit e8fcdcbfe5
91 changed files with 15798 additions and 4974 deletions

3569
LICENSE

File diff suppressed because it is too large Load Diff

618
NOTICE
View File

@ -76,620 +76,4 @@
Inspiration from jQuery color animation plugin by John Resig.
Released under the MIT license by Ole Laursen, October 2009.
********************************************************************************
Binary or packaged versions of this software (including versions built from source)
contains third party resources requiring the following notices:
For
cloud-ejb-api-3.0.jar
cloud-email.jar
cloud-jstl-1.2.jar
jaxb-api-2.1.jar
jaxb-impl-2.1.7.jar
jaxb-xjc-2.1.7.jar
jta-1.1.jar
mail-1.4.jar
NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
(CDDL)
The code released under the CDDL shall be governed by the laws of the State of
California (excluding conflict-of-law provisions). Any litigation relating to
this License shall be subject to the jurisdiction of the Federal Courts of the
Northern District of California and the state courts of the State of California,
with venue lying in Santa Clara County, California.
For
cloud-javax.persistence-2.0.0.jar
EclipseLink 2.0.0
Dec 10th, 2009
About
The EclipseLink project's goal is to provide a complete persistence framework
that is both comprehensive and universal. It will run in any Java environment
and read and write objects to virtually any type of data source, including
relational databases, and XML. EclipseLink will focus on providing leading edge
support, including advanced feature extensions, for the dominant persistence
standards for each target data source; Java Persistence API (JPA) for relational
databases, Java API for XML Binding (JAXB) for XML, Service Data Objects (SDO),
and Database Web services (DBWS).
For tips on getting started with EclipseLink, please see the following
resources:
EclipseLink 2.0.0 Release Notes Documentation Examples and How To License
The Eclipse Foundation makes available all content in this plug-in ("Content").
Unless otherwise indicated below, the Content is provided to you under the terms
and conditions of the Eclipse Public License Version 1.0 ("EPL") and Eclipse
Distribution License Version 1.0 ("EDL"). A copy of the EPL is available at
http://www.eclipse.org/legal/epl-v10.html and a copy of the EDL is available at
http://www.eclipse.org/org/documents/edl-v10.php. For purposes of the EPL,
"Program" will mean the Content.
If you did not receive this Content directly from the Eclipse Foundation, the
Content is being redistributed by another party ("Redistributor") and different
terms and conditions may apply to your use of any object code in the Content.
Check the Redistributor's license that was provided with the Content. If no such
license exists, contact the Redistributor. Unless otherwise indicated below, the
terms and conditions of the EPL and EDL still apply to any source code in the
Content and such source code may be obtained at http://www.eclipse.org.
Third Party Content
The Content includes items that have been sourced from third parties as set out
below. If you did not receive this Content directly from the Eclipse Foundation,
the following is provided for informational purposes only, and you should look
to the Redistributor's license for terms and conditions of use.
Foundation Dependencies ASM EclipseLink JPA ANTLR Java Persistence API (JPA) 1.0
- EJB 3.0 Java Persistence API (JPA) 2.0 EARLY ACCESS EclipseLink MOXy Java
Architecture for XML Binding (JAXB) Java Mail Java Activation Framework
Streaming API for XML (StAX) EclipseLink SDO Service Data Objects (SDO)
Utilities Java Connector Xerces WSDL4J 1.6.2 ASM v1.5.3
The EclipseLink Project includes ASM for the purpose of byte code weaving. The
AMS library is re-packaged within the source of the project
(org.persistence.eclipse.internal.libraries.asm.*) to avoid version collisions
with other usage of ASM. A custom patch has been added to the ASM 1.5.3 source
to handle an issue with other usages. This fix has also been contributed back to
the ASM project for inclusion in later projects.
The source code is available within the project's subversion repository. The
binaries are distributed within the eclipselink.jar and in the
org.eclipse.persistence.asm_2.0.0.v*.jar bundle.
http://asm.objectweb.org/license.html
Copyright (c) 2000-2005 INRIA, France Telecom, All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer. Redistributions in binary form must
reproduce the above copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with the
distribution. Neither the name of the copyright holders nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY
THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSEARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BELIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, ORCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OFSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER INCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OFTHE POSSIBILITY OF SUCH DAMAGE.
ANTLR v3.0
The ANTLR library (license) is included within EclipseLink Project to enable
parsing of the Java Persistence Query language (JP QL). The ANTLR library is re-
packaged within the project in the
org.eclipse.persistence.internal.libraries.antlr.* packages.
The source is available with the project's subversion repository. The binaries
are distributed within the eclipselink.jar and in the
org.eclipse.persistence.antlr_2.0.0.v*.jar bundle.
Java Architecture for XML Binding (JAXB) v2.0.5
The JAXB libraries distributed under CDDL v1.0 are included within the
EclipseLink Project to enable the MOXY component's implementation of JAXB.
JAXB Libraries:
/jlib/moxy/javax.xml.bind_2.1.12.v20090708-1500.jar /jlib/moxy/jaxb-impl.jar
/jlib/moxy/jaxb.xjc.jar Java Persistence (JPA) 1.0 - EJB 3.0
The Java Persistence API, included with EJB 3.0, is available for download from
the ejb-api directory in the glassfish CVS repository.It is distributed under
CDDLv1.0 . The jar is being shipped as an OSGi bundle and is required for
compilation of some container based fuctionality.
Java Persistence (JPA) 2.0.
EclipseLink is the Java Persistence (JPA) 2.0 Reference Implementation (JSR
317). The JPA 2.0 specification API is included in EclipseLink under the EPL and
EDL licenses.
Java Mail v1.4
The Java Mail library (mail.jar) is distributed with the JAXB v2.0.5 under CDDL
v1.0 and is included within the EclipseLink Project distribution to support Web
Services attachment handling in the MOXy component. It is only required when
using Java SE 5 (Java Mail is included in Java SE 6).
Java Activation Framework v1.1
The Java Activation Framework (activation.jar) is distributed with the JAXB
v2.0.5 under CDDL v1.0 and is included within the EclipseLink Project
distribution to support Web Services attachment handling in the MOXy component.
It is only required when using Java SE 5 (The Java Activation Framework is
included in Java SE 6).
Streaming API for XML (StAX) v1.0
The Streaming API for XML (StAX) library (jsr173_1.0_api.jar) is distributed
with the JAXB v2.0.5 under CDDL v1.0 and is included within the EclipseLink
Project distribution as an optional XML processing approach in the MOXy
component.
Service Data Objects (SDO) v2.1.1
The Service Data Objects (SDO) API is distributed under a CDDLv1.0 and custom
license. It provides the standard API implemented by the EclipseLink Project's
SDO component.
Java Connector v1.5
The JCA 1.5 API is available for download from the connector-api directory in
the glassfish CVS repository. It is distributed under CDDLv1.0 .
This jar is being shipped and required by the Workbench only. When using
EclipseLink in a container where JCA integration is required that container will
provide the necessary API libraries.
Xerces v2.9.0
Xerces 2.9.0 is available from the Xerces home page. It is distributed under
Apache 2.0.
This jar is shipped for the Workbench's use only in the reading and writing of
XML configuration files.
WSDL4j v1.6.2
WSDL4J 1.6.2 is available for download from the wsdl4j project. It distributed
under CPLv1.0 .
This jar is being shipped as a OSGi bundle and is only required for the DBWS
Builder utility.
For
cloud-commons-logging-1.1.1.jar
commons-logging-1.1.1.jar
// ------------------------------------------------------------------
// NOTICE file corresponding to the section 4d of The Apache License,
// Version 2.0, in this case for Commons Logging
// ------------------------------------------------------------------
Commons Logging
Copyright 2001-2007 The Apache Software Foundation
This product includes/uses software(s) developed by 'an unknown organization'
- Unnamed - avalon-framework:avalon-framework:jar:4.1.3
- Unnamed - log4j:log4j:jar:1.2.12
- Unnamed - logkit:logkit:jar:1.0.1
For
neethi-2.0.4.jar
=========================================================================
== NOTICE file corresponding to the section 4 d of ==
== the Apache License, Version 2.0, ==
== in this case for the Apache AXIOM distribution. ==
=========================================================================
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
Portions Copyright 2006 International Business Machines Corp.
Please read the different LICENSE files present in the licenses directory of
this distribution.
For
cloud-jasypt-1.9.jar
Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org)
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 distribution includes cryptographic software. The country in
which you currently reside may have restrictions on the import,
possession, use, and/or re-export to another country, of
encryption software. BEFORE using any encryption software, please
check your country's laws, regulations and policies concerning the
import, possession, or use, and re-export of encryption software, to
see if this is permitted. See http://www.wassenaar.org/ for more
information.
The U.S. Government Department of Commerce, Bureau of Industry and
Security (BIS), has classified this software as Export Commodity
Control Number (ECCN) 5D002.C.1, which includes information security
software using or performing cryptographic functions with asymmetric
algorithms. The form and manner of this distribution makes it
eligible for export under the License Exception ENC Technology
Software Unrestricted (TSU) exception (see the BIS Export
Administration Regulations, Section 740.13) for both object code and
source code.
The following provides more details on the cryptographic software
used (note that this software is not included in the distribution):
* The PBE Encryption facilities require the Java Cryptography
extensions: http://java.sun.com/javase/technologies/security/.
---------------------------------
Distributions of this software may include software developed by
The Apache Software Foundation (http://www.apache.org/).
---------------------------------
ICU License - ICU 1.8.1 and later
COPYRIGHT AND PERMISSION NOTICE
Copyright (c) 1995-2006 International Business Machines
Corporation and others
All rights reserved.
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so,
provided that the above copyright notice(s) and this
permission notice appear in all copies of the Software and
that both the above copyright notice(s) and this
permission notice appear in supporting documentation.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO
EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
USE OR PERFORMANCE OF THIS SOFTWARE.
Except as contained in this notice, the name of a copyright
holder shall not be used in advertising or otherwise to
promote the sale, use or other dealings in this Software
without prior written authorization of the copyright holder.
For
XmlSchema-1.4.3.jar
Portions Copyright 2006 International Business Machines Corp.
For
cloud-trilead-ssh2-build213.jar
Trilead SSH-2 for Java includes code that was written by Dr. Christian Plattner
during his PhD at ETH Zurich. The license states the following:
Copyright (c) 2005 - 2006 Swiss Federal Institute of Technology (ETH Zurich),
Department of Computer Science (http://www.inf.ethz.ch),
Christian Plattner. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
a.) Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
b.) Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
c.) Neither the name of ETH Zurich nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
The Java implementations of the AES, Blowfish and 3DES ciphers have been
taken (and slightly modified) from the cryptography package released by
"The Legion Of The Bouncy Castle".
Their license states the following:
Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle
(http://www.bouncycastle.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
For
axis2-1.5.1.jar
axis2-adb-1.5.1.jar
axis2-ant-plugin-1.5.1.jar
axis2-codegen-1.4.1.jar
axis2-jaxbri-1.5.1.jar
axis2-jaxws-1.5.1.jar
axis2-jibx-1.5.1.jar
axis2-json-1.5.1.jar
axis2-kernel-1.5.1.jar
axis2-transport-http-1.5.1.jar
axis2-transport-local-1.5.1.jar
axis2-webapp-1.5.1.war
cloud-axis.jar
=========================================================================
== NOTICE file corresponding to the section 4 d of ==
== the Apache License, Version 2.0, ==
== in this case for the Apache Axis2 distribution. ==
=========================================================================
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
Portions Copyright 2006 International Business Machines Corp.
Portions Copyright 2005-2007 WSO2, Inc.
This product also includes schemas and specification developed by:
- the W3C consortium (http://www.w3c.org)
This product also includes WS-* schemas developed by International
Business Machines Corporation, Microsoft Corporation, BEA Systems,
TIBCO Software, SAP AG, Sonic Software, and VeriSign
This product also includes a WSDL developed by salesforce.com
- Copyright 1999-2006 salesforce.com, inc.
Portions of the included xmlbeans library were originally based on the following:
- software copyright (c) 2000-2003, BEA Systems, <http://www.bea.com/>.
Please read the different LICENSE files present in the lib directory of
this distribution.
For
xml-apis.jar
=========================================================================
== NOTICE file corresponding to section 4(d) of the Apache License, ==
== Version 2.0, in this case for the Apache xml-commons xml-apis ==
== distribution. ==
=========================================================================
Apache XML Commons XML APIs
Copyright 2006 The Apache Software Foundation.
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
Portions of this software were originally based on the following:
- software copyright (c) 1999, IBM Corporation., http://www.ibm.com.
- software copyright (c) 1999, Sun Microsystems., http://www.sun.com.
- software copyright (c) 2000 World Wide Web Consortium, http://www.w3.org
For
cloud-commons-codec-1.5.jar
commons-codec-1.4.jar
Apache Commons Codec
Copyright 2002-2011 The Apache Software Foundation
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
--------------------------------------------------------------------------------
src/test/org/apache/commons/codec/language/DoubleMetaphoneTest.java contains
test data from http://aspell.sourceforge.net/test/batch0.tab.
Copyright (C) 2002 Kevin Atkinson (kevina@gnu.org). Verbatim copying
and distribution of this entire article is permitted in any medium,
provided this notice is preserved.
--------------------------------------------------------------------------------
For
rampart-lib
Apache Rampart
Copyright 2010 The Apache Software Foundation
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
Please read the different LICENSE files present in the lib directory of
this distribution.
For
xercesImpl.jar
=========================================================================
== NOTICE file corresponding to section 4(d) of the Apache License, ==
== Version 2.0, in this case for the Apache Xerces Java distribution. ==
=========================================================================
Apache Xerces Java
Copyright 1999-2012 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
Portions of this software were originally based on the following:
- software copyright (c) 1999, IBM Corporation., http://www.ibm.com.
- software copyright (c) 1999, Sun Microsystems., http://www.sun.com.
- voluntary contributions made by Paul Eng on behalf of the
Apache Software Foundation that were originally developed at iClick, Inc.,
software copyright (c) 1999.
For
woden-api-1.0M8.jar
woden-impl-dom-1.0M8.jar
=========================================================================
== NOTICE file corresponding to the section 4 d of ==
== the Apache License, Version 2.0, ==
== in this case for the Apache Woden distribution. ==
=========================================================================
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
This product also includes software developed by :
- IBM Corporation (http://www.ibm.com),
WSDL4J was the initial code contribution for the Apache Woden
project and some of the WSDL4J design and code has been reused.
- The W3C Consortium (http://www.w3c.org),
Common W3C XML Schema and DTD files are packaged with Apache Woden.
Please read the different LICENSE files present in the root directory of
this distribution.
For
axiom-api-1.2.8.jar
axiom-impl-1.2.8.jar
Axiom includes software from other projects, as follows:
This software includes the Woodstox High-performance XML processor
http://woodstox.codehaus.org/
licensed under the Apache License, Version 2.0
This software includes the Jaxen XPath library
http://jaxen.codehaus.org/
licensed under the following BSD 3 Clause license:
================================================================================
Copyright 2003-2006 The Werken Company. All Rights Reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Jaxen Project nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================
For
wss4j-1.5.8.jar
Apache WebServices - WSS4J
Copyright 2004-2011 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
This product includes software Copyright University of Southampton IT
Innovation Centre, 2006 (http://www.it-innovation.soton.ac.uk).
Released under the MIT license by Ole Laursen, October 2009.

View File

@ -318,4 +318,10 @@ public class EventTypes {
public static final String EVENT_AUTOSCALEVMGROUP_UPDATE = "AUTOSCALEVMGROUP.UPDATE";
public static final String EVENT_AUTOSCALEVMGROUP_ENABLE = "AUTOSCALEVMGROUP.ENABLE";
public static final String EVENT_AUTOSCALEVMGROUP_DISABLE = "AUTOSCALEVMGROUP.DISABLE";
public static final String EVENT_BAREMETAL_DHCP_SERVER_ADD = "PHYSICAL.DHCP.ADD";
public static final String EVENT_BAREMETAL_DHCP_SERVER_DELETE = "PHYSICAL.DHCP.DELETE";
public static final String EVENT_BAREMETAL_PXE_SERVER_ADD = "PHYSICAL.PXE.ADD";
public static final String EVENT_BAREMETAL_PXE_SERVER_DELETE = "PHYSICAL.PXE.DELETE";
}

View File

@ -39,6 +39,8 @@ public interface Host extends StateObject<Status>, Identity, InternalIdentity {
ExternalLoadBalancer(false),
ExternalVirtualSwitchSupervisor(false),
PxeServer(false),
BaremetalPxe(false),
BaremetalDhcp(false),
TrafficMonitor(false),
ExternalDhcp(false),

1
api/src/org/apache/cloudstack/api/ApiConstants.java Normal file → Executable file
View File

@ -428,6 +428,7 @@ public class ApiConstants {
public static final String CONDITION_IDS = "conditionids";
public static final String COUNTERPARAM_LIST = "counterparam";
public static final String AUTOSCALE_USER_ID = "autoscaleuserid";
public static final String BAREMETAL_DISCOVER_NAME = "baremetaldiscovername";
public enum HostDetails {
all, capacity, events, stats, min;

View File

@ -33,7 +33,7 @@ public enum ApiErrorCode {
ACCOUNT_RESOURCE_LIMIT_ERROR(532),
INSUFFICIENT_CAPACITY_ERROR(533),
RESOURCE_UNAVAILABLE_ERROR(534),
RESOURCE_ALLOCATION_ERROR(534),
RESOURCE_ALLOCATION_ERROR(535),
RESOURCE_IN_USE_ERROR(536),
NETWORK_RULE_CONFLICT_ERROR(537);

View File

@ -146,8 +146,7 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
"Mutually exclusive with securitygroupids parameter")
private List<String> securityGroupNameList;
@ACL(checkKeyAccess=true)
@Parameter(name = ApiConstants.IP_NETWORK_LIST, type = CommandType.MAP, entityType={Network.class, IpAddress.class},
@Parameter(name = ApiConstants.IP_NETWORK_LIST, type = CommandType.MAP,
description = "ip to network mapping. Can't be specified with networkIds parameter." +
" Example: iptonetworklist[0].ip=10.10.10.11&iptonetworklist[0].networkid=uuid - requests to use ip 10.10.10.11 in network id=uuid")
private Map ipToNetworkList;

View File

@ -21,7 +21,7 @@ import org.apache.log4j.Logger;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.response.DiskOfferingResponse;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.offering.ServiceOffering;
@ -44,7 +44,7 @@ public class UpgradeVMCmd extends BaseCmd {
required=true, description="The ID of the virtual machine")
private Long id;
@Parameter(name=ApiConstants.SERVICE_OFFERING_ID, type=CommandType.UUID, entityType=DiskOfferingResponse.class,
@Parameter(name=ApiConstants.SERVICE_OFFERING_ID, type=CommandType.UUID, entityType=ServiceOfferingResponse.class,
required=true, description="the service offering ID to apply to the virtual machine")
private Long serviceOfferingId;

View File

@ -25,6 +25,9 @@
<artifactId>cloudstack</artifactId>
<version>4.1.0-SNAPSHOT</version>
</parent>
<properties>
<mkisofs>mkisofs</mkisofs>
</properties>
<dependencies>
<dependency>
<groupId>log4j</groupId>
@ -167,6 +170,19 @@
</plugins>
</build>
<profiles>
<!-- Debian will never distribute mkisofs due to licensing issues.
Fortunately genisoimage is a work-alike -->
<profile>
<id>genisoimage</id>
<activation>
<file>
<exists>/usr/bin/genisoimage</exists>
</file>
</activation>
<properties>
<mkisofs>genisoimage</mkisofs>
</properties>
</profile>
<profile>
<id>vmware</id>
<activation>
@ -209,7 +225,7 @@
</execution>
</executions>
<configuration>
<executable>mkisofs</executable>
<executable>${mkisofs}</executable>
<workingDirectory>dist</workingDirectory>
<arguments>
<argument>-quiet</argument>

View File

@ -31,7 +31,7 @@
<para>Set the following paramaters:</para>
<programlisting>listen_tls = 0</programlisting>
<programlisting>listen_tcp = 1</programlisting>
<programlisting>tcp_port = 16059</programlisting>
<programlisting>tcp_port = "16059"</programlisting>
<programlisting>auth_tcp = "none"</programlisting>
<programlisting>mdns_adv = 0</programlisting>
</listitem>

144
docs/en-US/network-rate.xml Normal file
View File

@ -0,0 +1,144 @@
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "cloudstack.ent">
%BOOK_ENTITIES;
]>
<!-- Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<section id="network-rate">
<title>Network Throttling</title>
<para>Network throttling is the process of controlling the network access and bandwidth usage
based on certain rules. &PRODUCT; controls this behaviour of the guest networks in the cloud by
using the network rate parameter. This parameter is defined as the default data transfer rate in
Mbps (Megabits Per Second) allowed in a guest network. It defines the upper limits for network
utilization. If the current utilization is below the allowed upper limits, access is granted,
else revoked.</para>
<para>You can throttle the network bandwidth either to control the usage above a certain limit for
some accounts, or to control network congestion in a large cloud environment. The network rate
for your cloud can be configured on the following:</para>
<itemizedlist>
<listitem>
<para>Network Offering</para>
</listitem>
<listitem>
<para>Service Offering</para>
</listitem>
<listitem>
<para>Global parameter</para>
</listitem>
</itemizedlist>
<para>If network rate is set to NULL in service offering, the value provided in the
vm.network.throttling.rate global parameter is applied. If the value is set to NULL for network
offering, the value provided in the network.throttling.rate global parameter is
considered.</para>
<para>For the default public, storage, and management networks, network rate is set to 0. This
implies that the public, storage, and management networks will have unlimited bandwidth by
default. For default guest networks, network rate is set to NULL. In this case, network rate is
defaulted to the global parameter value.</para>
<para>The following table gives you an overview of how network rate is applied on different types
of networks in &PRODUCT;.</para>
<informaltable>
<tgroup cols="2" align="left" colsep="1" rowsep="1">
<colspec colwidth="1.0*" colname="1" colnum="1"/>
<colspec colwidth="3.18*" colname="2" colnum="2"/>
<thead>
<row>
<entry><para>Networks</para></entry>
<entry><para>Network Rate Is Taken from</para></entry>
</row>
</thead>
<tbody>
<row>
<entry><para>Guest network of Virtual Router</para></entry>
<entry><para>Guest Network Offering</para></entry>
</row>
<row>
<entry><para>Public network of Virtual Router</para></entry>
<entry><para>Guest Network Offering</para></entry>
</row>
<row>
<entry><para>Storage network of Secondary Storage VM</para></entry>
<entry><para>System Network Offering</para></entry>
</row>
<row>
<entry><para>Management network of Secondary Storage VM</para></entry>
<entry><para>System Network Offering</para></entry>
</row>
<row>
<entry><para>Storage network of Console Proxy VM</para></entry>
<entry><para>System Network Offering</para></entry>
</row>
<row>
<entry><para>Management network of Console Proxy VM</para></entry>
<entry><para>System Network Offering</para></entry>
</row>
<row>
<entry><para>Storage network of Virtual Router</para></entry>
<entry><para>System Network Offering</para></entry>
</row>
<row>
<entry><para>Management network of Virtual Router</para></entry>
<entry><para>System Network Offering</para></entry>
</row>
<row>
<entry><para>Public network of Secondary Storage VM</para></entry>
<entry><para>System Network Offering</para></entry>
</row>
<row>
<entry><para>Public network of Console Proxy VM</para></entry>
<entry><para>System Network Offering</para></entry>
</row>
<row>
<entry><para>Default network of a guest VM</para></entry>
<entry><para>Compute Offering</para></entry>
</row>
<row>
<entry><para>Additional networks of a guest VM</para></entry>
<entry><para>Corresponding Network Offerings</para></entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>A guest VM must have a default network, and can also have many additional networks.
Depending on various parameters, such as the host and virtual switch used, you can observe a
difference in the network rate in your cloud. For example, on a VMware host the actual network
rate varies based on where they are configured (compute offering, network offering, or both);
the network type (shared or isolated); and traffic direction (ingress or egress). </para>
<para>The network rate set for a network offering used by a particular network in &PRODUCT; is
used for the traffic shaping policy of a port group, for example: port group A, for that
network: a particular subnet or VLAN on the actual network. The virtual routers for that network
connects to the port group A, and by default instances in that network connects to this port
group. However, if an instance is deployed with a compute offering with the network rate set,
and if this rate is used for the traffic shaping policy of another port group for the network,
for example port group B, then instances using this compute offering are connected to the port
group B, instead of connecting to port group A.</para>
<para>The traffic shaping policy on standard port groups in VMware only applies to the egress
traffic, and the net effect depends on the type of network used in &PRODUCT;. In shared
networks, ingress traffic is unlimited for &PRODUCT;, and egress traffic is limited to the rate
that applies to the port group used by the instance if any. If the compute offering has a
network rate configured, this rate applies to the egress traffic, otherwise the network rate set
for the network offering applies. For isolated networks, the network rate set for the network
offering, if any, effectively applies to the ingress traffic. This is mainly because the network
rate set for the network offering applies to the egress traffic from the virtual router to the
instance. The egress traffic is limited by the rate that applies to the port group used by the
instance if any, similar to shared networks. </para>
<para>For example:</para>
<para>Network rate of network offering = 10 Mbps</para>
<para>Network rate of compute offering = 200 Mbps</para>
<para>In shared networks, ingress traffic will not be limited for &PRODUCT;, while egress traffic
will be limited to 200 Mbps. In an isolated network, ingress traffic will be limited to 10 Mbps
and egress to 200 Mbps.</para>
</section>

View File

@ -25,5 +25,6 @@
are discussed in the section on setting up networking for users.</para>
<xi:include href="compute-disk-service-offerings.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="system-service-offerings.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="network-rate.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="sys-offering-sysvm.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
</chapter>

View File

@ -21,253 +21,313 @@
specific language governing permissions and limitations
under the License.
-->
<section id="vmware-install">
<title>VMware vSphere Installation and Configuration</title>
<para>If you want to use the VMware vSphere hypervisor to run guest virtual machines, install vSphere on the host(s) in your cloud.</para>
<xi:include href="vmware-requirements.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<section id="vmware-preparation-checklist">
<title>VMware vSphere Installation and Configuration</title>
<para>If you want to use the VMware vSphere hypervisor to run guest virtual machines, install
vSphere on the host(s) in your cloud.</para>
<xi:include href="vmware-requirements.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<section id="vmware-preparation-checklist">
<title>Preparation Checklist for VMware</title>
<para>For a smoother installation, gather the following information before you start:</para>
<itemizedlist>
<listitem><para>Information listed in <xref linkend="vmware-vcenter-checklist" /></para></listitem>
<listitem><para>Information listed in <xref linkend="vmware-network-checklist" /></para></listitem>
<listitem>
<para>Information listed in <xref linkend="vmware-vcenter-checklist"/></para>
</listitem>
<listitem>
<para>Information listed in <xref linkend="vmware-network-checklist"/></para>
</listitem>
</itemizedlist>
<section id="vmware-vcenter-checklist">
<title>vCenter Checklist</title>
<para>You will need the following information about vCenter.</para>
<informaltable frame="all">
<title>vCenter Checklist</title>
<para>You will need the following information about vCenter.</para>
<informaltable frame="all">
<tgroup cols="3" align="left" colsep="1" rowsep="1">
<colspec colname="c1" />
<colspec colname="c2" />
<colspec colname="c3" />
<thead>
<colspec colname="c1"/>
<colspec colname="c2"/>
<colspec colname="c3"/>
<thead>
<row>
<entry><para>vCenter Requirement</para></entry>
<entry><para>Value</para></entry>
<entry><para>Notes</para></entry>
<entry><para>vCenter Requirement</para></entry>
<entry><para>Value</para></entry>
<entry><para>Notes</para></entry>
</row>
</thead>
<tbody>
</thead>
<tbody>
<row>
<entry><para>vCenter User</para></entry>
<entry><para></para></entry>
<entry><para>This user must have admin privileges.</para></entry>
<entry><para>vCenter User</para></entry>
<entry><para/></entry>
<entry><para>This user must have admin privileges.</para></entry>
</row>
<row>
<entry><para>vCenter User Password</para></entry>
<entry><para></para></entry>
<entry><para>Password for the above user.</para></entry>
<entry><para>vCenter User Password</para></entry>
<entry><para/></entry>
<entry><para>Password for the above user.</para></entry>
</row>
<row>
<entry><para>vCenter Datacenter Name</para></entry>
<entry><para></para></entry>
<entry><para>Name of the datacenter.</para></entry>
<entry><para>vCenter Datacenter Name</para></entry>
<entry><para/></entry>
<entry><para>Name of the datacenter.</para></entry>
</row>
<row>
<entry><para>vCenter Cluster Name</para></entry>
<entry><para></para></entry>
<entry><para>Name of the cluster.</para></entry>
<entry><para>vCenter Cluster Name</para></entry>
<entry><para/></entry>
<entry><para>Name of the cluster.</para></entry>
</row>
</tbody>
</tbody>
</tgroup>
</informaltable>
</informaltable>
</section>
<section id="vmware-network-checklist">
<title>Networking Checklist for VMware</title>
<para>You will need the following information about VLAN.</para>
<informaltable frame="all">
<title>Networking Checklist for VMware</title>
<para>You will need the following information about VLAN.</para>
<informaltable frame="all">
<tgroup cols="3" align="left" colsep="1" rowsep="1">
<colspec colname="c1" />
<colspec colname="c2" />
<colspec colname="c3" />
<thead>
<colspec colname="c1"/>
<colspec colname="c2"/>
<colspec colname="c3"/>
<thead>
<row>
<entry><para>VLAN Information</para></entry>
<entry><para>Value</para></entry>
<entry><para>Notes</para></entry>
<entry><para>VLAN Information</para></entry>
<entry><para>Value</para></entry>
<entry><para>Notes</para></entry>
</row>
</thead>
<tbody>
</thead>
<tbody>
<row>
<entry><para>ESXi VLAN</para></entry>
<entry><para></para></entry>
<entry><para>VLAN on which all your ESXi hypervisors reside.</para></entry>
<entry><para>ESXi VLAN</para></entry>
<entry><para/></entry>
<entry><para>VLAN on which all your ESXi hypervisors reside.</para></entry>
</row>
<row>
<entry><para>ESXI VLAN IP Address</para></entry>
<entry><para></para></entry>
<entry><para>IP Address Range in the ESXi VLAN. One address per Virtual Router is used from this range.</para></entry>
<entry><para>ESXI VLAN IP Address</para></entry>
<entry><para/></entry>
<entry><para>IP Address Range in the ESXi VLAN. One address per Virtual Router is used
from this range.</para></entry>
</row>
<row>
<entry><para>ESXi VLAN IP Gateway</para></entry>
<entry><para></para></entry>
<entry><para></para></entry>
<entry><para>ESXi VLAN IP Gateway</para></entry>
<entry><para/></entry>
<entry><para/></entry>
</row>
<row>
<entry><para>ESXi VLAN Netmask</para></entry>
<entry><para></para></entry>
<entry><para></para></entry>
<entry><para>ESXi VLAN Netmask</para></entry>
<entry><para/></entry>
<entry><para/></entry>
</row>
<row>
<entry><para>Management Server VLAN</para></entry>
<entry><para></para></entry>
<entry><para>VLAN on which the &PRODUCT; Management server is installed.</para></entry>
<entry><para>Management Server VLAN</para></entry>
<entry><para/></entry>
<entry><para>VLAN on which the &PRODUCT; Management server is
installed.</para></entry>
</row>
<row>
<entry><para>Public VLAN</para></entry>
<entry><para></para></entry>
<entry><para>VLAN for the Public Network.</para></entry>
<entry><para>Public VLAN</para></entry>
<entry><para/></entry>
<entry><para>VLAN for the Public Network.</para></entry>
</row>
<row>
<entry><para>Public VLAN Gateway</para></entry>
<entry><para></para></entry>
<entry><para></para></entry>
<entry><para>Public VLAN Gateway</para></entry>
<entry><para/></entry>
<entry><para/></entry>
</row>
<row>
<entry><para>Public VLAN Netmask</para></entry>
<entry><para></para></entry>
<entry><para></para></entry>
<entry><para>Public VLAN Netmask</para></entry>
<entry><para/></entry>
<entry><para/></entry>
</row>
<row>
<entry><para>Public VLAN IP Address Range</para></entry>
<entry><para></para></entry>
<entry><para>Range of Public IP Addresses available for &PRODUCT; use. These addresses will be used for virtual router on &PRODUCT; to route private traffic to external networks.</para></entry>
<entry><para>Public VLAN IP Address Range</para></entry>
<entry><para/></entry>
<entry><para>Range of Public IP Addresses available for &PRODUCT; use. These addresses
will be used for virtual router on &PRODUCT; to route private traffic to external
networks.</para></entry>
</row>
<row>
<entry><para>VLAN Range for Customer use</para></entry>
<entry><para></para></entry>
<entry><para>A contiguous range of non-routable VLANs. One VLAN will be assigned for each customer.</para></entry>
<entry><para>VLAN Range for Customer use</para></entry>
<entry><para/></entry>
<entry><para>A contiguous range of non-routable VLANs. One VLAN will be assigned for
each customer.</para></entry>
</row>
</tbody>
</tbody>
</tgroup>
</informaltable>
</informaltable>
</section>
</section>
<section id="vmware-vsphere-installation-steps">
</section>
<section id="vmware-vsphere-installation-steps">
<title>vSphere Installation Steps</title>
<orderedlist>
<listitem><para>If you haven't already, you'll need to download and purchase vSphere from the VMware Website (<ulink url="https://www.vmware.com/tryvmware/index.php?p=vmware-vsphere&amp;lp=1">https://www.vmware.com/tryvmware/index.php?p=vmware-vsphere&amp;lp=1</ulink>) and install it by following the VMware vSphere Installation Guide.</para></listitem>
<listitem>
<para>Following installation, perform the following configuration, which are described in the next few sections:</para>
<listitem>
<para>If you haven't already, you'll need to download and purchase vSphere from the VMware
Website (<ulink url="https://www.vmware.com/tryvmware/index.php?p=vmware-vsphere&amp;lp=1"
>https://www.vmware.com/tryvmware/index.php?p=vmware-vsphere&amp;lp=1</ulink>) and
install it by following the VMware vSphere Installation Guide.</para>
</listitem>
<listitem>
<para>Following installation, perform the following configuration, which are described in
the next few sections:</para>
<informaltable frame="all">
<tgroup cols="2" align="left" colsep="1" rowsep="1">
<colspec colname="c1" />
<colspec colname="c2" />
<tgroup cols="2" align="left" colsep="1" rowsep="1">
<colspec colname="c1"/>
<colspec colname="c2"/>
<thead>
<row>
<row>
<entry><para>Required</para></entry>
<entry><para>Optional</para></entry>
</row>
</row>
</thead>
<tbody>
<row>
<row>
<entry><para>ESXi host setup</para></entry>
<entry><para>NIC bonding</para></entry>
</row>
<row>
<entry><para>Configure host physical networking, virtual switch, vCenter Management Network, and extended port range</para></entry>
</row>
<row>
<entry><para>Configure host physical networking, virtual switch, vCenter Management
Network, and extended port range</para></entry>
<entry><para>Multipath storage</para></entry>
</row>
<row>
</row>
<row>
<entry><para>Prepare storage for iSCSI</para></entry>
<entry><para></para></entry>
</row>
<row>
<entry><para>Configure clusters in vCenter and add hosts to them, or add hosts without clusters to vCenter</para></entry>
<entry><para></para></entry>
</row>
<entry><para/></entry>
</row>
<row>
<entry><para>Configure clusters in vCenter and add hosts to them, or add hosts
without clusters to vCenter</para></entry>
<entry><para/></entry>
</row>
</tbody>
</tgroup>
</tgroup>
</informaltable>
</listitem>
</listitem>
</orderedlist>
</section>
<section id="vmware-esxi-host-setup">
</section>
<section id="vmware-esxi-host-setup">
<title>ESXi Host setup</title>
<para>All ESXi hosts should enable CPU hardware virtualization support in BIOS. Please note hardware virtualization support is not enabled by default on most servers.</para>
</section>
<section id="vmware-physical-host-networking">
<para>All ESXi hosts should enable CPU hardware virtualization support in BIOS. Please note
hardware virtualization support is not enabled by default on most servers.</para>
</section>
<section id="vmware-physical-host-networking">
<title>Physical Host Networking</title>
<para>You should have a plan for cabling the vSphere hosts. Proper network configuration is required before adding a vSphere host to &PRODUCT;. To configure an ESXi host, you can use vClient to add it as standalone host to vCenter first. Once you see the host appearing in the vCenter inventory tree, click the host node in the inventory tree, and navigate to the Configuration tab.</para>
<para>You should have a plan for cabling the vSphere hosts. Proper network configuration is
required before adding a vSphere host to &PRODUCT;. To configure an ESXi host, you can use
vClient to add it as standalone host to vCenter first. Once you see the host appearing in the
vCenter inventory tree, click the host node in the inventory tree, and navigate to the
Configuration tab.</para>
<mediaobject>
<imageobject>
<imageobject>
<imagedata fileref="./images/vmware-physical-network.png"/>
</imageobject>
<textobject>
</imageobject>
<textobject>
<phrase>vsphereclient.png: vSphere client</phrase>
</textobject>
</textobject>
</mediaobject>
<para>In the host configuration tab, click the &quot;Hardware/Networking&quot; link to bring up the networking configuration page as above.</para>
<section id="vmware-physical-host-networking-config-vswitch">
<title>Configure Virtual Switch</title>
<para>A default virtual switch vSwitch0 is created. &PRODUCT; requires all ESXi hosts in the cloud to use the same set of virtual switch names. If you change the default virtual switch name, you will need to configure one or more &PRODUCT; configuration variables as well.</para>
<section id="vmware-physical-host-networking-config-vswitch-separate-traffic">
<para>In the host configuration tab, click the &quot;Hardware/Networking&quot; link to bring up
the networking configuration page as above.</para>
<section id="vmware-physical-host-networking-config-vswitch">
<title>Configure Virtual Switch</title>
<para>A default virtual switch vSwitch0 is created. &PRODUCT; requires all ESXi hosts in the
cloud to use the same set of virtual switch names. If you change the default virtual switch
name, you will need to configure one or more &PRODUCT; configuration variables as
well.</para>
<section id="vmware-physical-host-networking-config-vswitch-separate-traffic">
<title>Separating Traffic</title>
<para>&PRODUCT; allows you to use vCenter to configure three separate networks per ESXi host. These networks are identified by the name of the vSwitch they are connected to. The allowed networks for configuration are public (for traffic to/from the public internet), guest (for guest-guest traffic), and private (for management and usually storage traffic). You can use the default virtual switch for all three, or create one or two other vSwitches for those traffic types.</para>
<para>If you want to separate traffic in this way you should first create and configure vSwitches in vCenter according to the vCenter instructions. Take note of the vSwitch names you have used for each traffic type. You will configure &PRODUCT; to use these vSwitches.</para>
</section>
<section id="vmware-physical-host-networking-config-vswitch-increasing-port">
<para>&PRODUCT; allows you to use vCenter to configure three separate networks per ESXi
host. These networks are identified by the name of the vSwitch they are connected to. The
allowed networks for configuration are public (for traffic to/from the public internet),
guest (for guest-guest traffic), and private (for management and usually storage traffic).
You can use the default virtual switch for all three, or create one or two other vSwitches
for those traffic types.</para>
<para>If you want to separate traffic in this way you should first create and configure
vSwitches in vCenter according to the vCenter instructions. Take note of the vSwitch names
you have used for each traffic type. You will configure &PRODUCT; to use these
vSwitches.</para>
</section>
<section id="vmware-physical-host-networking-config-vswitch-increasing-port">
<title>Increasing Ports</title>
<para>By default a virtual switch on ESXi hosts is created with 56 ports. We recommend setting it to 4088, the maximum number of ports allowed. To do that, click the &quot;Properties...&quot; link for virtual switch (note this is not the Properties link for Networking).</para>
<para>By default a virtual switch on ESXi hosts is created with 56 ports. We recommend
setting it to 4088, the maximum number of ports allowed. To do that, click the
&quot;Properties...&quot; link for virtual switch (note this is not the Properties link
for Networking).</para>
<mediaobject>
<imageobject>
<imageobject>
<imagedata fileref="./images/vmware-increase-ports.png"/>
</imageobject>
<textobject>
</imageobject>
<textobject>
<phrase>vsphereclient.png: vSphere client</phrase>
</textobject>
</textobject>
</mediaobject>
<para>In vSwitch properties dialog, select the vSwitch and click Edit. You should see the following dialog:</para>
<para>In vSwitch properties dialog, select the vSwitch and click Edit. You should see the
following dialog:</para>
<mediaobject>
<imageobject>
<imageobject>
<imagedata fileref="./images/vmware-vswitch-properties.png"/>
</imageobject>
<textobject>
</imageobject>
<textobject>
<phrase>vsphereclient.png: vSphere client</phrase>
</textobject>
</textobject>
</mediaobject>
<para>In this dialog, you can change the number of switch ports. After you&apos;ve done that, ESXi hosts are required to reboot in order for the setting to take effect.</para>
</section>
<para>In this dialog, you can change the number of switch ports. After you&apos;ve done
that, ESXi hosts are required to reboot in order for the setting to take effect.</para>
</section>
</section>
<section id="vmware-physical-host-networking-config-vcenter-mgt">
<title>Configure vCenter Management Network</title>
<para>In the vSwitch properties dialog box, you may see a vCenter management network. This same network will also be used as the &PRODUCT; management network. &PRODUCT; requires the vCenter management network to be configured properly. Select the management network item in the dialog, then click Edit.</para>
<mediaobject>
<title>Configure vCenter Management Network</title>
<para>In the vSwitch properties dialog box, you may see a vCenter management network. This
same network will also be used as the &PRODUCT; management network. &PRODUCT; requires the
vCenter management network to be configured properly. Select the management network item in
the dialog, then click Edit.</para>
<mediaobject>
<imageobject>
<imagedata fileref="./images/vmware-mgt-network-properties.png"/>
<imagedata fileref="./images/vmware-mgt-network-properties.png"/>
</imageobject>
<textobject>
<phrase>vsphereclient.png: vSphere client</phrase>
<phrase>vsphereclient.png: vSphere client</phrase>
</textobject>
</mediaobject>
<para>Make sure the following values are set:</para>
<itemizedlist>
<listitem><para>VLAN ID set to the desired ID</para></listitem>
<listitem><para>vMotion enabled.</para></listitem>
<listitem><para>Management traffic enabled.</para></listitem>
</itemizedlist>
<para>If the ESXi hosts have multiple VMKernel ports, and ESXi is not using the default value &quot;Management Network&quot; as the management network name, you must follow these guidelines to configure the management network port group so that &PRODUCT; can find it:</para>
<itemizedlist>
<listitem><para>Use one label for the management network port across all ESXi hosts.</para></listitem>
<listitem><para>In the &PRODUCT; UI, go to Configuration - Global Settings and set vmware.management.portgroup to the management network label from the ESXi hosts.</para></listitem>
</itemizedlist>
</mediaobject>
<para>Make sure the following values are set:</para>
<itemizedlist>
<listitem>
<para>VLAN ID set to the desired ID</para>
</listitem>
<listitem>
<para>vMotion enabled.</para>
</listitem>
<listitem>
<para>Management traffic enabled.</para>
</listitem>
</itemizedlist>
<para>If the ESXi hosts have multiple VMKernel ports, and ESXi is not using the default value
&quot;Management Network&quot; as the management network name, you must follow these
guidelines to configure the management network port group so that &PRODUCT; can find
it:</para>
<itemizedlist>
<listitem>
<para>Use one label for the management network port across all ESXi hosts.</para>
</listitem>
<listitem>
<para>In the &PRODUCT; UI, go to Configuration - Global Settings and set
vmware.management.portgroup to the management network label from the ESXi hosts.</para>
</listitem>
</itemizedlist>
</section>
<section id="vmware-physical-networking-extend-port-console-proxy">
<title>Extend Port Range for &PRODUCT; Console Proxy</title>
<para>(Applies only to VMware vSphere version 4.x)</para>
<para>You need to extend the range of firewall ports that the console proxy works with on the hosts. This is to enable the console proxy to work with VMware-based VMs. The default additional port range is 59000-60000. To extend the port range, log in to the VMware ESX service console on each host and run the following commands:</para>
<programlisting>
<title>Extend Port Range for &PRODUCT; Console Proxy</title>
<para>(Applies only to VMware vSphere version 4.x)</para>
<para>You need to extend the range of firewall ports that the console proxy works with on the
hosts. This is to enable the console proxy to work with VMware-based VMs. The default
additional port range is 59000-60000. To extend the port range, log in to the VMware ESX
service console on each host and run the following commands:</para>
<programlisting>
esxcfg-firewall -o 59000-60000,tcp,in,vncextras
esxcfg-firewall -o 59000-60000,tcp,out,vncextras
</programlisting>
</section>
<section id="vmware-physical-networking-config-vsphere-nic-bond">
<title>Configure NIC Bonding for vSphere</title>
<para>NIC bonding on vSphere hosts may be done according to the vSphere installation guide.</para>
<title>Configure NIC Bonding for vSphere</title>
<para>NIC bonding on vSphere hosts may be done according to the vSphere installation
guide.</para>
</section>
</section>
<!-- <section id="vmware-vsphere-cluster-config-nexus-vswitch">
</section>
<!-- <section id="vmware-vsphere-cluster-config-nexus-vswitch">
<title>Configuring a vSphere Cluster with Nexus 1000v Virtual Switch</title>
<para>&PRODUCT; supports Cisco Nexus 1000v dvSwitch (Distributed Virtual Switch) for virtual network configuration in a VMware vSphere environment. This section helps you configure a vSphere cluster with Nexus 1000v virtual switch in a VMware vCenter environment. For information on creating a vSphere cluster, see <xref linkend="vmware-install" /></para>
<section id="vmware-vsphere-cluster-config-nexus-vswitch-about">
@ -543,89 +603,169 @@ esxcfg-firewall -o 59000-60000,tcp,out,vncextras
</orderedlist>
</section>
</section> -->
<section id="vmware-vsphere-iscsi-storage-preparation">
<section id="vmware-vsphere-iscsi-storage-preparation">
<title>Storage Preparation for vSphere (iSCSI only)</title>
<para>Use of iSCSI requires preparatory work in vCenter. You must add an iSCSI target and create an iSCSI datastore.</para>
<para>Use of iSCSI requires preparatory work in vCenter. You must add an iSCSI target and create
an iSCSI datastore.</para>
<para>If you are using NFS, skip this section.</para>
<section id="vmware-vsphere-iscsi-storage-enable-initiator">
<title>Enable iSCSI initiator for ESXi hosts</title>
<orderedlist>
<title>Enable iSCSI initiator for ESXi hosts</title>
<orderedlist>
<listitem>
<para>In vCenter, go to hosts and Clusters/Configuration, and click Storage Adapters link. You will see:</para>
<mediaobject>
<para>In vCenter, go to hosts and Clusters/Configuration, and click Storage Adapters link.
You will see:</para>
<mediaobject>
<imageobject>
<imagedata fileref="./images/vmware-iscsi-initiator.png"/>
<imagedata fileref="./images/vmware-iscsi-initiator.png"/>
</imageobject>
<textobject>
<phrase>vsphereclient.png: vSphere client</phrase>
<phrase>vsphereclient.png: vSphere client</phrase>
</textobject>
</mediaobject>
</mediaobject>
</listitem>
<listitem>
<para>Select iSCSI software adapter and click Properties.</para>
<mediaobject>
<para>Select iSCSI software adapter and click Properties.</para>
<mediaobject>
<imageobject>
<imagedata fileref="./images/vmware-iscsi-initiator-properties.png"/>
<imagedata fileref="./images/vmware-iscsi-initiator-properties.png"/>
</imageobject>
<textobject>
<phrase>vsphereclient.png: vSphere client</phrase>
<phrase>vsphereclient.png: vSphere client</phrase>
</textobject>
</mediaobject>
</mediaobject>
</listitem>
<listitem>
<para>Click the Configure... button.</para>
<mediaobject>
<para>Click the Configure... button.</para>
<mediaobject>
<imageobject>
<imagedata fileref="./images/vmware-iscsi-general.png"/>
<imagedata fileref="./images/vmware-iscsi-general.png"/>
</imageobject>
<textobject>
<phrase>vsphereclient.png: vSphere client</phrase>
<phrase>vsphereclient.png: vSphere client</phrase>
</textobject>
</mediaobject>
</mediaobject>
</listitem>
<listitem><para>Check Enabled to enable the initiator.</para></listitem>
<listitem><para>Click OK to save.</para></listitem>
</orderedlist>
<listitem>
<para>Check Enabled to enable the initiator.</para>
</listitem>
<listitem>
<para>Click OK to save.</para>
</listitem>
</orderedlist>
</section>
<section id="vmware-vsphere-iscsi-storage-add-target">
<title>Add iSCSI target</title>
<para>Under the properties dialog, add the iSCSI target info:</para>
<mediaobject>
<title>Add iSCSI target</title>
<para>Under the properties dialog, add the iSCSI target info:</para>
<mediaobject>
<imageobject>
<imagedata fileref="./images/vmware-iscsi-target-add.png"/>
<imagedata fileref="./images/vmware-iscsi-target-add.png"/>
</imageobject>
<textobject>
<phrase>vsphereclient.png: vSphere client</phrase>
<phrase>vsphereclient.png: vSphere client</phrase>
</textobject>
</mediaobject>
<para>Repeat these steps for all ESXi hosts in the cluster.</para>
</mediaobject>
<para>Repeat these steps for all ESXi hosts in the cluster.</para>
</section>
<section id="vmware-vsphere-iscsi-storage-create-datastore">
<title>Create an iSCSI datastore</title>
<para>You should now create a VMFS datastore. Follow these steps to do so:</para>
<orderedlist>
<listitem><para>Select Home/Inventory/Datastores.</para></listitem>
<listitem><para>Right click on the datacenter node.</para></listitem>
<listitem><para>Choose Add Datastore... command.</para></listitem>
<listitem><para>Follow the wizard to create a iSCSI datastore.</para></listitem>
</orderedlist>
<para>This procedure should be done on one host in the cluster. It is not necessary to do this on all hosts.</para>
<mediaobject>
<title>Create an iSCSI datastore</title>
<para>You should now create a VMFS datastore. Follow these steps to do so:</para>
<orderedlist>
<listitem>
<para>Select Home/Inventory/Datastores.</para>
</listitem>
<listitem>
<para>Right click on the datacenter node.</para>
</listitem>
<listitem>
<para>Choose Add Datastore... command.</para>
</listitem>
<listitem>
<para>Follow the wizard to create a iSCSI datastore.</para>
</listitem>
</orderedlist>
<para>This procedure should be done on one host in the cluster. It is not necessary to do this
on all hosts.</para>
<mediaobject>
<imageobject>
<imagedata fileref="./images/vmware-iscsi-datastore.png"/>
<imagedata fileref="./images/vmware-iscsi-datastore.png"/>
</imageobject>
<textobject>
<phrase>vsphereclient.png: vSphere client</phrase>
<phrase>vsphereclient.png: vSphere client</phrase>
</textobject>
</mediaobject>
</mediaobject>
</section>
<section id="vmware-vsphere-iscsi-storage-multipathing">
<title>Multipathing for vSphere (Optional)</title>
<para>Storage multipathing on vSphere nodes may be done according to the vSphere installation guide.</para>
<title>Multipathing for vSphere (Optional)</title>
<para>Storage multipathing on vSphere nodes may be done according to the vSphere installation
guide.</para>
</section>
</section>
<section id="vmware-add-hosts-config-vsphere-cluster">
</section>
<section id="vmware-add-hosts-config-vsphere-cluster">
<title>Add Hosts or Configure Clusters (vSphere)</title>
<para>Use vCenter to create a vCenter cluster and add your desired hosts to the cluster. You will later add the entire cluster to &PRODUCT;. (see <xref linkend="add-clusters-vsphere" />).</para>
</section>
<para>Use vCenter to create a vCenter cluster and add your desired hosts to the cluster. You
will later add the entire cluster to &PRODUCT;. (see <xref linkend="add-clusters-vsphere"
/>).</para>
</section>
<section id="esxi-patch-install">
<title>Applying Hotfixes to a VMware vSphere Host</title>
<orderedlist>
<listitem>
<para>Disconnect the VMware vSphere cluster from &PRODUCT;. It should remain disconnected
long enough to apply the hotfix on the host.</para>
<orderedlist numeration="loweralpha">
<listitem>
<para>Log in to the &PRODUCT; UI as root. </para>
<para>See <xref linkend="log-in"/>.</para>
</listitem>
<listitem>
<para>Navigate to the VMware cluster, click Actions, and select Unmanage.</para>
</listitem>
<listitem>
<para>Watch the cluster status until it shows Unmanaged.</para>
</listitem>
</orderedlist>
</listitem>
<listitem>
<para>Perform the following on each of the ESXi hosts in the cluster:</para>
<orderedlist numeration="loweralpha">
<listitem>
<para>Move each of the ESXi hosts in the cluster to maintenance mode.</para>
</listitem>
<listitem>
<para>Ensure that all the VMs are migrated to other hosts in that cluster.</para>
</listitem>
<listitem>
<para>If there is only one host in that cluster, shutdown all the VMs and move the host
into maintenance mode.</para>
</listitem>
<listitem>
<para>Apply the patch on the ESXi host.</para>
</listitem>
<listitem>
<para>Restart the host if prompted.</para>
</listitem>
<listitem>
<para>Cancel the maintenance mode on the host.</para>
</listitem>
</orderedlist>
</listitem>
<listitem>
<para>Reconnect the cluster to &PRODUCT;:</para>
<orderedlist numeration="loweralpha">
<listitem>
<para>Log in to the &PRODUCT; UI as root.</para>
</listitem>
<listitem>
<para>Navigate to the VMware cluster, click Actions, and select Manage.</para>
</listitem>
<listitem>
<para>Watch the status to see that all the hosts come up. It might take several minutes
for the hosts to come up.</para>
<para>Alternatively, verify the host state is properly synchronized and updated in the
&PRODUCT; database.</para>
</listitem>
</orderedlist>
</listitem>
</orderedlist>
</section>
</section>

View File

@ -58,7 +58,7 @@ export JAVA_HOME
SCP=""
DCP=""
ACP=`ls /usr/share/cloud/java/* | tr '\n' ':'`
JCP="/usr/share/java/commons-daemon.jar"
JCP="/usr/share/java/jna.jar:/usr/share/java/commons-daemon.jar"
# We need to append the JSVC daemon JAR to the classpath
# AgentShell implements the JSVC daemon methods

138
packaging/centos63/cloud-usage.rc Executable file
View File

@ -0,0 +1,138 @@
#!/bin/bash
### BEGIN INIT INFO
# Provides: cloud usage
# Required-Start: $network $local_fs
# Required-Stop: $network $local_fs
# Default-Start: 3 4 5
# Default-Stop: 0 1 2 6
# Short-Description: Start/stop Apache CloudStack Usage Monitor
# Description: This scripts Starts/Stops the Apache CloudStack Usage Monitor
## The CloudStack Usage Monitor is a part of the Apache CloudStack project and is used
## for storing usage statistics from instances.
## JSVC (Java daemonizing) is used for starting and stopping the usage monitor.
### END INIT INFO
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
. /etc/rc.d/init.d/functions
SHORTNAME="cloud-usage"
PIDFILE=/var/run/"$SHORTNAME".pid
LOCKFILE=/var/lock/subsys/"$SHORTNAME"
LOGFILE=/var/log/cloud/usage/usage.log
PROGNAME="CloudStack Usage Monitor"
CLASS="com.cloud.usage.UsageServer"
PROG="jsvc"
DAEMON="/usr/bin/jsvc"
USER=cloud
unset OPTIONS
[ -r /etc/sysconfig/default/"$SHORTNAME" ] && source /etc/sysconfig/default/"$SHORTNAME"
# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT)
JDK_DIRS="/usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun /usr/lib/jvm/jre-1.6.0 /usr/lib/j2sdk1.5-sun /usr/lib/jre-openjdk"
for jdir in $JDK_DIRS; do
if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then
JAVA_HOME="$jdir"
fi
done
export JAVA_HOME
SCP=""
DCP=""
UCP=`ls /usr/share/cloud/usage/java/* | tr '\n' ':'`
JCP="/usr/share/java/commons-daemon.jar"
# We need to append the JSVC daemon JAR to the classpath
# AgentShell implements the JSVC daemon methods
export CLASSPATH="$SCP:$DCP:$UCP:$JCP:/etc/sysconfig
start() {
if [ -s "$PIDFILE" ] && kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then
echo "$PROGNAME apparently already running"
exit 0
fi
if hostname --fqdn >/dev/null 2>&1 ; then
true
else
echo "The host name does not resolve properly to an IP address. Cannot start $PROGNAME"
exit 1
fi
echo -n "Starting $PROGNAME" "$SHORTNAME"
if daemon --pidfile $PIDFILE $DAEMON -cp "$CLASSPATH" -pidfile "$PIDFILE" -user "$USER" -errfile SYSLOG -Dpid=$$ $CLASS
RETVAL=$?
then
rc=0
sleep 1
if ! kill -0 $(cat "$PIDFILE") >/dev/null 2>&1; then
failure
rc=1
fi
else
rc=1
fi
if [ $rc -eq 0 ]; then
success
else
failure
rm -f "$PIDFILE"
fi
echo
}
stop() {
echo -n "Stopping $PROGNAME" "$SHORTNAME"
killproc -p $PIDFILE $DAEMON
if [ "$?" -eq 0 ]; then
success
else
failure
fi
rm -f "$PIDFILE"
echo
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status -p $PIDFILE $SHORTNAME
RETVAL=$?
;;
restart | force-reload)
stop
sleep 3
start
;;
*)
echo "Usage: $0 {start|stop|restart|force-reload|status}"
RETVAL=3
esac
exit $RETVAL

View File

@ -112,10 +112,21 @@ Requires: bridge-utils
Requires: ebtables
Requires: jsvc
Requires: jna
Requires: jakarta-commons-daemon
Requires: jakarta-commons-daemon-jsvc
Group: System Environment/Libraries
%description agent
The CloudStack agent for KVM hypervisors
%package usage
Summary: CloudStack Usage calculation server
Requires: java >= 1.6.0
Requires: jsvc
Requires: jakarta-commons-daemon
Requires: jakarta-commons-daemon-jsvc
%description usage
The CloudStack usage calculation service
%prep
echo Doing CloudStack build
@ -196,6 +207,7 @@ chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management
chmod 770 ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/agent
chmod -R ugo+x ${RPM_BUILD_ROOT}/usr/share/%{name}/management/webapps/client/WEB-INF/classes/scripts
# KVM Agent
mkdir -p ${RPM_BUILD_ROOT}/etc/cloud/agent
mkdir -p ${RPM_BUILD_ROOT}/var/log/cloud/agent
install -D packaging/centos63/cloud-agent.rc ${RPM_BUILD_ROOT}/etc/init.d/%{name}-agent
@ -204,12 +216,17 @@ install -D agent/target/transformed/environment.properties ${RPM_BUILD_ROOT}/etc
install -D agent/target/transformed/log4j-cloud.xml ${RPM_BUILD_ROOT}/etc/cloud/agent/log4j-cloud.xml
install -D agent/target/transformed/cloud-setup-agent ${RPM_BUILD_ROOT}/usr/bin/cloud-setup-agent
install -D agent/target/transformed/cloud-ssh ${RPM_BUILD_ROOT}/usr/bin/cloud-ssh
install -D plugins/hypervisors/kvm/target/%{name}-plugin-hypervisor-kvm-%{_maventag}.jar ${RPM_BUILD_ROOT}/usr/share/cloud/java/%{name}-plugin-hypervisor-kvm-%{_maventag}.jar
cp plugins/hypervisors/kvm/target/dependencies/* ${RPM_BUILD_ROOT}/usr/share/cloud/java
mkdir -p ${RPM_BUILD_ROOT}/usr/share/cloud/scripts
cp -r scripts/* ${RPM_BUILD_ROOT}/usr/share/cloud/scripts
# Usage server
install -D usage/target/%{name}-usage-%{_maventag}.jar ${RPM_BUILD_ROOT}/usr/share/cloud/usage/java/%{name}-usage-%{_maventag}.jar
cp usage/target/dependencies/* ${RPM_BUILD_ROOT}/usr/share/cloud/usage/java
install -D packaging/centos63/cloud-usage.rc ${RPM_BUILD_ROOT}/etc/init.d/%{name}-usage
mkdir -p ${RPM_BUILD_ROOT}/var/log/cloud/usage/
%clean
[ ${RPM_BUILD_ROOT} != "/" ] && rm -rf ${RPM_BUILD_ROOT}
@ -306,6 +323,11 @@ fi
%attr(0644,root,root) /usr/share/cloud/java/*.jar
%attr(0755,root,root) /usr/share/cloud/scripts
%files usage
%attr(0755,root,root) %{_sysconfdir}/init.d/cloud-usage
%attr(0644,root,root) /usr/share/cloud/usage/java/*.jar
%dir /var/log/cloud/usage
%changelog
* Fri Oct 03 2012 Hugo Trippaers <hugo@apache.org> 4.1.0
- new style spec file

View File

@ -181,7 +181,7 @@ public class ApiRateLimitTest {
assertTrue("The first request should be allowed", isUnderLimit(key));
// Allow the token to expire
Thread.sleep(1001);
Thread.sleep(1020);
assertTrue("Another request after interval should be allowed as well", isUnderLimit(key));
}
@ -219,7 +219,8 @@ public class ApiRateLimitTest {
ApiLimitResponse response = _limitService.searchApiLimit(testAccount);
assertEquals("apiIssued is incorrect", 5, response.getApiIssued());
assertEquals("apiAllowed is incorrect", 5, response.getApiAllowed());
assertTrue("expiredAfter is incorrect", response.getExpireAfter() < 1000);
// using <= to account for inaccurate System.currentTimeMillis() clock in Windows environment
assertTrue("expiredAfter is incorrect", response.getExpireAfter() <= 1000);
}

View File

@ -0,0 +1,37 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
<version>4.1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>cloud-plugin-hypervisor-baremetal</artifactId>
<name>Apache CloudStack Plugin - Hypervisor Baremetal</name>
<dependencies>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,67 @@
#!/bin/sh
# the following is chkconfig init header
#
# cs-sgagent: cloudStack baremetal sercurity group agent
#
# chkconfig: 345 97 03
# description: This is a daemon instructed by CloudStack management server \
# to perform baremetal security group related operations\
#
# processname: cs-sgagent
# pidfile: /var/run/cssgagent.pid
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
check_status() {
pidfile='/var/run/cssgagent.pid'
if [ ! -f $pidfile ]; then
echo "cloudstack baremetal security group agent is stopped"
exit 1
else
pid=`cat $pidfile`
ps -p $pid > /dev/null
if [ $? -eq 0 ]; then
echo "cloudstack baremetal security group agent is running, pid is $pid"
exit 0
else
echo "cloudstack baremetal security group agent is stopped, but pidfile at $pidfile is not cleaned. It may be caused by the agent crashed at last time, manually cleaning it would be ok"
exit 1
fi
fi
}
if [ $# -eq 0 ]; then
echo "usage: $0
[start|stop|restart|status]"
exit 1
fi
if [ "$@" = "status" ]; then
check_status
else
python -c "from security_group_agent import cs_sg_agent; cs_sg_agent.main()" $@
fi
if [ $? -eq 0 ]; then
echo "$@ cloudstack baremetal security group agent .... SUCCESS"
exit 0
else
echo "$@ cloudstack baremetal security group agent .... FAILED"
exit 1
fi

View File

@ -0,0 +1,18 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Automatically generated by addcopyright.py at 01/29/2013

View File

@ -0,0 +1,237 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Automatically generated by addcopyright.py at 01/29/2013
'''
Created on Jan 2, 2013
@author: frank
'''
import cherrypy
import sglib
import xmlobject
import types
import uuid
import os.path
import sys
import os
class SGRule(object):
def __init__(self):
self.protocol = None
self.start_port = None
self.end_port = None
self.allowed_ips = []
class IPSet(object):
IPSET_TYPE = 'hash:ip'
def __init__(self, setname, ips):
self.ips = ips
self.name = setname
def create(self):
tmpname = str(uuid.uuid4()).replace('-', '')[0:30]
sglib.ShellCmd('ipset -N %s %s' % (tmpname, self.IPSET_TYPE))()
try:
for ip in self.ips:
sglib.ShellCmd('ipset -A %s %s' % (tmpname, ip))()
try:
sglib.ShellCmd('ipset -N %s %s' % (self.name, self.IPSET_TYPE))()
cherrypy.log('created new ipset: %s' % self.name)
except Exception:
cherrypy.log('%s already exists, no need to create new' % self.name)
finally:
sglib.ShellCmd('ipset -W %s %s' % (tmpname, self.name))()
sglib.ShellCmd('ipset -F %s' % tmpname)()
sglib.ShellCmd('ipset -X %s' % tmpname)()
@staticmethod
def destroy_sets(sets_to_keep):
sets = sglib.ShellCmd('ipset list')()
for s in sets.split('\n'):
if 'Name:' in s:
set_name = s.split(':', 1)[1].strip()
if not set_name in sets_to_keep:
sglib.ShellCmd('ipset destroy %s' % set_name)()
cherrypy.log('destroyed unused ipset: %s' % set_name)
class SGAgent(object):
def __init__(self):
pass
def _self_list(self, obj):
if isinstance(obj, types.ListType):
return obj
else:
return [obj]
def set_rules(self, req):
body = req.body
doc = xmlobject.loads(body)
vm_name = doc.vmName.text_
vm_id = doc.vmId.text_
vm_ip = doc.vmIp.text_
vm_mac = doc.vmMac.text_
sig = doc.signature.text_
seq = doc.sequenceNumber.text_
def parse_rules(rules, lst):
for i in self._self_list(rules):
r = SGRule()
r.protocol = i.protocol.text_
r.start_port = i.startPort.text_
r.end_port = i.endPort.text_
if hasattr(i, 'ip'):
for ip in self._self_list(i.ip):
r.allowed_ips.append(ip.text_)
lst.append(r)
i_rules = []
if hasattr(doc, 'ingressRules'):
parse_rules(doc.ingressRules, i_rules)
e_rules = []
if hasattr(doc, 'egressRules'):
parse_rules(doc.egressRules, e_rules)
def create_chain(name):
try:
sglib.ShellCmd('iptables -F %s' % name)()
except Exception:
sglib.ShellCmd('iptables -N %s' % name)()
def apply_rules(rules, chainname, direction, action, current_set_names):
create_chain(chainname)
for r in i_rules:
allow_any = False
if '0.0.0.0/0' in r.allowed_ips:
allow_any = True
r.allowed_ips.remove('0.0.0.0/0')
if r.allowed_ips:
setname = '_'.join([chainname, r.protocol, r.start_port, r.end_port])
ipset = IPSet(setname, r.allowed_ips)
ipset.create()
current_set_names.append(setname)
if r.protocol == 'all':
cmd = ['iptables -I', chainname, '-m state --state NEW -m set --set', setname, direction, '-j', action]
sglib.ShellCmd(' '.join(cmd))()
elif r.protocol != 'icmp':
port_range = ":".join([r.start_port, r.end_port])
cmd = ['iptables', '-I', chainname, '-p', r.protocol, '-m', r.protocol, '--dport', port_range, '-m state --state NEW -m set --set', setname, direction, '-j', action]
sglib.ShellCmd(' '.join(cmd))()
else:
port_range = "/".join([r.start_port, r.end_port])
if r.start_port == "-1":
port_range = "any"
cmd = ['iptables', '-I', i_chain_name, '-p', 'icmp', '--icmp-type', port_range, '-m set --set', setname, direction, '-j', action]
sglib.ShellCmd(' '.join(cmd))()
if allow_any and r.protocol != 'all':
if r.protocol != 'icmp':
port_range = ":".join([r.start_port, r.end_port])
cmd = ['iptables', '-I', chainname, '-p', r.protocol, '-m', r.protocol, '--dport', port_range, '-m', 'state', '--state', 'NEW', '-j', action]
sglib.ShellCmd(' '.join(cmd))()
else:
port_range = "/".join([r.start_port, r.end_port])
if r.start_port == "-1":
port_range = "any"
cmd = ['iptables', '-I', i_chain_name, '-p', 'icmp', '--icmp-type', port_range, '-j', action]
sglib.ShellCmd(' '.join(cmd))()
current_sets = []
i_chain_name = vm_name + '-in'
apply_rules(i_rules, i_chain_name, 'src', 'ACCEPT', current_sets)
e_chain_name = vm_name + '-eg'
apply_rules(e_rules, e_chain_name, 'dst', 'RETURN', current_sets)
if e_rules:
sglib.ShellCmd('iptables -A %s -j RETURN' % e_chain_name)
else:
sglib.ShellCmd('iptables -A %s -j DROP' % e_chain_name)
sglib.ShellCmd('iptables -A %s -j DROP' % i_chain_name)
IPSet.destroy_sets(current_sets)
def echo(self, req):
cherrypy.log("echo: I am alive")
def index(self):
req = sglib.Request.from_cherrypy_request(cherrypy.request)
cmd_name = req.headers['command']
if not hasattr(self, cmd_name):
raise ValueError("SecurityGroupAgent doesn't have a method called '%s'" % cmd_name)
method = getattr(self, cmd_name)
return method(req)
index.exposed = True
@staticmethod
def start():
cherrypy.log.access_file = '/var/log/cs-securitygroup.log'
cherrypy.log.error_file = '/var/log/cs-securitygroup.log'
cherrypy.server.socket_host = '0.0.0.0'
cherrypy.server.socket_port = 9988
cherrypy.quickstart(SGAgent())
@staticmethod
def stop():
cherrypy.engine.exit()
PID_FILE = '/var/run/cssgagent.pid'
class SGAgentDaemon(sglib.Daemon):
def __init__(self):
super(SGAgentDaemon, self).__init__(PID_FILE)
self.is_stopped = False
self.agent = SGAgent()
sglib.Daemon.register_atexit_hook(self._do_stop)
def _do_stop(self):
if self.is_stopped:
return
self.is_stopped = True
self.agent.stop()
def run(self):
self.agent.start()
def stop(self):
self.agent.stop()
super(SGAgentDaemon, self).stop()
def main():
usage = 'usage: python -c "from security_group_agent import cs_sg_agent; cs_sg_agent.main()" start|stop|restart'
if len(sys.argv) != 2 or not sys.argv[1] in ['start', 'stop', 'restart']:
print usage
sys.exit(1)
cmd = sys.argv[1]
agentdaemon = SGAgentDaemon()
if cmd == 'start':
agentdaemon.start()
elif cmd == 'stop':
agentdaemon.stop()
else:
agentdaemon.restart()
sys.exit(0)

View File

@ -0,0 +1,226 @@
#!/usr/bin/env python
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Automatically generated by addcopyright.py at 01/29/2013
import sys, os, time, atexit
import traceback
import subprocess
from signal import SIGTERM
import cherrypy
import copy
class Request(object):
def __init__(self):
self.headers = None
self.body = None
self.method = None
self.query_string = None
@staticmethod
def from_cherrypy_request(creq):
req = Request()
req.headers = copy.copy(creq.headers)
req.body = creq.body.fp.read() if creq.body else None
req.method = copy.copy(creq.method)
req.query_string = copy.copy(creq.query_string) if creq.query_string else None
return req
class ShellError(Exception):
'''shell error'''
class ShellCmd(object):
'''
classdocs
'''
def __init__(self, cmd, workdir=None, pipe=True):
'''
Constructor
'''
self.cmd = cmd
if pipe:
self.process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, executable='/bin/sh', cwd=workdir)
else:
self.process = subprocess.Popen(cmd, shell=True, executable='/bin/sh', cwd=workdir)
self.stdout = None
self.stderr = None
self.return_code = None
def __call__(self, is_exception=True):
(self.stdout, self.stderr) = self.process.communicate()
if is_exception and self.process.returncode != 0:
err = []
err.append('failed to execute shell command: %s' % self.cmd)
err.append('return code: %s' % self.process.returncode)
err.append('stdout: %s' % self.stdout)
err.append('stderr: %s' % self.stderr)
raise ShellError('\n'.join(err))
self.return_code = self.process.returncode
return self.stdout
class Daemon(object):
"""
A generic daemon class.
Usage: subclass the Daemon class and override the run() method
"""
atexit_hooks = []
def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.pidfile = pidfile
@staticmethod
def register_atexit_hook(hook):
Daemon.atexit_hooks.append(hook)
@staticmethod
def _atexit():
for hook in Daemon.atexit_hooks:
try:
hook()
except Exception:
content = traceback.format_exc()
err = 'Exception when calling atexit hook[%s]\n%s' % (hook.__name__, content)
#logger.error(err)
def daemonize(self):
"""
do the UNIX double-fork magic, see Stevens' "Advanced
Programming in the UNIX Environment" for details (ISBN 0201563177)
http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
"""
try:
pid = os.fork()
if pid > 0:
# exit first parent
sys.exit(0)
except OSError, e:
sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
# decouple from parent environment
os.chdir("/")
os.setsid()
os.umask(0)
# do second fork
try:
pid = os.fork()
if pid > 0:
# exit from second parent
sys.exit(0)
except OSError, e:
sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
# redirect standard file descriptors
sys.stdout.flush()
sys.stderr.flush()
si = file(self.stdin, 'r')
so = file(self.stdout, 'a+')
se = file(self.stderr, 'a+', 0)
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
# write pidfile
Daemon.register_atexit_hook(self.delpid)
atexit.register(Daemon._atexit)
pid = str(os.getpid())
file(self.pidfile,'w').write("%s\n" % pid)
def delpid(self):
os.remove(self.pidfile)
def start(self):
"""
Start the daemon
"""
# Check for a pidfile to see if the daemon already runs
try:
pf = file(self.pidfile,'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
if pid:
pscmd = ShellCmd('ps -p %s > /dev/null' % pid)
pscmd(is_exception=False)
if pscmd.return_code == 0:
message = "Daemon already running, pid is %s\n"
sys.stderr.write(message % pid)
sys.exit(0)
# Start the daemon
self.daemonize()
try:
self.run()
except Exception:
content = traceback.format_exc()
#logger.error(content)
sys.exit(1)
def stop(self):
"""
Stop the daemon
"""
# Get the pid from the pidfile
try:
pf = file(self.pidfile,'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
if not pid:
message = "pidfile %s does not exist. Daemon not running?\n"
sys.stderr.write(message % self.pidfile)
return # not an error in a restart
# Try killing the daemon process
try:
while 1:
os.kill(pid, SIGTERM)
time.sleep(0.1)
except OSError, err:
err = str(err)
if err.find("No such process") > 0:
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
else:
print str(err)
sys.exit(1)
def restart(self):
"""
Restart the daemon
"""
self.stop()
self.start()
def run(self):
"""
You should override this method when you subclass Daemon. It will be called after the process has been
daemonized by start() or restart().
"""

View File

@ -0,0 +1,97 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Automatically generated by addcopyright.py at 01/29/2013
'''
Created on Dec 25, 2012
@author: Frank
'''
import xml.etree.ElementTree as etree
import re
import types
class XmlObject(object):
def __init__(self, tag):
self.__tag_name__ = tag
def put_attr(self, name, val):
val = val.strip().strip('\t')
setattr(self, name + '_', val)
def put_text(self, val):
val = val.strip().strip('\n').strip('\t')
if val == "":
setattr(self, 'text_', None)
else:
setattr(self, 'text_', val)
def put_node(self, name, val):
if not hasattr(self, name):
setattr(self, name, val)
return
nodes = getattr(self, name)
if not isinstance(nodes, types.ListType):
nodes = []
old = getattr(self, name)
nodes.append(old)
nodes.append(val)
setattr(self, name, nodes)
else:
nodes.append(val)
setattr(self, name, nodes)
def get(self, name, default=None):
if hasattr(self, name):
val = getattr(self, name)
if name.endswith('_'):
return val
else:
return val.text_
else:
return default
def __getattr__(self, name):
if name.endswith('__'):
n = name[:-1]
if hasattr(self, n):
return getattr(self, n)
else:
return None
else:
e = AttributeError('%s has no attribute %s. missing attribute %s in element <%s>' % (self.__class__.__name__, name, name, self.__tag_name__))
setattr(e, 'missing_attrib', name)
setattr(e, 'tag_name', self.__tag_name__)
raise e
def _loads(node):
xo = XmlObject(node.tag)
for key in node.attrib.keys():
xo.put_attr(key, node.attrib.get(key))
if node.text:
xo.put_text(node.text)
for n in list(node):
sub_xo = _loads(n)
xo.put_node(n.tag, sub_xo)
return xo
def loads(xmlstr):
xmlstr = re.sub(r'xmlns=".*"', '', xmlstr)
root = etree.fromstring(xmlstr)
return _loads(root)

View File

@ -0,0 +1,44 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Automatically generated by addcopyright.py at 01/29/2013
from setuptools import setup, find_packages
import sys, os
version = '1.0'
setup(name='security_group_agent',
version=version,
description="security group agent for CloudStack Baremetal",
long_description="""\
security group agent for CloudStack Baremetal""",
classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
keywords='security group cloudstack',
author='Frank Zhang',
author_email='frank.zhang@citrix.com',
url='http://incubator.apache.org/cloudstack/',
license='Apache License 2',
packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
include_package_data=True,
zip_safe=True,
install_requires=[
'CherryPy',
],
entry_points="""
# -*- Entry points: -*-
""",
)

View File

@ -0,0 +1,25 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.database;
import com.cloud.utils.db.GenericDao;
public interface BaremetalCmdbDao extends GenericDao<BaremetalCmdbVO, Long> {
}

View File

@ -0,0 +1,29 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.database;
import javax.ejb.Local;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GenericDaoBase;
@Local(value = {BaremetalCmdbDao.class})
@DB(txn = false)
public class BaremetalCmdbDaoImpl extends GenericDaoBase<BaremetalCmdbVO, Long> implements BaremetalCmdbDao {
}

View File

@ -0,0 +1,104 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.database;
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="baremetal_cmdb")
public class BaremetalCmdbVO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name="uuid")
private String uuid;
@Column(name="zone_id")
private long zoneId;
@Column(name="url")
private String url;
@Column(name="password")
private String password;
@Column(name="username")
private String username;
public BaremetalCmdbVO() {
uuid = UUID.randomUUID().toString();
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public long getZoneId() {
return zoneId;
}
public void setZoneId(long zoneId) {
this.zoneId = zoneId;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}

View File

@ -0,0 +1,25 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.database;
import com.cloud.utils.db.GenericDao;
public interface BaremetalDhcpDao extends GenericDao<BaremetalDhcpVO, Long> {
}

View File

@ -0,0 +1,42 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.database;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria2;
@Local(value=BaremetalDhcpDao.class)
@DB(txn=false)
public class BaremetalDhcpDaoImpl extends GenericDaoBase<BaremetalDhcpVO, Long> implements BaremetalDhcpDao {
public BaremetalDhcpDaoImpl() {
}
}

View File

@ -0,0 +1,118 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.database;
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="baremetal_dhcp_devices")
public class BaremetalDhcpVO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name="uuid")
private String uuid;
@Column(name = "host_id")
private long hostId;
@Column(name = "pod_id")
private long podId;
@Column(name = "physical_network_id")
private long physicalNetworkId;
@Column(name = "nsp_id")
private long networkServiceProviderId ;
@Column(name = "device_type")
private String deviceType;
public BaremetalDhcpVO() {
super();
this.uuid = UUID.randomUUID().toString();
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public long getHostId() {
return hostId;
}
public void setHostId(long hostId) {
this.hostId = hostId;
}
public long getPhysicalNetworkId() {
return physicalNetworkId;
}
public void setPhysicalNetworkId(long physicalNetworkId) {
this.physicalNetworkId = physicalNetworkId;
}
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
public long getNetworkServiceProviderId() {
return networkServiceProviderId;
}
public void setNetworkServiceProviderId(long networkServiceProviderId) {
this.networkServiceProviderId = networkServiceProviderId;
}
public long getPodId() {
return podId;
}
public void setPodId(long podId) {
this.podId = podId;
}
}

View File

@ -0,0 +1,26 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.database;
import com.cloud.utils.db.GenericDao;
import com.cloud.utils.db.GenericDaoBase;
public interface BaremetalPxeDao extends GenericDao<BaremetalPxeVO, Long> {
}

View File

@ -0,0 +1,38 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.database;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria2;
@Local(value = {BaremetalPxeDao.class})
@DB(txn = false)
public class BaremetalPxeDaoImpl extends GenericDaoBase<BaremetalPxeVO, Long> implements BaremetalPxeDao {
}

View File

@ -0,0 +1,115 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.database;
import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="baremetal_pxe_devices")
public class BaremetalPxeVO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name="uuid")
private String uuid;
@Column(name = "host_id")
private long hostId;
@Column(name = "pod_id")
private long podId;
@Column(name = "physical_network_id")
private long physicalNetworkId;
@Column(name = "nsp_id")
private long networkServiceProviderId ;
@Column(name = "device_type")
private String deviceType;
public long getId() {
return id;
}
public BaremetalPxeVO() {
uuid = UUID.randomUUID().toString();
}
public void setId(long id) {
this.id = id;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public long getHostId() {
return hostId;
}
public void setHostId(long hostId) {
this.hostId = hostId;
}
public long getPhysicalNetworkId() {
return physicalNetworkId;
}
public void setPhysicalNetworkId(long physicalNetworkId) {
this.physicalNetworkId = physicalNetworkId;
}
public long getNetworkServiceProviderId() {
return networkServiceProviderId;
}
public void setNetworkServiceProviderId(long networkServiceProviderId) {
this.networkServiceProviderId = networkServiceProviderId;
}
public long getPodId() {
return podId;
}
public void setPodId(long podId) {
this.podId = podId;
}
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
}

View File

@ -0,0 +1,41 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.manager;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.command.admin.host.AddHostCmd;
public class AddBaremetalHostCmd extends AddHostCmd {
@Parameter(name=ApiConstants.IP_ADDRESS, type=CommandType.STRING, description="ip address intentionally allocated to this host after provisioning")
private String vmIpAddress;
public AddBaremetalHostCmd() {
this.getFullUrlParams().put(ApiConstants.BAREMETAL_DISCOVER_NAME, BareMetalDiscoverer.class.getName());
}
public String getVmIpAddress() {
return vmIpAddress;
}
public void setVmIpAddress(String vmIpAddress) {
this.vmIpAddress = vmIpAddress;
}
}

View File

@ -0,0 +1,280 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.manager;
import java.net.InetAddress;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.log4j.Logger;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.baremetal.networkservice.BareMetalResourceBase;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.exception.DiscoveryException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
import com.cloud.resource.Discoverer;
import com.cloud.resource.DiscovererBase;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ResourceStateAdapter;
import com.cloud.resource.ServerResource;
import com.cloud.resource.UnableDeleteHostException;
import com.cloud.utils.component.Inject;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
import com.cloud.utils.script.Script2;
import com.cloud.utils.script.Script2.ParamType;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.VMInstanceDao;
@Local(value=Discoverer.class)
public class BareMetalDiscoverer extends DiscovererBase implements Discoverer, ResourceStateAdapter {
protected static final Logger s_logger = Logger.getLogger(BareMetalDiscoverer.class);
@Inject protected ClusterDao _clusterDao;
@Inject protected HostDao _hostDao;
@Inject protected DataCenterDao _dcDao;
@Inject protected VMInstanceDao _vmDao = null;
@Inject protected ResourceManager _resourceMgr;
@Inject protected ConfigurationDao _configDao;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
return super.configure(name, params);
}
@Override
public boolean stop() {
_resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName());
return super.stop();
}
@Override
public Map<? extends ServerResource, Map<String, String>> find(long dcId, Long podId, Long clusterId, URI url, String username, String password, List<String> hostTags)
throws DiscoveryException {
String discoverName = _params.get(ApiConstants.BAREMETAL_DISCOVER_NAME);
if (!this.getClass().getName().equals(discoverName)) {
return null;
}
Map<BareMetalResourceBase, Map<String, String>> resources = new HashMap<BareMetalResourceBase, Map<String, String>>();
Map<String, String> details = new HashMap<String, String>();
if (!url.getScheme().equals("http")) {
String msg = "urlString is not http so we're not taking care of the discovery for this: " + url;
s_logger.debug(msg);
return null;
}
if (clusterId == null) {
String msg = "must specify cluster Id when add host";
s_logger.debug(msg);
throw new RuntimeException(msg);
}
if (podId == null) {
String msg = "must specify pod Id when add host";
s_logger.debug(msg);
throw new RuntimeException(msg);
}
ClusterVO cluster = _clusterDao.findById(clusterId);
if (cluster == null || (cluster.getHypervisorType() != HypervisorType.BareMetal)) {
if (s_logger.isInfoEnabled())
s_logger.info("invalid cluster id or cluster is not for Bare Metal hosts");
return null;
}
DataCenterVO zone = _dcDao.findById(dcId);
if (zone == null) {
throw new RuntimeException("Cannot find zone " + dcId);
}
try {
String hostname = url.getHost();
InetAddress ia = InetAddress.getByName(hostname);
String ipmiIp = ia.getHostAddress();
String guid = UUID.nameUUIDFromBytes(ipmiIp.getBytes()).toString();
String injectScript = "scripts/util/ipmi.py";
String scriptPath = Script.findScript("", injectScript);
if (scriptPath == null) {
throw new CloudRuntimeException("Unable to find key ipmi script "
+ injectScript);
}
final Script2 command = new Script2(scriptPath, s_logger);
command.add("ping");
command.add("hostname="+ipmiIp);
command.add("usrname="+username);
command.add("password="+password, ParamType.PASSWORD);
final String result = command.execute();
if (result != null) {
s_logger.warn(String.format("Can not set up ipmi connection(ip=%1$s, username=%2$s, password=%3$s, args) because %4$s", ipmiIp, username, "******", result));
return null;
}
ClusterVO clu = _clusterDao.findById(clusterId);
if (clu.getGuid() == null) {
clu.setGuid(UUID.randomUUID().toString());
_clusterDao.update(clusterId, clu);
}
Map<String, Object> params = new HashMap<String, Object>();
params.putAll(_params);
params.put("zone", Long.toString(dcId));
params.put("pod", Long.toString(podId));
params.put("cluster", Long.toString(clusterId));
params.put("guid", guid);
params.put(ApiConstants.PRIVATE_IP, ipmiIp);
params.put(ApiConstants.USERNAME, username);
params.put(ApiConstants.PASSWORD, password);
String resourceClassName = _configDao.getValue(Config.ExternalBaremetalResourceClassName.key());
BareMetalResourceBase resource = null;
if (resourceClassName != null) {
Class<?> clazz = Class.forName(resourceClassName);
resource = (BareMetalResourceBase) clazz.newInstance();
String externalUrl = _configDao.getValue(Config.ExternalBaremetalSystemUrl.key());
if (externalUrl == null) {
throw new IllegalArgumentException(String.format("You must specify ExternalBaremetalSystemUrl in global config page as ExternalBaremetalResourceClassName is not null"));
}
details.put(BaremetalManager.ExternalBaremetalSystemUrl, externalUrl);
} else {
resource = new BareMetalResourceBase();
}
resource.configure("Bare Metal Agent", params);
String memCapacity = (String)params.get(ApiConstants.MEMORY);
String cpuCapacity = (String)params.get(ApiConstants.CPU_SPEED);
String cpuNum = (String)params.get(ApiConstants.CPU_NUMBER);
String mac = (String)params.get(ApiConstants.HOST_MAC);
if (hostTags != null && hostTags.size() != 0) {
details.put("hostTag", hostTags.get(0));
}
details.put(ApiConstants.MEMORY, memCapacity);
details.put(ApiConstants.CPU_SPEED, cpuCapacity);
details.put(ApiConstants.CPU_NUMBER, cpuNum);
details.put(ApiConstants.HOST_MAC, mac);
details.put(ApiConstants.USERNAME, username);
details.put(ApiConstants.PASSWORD, password);
details.put(ApiConstants.PRIVATE_IP, ipmiIp);
String vmIp = (String)params.get(ApiConstants.IP_ADDRESS);
if (vmIp != null) {
details.put(ApiConstants.IP_ADDRESS, vmIp);
}
String isEchoScAgent = _configDao.getValue(Config.EnableBaremetalSecurityGroupAgentEcho.key());
details.put(BaremetalManager.EchoSecurityGroupAgent, isEchoScAgent);
resources.put(resource, details);
resource.start();
zone.setGatewayProvider(Network.Provider.ExternalGateWay.getName());
zone.setDnsProvider(Network.Provider.ExternalDhcpServer.getName());
zone.setDhcpProvider(Network.Provider.ExternalDhcpServer.getName());
_dcDao.update(zone.getId(), zone);
s_logger.debug(String.format("Discover Bare Metal host successfully(ip=%1$s, username=%2$s, password=%3%s," +
"cpuNum=%4$s, cpuCapacity-%5$s, memCapacity=%6$s)", ipmiIp, username, "******", cpuNum, cpuCapacity, memCapacity));
return resources;
} catch (Exception e) {
s_logger.warn("Can not set up bare metal agent", e);
}
return null;
}
@Override
public void postDiscovery(List<HostVO> hosts, long msId)
throws DiscoveryException {
}
@Override
public boolean matchHypervisor(String hypervisor) {
return hypervisor.equalsIgnoreCase(Hypervisor.HypervisorType.BareMetal.toString());
}
@Override
public HypervisorType getHypervisorType() {
return Hypervisor.HypervisorType.BareMetal;
}
@Override
public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
// TODO Auto-generated method stub
return null;
}
@Override
public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details,
List<String> hostTags) {
StartupCommand firstCmd = startup[0];
if (!(firstCmd instanceof StartupRoutingCommand)) {
return null;
}
StartupRoutingCommand ssCmd = ((StartupRoutingCommand) firstCmd);
if (ssCmd.getHypervisorType() != HypervisorType.BareMetal) {
return null;
}
return _resourceMgr.fillRoutingHostVO(host, ssCmd, HypervisorType.BareMetal, details, hostTags);
}
@Override
public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
if (host.getType() != Host.Type.Routing || host.getHypervisorType() != HypervisorType.BareMetal) {
return null;
}
List<VMInstanceVO> deadVms = _vmDao.listByLastHostId(host.getId());
for (VMInstanceVO vm : deadVms) {
if (vm.getState() == State.Running || vm.getHostId() != null) {
throw new CloudRuntimeException("VM " + vm.getId() + "is still running on host " + host.getId());
}
_vmDao.remove(vm.getId());
}
return new DeleteHostAnswer(true);
}
}

View File

@ -0,0 +1,87 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.manager;
import java.util.HashMap;
import java.util.Map;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.hypervisor.HypervisorGuru;
import com.cloud.hypervisor.HypervisorGuruBase;
import com.cloud.storage.GuestOSVO;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.utils.component.Inject;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.VMInstanceDao;
@Local(value=HypervisorGuru.class)
public class BareMetalGuru extends HypervisorGuruBase implements HypervisorGuru {
private static final Logger s_logger = Logger.getLogger(BareMetalGuru.class);
@Inject GuestOSDao _guestOsDao;
@Inject HostDao _hostDao;
@Inject VMInstanceDao _vmDao;
protected BareMetalGuru() {
super();
}
@Override
public HypervisorType getHypervisorType() {
return HypervisorType.BareMetal;
}
@Override
public <T extends VirtualMachine> VirtualMachineTO implement(VirtualMachineProfile<T> vm) {
VirtualMachineTO to = toVirtualMachineTO(vm);
VMInstanceVO vo = _vmDao.findById(vm.getId());
if (vo.getLastHostId() == null) {
to.setBootArgs(BaremetalManager.DO_PXE);
}
Map<String, String> details = new HashMap<String, String>();
details.put("template", vm.getTemplate().getUrl());
to.setDetails(details);
// Determine the VM's OS description
GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId());
to.setOs(guestOS.getDisplayName());
return to;
}
@Override
public boolean trackVmHostChange() {
return false;
}
}

View File

@ -0,0 +1,217 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.manager;
import java.util.Date;
import java.util.List;
import javax.ejb.Local;
import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
import org.apache.log4j.Logger;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.dc.DataCenterVO;
import com.cloud.event.EventTypes;
import com.cloud.event.UsageEventVO;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.resource.ResourceManager;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VMTemplateZoneVO;
import com.cloud.template.TemplateAdapter;
import com.cloud.template.TemplateAdapterBase;
import com.cloud.template.TemplateProfile;
import com.cloud.user.Account;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.exception.CloudRuntimeException;
@Local(value=TemplateAdapter.class)
public class BareMetalTemplateAdapter extends TemplateAdapterBase implements TemplateAdapter {
private final static Logger s_logger = Logger.getLogger(BareMetalTemplateAdapter.class);
@Inject HostDao _hostDao;
@Inject ResourceManager _resourceMgr;
@Override
public TemplateProfile prepare(RegisterTemplateCmd cmd) throws ResourceAllocationException {
TemplateProfile profile = super.prepare(cmd);
if (profile.getZoneId() == null || profile.getZoneId() == -1) {
List<DataCenterVO> dcs = _dcDao.listAllIncludingRemoved();
for (DataCenterVO dc : dcs) {
List<HostVO> pxeServers = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, dc.getId());
if (pxeServers.size() == 0) {
throw new CloudRuntimeException("Please add PXE server before adding baremetal template in zone " + dc.getName());
}
}
} else {
List<HostVO> pxeServers = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, profile.getZoneId());
if (pxeServers.size() == 0) {
throw new CloudRuntimeException("Please add PXE server before adding baremetal template in zone " + profile.getZoneId());
}
}
return profile;
}
@Override
public TemplateProfile prepare(RegisterIsoCmd cmd) throws ResourceAllocationException {
throw new CloudRuntimeException("Baremetal doesn't support ISO template");
}
private void templateCreateUsage(VMTemplateVO template, HostVO host) {
if (template.getAccountId() != Account.ACCOUNT_ID_SYSTEM) {
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_TEMPLATE_CREATE, template.getAccountId(), host.getDataCenterId(),
template.getId(), template.getName(), null, template.getSourceTemplateId(), 0L);
_usageEventDao.persist(usageEvent);
}
}
@Override
public VMTemplateVO create(TemplateProfile profile) {
VMTemplateVO template = persistTemplate(profile);
Long zoneId = profile.getZoneId();
/* There is no secondary storage vm for baremetal, we use pxe server id.
* Tempalte is not bound to pxeserver right now, and we assume the pxeserver
* cannot be removed once it was added. so we use host id of first found pxe
* server as reference in template_host_ref.
* This maybe a FIXME in future.
*/
VMTemplateHostVO vmTemplateHost = null;
if (zoneId == null || zoneId == -1) {
List<DataCenterVO> dcs = _dcDao.listAllIncludingRemoved();
for (DataCenterVO dc : dcs) {
HostVO pxe = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, dc.getId()).get(0);
vmTemplateHost = _tmpltHostDao.findByHostTemplate(dc.getId(), template.getId());
if (vmTemplateHost == null) {
vmTemplateHost = new VMTemplateHostVO(pxe.getId(), template.getId(), new Date(), 100,
Status.DOWNLOADED, null, null, null, null, template.getUrl());
_tmpltHostDao.persist(vmTemplateHost);
templateCreateUsage(template, pxe);
}
}
} else {
HostVO pxe = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, zoneId).get(0);
vmTemplateHost = new VMTemplateHostVO(pxe.getId(), template.getId(), new Date(), 100,
Status.DOWNLOADED, null, null, null, null, template.getUrl());
_tmpltHostDao.persist(vmTemplateHost);
templateCreateUsage(template, pxe);
}
_resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template);
return template;
}
public TemplateProfile prepareDelete(DeleteIsoCmd cmd) {
throw new CloudRuntimeException("Baremetal doesn't support ISO, how the delete get here???");
}
@Override @DB
public boolean delete(TemplateProfile profile) {
VMTemplateVO template = profile.getTemplate();
Long templateId = template.getId();
boolean success = true;
String zoneName;
boolean isAllZone;
if (!template.isCrossZones() && profile.getZoneId() != null) {
isAllZone = false;
zoneName = profile.getZoneId().toString();
} else {
zoneName = "all zones";
isAllZone = true;
}
s_logger.debug("Attempting to mark template host refs for template: " + template.getName() + " as destroyed in zone: " + zoneName);
Account account = _accountDao.findByIdIncludingRemoved(template.getAccountId());
String eventType = EventTypes.EVENT_TEMPLATE_DELETE;
List<VMTemplateHostVO> templateHostVOs = _tmpltHostDao.listByTemplateId(templateId);
for (VMTemplateHostVO vo : templateHostVOs) {
VMTemplateHostVO lock = null;
try {
HostVO pxeServer = _hostDao.findById(vo.getHostId());
if (!isAllZone && pxeServer.getDataCenterId() != profile.getZoneId()) {
continue;
}
lock = _tmpltHostDao.acquireInLockTable(vo.getId());
if (lock == null) {
s_logger.debug("Failed to acquire lock when deleting templateHostVO with ID: " + vo.getId());
success = false;
break;
}
vo.setDestroyed(true);
_tmpltHostDao.update(vo.getId(), vo);
VMTemplateZoneVO templateZone = _tmpltZoneDao.findByZoneTemplate(pxeServer.getDataCenterId(), templateId);
if (templateZone != null) {
_tmpltZoneDao.remove(templateZone.getId());
}
UsageEventVO usageEvent = new UsageEventVO(eventType, account.getId(), pxeServer.getDataCenterId(), templateId, null);
_usageEventDao.persist(usageEvent);
} finally {
if (lock != null) {
_tmpltHostDao.releaseFromLockTable(lock.getId());
}
}
}
s_logger.debug("Successfully marked template host refs for template: " + template.getName() + " as destroyed in zone: " + zoneName);
// If there are no more non-destroyed template host entries for this template, delete it
if (success && (_tmpltHostDao.listByTemplateId(templateId).size() == 0)) {
long accountId = template.getAccountId();
VMTemplateVO lock = _tmpltDao.acquireInLockTable(templateId);
try {
if (lock == null) {
s_logger.debug("Failed to acquire lock when deleting template with ID: " + templateId);
success = false;
} else if (_tmpltDao.remove(templateId)) {
// Decrement the number of templates
_resourceLimitMgr.decrementResourceCount(accountId, ResourceType.template);
}
} finally {
if (lock != null) {
_tmpltDao.releaseFromLockTable(lock.getId());
}
}
s_logger.debug("Removed template: " + template.getName() + " because all of its template host refs were marked as destroyed.");
}
return success;
}
}

View File

@ -0,0 +1,28 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.manager;
import com.cloud.network.Network.Provider;
import com.cloud.utils.component.Manager;
public interface BaremetalManager extends Manager {
public static final String EchoSecurityGroupAgent = "EchoSecurityGroupAgent";
public static final String ExternalBaremetalSystemUrl = "ExternalBaremetalSystemUrl";
public static final String DO_PXE = "doPxe";
}

View File

@ -0,0 +1,112 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.manager;
import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.api.StopAnswer;
import com.cloud.agent.manager.Commands;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.utils.component.Inject;
import com.cloud.utils.fsm.StateListener;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineGuru;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.VirtualMachineName;
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.VirtualMachineProfile;
@Local(value = {BaremetalManager.class})
public class BaremetalManagerImpl implements BaremetalManager, StateListener<State, VirtualMachine.Event, VirtualMachine> {
private static final Logger s_logger = Logger.getLogger(BaremetalManagerImpl.class);
@Inject
protected HostDao _hostDao;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
VirtualMachine.State.getStateMachine().registerListener(this);
return true;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public String getName() {
return "Baremetal Manager";
}
@Override
public boolean preStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, boolean status, Object opaque) {
return false;
}
@Override
public boolean postStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, boolean status, Object opaque) {
if (newState != State.Starting && newState != State.Error && newState != State.Expunging) {
return true;
}
if (vo.getHypervisorType() != HypervisorType.BareMetal) {
return true;
}
HostVO host = _hostDao.findById(vo.getHostId());
if (host == null) {
s_logger.debug("Skip oldState " + oldState + " to " + "newState " + newState + " transimtion");
return true;
}
_hostDao.loadDetails(host);
if (newState == State.Starting) {
host.setDetail("vmName", vo.getInstanceName());
s_logger.debug("Add vmName " + host.getDetail("vmName") + " to host " + host.getId() + " details");
} else {
if (host.getDetail("vmName") != null && host.getDetail("vmName").equalsIgnoreCase(vo.getInstanceName())) {
s_logger.debug("Remove vmName " + host.getDetail("vmName") + " from host " + host.getId() + " details");
host.getDetails().remove("vmName");
}
}
_hostDao.saveDetails(host);
return true;
}
}

View File

@ -0,0 +1,149 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.BaseCmd.CommandType;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.PlugService;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.log4j.Logger;
import com.cloud.baremetal.database.BaremetalDhcpVO;
import com.cloud.event.EventTypes;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.UserContext;
public class AddBaremetalDhcpCmd extends BaseAsyncCmd {
private static final String s_name = "addexternaldhcpresponse";
public static final Logger s_logger = Logger.getLogger(AddBaremetalDhcpCmd.class);
@PlugService BaremetalDhcpManager mgr;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.LONG, required=true, description="the Physical Network ID")
private Long physicalNetworkId;
@Parameter(name=ApiConstants.POD_ID, type=CommandType.LONG, required = true, description="Pod Id")
private Long podId;
@Parameter(name=ApiConstants.DHCP_SERVER_TYPE, type=CommandType.STRING, required = true, description="Type of dhcp device")
private String dhcpType;
@Parameter(name=ApiConstants.URL, type=CommandType.STRING, required = true, description="URL of the external dhcp appliance.")
private String url;
@Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required = true, description="Credentials to reach external dhcp device")
private String username;
@Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required = true, description="Credentials to reach external dhcp device")
private String password;
@Override
public String getEventType() {
return EventTypes.EVENT_BAREMETAL_DHCP_SERVER_ADD;
}
@Override
public String getEventDescription() {
return "Adding an external DHCP server";
}
@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
ResourceAllocationException, NetworkRuleConflictException {
try {
BaremetalDhcpVO vo = mgr.addDchpServer(this);
BaremetalDhcpResponse response = mgr.generateApiResponse(vo);
response.setObjectName(s_name);
response.setResponseName(getCommandName());
this.setResponseObject(response);
} catch (Exception e) {
s_logger.warn("Unable to add external dhcp server with url: " + getUrl(), e);
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
}
}
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return UserContext.current().getCaller().getId();
}
public Long getPodId() {
return podId;
}
public void setPodId(Long podId) {
this.podId = podId;
}
public String getDhcpType() {
return dhcpType;
}
public void setDhcpType(String dhcpType) {
this.dhcpType = dhcpType;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Long getPhysicalNetworkId() {
return physicalNetworkId;
}
public void setPhysicalNetworkId(Long physicalNetworkId) {
this.physicalNetworkId = physicalNetworkId;
}
}

View File

@ -0,0 +1,36 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd.CommandType;
import org.apache.cloudstack.api.Parameter;
public class AddBaremetalKickStartPxeCmd extends AddBaremetalPxeCmd {
@Parameter(name=ApiConstants.TFTP_DIR, type=CommandType.STRING, required = true, description="Tftp root directory of PXE server")
private String tftpDir;
public String getTftpDir() {
return tftpDir;
}
public void setTftpDir(String tftpDir) {
this.tftpDir = tftpDir;
}
}

View File

@ -0,0 +1,144 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.BaseCmd.CommandType;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.PlugService;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.log4j.Logger;
import com.cloud.baremetal.database.BaremetalPxeVO;
import com.cloud.event.EventTypes;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.UserContext;
public class AddBaremetalPxeCmd extends BaseAsyncCmd {
private static final String s_name = "addexternalpxeresponse";
public static final Logger s_logger = Logger.getLogger(AddBaremetalPxeCmd.class);
@PlugService BaremetalPxeManager pxeMgr;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.LONG, required=true, description="the Physical Network ID")
private Long physicalNetworkId;
@Parameter(name=ApiConstants.POD_ID, type=CommandType.LONG, description="Pod Id")
private Long podId;
@Parameter(name=ApiConstants.URL, type=CommandType.STRING, required = true, description="URL of the external pxe device")
private String url;
@Parameter(name=ApiConstants.PXE_SERVER_TYPE, type=CommandType.STRING, required = true, description="type of pxe device")
private String deviceType;
@Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required = true, description="Credentials to reach external pxe device")
private String username;
@Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required = true, description="Credentials to reach external pxe device")
private String password;
@Override
public String getEventType() {
return EventTypes.EVENT_BAREMETAL_PXE_SERVER_ADD;
}
@Override
public String getEventDescription() {
return "Adding an external pxe server";
}
@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
ResourceAllocationException, NetworkRuleConflictException {
try {
BaremetalPxeVO vo = pxeMgr.addPxeServer(this);
} catch (Exception e) {
s_logger.warn("Unable to add external pxe server with url: " + getUrl(), e);
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
}
}
@Override
public String getCommandName() {
return s_name;
}
@Override
public long getEntityOwnerId() {
return UserContext.current().getCaller().getId();
}
public Long getPhysicalNetworkId() {
return physicalNetworkId;
}
public void setPhysicalNetworkId(Long physicalNetworkId) {
this.physicalNetworkId = physicalNetworkId;
}
public Long getPodId() {
return podId;
}
public void setPodId(Long podId) {
this.podId = podId;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
}

View File

@ -0,0 +1,80 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.Parameter;
public class AddBaremetalPxePingServerCmd extends AddBaremetalPxeCmd {
@Parameter(name=ApiConstants.PING_STORAGE_SERVER_IP, type=CommandType.STRING, required = true, description="PING storage server ip")
private String pingStorageServerIp;
@Parameter(name=ApiConstants.PING_DIR, type=CommandType.STRING, required = true, description="Root directory on PING storage server")
private String pingDir;
@Parameter(name=ApiConstants.TFTP_DIR, type=CommandType.STRING, required = true, description="Tftp root directory of PXE server")
private String tftpDir;
@Parameter(name=ApiConstants.PING_CIFS_USERNAME, type=CommandType.STRING, description="Username of PING storage server")
private String pingStorageServerUserName;
@Parameter(name=ApiConstants.PING_CIFS_PASSWORD, type=CommandType.STRING, description="Password of PING storage server")
private String pingStorageServerPassword;
public String getPingStorageServerIp() {
return pingStorageServerIp;
}
public void setPingStorageServerIp(String pingStorageServerIp) {
this.pingStorageServerIp = pingStorageServerIp;
}
public String getPingDir() {
return pingDir;
}
public void setPingDir(String pingDir) {
this.pingDir = pingDir;
}
public String getTftpDir() {
return tftpDir;
}
public void setTftpDir(String tftpDir) {
this.tftpDir = tftpDir;
}
public String getPingStorageServerUserName() {
return pingStorageServerUserName;
}
public void setPingStorageServerUserName(String pingStorageServerUserName) {
this.pingStorageServerUserName = pingStorageServerUserName;
}
public String getPingStorageServerPassword() {
return pingStorageServerPassword;
}
public void setPingStorageServerPassword(String pingStorageServerPassword) {
this.pingStorageServerPassword = pingStorageServerPassword;
}
}

View File

@ -0,0 +1,300 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand;
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand.BootDev;
import com.cloud.agent.api.baremetal.PreparePxeServerAnswer;
import com.cloud.agent.api.baremetal.PreparePxeServerCommand;
import com.cloud.agent.api.baremetal.prepareCreateTemplateCommand;
import com.cloud.baremetal.database.BaremetalPxeDao;
import com.cloud.baremetal.database.BaremetalPxeVO;
import com.cloud.baremetal.networkservice.BaremetalPxeManager.BaremetalPxeType;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.deploy.DeployDestination;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDetailsDao;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.PhysicalNetworkVO;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ServerResource;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.SearchCriteria2;
import com.cloud.utils.db.SearchCriteriaService;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicProfile;
import com.cloud.vm.NicVO;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachineProfile;
@Local(value=BaremetalPxeService.class)
public class BareMetalPingServiceImpl extends BareMetalPxeServiceBase implements BaremetalPxeService {
private static final Logger s_logger = Logger.getLogger(BareMetalPingServiceImpl.class);
@Inject ResourceManager _resourceMgr;
@Inject PhysicalNetworkDao _physicalNetworkDao;
@Inject PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
@Inject HostDetailsDao _hostDetailsDao;
@Inject BaremetalPxeDao _pxeDao;
@Override
public boolean prepare(VirtualMachineProfile<UserVmVO> profile, NicProfile pxeNic, DeployDestination dest, ReservationContext context) {
SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, BaremetalPxeType.PING.toString());
sc.addAnd(sc.getEntity().getPodId(), Op.EQ, dest.getPod().getId());
BaremetalPxeVO pxeVo = sc.find();
if (pxeVo == null) {
throw new CloudRuntimeException("No PING PXE server found in pod: " + dest.getPod().getId() + ", you need to add it before starting VM");
}
long pxeServerId = pxeVo.getHostId();
String mac = pxeNic.getMacAddress();
String ip = pxeNic.getIp4Address();
String gateway = pxeNic.getGateway();
String mask = pxeNic.getNetmask();
String dns = pxeNic.getDns1();
if (dns == null) {
dns = pxeNic.getDns2();
}
try {
String tpl = profile.getTemplate().getUrl();
assert tpl != null : "How can a null template get here!!!";
PreparePxeServerCommand cmd = new PreparePxeServerCommand(ip, mac, mask, gateway, dns, tpl,
profile.getVirtualMachine().getInstanceName(), dest.getHost().getName());
PreparePxeServerAnswer ans = (PreparePxeServerAnswer) _agentMgr.send(pxeServerId, cmd);
if (!ans.getResult()) {
s_logger.warn("Unable tot program PXE server: " + pxeVo.getId() + " because " + ans.getDetails());
return false;
}
IpmISetBootDevCommand bootCmd = new IpmISetBootDevCommand(BootDev.pxe);
Answer anw = _agentMgr.send(dest.getHost().getId(), bootCmd);
if (!anw.getResult()) {
s_logger.warn("Unable to set host: " + dest.getHost().getId() + " to PXE boot because " + anw.getDetails());
}
return anw.getResult();
} catch (Exception e) {
s_logger.warn("Cannot prepare PXE server", e);
return false;
}
}
@Override
public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl) {
List<NicVO> nics = _nicDao.listByVmId(vm.getId());
if (nics.size() != 1) {
throw new CloudRuntimeException("Wrong nic number " + nics.size() + " of vm " + vm.getId());
}
/* use last host id when VM stopped */
Long hostId = (vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId());
HostVO host = _hostDao.findById(hostId);
DataCenterVO dc = _dcDao.findById(host.getDataCenterId());
NicVO nic = nics.get(0);
String mask = nic.getNetmask();
String mac = nic.getMacAddress();
String ip = nic.getIp4Address();
String gateway = nic.getGateway();
String dns = dc.getDns1();
if (dns == null) {
dns = dc.getDns2();
}
try {
prepareCreateTemplateCommand cmd = new prepareCreateTemplateCommand(ip, mac, mask, gateway, dns, templateUrl);
Answer ans = _agentMgr.send(pxeServerId, cmd);
return ans.getResult();
} catch (Exception e) {
s_logger.debug("Prepare for creating baremetal template failed", e);
return false;
}
}
@Override
@DB
public BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd) {
AddBaremetalPxePingServerCmd pcmd = (AddBaremetalPxePingServerCmd)cmd;
PhysicalNetworkVO pNetwork = null;
long zoneId;
if (cmd.getPhysicalNetworkId() == null || cmd.getUrl() == null || cmd.getUsername() == null || cmd.getPassword() == null) {
throw new IllegalArgumentException("At least one of the required parameters(physical network id, url, username, password) is null");
}
pNetwork = _physicalNetworkDao.findById(cmd.getPhysicalNetworkId());
if (pNetwork == null) {
throw new IllegalArgumentException("Could not find phyical network with ID: " + cmd.getPhysicalNetworkId());
}
zoneId = pNetwork.getDataCenterId();
PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER.getName());
if (ntwkSvcProvider == null) {
throw new CloudRuntimeException("Network Service Provider: " + BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER.getName() +
" is not enabled in the physical network: " + cmd.getPhysicalNetworkId() + "to add this device");
} else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() +
" is in shutdown state in the physical network: " + cmd.getPhysicalNetworkId() + "to add this device");
}
HostPodVO pod = _podDao.findById(cmd.getPodId());
if (pod == null) {
throw new IllegalArgumentException("Could not find pod with ID: " + cmd.getPodId());
}
List<HostVO> pxes = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.BaremetalPxe, null, cmd.getPodId(), zoneId);
if (pxes.size() != 0) {
throw new IllegalArgumentException("Already had a PXE server in Pod: " + cmd.getPodId() + " zone: " + zoneId);
}
String storageServerIp = pcmd.getPingStorageServerIp();
if (storageServerIp == null) {
throw new IllegalArgumentException("No IP for storage server specified");
}
String pingDir = pcmd.getPingDir();
if (pingDir == null) {
throw new IllegalArgumentException("No direcotry for storage server specified");
}
String tftpDir = pcmd.getTftpDir();
if (tftpDir == null) {
throw new IllegalArgumentException("No TFTP directory specified");
}
String cifsUsername = pcmd.getPingStorageServerUserName();
if (cifsUsername == null || cifsUsername.equalsIgnoreCase("")) {
cifsUsername = "xxx";
}
String cifsPassword = pcmd.getPingStorageServerPassword();
if (cifsPassword == null || cifsPassword.equalsIgnoreCase("")) {
cifsPassword = "xxx";
}
URI uri;
try {
uri = new URI(cmd.getUrl());
} catch (Exception e) {
s_logger.debug(e);
throw new IllegalArgumentException(e.getMessage());
}
String ipAddress = uri.getHost();
String guid = getPxeServerGuid(Long.toString(zoneId) + "-" + pod.getId(), BaremetalPxeType.PING.toString(), ipAddress);
ServerResource resource = null;
Map params = new HashMap<String, String>();
params.put(BaremetalPxeService.PXE_PARAM_ZONE, Long.toString(zoneId));
params.put(BaremetalPxeService.PXE_PARAM_POD, String.valueOf(pod.getId()));
params.put(BaremetalPxeService.PXE_PARAM_IP, ipAddress);
params.put(BaremetalPxeService.PXE_PARAM_USERNAME, cmd.getUsername());
params.put(BaremetalPxeService.PXE_PARAM_PASSWORD, cmd.getPassword());
params.put(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_IP, storageServerIp);
params.put(BaremetalPxeService.PXE_PARAM_PING_ROOT_DIR, pingDir);
params.put(BaremetalPxeService.PXE_PARAM_TFTP_DIR, tftpDir);
params.put(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_USERNAME, cifsUsername);
params.put(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_PASSWORD, cifsPassword);
params.put(BaremetalPxeService.PXE_PARAM_GUID, guid);
resource = new BaremetalPingPxeResource();
try {
resource.configure("PING PXE resource", params);
} catch (Exception e) {
s_logger.debug(e);
throw new CloudRuntimeException(e.getMessage());
}
Host pxeServer = _resourceMgr.addHost(zoneId, resource, Host.Type.BaremetalPxe, params);
if (pxeServer == null) {
throw new CloudRuntimeException("Cannot add PXE server as a host");
}
BaremetalPxeVO vo = new BaremetalPxeVO();
Transaction txn = Transaction.currentTxn();
vo.setHostId(pxeServer.getId());
vo.setNetworkServiceProviderId(ntwkSvcProvider.getId());
vo.setPodId(pod.getId());
vo.setPhysicalNetworkId(pcmd.getPhysicalNetworkId());
vo.setDeviceType(BaremetalPxeType.PING.toString());
txn.start();
_pxeDao.persist(vo);
txn.commit();
return vo;
}
@Override
public BaremetalPxeResponse getApiResponse(BaremetalPxeVO vo) {
BaremetalPxePingResponse response = new BaremetalPxePingResponse();
response.setId(String.valueOf(vo.getId()));
response.setPhysicalNetworkId(String.valueOf(vo.getPhysicalNetworkId()));
response.setPodId(String.valueOf(vo.getPodId()));
Map<String, String> details = _hostDetailsDao.findDetails(vo.getHostId());
response.setPingStorageServerIp(details.get(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_IP));
response.setPingDir(details.get(BaremetalPxeService.PXE_PARAM_PING_ROOT_DIR));
response.setTftpDir(details.get(BaremetalPxeService.PXE_PARAM_TFTP_DIR));
return response;
}
@Override
public List<BaremetalPxeResponse> listPxeServers(ListBaremetalPxePingServersCmd cmd) {
SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, BaremetalPxeType.PING.toString());
if (cmd.getPodId() != null) {
sc.addAnd(sc.getEntity().getPodId(), Op.EQ, cmd.getPodId());
if (cmd.getId() != null) {
sc.addAnd(sc.getEntity().getId(), Op.EQ, cmd.getId());
}
}
List<BaremetalPxeVO> vos = sc.list();
List<BaremetalPxeResponse> responses = new ArrayList<BaremetalPxeResponse>(vos.size());
for (BaremetalPxeVO vo : vos) {
responses.add(getApiResponse(vo));
}
return responses;
}
}

View File

@ -0,0 +1,68 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.Map;
import javax.naming.ConfigurationException;
import com.cloud.agent.AgentManager;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.host.dao.HostDao;
import com.cloud.utils.component.Inject;
import com.cloud.vm.dao.NicDao;
public abstract class BareMetalPxeServiceBase implements BaremetalPxeService {
protected String _name;
@Inject DataCenterDao _dcDao;
@Inject HostDao _hostDao;
@Inject AgentManager _agentMgr;
@Inject HostPodDao _podDao;
@Inject NicDao _nicDao;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_name = name;
return true;
}
@Override
public String getName() {
return _name;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
protected String getPxeServerGuid(String zoneId, String name, String ip) {
return zoneId + "-" + name + "-" + ip;
}
}

View File

@ -0,0 +1,618 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.log4j.Logger;
import com.cloud.agent.IAgentControl;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.CheckNetworkAnswer;
import com.cloud.agent.api.CheckNetworkCommand;
import com.cloud.agent.api.CheckVirtualMachineAnswer;
import com.cloud.agent.api.CheckVirtualMachineCommand;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.MaintainAnswer;
import com.cloud.agent.api.MaintainCommand;
import com.cloud.agent.api.MigrateAnswer;
import com.cloud.agent.api.MigrateCommand;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.PrepareForMigrationAnswer;
import com.cloud.agent.api.PrepareForMigrationCommand;
import com.cloud.agent.api.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.RebootAnswer;
import com.cloud.agent.api.RebootCommand;
import com.cloud.agent.api.SecurityGroupRulesCmd;
import com.cloud.agent.api.StartAnswer;
import com.cloud.agent.api.StartCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.StopAnswer;
import com.cloud.agent.api.StopCommand;
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand;
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand.BootDev;
import com.cloud.agent.api.baremetal.IpmiBootorResetCommand;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.baremetal.manager.BaremetalManager;
import com.cloud.host.Host.Type;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.resource.ServerResource;
import com.cloud.server.ManagementServer;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.OutputInterpreter;
import com.cloud.utils.script.Script;
import com.cloud.utils.script.Script2;
import com.cloud.utils.script.Script2.ParamType;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.VMInstanceDao;
import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
@Local(value = ServerResource.class)
public class BareMetalResourceBase implements ServerResource {
private static final Logger s_logger = Logger.getLogger(BareMetalResourceBase.class);
protected HashMap<String, State> _vms = new HashMap<String, State>(2);
protected String _name;
protected String _uuid;
protected String _zone;
protected String _pod;
protected Long hostId;
protected String _cluster;
protected long _memCapacity;
protected long _cpuCapacity;
protected long _cpuNum;
protected String _mac;
protected String _username;
protected String _password;
protected String _ip;
protected boolean _isEchoScAgent;
protected IAgentControl _agentControl;
protected Script2 _pingCommand;
protected Script2 _setPxeBootCommand;
protected Script2 _setDiskBootCommand;
protected Script2 _rebootCommand;
protected Script2 _getStatusCommand;
protected Script2 _powerOnCommand;
protected Script2 _powerOffCommand;
protected Script2 _forcePowerOffCommand;
protected Script2 _bootOrRebootCommand;
protected String _vmName;
protected VMInstanceDao vmDao;
private void changeVmState(String vmName, VirtualMachine.State state) {
synchronized (_vms) {
_vms.put(vmName, state);
}
}
private State removeVmState(String vmName) {
synchronized (_vms) {
return _vms.remove(vmName);
}
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_name = name;
_uuid = (String) params.get("guid");
try {
_memCapacity = Long.parseLong((String) params.get(ApiConstants.MEMORY)) * 1024L * 1024L;
_cpuCapacity = Long.parseLong((String) params.get(ApiConstants.CPU_SPEED));
_cpuNum = Long.parseLong((String) params.get(ApiConstants.CPU_NUMBER));
} catch (NumberFormatException e) {
throw new ConfigurationException(String.format("Unable to parse number of CPU or memory capacity "
+ "or cpu capacity(cpu number = %1$s memCapacity=%2$s, cpuCapacity=%3$s", (String) params.get(ApiConstants.CPU_NUMBER),
(String) params.get(ApiConstants.MEMORY), (String) params.get(ApiConstants.CPU_SPEED)));
}
_zone = (String) params.get("zone");
_pod = (String) params.get("pod");
_cluster = (String) params.get("cluster");
hostId = (Long) params.get("hostId");
_ip = (String) params.get(ApiConstants.PRIVATE_IP);
_mac = (String) params.get(ApiConstants.HOST_MAC);
_username = (String) params.get(ApiConstants.USERNAME);
_password = (String) params.get(ApiConstants.PASSWORD);
_vmName = (String) params.get("vmName");
String echoScAgent = (String) params.get(BaremetalManager.EchoSecurityGroupAgent);
if (_pod == null) {
throw new ConfigurationException("Unable to get the pod");
}
if (_cluster == null) {
throw new ConfigurationException("Unable to get the pod");
}
if (_ip == null) {
throw new ConfigurationException("Unable to get the host address");
}
if (_mac.equalsIgnoreCase("unknown")) {
throw new ConfigurationException("Unable to get the host mac address");
}
if (_mac.split(":").length != 6) {
throw new ConfigurationException("Wrong MAC format(" + _mac
+ "). It must be in format of for example 00:11:ba:33:aa:dd which is not case sensitive");
}
if (_uuid == null) {
throw new ConfigurationException("Unable to get the uuid");
}
if (echoScAgent != null) {
_isEchoScAgent = Boolean.valueOf(echoScAgent);
}
String injectScript = "scripts/util/ipmi.py";
String scriptPath = Script.findScript("", injectScript);
if (scriptPath == null) {
throw new ConfigurationException("Cannot find ping script " + scriptPath);
}
_pingCommand = new Script2(scriptPath, s_logger);
_pingCommand.add("ping");
_pingCommand.add("hostname=" + _ip);
_pingCommand.add("usrname=" + _username);
_pingCommand.add("password=" + _password, ParamType.PASSWORD);
_setPxeBootCommand = new Script2(scriptPath, s_logger);
_setPxeBootCommand.add("boot_dev");
_setPxeBootCommand.add("hostname=" + _ip);
_setPxeBootCommand.add("usrname=" + _username);
_setPxeBootCommand.add("password=" + _password, ParamType.PASSWORD);
_setPxeBootCommand.add("dev=pxe");
_setDiskBootCommand = new Script2(scriptPath, s_logger);
_setDiskBootCommand.add("boot_dev");
_setDiskBootCommand.add("hostname=" + _ip);
_setDiskBootCommand.add("usrname=" + _username);
_setDiskBootCommand.add("password=" + _password, ParamType.PASSWORD);
_setDiskBootCommand.add("dev=disk");
_rebootCommand = new Script2(scriptPath, s_logger);
_rebootCommand.add("reboot");
_rebootCommand.add("hostname=" + _ip);
_rebootCommand.add("usrname=" + _username);
_rebootCommand.add("password=" + _password, ParamType.PASSWORD);
_getStatusCommand = new Script2(scriptPath, s_logger);
_getStatusCommand.add("ping");
_getStatusCommand.add("hostname=" + _ip);
_getStatusCommand.add("usrname=" + _username);
_getStatusCommand.add("password=" + _password, ParamType.PASSWORD);
_powerOnCommand = new Script2(scriptPath, s_logger);
_powerOnCommand.add("power");
_powerOnCommand.add("hostname=" + _ip);
_powerOnCommand.add("usrname=" + _username);
_powerOnCommand.add("password=" + _password, ParamType.PASSWORD);
_powerOnCommand.add("action=on");
_powerOffCommand = new Script2(scriptPath, s_logger);
_powerOffCommand.add("power");
_powerOffCommand.add("hostname=" + _ip);
_powerOffCommand.add("usrname=" + _username);
_powerOffCommand.add("password=" + _password, ParamType.PASSWORD);
_powerOffCommand.add("action=soft");
_forcePowerOffCommand = new Script2(scriptPath, s_logger);
_forcePowerOffCommand.add("power");
_forcePowerOffCommand.add("hostname=" + _ip);
_forcePowerOffCommand.add("usrname=" + _username);
_forcePowerOffCommand.add("password=" + _password, ParamType.PASSWORD);
_forcePowerOffCommand.add("action=off");
_bootOrRebootCommand = new Script2(scriptPath, s_logger);
_bootOrRebootCommand.add("boot_or_reboot");
_bootOrRebootCommand.add("hostname=" + _ip);
_bootOrRebootCommand.add("usrname=" + _username);
_bootOrRebootCommand.add("password=" + _password, ParamType.PASSWORD);
return true;
}
protected boolean doScript(Script cmd) {
return doScript(cmd, null);
}
protected boolean doScript(Script cmd, OutputInterpreter interpreter) {
int retry = 5;
String res = null;
while (retry-- > 0) {
if (interpreter == null) {
res = cmd.execute();
} else {
res = cmd.execute(interpreter);
}
if (res != null && res.startsWith("Error: Unable to establish LAN")) {
s_logger.warn("IPMI script timeout(" + cmd.toString() + "), will retry " + retry + " times");
continue;
} else if (res == null) {
return true;
} else {
break;
}
}
s_logger.warn("IPMI Scirpt failed due to " + res + "(" + cmd.toString() + ")");
return false;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public String getName() {
return _name;
}
@Override
public Type getType() {
return com.cloud.host.Host.Type.Routing;
}
protected State getVmState() {
OutputInterpreter.AllLinesParser interpreter = new OutputInterpreter.AllLinesParser();
if (!doScript(_getStatusCommand, interpreter)) {
s_logger.warn("Cannot get power status of " + _name + ", assume VM state was not changed");
return null;
}
if (isPowerOn(interpreter.getLines())) {
return State.Running;
} else {
return State.Stopped;
}
}
protected Map<String, State> fullSync() {
Map<String, State> states = new HashMap<String, State>();
if (hostId != null) {
ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name);
vmDao = locator.getDao(VMInstanceDao.class);
final List<? extends VMInstanceVO> vms = vmDao.listByHostId(hostId);
for (VMInstanceVO vm : vms) {
states.put(vm.getInstanceName(), vm.getState());
}
}
/*
* Map<String, State> changes = new HashMap<String, State>();
*
* if (_vmName != null) { State state = getVmState(); if (state != null)
* { changes.put(_vmName, state); } }
*/
return states;
}
@Override
public StartupCommand[] initialize() {
StartupRoutingCommand cmd = new StartupRoutingCommand(0, 0, 0, 0, null, Hypervisor.HypervisorType.BareMetal, new HashMap<String, String>(), null);
cmd.setDataCenter(_zone);
cmd.setPod(_pod);
cmd.setCluster(_cluster);
cmd.setGuid(_uuid);
cmd.setName(_ip);
cmd.setPrivateIpAddress(_ip);
cmd.setStorageIpAddress(_ip);
cmd.setVersion(BareMetalResourceBase.class.getPackage().getImplementationVersion());
cmd.setCpus((int) _cpuNum);
cmd.setSpeed(_cpuCapacity);
cmd.setMemory(_memCapacity);
cmd.setPrivateMacAddress(_mac);
cmd.setPublicMacAddress(_mac);
cmd.setStateChanges(fullSync());
return new StartupCommand[] { cmd };
}
private boolean ipmiPing() {
return doScript(_pingCommand);
}
@Override
public PingCommand getCurrentStatus(long id) {
try {
if (!ipmiPing()) {
Thread.sleep(1000);
if (!ipmiPing()) {
s_logger.warn("Cannot ping ipmi nic " + _ip);
return null;
}
}
} catch (Exception e) {
s_logger.debug("Cannot ping ipmi nic " + _ip, e);
return null;
}
return new PingRoutingCommand(getType(), id, deltaSync());
}
protected Answer execute(IpmISetBootDevCommand cmd) {
Script bootCmd = null;
if (cmd.getBootDev() == BootDev.disk) {
bootCmd = _setDiskBootCommand;
} else if (cmd.getBootDev() == BootDev.pxe) {
bootCmd = _setPxeBootCommand;
} else {
throw new CloudRuntimeException("Unkonwn boot dev " + cmd.getBootDev());
}
String bootDev = cmd.getBootDev().name();
if (!doScript(bootCmd)) {
s_logger.warn("Set " + _ip + " boot dev to " + bootDev + "failed");
return new Answer(cmd, false, "Set " + _ip + " boot dev to " + bootDev + "failed");
}
s_logger.warn("Set " + _ip + " boot dev to " + bootDev + "Success");
return new Answer(cmd, true, "Set " + _ip + " boot dev to " + bootDev + "Success");
}
protected MaintainAnswer execute(MaintainCommand cmd) {
return new MaintainAnswer(cmd, false);
}
protected PrepareForMigrationAnswer execute(PrepareForMigrationCommand cmd) {
return new PrepareForMigrationAnswer(cmd);
}
protected MigrateAnswer execute(MigrateCommand cmd) {
if (!doScript(_powerOffCommand)) {
return new MigrateAnswer(cmd, false, "IPMI power off failed", null);
}
return new MigrateAnswer(cmd, true, "success", null);
}
protected CheckVirtualMachineAnswer execute(final CheckVirtualMachineCommand cmd) {
return new CheckVirtualMachineAnswer(cmd, State.Stopped, null);
}
protected Answer execute(IpmiBootorResetCommand cmd) {
if (!doScript(_bootOrRebootCommand)) {
return new Answer(cmd, false, "IPMI boot or reboot failed");
}
return new Answer(cmd, true, "Success");
}
protected CheckNetworkAnswer execute(CheckNetworkCommand cmd) {
return new CheckNetworkAnswer(cmd, true, "Success");
}
protected Answer execute(SecurityGroupRulesCmd cmd) {
SecurityGroupHttpClient hc = new SecurityGroupHttpClient();
return hc.call(cmd.getGuestIp(), cmd);
}
@Override
public Answer executeRequest(Command cmd) {
try {
if (cmd instanceof ReadyCommand) {
return execute((ReadyCommand) cmd);
} else if (cmd instanceof StartCommand) {
return execute((StartCommand) cmd);
} else if (cmd instanceof StopCommand) {
return execute((StopCommand) cmd);
} else if (cmd instanceof RebootCommand) {
return execute((RebootCommand) cmd);
} else if (cmd instanceof IpmISetBootDevCommand) {
return execute((IpmISetBootDevCommand) cmd);
} else if (cmd instanceof MaintainCommand) {
return execute((MaintainCommand) cmd);
} else if (cmd instanceof PrepareForMigrationCommand) {
return execute((PrepareForMigrationCommand) cmd);
} else if (cmd instanceof MigrateCommand) {
return execute((MigrateCommand) cmd);
} else if (cmd instanceof CheckVirtualMachineCommand) {
return execute((CheckVirtualMachineCommand) cmd);
} else if (cmd instanceof IpmiBootorResetCommand) {
return execute((IpmiBootorResetCommand) cmd);
} else if (cmd instanceof SecurityGroupRulesCmd) {
return execute((SecurityGroupRulesCmd) cmd);
} else if (cmd instanceof CheckNetworkCommand) {
return execute((CheckNetworkCommand) cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
} catch (Throwable t) {
s_logger.debug(t.getMessage(), t);
return new Answer(cmd, false, t.getMessage());
}
}
protected boolean isPowerOn(String str) {
if (str.startsWith("Chassis Power is on")) {
return true;
} else if (str.startsWith("Chassis Power is off")) {
return false;
} else {
throw new CloudRuntimeException("Cannot parse IPMI power status " + str);
}
}
protected RebootAnswer execute(final RebootCommand cmd) {
if (!doScript(_rebootCommand)) {
return new RebootAnswer(cmd, "IPMI reboot failed", false);
}
return new RebootAnswer(cmd, "reboot succeeded", true);
}
protected StopAnswer execute(final StopCommand cmd) {
boolean success = false;
int count = 0;
Script powerOff = _powerOffCommand;
while (count < 10) {
if (!doScript(powerOff)) {
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
OutputInterpreter.AllLinesParser interpreter = new OutputInterpreter.AllLinesParser();
if (!doScript(_getStatusCommand, interpreter)) {
s_logger.warn("Cannot get power status of " + _name + ", assume VM state was not changed");
break;
}
if (!isPowerOn(interpreter.getLines())) {
success = true;
break;
} else {
powerOff = _forcePowerOffCommand;
}
count++;
}
return success ? new StopAnswer(cmd, "Success", 0, true) : new StopAnswer(cmd, "IPMI power off failed", false);
}
protected StartAnswer execute(StartCommand cmd) {
VirtualMachineTO vm = cmd.getVirtualMachine();
State state = State.Stopped;
try {
changeVmState(vm.getName(), State.Starting);
OutputInterpreter.AllLinesParser interpreter = new OutputInterpreter.AllLinesParser();
if (!doScript(_getStatusCommand, interpreter)) {
return new StartAnswer(cmd, "Cannot get current power status of " + _name);
}
if (isPowerOn(interpreter.getLines())) {
if (!doScript(_rebootCommand)) {
return new StartAnswer(cmd, "IPMI reboot failed");
}
} else {
if (!doScript(_powerOnCommand)) {
return new StartAnswer(cmd, "IPMI power on failed");
}
}
if (_isEchoScAgent) {
SecurityGroupHttpClient hc = new SecurityGroupHttpClient();
boolean echoRet = hc.echo(vm.getNics()[0].getIp(), TimeUnit.MINUTES.toMillis(30), TimeUnit.MINUTES.toMillis(1));
if (!echoRet) {
return new StartAnswer(cmd, String.format("Call security group agent on vm[%s] timeout", vm.getNics()[0].getIp()));
}
}
s_logger.debug("Start bare metal vm " + vm.getName() + "successfully");
state = State.Running;
_vmName = vm.getName();
return new StartAnswer(cmd);
} finally {
if (state != State.Stopped) {
changeVmState(vm.getName(), state);
} else {
removeVmState(vm.getName());
}
}
}
protected HashMap<String, State> deltaSync() {
final HashMap<String, State> changes = new HashMap<String, State>();
/*
* Disable sync until we find a way that only tracks status but not does
* action
*
* The scenario is: Baremetal will reboot host when creating template.
* Given most servers take a long time to boot up, there would be a
* period that mgmt server finds the host is stopped through fullsync.
* Then mgmt server updates database with marking the host as stopped,
* after that, the host comes up and full sync then indicates it's
* running. Because in database the host is already stopped, mgmt server
* sends out a stop command. As a result, creating image gets never
* happened.
*
* if (_vmName == null) { return null; }
*
* State newState = getVmState(); if (newState == null) {
* s_logger.warn("Cannot get power state of VM " + _vmName); return
* null; }
*
* final State oldState = removeVmState(_vmName); if (oldState == null)
* { changeVmState(_vmName, newState); changes.put(_vmName, newState); }
* else if (oldState == State.Starting) { if (newState == State.Running)
* { changeVmState(_vmName, newState); } else if (newState ==
* State.Stopped) { s_logger.debug("Ignoring vm " + _vmName +
* " because of a lag in starting the vm."); } } else if (oldState ==
* State.Migrating) {
* s_logger.warn("How can baremetal VM get into migrating state???"); }
* else if (oldState == State.Stopping) { if (newState == State.Stopped)
* { changeVmState(_vmName, newState); } else if (newState ==
* State.Running) { s_logger.debug("Ignoring vm " + _vmName +
* " because of a lag in stopping the vm. "); } } else if (oldState !=
* newState) { changeVmState(_vmName, newState); changes.put(_vmName,
* newState); }
*/
return changes;
}
protected ReadyAnswer execute(ReadyCommand cmd) {
// derived resource should check if the PXE server is ready
s_logger.debug("Bare metal resource " + _name + " is ready");
return new ReadyAnswer(cmd);
}
@Override
public void disconnected() {
}
@Override
public IAgentControl getAgentControl() {
return _agentControl;
}
@Override
public void setAgentControl(IAgentControl agentControl) {
_agentControl = agentControl;
}
}

View File

@ -0,0 +1,173 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import java.net.URI;
import javax.ejb.Local;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.log4j.Logger;
import com.cloud.dc.DataCenter;
import com.cloud.dc.Pod;
import com.cloud.dc.PodVlanMapVO;
import com.cloud.dc.Vlan;
import com.cloud.dc.Vlan.VlanType;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.PodVlanMapDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.IPAddressVO;
import com.cloud.network.Network;
import com.cloud.network.NetworkManager;
import com.cloud.network.Networks.AddressFormat;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.addr.PublicIp;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.guru.DirectPodBasedNetworkGuru;
import com.cloud.network.guru.NetworkGuru;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.Transaction;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
@Local(value = { NetworkGuru.class })
public class BaremetaNetworkGuru extends DirectPodBasedNetworkGuru {
private static final Logger s_logger = Logger.getLogger(BaremetaNetworkGuru.class);
@Inject
private HostDao _hostDao;
@Inject
DataCenterDao _dcDao;
@Inject
VlanDao _vlanDao;
@Inject
NetworkManager _networkMgr;
@Inject
IPAddressDao _ipAddressDao;
@Inject
NetworkOfferingDao _networkOfferingDao;
@Inject
PodVlanMapDao _podVlanDao;
@Override
public void reserve(NicProfile nic, Network network, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest, ReservationContext context)
throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException {
if (dest.getHost().getHypervisorType() != HypervisorType.BareMetal) {
super.reserve(nic, network, vm, dest, context);
return;
}
HostVO host = _hostDao.findById(dest.getHost().getId());
_hostDao.loadDetails(host);
String intentIp = host.getDetail(ApiConstants.IP_ADDRESS);
if (intentIp == null) {
super.reserve(nic, network, vm, dest, context);
return;
}
String oldIp = nic.getIp4Address();
boolean getNewIp = false;
if (oldIp == null) {
getNewIp = true;
} else {
// we need to get a new ip address if we try to deploy a vm in a
// different pod
IPAddressVO ipVO = _ipAddressDao.findByIpAndSourceNetworkId(network.getId(), oldIp);
if (ipVO != null) {
PodVlanMapVO mapVO = _podVlanDao.listPodVlanMapsByVlan(ipVO.getVlanId());
if (mapVO.getPodId() != dest.getPod().getId()) {
Transaction txn = Transaction.currentTxn();
txn.start();
// release the old ip here
_networkMgr.markIpAsUnavailable(ipVO.getId());
_ipAddressDao.unassignIpAddress(ipVO.getId());
txn.commit();
nic.setIp4Address(null);
getNewIp = true;
}
}
}
if (getNewIp) {
// we don't set reservationStrategy to Create because we need this
// method to be called again for the case when vm fails to deploy in
// Pod1, and we try to redeploy it in Pod2
getBaremetalIp(nic, dest.getPod(), vm, network, intentIp);
}
DataCenter dc = _dcDao.findById(network.getDataCenterId());
nic.setDns1(dc.getDns1());
nic.setDns2(dc.getDns2());
/*
* Pod pod = dest.getPod(); Pair<String, Long> ip =
* _dcDao.allocatePrivateIpAddress(dest.getDataCenter().getId(),
* dest.getPod().getId(), nic.getId(), context.getReservationId(),
* intentIp); if (ip == null) { throw new
* InsufficientAddressCapacityException
* ("Unable to get a management ip address", Pod.class, pod.getId()); }
*
* nic.setIp4Address(ip.first());
* nic.setMacAddress(NetUtils.long2Mac(NetUtils
* .createSequenceBasedMacAddress(ip.second())));
* nic.setGateway(pod.getGateway()); nic.setFormat(AddressFormat.Ip4);
* String netmask = NetUtils.getCidrNetmask(pod.getCidrSize());
* nic.setNetmask(netmask);
* nic.setBroadcastType(BroadcastDomainType.Native);
* nic.setBroadcastUri(null); nic.setIsolationUri(null);
*/
s_logger.debug("Allocated a nic " + nic + " for " + vm);
}
private void getBaremetalIp(NicProfile nic, Pod pod, VirtualMachineProfile<? extends VirtualMachine> vm, Network network, String requiredIp)
throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException, ConcurrentOperationException {
DataCenter dc = _dcDao.findById(pod.getDataCenterId());
if (nic.getIp4Address() == null) {
s_logger.debug(String.format("Requiring ip address: %s", nic.getIp4Address()));
PublicIp ip = _networkMgr.assignPublicIpAddress(dc.getId(), pod.getId(), vm.getOwner(), VlanType.DirectAttached, network.getId(), requiredIp, false);
nic.setIp4Address(ip.getAddress().toString());
nic.setFormat(AddressFormat.Ip4);
nic.setGateway(ip.getGateway());
nic.setNetmask(ip.getNetmask());
if (ip.getVlanTag() != null && ip.getVlanTag().equalsIgnoreCase(Vlan.UNTAGGED)) {
nic.setIsolationUri(URI.create("ec2://" + Vlan.UNTAGGED));
nic.setBroadcastUri(URI.create("vlan://" + Vlan.UNTAGGED));
nic.setBroadcastType(BroadcastDomainType.Native);
}
nic.setReservationId(String.valueOf(ip.getVlanTag()));
nic.setMacAddress(ip.getMacAddress());
}
nic.setDns1(dc.getDns1());
nic.setDns2(dc.getDns2());
}
}

View File

@ -0,0 +1,178 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.baremetal.database.BaremetalDhcpVO;
import com.cloud.baremetal.database.BaremetalPxeVO;
import com.cloud.dc.Pod;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.Host;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.GuestType;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.element.DhcpServiceProvider;
import com.cloud.network.element.IpDeployer;
import com.cloud.network.element.NetworkElement;
import com.cloud.offering.NetworkOffering;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.SearchCriteria2;
import com.cloud.utils.db.SearchCriteriaService;
import com.cloud.utils.db.Transaction;
import com.cloud.vm.NicProfile;
import com.cloud.vm.NicVO;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.VirtualMachineProfile;
@Local(value = NetworkElement.class)
public class BaremetalDhcpElement extends AdapterBase implements DhcpServiceProvider {
private static final Logger s_logger = Logger.getLogger(BaremetalDhcpElement.class);
private static final Map<Service, Map<Capability, String>> capabilities;
@Inject NicDao _nicDao;
@Inject BaremetalDhcpManager _dhcpMgr;
static {
Capability cap = new Capability(BaremetalDhcpManager.BAREMETAL_DHCP_SERVICE_CAPABITLITY);
Map<Capability, String> baremetalCaps = new HashMap<Capability, String>();
baremetalCaps.put(cap, null);
capabilities = new HashMap<Service, Map<Capability, String>>();
capabilities.put(Service.Dhcp, baremetalCaps);
}
@Override
public Map<Service, Map<Capability, String>> getCapabilities() {
return capabilities;
}
@Override
public Provider getProvider() {
return BaremetalDhcpManager.BAREMETAL_DHCP_SERVICE_PROVIDER;
}
private boolean canHandle(DeployDestination dest, TrafficType trafficType, GuestType networkType) {
Pod pod = dest.getPod();
if (pod != null && dest.getDataCenter().getNetworkType() == NetworkType.Basic && trafficType == TrafficType.Guest) {
SearchCriteriaService<BaremetalDhcpVO, BaremetalDhcpVO> sc = SearchCriteria2.create(BaremetalDhcpVO.class);
sc.addAnd(sc.getEntity().getPodId(), Op.EQ, pod.getId());
return sc.find() != null;
}
return false;
}
@Override
public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
if (offering.isSystemOnly() || !canHandle(dest, offering.getTrafficType(), network.getGuestType())) {
s_logger.debug("BaremetalDhcpElement can not handle networkoffering: " + offering.getName());
return false;
}
return true;
}
@Override
@DB
public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest,
ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
Host host = dest.getHost();
if (vm.getType() != Type.User || vm.getHypervisorType() != HypervisorType.BareMetal) {
return false;
}
Transaction txn = Transaction.currentTxn();
txn.start();
nic.setMacAddress(host.getPrivateMacAddress());
NicVO vo = _nicDao.findById(nic.getId());
assert vo != null : "Where ths nic " + nic.getId() + " going???";
vo.setMacAddress(nic.getMacAddress());
_nicDao.update(vo.getId(), vo);
txn.commit();
return true;
}
@Override
public boolean release(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
return true;
}
@Override
public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
return true;
}
@Override
public boolean isReady(PhysicalNetworkServiceProvider provider) {
return true;
}
@Override
public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException,
ResourceUnavailableException {
return true;
}
@Override
public boolean canEnableIndividualServices() {
return false;
}
@Override
public boolean verifyServicesCombination(Set<Service> services) {
return true;
}
public boolean addDhcpEntry(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest,
ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
if (vm.getHypervisorType() != HypervisorType.BareMetal || !canHandle(dest, network.getTrafficType(), network.getGuestType())) {
return false;
}
return _dhcpMgr.addVirtualMachineIntoNetwork(network, nic, vm, dest, context);
}
}

View File

@ -0,0 +1,58 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.List;
import com.cloud.baremetal.database.BaremetalDhcpVO;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.Host;
import com.cloud.network.Network;
import com.cloud.network.Network.Provider;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.PluggableService;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
public interface BaremetalDhcpManager extends Manager, PluggableService {
public static enum BaremetalDhcpType {
DNSMASQ,
DHCPD,
}
boolean addVirtualMachineIntoNetwork(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException;
BaremetalDhcpVO addDchpServer(AddBaremetalDhcpCmd cmd);
BaremetalDhcpResponse generateApiResponse(BaremetalDhcpVO vo);
List<BaremetalDhcpResponse> listBaremetalDhcps(ListBaremetalDhcpCmd cmd);
public static final String BAREMETAL_DHCP_SERVICE_CAPABITLITY = "BaremetalDhcp";
public static final String BAREMETAL_DHCP_SERVICE_PROPERTIES = "baremetaldhcp_commands.properties";
public static final Provider BAREMETAL_DHCP_SERVICE_PROVIDER = new Provider("BaremetalDhcpProvider", true);
}

View File

@ -0,0 +1,323 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupExternalDhcpCommand;
import com.cloud.agent.api.routing.DhcpEntryCommand;
import com.cloud.baremetal.database.BaremetalDhcpDao;
import com.cloud.baremetal.database.BaremetalDhcpVO;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.network.Network;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.PhysicalNetworkVO;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ResourceStateAdapter;
import com.cloud.resource.ServerResource;
import com.cloud.resource.UnableDeleteHostException;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.SearchCriteria2;
import com.cloud.utils.db.SearchCriteriaService;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
@Local(value = { BaremetalDhcpManager.class })
public class BaremetalDhcpManagerImpl implements BaremetalDhcpManager, ResourceStateAdapter {
private static final org.apache.log4j.Logger s_logger = Logger.getLogger(BaremetalDhcpManagerImpl.class);
protected String _name;
@Inject
DataCenterDao _dcDao;
@Inject
HostDao _hostDao;
@Inject
AgentManager _agentMgr;
@Inject
HostPodDao _podDao;
@Inject
UserVmDao _userVmDao;
@Inject
ResourceManager _resourceMgr;
@Inject
NicDao _nicDao;
@Inject
PhysicalNetworkDao _physicalNetworkDao;
@Inject
PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
@Inject
BaremetalDhcpDao _extDhcpDao;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
return true;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
_resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName());
return true;
}
@Override
public String getName() {
return _name;
}
protected String getDhcpServerGuid(String zoneId, String name, String ip) {
return zoneId + "-" + name + "-" + ip;
}
@Override
public boolean addVirtualMachineIntoNetwork(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> profile,
DeployDestination dest, ReservationContext context) throws ResourceUnavailableException {
Long zoneId = profile.getVirtualMachine().getDataCenterIdToDeployIn();
Long podId = profile.getVirtualMachine().getPodIdToDeployIn();
List<HostVO> hosts = _resourceMgr.listAllUpAndEnabledHosts(Type.BaremetalDhcp, null, podId, zoneId);
if (hosts.size() == 0) {
throw new CloudRuntimeException("No external Dhcp found in zone " + zoneId + " pod " + podId);
}
if (hosts.size() > 1) {
throw new CloudRuntimeException("Something wrong, more than 1 external Dhcp found in zone " + zoneId + " pod " + podId);
}
HostVO h = hosts.get(0);
String dns = nic.getDns1();
if (dns == null) {
dns = nic.getDns2();
}
DhcpEntryCommand dhcpCommand = new DhcpEntryCommand(nic.getMacAddress(), nic.getIp4Address(), profile.getVirtualMachine().getHostName(), dns,
nic.getGateway());
String errMsg = String.format("Set dhcp entry on external DHCP %1$s failed(ip=%2$s, mac=%3$s, vmname=%4$s)", h.getPrivateIpAddress(),
nic.getIp4Address(), nic.getMacAddress(), profile.getVirtualMachine().getHostName());
// prepareBareMetalDhcpEntry(nic, dhcpCommand);
try {
Answer ans = _agentMgr.send(h.getId(), dhcpCommand);
if (ans.getResult()) {
s_logger.debug(String.format("Set dhcp entry on external DHCP %1$s successfully(ip=%2$s, mac=%3$s, vmname=%4$s)", h.getPrivateIpAddress(),
nic.getIp4Address(), nic.getMacAddress(), profile.getVirtualMachine().getHostName()));
return true;
} else {
s_logger.debug(errMsg + " " + ans.getDetails());
throw new ResourceUnavailableException(errMsg, DataCenter.class, zoneId);
}
} catch (Exception e) {
s_logger.debug(errMsg, e);
throw new ResourceUnavailableException(errMsg + e.getMessage(), DataCenter.class, zoneId);
}
}
@Override
public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
// TODO Auto-generated method stub
return null;
}
@Override
public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details,
List<String> hostTags) {
if (!(startup[0] instanceof StartupExternalDhcpCommand)) {
return null;
}
host.setType(Host.Type.BaremetalDhcp);
return host;
}
@Override
public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
// TODO Auto-generated method stub
return null;
}
@Override
@DB
public BaremetalDhcpVO addDchpServer(AddBaremetalDhcpCmd cmd) {
PhysicalNetworkVO pNetwork = null;
long zoneId;
if (cmd.getPhysicalNetworkId() == null || cmd.getUrl() == null || cmd.getUsername() == null || cmd.getPassword() == null) {
throw new IllegalArgumentException("At least one of the required parameters(physical network id, url, username, password) is null");
}
pNetwork = _physicalNetworkDao.findById(cmd.getPhysicalNetworkId());
if (pNetwork == null) {
throw new IllegalArgumentException("Could not find phyical network with ID: " + cmd.getPhysicalNetworkId());
}
zoneId = pNetwork.getDataCenterId();
DataCenterVO zone = _dcDao.findById(zoneId);
PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(),
BaremetalDhcpManager.BAREMETAL_DHCP_SERVICE_PROVIDER.getName());
if (ntwkSvcProvider == null) {
throw new CloudRuntimeException("Network Service Provider: " + BaremetalDhcpManager.BAREMETAL_DHCP_SERVICE_PROVIDER.getName() + " is not enabled in the physical network: "
+ cmd.getPhysicalNetworkId() + "to add this device");
} else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName()
+ " is in shutdown state in the physical network: " + cmd.getPhysicalNetworkId() + "to add this device");
}
HostPodVO pod = _podDao.findById(cmd.getPodId());
if (pod == null) {
throw new IllegalArgumentException("Could not find pod with ID: " + cmd.getPodId());
}
List<HostVO> dhcps = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.BaremetalDhcp, null, cmd.getPodId(), zoneId);
if (dhcps.size() != 0) {
throw new IllegalArgumentException("Already had a DHCP server in Pod: " + cmd.getPodId() + " zone: " + zoneId);
}
URI uri;
try {
uri = new URI(cmd.getUrl());
} catch (Exception e) {
s_logger.debug(e);
throw new IllegalArgumentException(e.getMessage());
}
String ipAddress = uri.getHost();
String guid = getDhcpServerGuid(Long.toString(zoneId) + "-" + Long.toString(cmd.getPodId()), "ExternalDhcp", ipAddress);
Map params = new HashMap<String, String>();
params.put("type", cmd.getDhcpType());
params.put("zone", Long.toString(zoneId));
params.put("pod", cmd.getPodId().toString());
params.put("ip", ipAddress);
params.put("username", cmd.getUsername());
params.put("password", cmd.getPassword());
params.put("guid", guid);
params.put("gateway", pod.getGateway());
String dns = zone.getDns1();
if (dns == null) {
dns = zone.getDns2();
}
params.put("dns", dns);
ServerResource resource = null;
try {
if (cmd.getDhcpType().equalsIgnoreCase(BaremetalDhcpType.DNSMASQ.toString())) {
resource = new BaremetalDnsmasqResource();
resource.configure("Dnsmasq resource", params);
} else if (cmd.getDhcpType().equalsIgnoreCase(BaremetalDhcpType.DHCPD.toString())) {
resource = new BaremetalDhcpdResource();
resource.configure("Dhcpd resource", params);
} else {
throw new CloudRuntimeException("Unsupport DHCP server type: " + cmd.getDhcpType());
}
} catch (Exception e) {
s_logger.debug(e);
throw new CloudRuntimeException(e.getMessage());
}
Host dhcpServer = _resourceMgr.addHost(zoneId, resource, Host.Type.BaremetalDhcp, params);
if (dhcpServer == null) {
throw new CloudRuntimeException("Cannot add external Dhcp server as a host");
}
BaremetalDhcpVO vo = new BaremetalDhcpVO();
vo.setDeviceType(cmd.getDhcpType());
vo.setHostId(dhcpServer.getId());
vo.setNetworkServiceProviderId(ntwkSvcProvider.getId());
vo.setPhysicalNetworkId(cmd.getPhysicalNetworkId());
vo.setPodId(cmd.getPodId());
Transaction txn = Transaction.currentTxn();
txn.start();
_extDhcpDao.persist(vo);
txn.commit();
return vo;
}
@Override
public BaremetalDhcpResponse generateApiResponse(BaremetalDhcpVO vo) {
BaremetalDhcpResponse response = new BaremetalDhcpResponse();
response.setDeviceType(vo.getDeviceType());
response.setId(String.valueOf(vo.getId()));
response.setPhysicalNetworkId(String.valueOf(vo.getPhysicalNetworkId()));
response.setProviderId(String.valueOf(vo.getNetworkServiceProviderId()));
return response;
}
@Override
public List<BaremetalDhcpResponse> listBaremetalDhcps(ListBaremetalDhcpCmd cmd) {
SearchCriteriaService<BaremetalDhcpVO, BaremetalDhcpVO> sc = SearchCriteria2.create(BaremetalDhcpVO.class);
if (cmd.getDeviceType() != null) {
sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, cmd.getDeviceType());
}
if (cmd.getPodId() != null) {
sc.addAnd(sc.getEntity().getPodId(), Op.EQ, cmd.getPodId());
if (cmd.getId() != null) {
sc.addAnd(sc.getEntity().getId(), Op.EQ, cmd.getId());
}
}
List<BaremetalDhcpVO> vos = sc.list();
List<BaremetalDhcpResponse> responses = new ArrayList<BaremetalDhcpResponse>(vos.size());
for (BaremetalDhcpVO vo : vos) {
responses.add(generateApiResponse(vo));
}
return responses;
}
@Override
public List<Class<?>> getCommands() {
return null;
}
}

View File

@ -0,0 +1,174 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.HashMap;
import java.util.Map;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.IAgentControl;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupExternalDhcpCommand;
import com.cloud.agent.api.StartupPxeServerCommand;
import com.cloud.host.Host.Type;
import com.cloud.resource.ServerResource;
import com.cloud.utils.script.Script;
import com.cloud.utils.ssh.SSHCmdHelper;
import com.cloud.vm.VirtualMachine.State;
import com.trilead.ssh2.SCPClient;
public class BaremetalDhcpResourceBase implements ServerResource {
private static final Logger s_logger = Logger.getLogger(BaremetalDhcpResourceBase.class);
String _name;
String _guid;
String _username;
String _password;
String _ip;
String _zoneId;
String _podId;
String _gateway;
String _dns;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_name = name;
_guid = (String)params.get("guid");
_ip = (String)params.get("ip");
_username = (String)params.get("username");
_password = (String)params.get("password");
_zoneId = (String)params.get("zone");
_podId = (String)params.get("pod");
_gateway = (String)params.get("gateway");
_dns = (String)params.get("dns");
if (_guid == null) {
throw new ConfigurationException("No Guid specified");
}
if (_zoneId == null) {
throw new ConfigurationException("No Zone specified");
}
if (_podId == null) {
throw new ConfigurationException("No Pod specified");
}
if (_ip == null) {
throw new ConfigurationException("No IP specified");
}
if (_username == null) {
throw new ConfigurationException("No username specified");
}
if (_password == null) {
throw new ConfigurationException("No password specified");
}
if (_gateway == null) {
throw new ConfigurationException("No gateway specified");
}
if (_dns == null) {
throw new ConfigurationException("No dns specified");
}
return true;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public String getName() {
return _name;
}
@Override
public Type getType() {
return Type.BaremetalDhcp;
}
@Override
public StartupCommand[] initialize() {
StartupExternalDhcpCommand cmd = new StartupExternalDhcpCommand();
cmd.setName(_name);
cmd.setDataCenter(_zoneId);
cmd.setPod(_podId);
cmd.setPrivateIpAddress(_ip);
cmd.setStorageIpAddress("");
cmd.setVersion("");
cmd.setGuid(_guid);
return new StartupCommand[]{cmd};
}
@Override
public PingCommand getCurrentStatus(long id) {
//TODO: check server
return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
}
protected ReadyAnswer execute(ReadyCommand cmd) {
s_logger.debug("External DHCP resource " + _name + " is ready");
return new ReadyAnswer(cmd);
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof ReadyCommand) {
return execute((ReadyCommand) cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
}
@Override
public void disconnected() {
}
@Override
public IAgentControl getAgentControl() {
return null;
}
@Override
public void setAgentControl(IAgentControl agentControl) {
}
}

View File

@ -0,0 +1,71 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public class BaremetalDhcpResponse extends BaseResponse {
@SerializedName(ApiConstants.ID) @Param(description="device id of ")
private String id;
@SerializedName(ApiConstants.PHYSICAL_NETWORK_ID) @Param(description="the physical network to which this external dhcp device belongs to")
private String physicalNetworkId;
@SerializedName(ApiConstants.PROVIDER) @Param(description="name of the provider")
private String providerId;
@SerializedName(ApiConstants.DHCP_SERVER_TYPE) @Param(description="name of the provider")
private String deviceType;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPhysicalNetworkId() {
return physicalNetworkId;
}
public void setPhysicalNetworkId(String physicalNetworkId) {
this.physicalNetworkId = physicalNetworkId;
}
public String getProviderId() {
return providerId;
}
public void setProviderId(String providerId) {
this.providerId = providerId;
}
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
}

View File

@ -0,0 +1,139 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.HashMap;
import java.util.Map;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.routing.DhcpEntryCommand;
import com.cloud.utils.script.Script;
import com.cloud.utils.ssh.SSHCmdHelper;
import com.cloud.vm.VirtualMachine.State;
import com.trilead.ssh2.SCPClient;
public class BaremetalDhcpdResource extends BaremetalDhcpResourceBase {
private static final Logger s_logger = Logger.getLogger(BaremetalDhcpdResource.class);
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
com.trilead.ssh2.Connection sshConnection = null;
try {
super.configure(name, params);
s_logger.debug(String.format("Trying to connect to DHCP server(IP=%1$s, username=%2$s, password=%3$s)", _ip, _username, "******"));
sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
if (sshConnection == null) {
throw new ConfigurationException(
String.format("Cannot connect to DHCP server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username, "******"));
}
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, "[ -f '/usr/sbin/dhcpd' ]")) {
throw new ConfigurationException("Cannot find dhcpd.conf /etc/dhcpd.conf at on " + _ip);
}
SCPClient scp = new SCPClient(sshConnection);
String editHosts = "scripts/network/exdhcp/dhcpd_edithosts.py";
String editHostsPath = Script.findScript("", editHosts);
if (editHostsPath == null) {
throw new ConfigurationException("Can not find script dnsmasq_edithosts.sh at " + editHosts);
}
scp.put(editHostsPath, "/usr/bin/", "0755");
String prepareDhcpdScript = "scripts/network/exdhcp/prepare_dhcpd.sh";
String prepareDhcpdScriptPath = Script.findScript("", prepareDhcpdScript);
if (prepareDhcpdScriptPath == null) {
throw new ConfigurationException("Can not find prepare_dhcpd.sh at " + prepareDhcpdScriptPath);
}
scp.put(prepareDhcpdScriptPath, "/usr/bin/", "0755");
//TODO: tooooooooooooooo ugly here!!!
String[] ips = _ip.split("\\.");
ips[3] = "0";
StringBuffer buf = new StringBuffer();
int i;
for (i=0;i<ips.length-1;i++) {
buf.append(ips[i]).append(".");
}
buf.append(ips[i]);
String subnet = buf.toString();
String cmd = String.format("sh /usr/bin/prepare_dhcpd.sh %1$s", subnet);
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) {
throw new ConfigurationException("prepare Dhcpd at " + _ip + " failed, command:" + cmd);
}
s_logger.debug("Dhcpd resource configure successfully");
return true;
} catch (Exception e) {
s_logger.debug("Dhcpd resorce configure failed", e);
throw new ConfigurationException(e.getMessage());
} finally {
SSHCmdHelper.releaseSshConnection(sshConnection);
}
}
@Override
public PingCommand getCurrentStatus(long id) {
com.trilead.ssh2.Connection sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
if (sshConnection == null) {
return null;
} else {
SSHCmdHelper.releaseSshConnection(sshConnection);
return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
}
}
Answer execute(DhcpEntryCommand cmd) {
com.trilead.ssh2.Connection sshConnection = null;
try {
sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
if (sshConnection == null) {
return new Answer(cmd, false, "ssh authenticate failed");
}
String addDhcp = String.format("python /usr/bin/dhcpd_edithosts.py %1$s %2$s %3$s %4$s %5$s %6$s",
cmd.getVmMac(), cmd.getVmIpAddress(), cmd.getVmName(), cmd.getDns(), cmd.getGateway(), cmd.getNextServer());
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, addDhcp)) {
return new Answer(cmd, false, "add Dhcp entry failed");
} else {
return new Answer(cmd);
}
} finally {
SSHCmdHelper.releaseSshConnection(sshConnection);
}
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof DhcpEntryCommand) {
return execute((DhcpEntryCommand)cmd);
} else {
return super.executeRequest(cmd);
}
}
}

View File

@ -0,0 +1,129 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.routing.DhcpEntryCommand;
import com.cloud.utils.script.Script;
import com.cloud.utils.ssh.SSHCmdHelper;
import com.cloud.vm.VirtualMachine.State;
import com.trilead.ssh2.SCPClient;
public class BaremetalDnsmasqResource extends BaremetalDhcpResourceBase {
private static final Logger s_logger = Logger.getLogger(BaremetalDnsmasqResource.class);
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
com.trilead.ssh2.Connection sshConnection = null;
try {
super.configure(name, params);
s_logger.debug(String.format("Trying to connect to DHCP server(IP=%1$s, username=%2$s, password=%3$s)", _ip, _username, _password));
sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
if (sshConnection == null) {
throw new ConfigurationException(
String.format("Cannot connect to DHCP server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username, _password));
}
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, "[ -f '/usr/sbin/dnsmasq' ]")) {
throw new ConfigurationException("Cannot find dnsmasq at /usr/sbin/dnsmasq on " + _ip);
}
SCPClient scp = new SCPClient(sshConnection);
String editHosts = "scripts/network/exdhcp/dnsmasq_edithosts.sh";
String editHostsPath = Script.findScript("", editHosts);
if (editHostsPath == null) {
throw new ConfigurationException("Can not find script dnsmasq_edithosts.sh at " + editHosts);
}
scp.put(editHostsPath, "/usr/bin/", "0755");
String prepareDnsmasq = "scripts/network/exdhcp/prepare_dnsmasq.sh";
String prepareDnsmasqPath = Script.findScript("", prepareDnsmasq);
if (prepareDnsmasqPath == null) {
throw new ConfigurationException("Can not find script prepare_dnsmasq.sh at " + prepareDnsmasq);
}
scp.put(prepareDnsmasqPath, "/usr/bin/", "0755");
String prepareCmd = String.format("sh /usr/bin/prepare_dnsmasq.sh %1$s %2$s %3$s", _gateway, _dns, _ip);
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, prepareCmd)) {
throw new ConfigurationException("prepare dnsmasq at " + _ip + " failed");
}
s_logger.debug("Dnsmasq resource configure successfully");
return true;
} catch (Exception e) {
s_logger.debug("Dnsmasq resorce configure failed", e);
throw new ConfigurationException(e.getMessage());
} finally {
SSHCmdHelper.releaseSshConnection(sshConnection);
}
}
@Override
public PingCommand getCurrentStatus(long id) {
com.trilead.ssh2.Connection sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
if (sshConnection == null) {
return null;
} else {
SSHCmdHelper.releaseSshConnection(sshConnection);
return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
}
}
Answer execute(DhcpEntryCommand cmd) {
com.trilead.ssh2.Connection sshConnection = null;
try {
sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
if (sshConnection == null) {
return new Answer(cmd, false, "ssh authenticate failed");
}
String addDhcp = String.format("/usr/bin/dnsmasq_edithosts.sh %1$s %2$s %3$s", cmd.getVmMac(), cmd.getVmIpAddress(), cmd.getVmName());
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, addDhcp)) {
return new Answer(cmd, false, "add Dhcp entry failed");
} else {
return new Answer(cmd);
}
} finally {
SSHCmdHelper.releaseSshConnection(sshConnection);
}
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof DhcpEntryCommand) {
return execute((DhcpEntryCommand)cmd);
} else {
return super.executeRequest(cmd);
}
}
}

View File

@ -0,0 +1,201 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.naming.ConfigurationException;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.routing.VmDataCommand;
import com.cloud.utils.script.Script;
import com.cloud.utils.ssh.SSHCmdHelper;
import com.cloud.vm.VirtualMachine.State;
import com.trilead.ssh2.SCPClient;
public class BaremetalKickStartPxeResource extends BaremetalPxeResourceBase {
private static final Logger s_logger = Logger.getLogger(BaremetalKickStartPxeResource.class);
private static final String _name = "BaremetalKickStartPxeResource";
String _tftpDir;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
super.configure(name, params);
_tftpDir = (String) params.get(BaremetalPxeService.PXE_PARAM_TFTP_DIR);
if (_tftpDir == null) {
throw new ConfigurationException("No tftp directory specified");
}
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
s_logger.debug(String.format("Trying to connect to kickstart PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username, "******"));
try {
sshConnection.connect(null, 60000, 60000);
if (!sshConnection.authenticateWithPassword(_username, _password)) {
s_logger.debug("SSH Failed to authenticate");
throw new ConfigurationException(String.format("Cannot connect to kickstart PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
"******"));
}
String cmd = String.format("[ -f /%1$s/pxelinux.0 ]", _tftpDir);
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) {
throw new ConfigurationException("Miss files in TFTP directory at " + _tftpDir + " check if pxelinux.0 are here");
}
SCPClient scp = new SCPClient(sshConnection);
String prepareScript = "scripts/network/ping/prepare_kickstart_bootfile.py";
String prepareScriptPath = Script.findScript("", prepareScript);
if (prepareScriptPath == null) {
throw new ConfigurationException("Can not find prepare_kickstart_bootfile.py at " + prepareScriptPath);
}
scp.put(prepareScriptPath, "/usr/bin/", "0755");
String cpScript = "scripts/network/ping/prepare_kickstart_kernel_initrd.py";
String cpScriptPath = Script.findScript("", cpScript);
if (cpScriptPath == null) {
throw new ConfigurationException("Can not find prepare_kickstart_kernel_initrd.py at " + cpScriptPath);
}
scp.put(cpScriptPath, "/usr/bin/", "0755");
String userDataScript = "scripts/network/ping/baremetal_user_data.py";
String userDataScriptPath = Script.findScript("", userDataScript);
if (userDataScriptPath == null) {
throw new ConfigurationException("Can not find baremetal_user_data.py at " + userDataScriptPath);
}
scp.put(userDataScriptPath, "/usr/bin/", "0755");
return true;
} catch (Exception e) {
throw new ConfigurationException(e.getMessage());
} finally {
if (sshConnection != null) {
sshConnection.close();
}
}
}
@Override
public PingCommand getCurrentStatus(long id) {
com.trilead.ssh2.Connection sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
if (sshConnection == null) {
return null;
} else {
SSHCmdHelper.releaseSshConnection(sshConnection);
return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
}
}
private Answer execute(VmDataCommand cmd) {
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
try {
List<String[]> vmData = cmd.getVmData();
StringBuilder sb = new StringBuilder();
for (String[] data : vmData) {
String folder = data[0];
String file = data[1];
String contents = (data[2] == null) ? "none" : data[2];
sb.append(cmd.getVmIpAddress());
sb.append(",");
sb.append(folder);
sb.append(",");
sb.append(file);
sb.append(",");
sb.append(contents);
sb.append(";");
}
String arg = StringUtils.stripEnd(sb.toString(), ";");
sshConnection.connect(null, 60000, 60000);
if (!sshConnection.authenticateWithPassword(_username, _password)) {
s_logger.debug("SSH Failed to authenticate");
throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
_password));
}
String script = String.format("python /usr/bin/baremetal_user_data.py '%s'", arg);
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
return new Answer(cmd, false, "Failed to add user data, command:" + script);
}
return new Answer(cmd, true, "Success");
} catch (Exception e){
s_logger.debug("Prepare for creating baremetal template failed", e);
return new Answer(cmd, false, e.getMessage());
} finally {
if (sshConnection != null) {
sshConnection.close();
}
}
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof PrepareKickstartPxeServerCommand) {
return execute((PrepareKickstartPxeServerCommand) cmd);
} else if (cmd instanceof VmDataCommand) {
return execute((VmDataCommand)cmd);
} else {
return super.executeRequest(cmd);
}
}
private Answer execute(PrepareKickstartPxeServerCommand cmd) {
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
try {
sshConnection.connect(null, 60000, 60000);
if (!sshConnection.authenticateWithPassword(_username, _password)) {
s_logger.debug("SSH Failed to authenticate");
throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
_password));
}
String copyTo = String.format("%s/%s", _tftpDir, cmd.getTemplateUuid());
String script = String.format("python /usr/bin/prepare_kickstart_kernel_initrd.py %s %s", cmd.getRepo(), copyTo);
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
return new Answer(cmd, false, "prepare kickstart at pxe server " + _ip + " failed, command:" + script);
}
String kernelPath = String.format("%s/vmlinuz", cmd.getTemplateUuid());
String initrdPath = String.format("%s/initrd.img", cmd.getTemplateUuid());
script = String.format("python /usr/bin/prepare_kickstart_bootfile.py %s %s %s %s %s %s", _tftpDir, cmd.getMac(), kernelPath, initrdPath, cmd.getKsFile(), cmd.getMac());
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
return new Answer(cmd, false, "prepare kickstart at pxe server " + _ip + " failed, command:" + script);
}
s_logger.debug("Prepare kickstart PXE server successfully");
return new Answer(cmd, true, "Success");
} catch (Exception e){
s_logger.debug("Prepare for kickstart server failed", e);
return new Answer(cmd, false, e.getMessage());
} finally {
if (sshConnection != null) {
sshConnection.close();
}
}
}
}

View File

@ -0,0 +1,238 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand;
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand.BootDev;
import com.cloud.baremetal.database.BaremetalPxeDao;
import com.cloud.baremetal.database.BaremetalPxeVO;
import com.cloud.baremetal.networkservice.BaremetalPxeManager.BaremetalPxeType;
import com.cloud.deploy.DeployDestination;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDetailsDao;
import com.cloud.network.NetworkVO;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.PhysicalNetworkVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ServerResource;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.SearchCriteria2;
import com.cloud.utils.db.SearchCriteriaService;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachineProfile;
@Local(value = BaremetalPxeService.class)
public class BaremetalKickStartServiceImpl extends BareMetalPxeServiceBase implements BaremetalPxeService {
private static final Logger s_logger = Logger.getLogger(BaremetalKickStartServiceImpl.class);
@Inject
ResourceManager _resourceMgr;
@Inject
PhysicalNetworkDao _physicalNetworkDao;
@Inject
PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
@Inject
HostDetailsDao _hostDetailsDao;
@Inject
BaremetalPxeDao _pxeDao;
@Inject
NetworkDao _nwDao;
@Inject
VMTemplateDao _tmpDao;
@Override
public boolean prepare(VirtualMachineProfile<UserVmVO> profile, NicProfile nic, DeployDestination dest, ReservationContext context) {
NetworkVO nwVO = _nwDao.findById(nic.getNetworkId());
SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, BaremetalPxeType.KICK_START.toString());
sc.addAnd(sc.getEntity().getPhysicalNetworkId(), Op.EQ, nwVO.getPhysicalNetworkId());
BaremetalPxeVO pxeVo = sc.find();
if (pxeVo == null) {
throw new CloudRuntimeException("No kickstart PXE server found in pod: " + dest.getPod().getId() + ", you need to add it before starting VM");
}
VMTemplateVO template = _tmpDao.findById(profile.getTemplateId());
try {
String tpl = profile.getTemplate().getUrl();
assert tpl != null : "How can a null template get here!!!";
String[] tpls = tpl.split(";");
assert tpls.length == 2 : "Template is not correctly encoded. " + tpl;
PrepareKickstartPxeServerCommand cmd = new PrepareKickstartPxeServerCommand();
cmd.setKsFile(tpls[0]);
cmd.setRepo(tpls[1]);
cmd.setMac(nic.getMacAddress());
cmd.setTemplateUuid(template.getUuid());
Answer aws = _agentMgr.send(pxeVo.getHostId(), cmd);
if (!aws.getResult()) {
s_logger.warn("Unable to set host: " + dest.getHost().getId() + " to PXE boot because " + aws.getDetails());
return aws.getResult();
}
IpmISetBootDevCommand bootCmd = new IpmISetBootDevCommand(BootDev.pxe);
aws = _agentMgr.send(dest.getHost().getId(), bootCmd);
if (!aws.getResult()) {
s_logger.warn("Unable to set host: " + dest.getHost().getId() + " to PXE boot because " + aws.getDetails());
}
return aws.getResult();
} catch (Exception e) {
s_logger.warn("Cannot prepare PXE server", e);
return false;
}
}
@Override
public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl) {
// TODO Auto-generated method stub
return false;
}
@Override
@DB
public BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd) {
AddBaremetalKickStartPxeCmd kcmd = (AddBaremetalKickStartPxeCmd)cmd;
PhysicalNetworkVO pNetwork = null;
long zoneId;
if (cmd.getPhysicalNetworkId() == null || cmd.getUrl() == null || cmd.getUsername() == null || cmd.getPassword() == null) {
throw new IllegalArgumentException("At least one of the required parameters(physical network id, url, username, password) is null");
}
pNetwork = _physicalNetworkDao.findById(cmd.getPhysicalNetworkId());
if (pNetwork == null) {
throw new IllegalArgumentException("Could not find phyical network with ID: " + cmd.getPhysicalNetworkId());
}
zoneId = pNetwork.getDataCenterId();
PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER.getName());
if (ntwkSvcProvider == null) {
throw new CloudRuntimeException("Network Service Provider: " + BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER.getName() +
" is not enabled in the physical network: " + cmd.getPhysicalNetworkId() + "to add this device");
} else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() +
" is in shutdown state in the physical network: " + cmd.getPhysicalNetworkId() + "to add this device");
}
List<HostVO> pxes = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, zoneId);
if (!pxes.isEmpty()) {
throw new IllegalArgumentException("Already had a PXE server zone: " + zoneId);
}
String tftpDir = kcmd.getTftpDir();
if (tftpDir == null) {
throw new IllegalArgumentException("No TFTP directory specified");
}
URI uri;
try {
uri = new URI(cmd.getUrl());
} catch (Exception e) {
s_logger.debug(e);
throw new IllegalArgumentException(e.getMessage());
}
String ipAddress = uri.getHost();
String guid = getPxeServerGuid(Long.toString(zoneId), BaremetalPxeType.KICK_START.toString(), ipAddress);
ServerResource resource = null;
Map params = new HashMap<String, String>();
params.put(BaremetalPxeService.PXE_PARAM_ZONE, Long.toString(zoneId));
params.put(BaremetalPxeService.PXE_PARAM_IP, ipAddress);
params.put(BaremetalPxeService.PXE_PARAM_USERNAME, cmd.getUsername());
params.put(BaremetalPxeService.PXE_PARAM_PASSWORD, cmd.getPassword());
params.put(BaremetalPxeService.PXE_PARAM_TFTP_DIR, tftpDir);
params.put(BaremetalPxeService.PXE_PARAM_GUID, guid);
resource = new BaremetalKickStartPxeResource();
try {
resource.configure("KickStart PXE resource", params);
} catch (Exception e) {
throw new CloudRuntimeException(e.getMessage(), e);
}
Host pxeServer = _resourceMgr.addHost(zoneId, resource, Host.Type.BaremetalPxe, params);
if (pxeServer == null) {
throw new CloudRuntimeException("Cannot add PXE server as a host");
}
BaremetalPxeVO vo = new BaremetalPxeVO();
Transaction txn = Transaction.currentTxn();
vo.setHostId(pxeServer.getId());
vo.setNetworkServiceProviderId(ntwkSvcProvider.getId());
vo.setPhysicalNetworkId(kcmd.getPhysicalNetworkId());
vo.setDeviceType(BaremetalPxeType.KICK_START.toString());
txn.start();
_pxeDao.persist(vo);
txn.commit();
return vo;
}
@Override
public BaremetalPxeResponse getApiResponse(BaremetalPxeVO vo) {
BaremetalPxeKickStartResponse response = new BaremetalPxeKickStartResponse();
response.setId(String.valueOf(vo.getId()));
response.setPhysicalNetworkId(String.valueOf(vo.getPhysicalNetworkId()));
response.setPodId(String.valueOf(vo.getPodId()));
Map<String, String> details = _hostDetailsDao.findDetails(vo.getHostId());
response.setTftpDir(details.get(BaremetalPxeService.PXE_PARAM_TFTP_DIR));
return response;
}
@Override
public List<BaremetalPxeResponse> listPxeServers(ListBaremetalPxePingServersCmd cmd) {
SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, BaremetalPxeType.KICK_START.toString());
if (cmd.getPodId() != null) {
sc.addAnd(sc.getEntity().getPodId(), Op.EQ, cmd.getPodId());
if (cmd.getId() != null) {
sc.addAnd(sc.getEntity().getId(), Op.EQ, cmd.getId());
}
}
List<BaremetalPxeVO> vos = sc.list();
List<BaremetalPxeResponse> responses = new ArrayList<BaremetalPxeResponse>(vos.size());
for (BaremetalPxeVO vo : vos) {
responses.add(getApiResponse(vo));
}
return responses;
}
}

View File

@ -0,0 +1,260 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.baremetal.PreparePxeServerAnswer;
import com.cloud.agent.api.baremetal.PreparePxeServerCommand;
import com.cloud.agent.api.baremetal.prepareCreateTemplateCommand;
import com.cloud.agent.api.routing.VmDataCommand;
import com.cloud.utils.script.Script;
import com.cloud.utils.ssh.SSHCmdHelper;
import com.cloud.vm.VirtualMachine.State;
import com.trilead.ssh2.SCPClient;
public class BaremetalPingPxeResource extends BaremetalPxeResourceBase {
private static final Logger s_logger = Logger.getLogger(BaremetalPingPxeResource.class);
private static final String _name = "BaremetalPingPxeResource";
String _storageServer;
String _pingDir;
String _share;
String _dir;
String _tftpDir;
String _cifsUserName;
String _cifsPassword;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
super.configure(name, params);
_storageServer = (String)params.get(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_IP);
_pingDir = (String)params.get(BaremetalPxeService.PXE_PARAM_PING_ROOT_DIR);
_tftpDir = (String)params.get(BaremetalPxeService.PXE_PARAM_TFTP_DIR);
_cifsUserName = (String)params.get(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_USERNAME);
_cifsPassword = (String)params.get(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_PASSWORD);
if (_podId == null) {
throw new ConfigurationException("No Pod specified");
}
if (_storageServer == null) {
throw new ConfigurationException("No stroage server specified");
}
if (_tftpDir == null) {
throw new ConfigurationException("No tftp directory specified");
}
if (_pingDir == null) {
throw new ConfigurationException("No PING directory specified");
}
if (_cifsUserName == null || _cifsUserName.equalsIgnoreCase("")) {
_cifsUserName = "xxx";
}
if (_cifsPassword == null || _cifsPassword.equalsIgnoreCase("")) {
_cifsPassword = "xxx";
}
String pingDirs[]= _pingDir.split("/");
if (pingDirs.length != 2) {
throw new ConfigurationException("PING dir should have format like myshare/direcotry, eg: windows/64bit");
}
_share = pingDirs[0];
_dir = pingDirs[1];
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
s_logger.debug(String.format("Trying to connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username, "******"));
try {
sshConnection.connect(null, 60000, 60000);
if (!sshConnection.authenticateWithPassword(_username, _password)) {
s_logger.debug("SSH Failed to authenticate");
throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
"******"));
}
String cmd = String.format("[ -f /%1$s/pxelinux.0 ] && [ -f /%2$s/kernel ] && [ -f /%3$s/initrd.gz ] ", _tftpDir, _tftpDir, _tftpDir);
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) {
throw new ConfigurationException("Miss files in TFTP directory at " + _tftpDir + " check if pxelinux.0, kernel initrd.gz are here");
}
SCPClient scp = new SCPClient(sshConnection);
String prepareScript = "scripts/network/ping/prepare_tftp_bootfile.py";
String prepareScriptPath = Script.findScript("", prepareScript);
if (prepareScriptPath == null) {
throw new ConfigurationException("Can not find prepare_tftp_bootfile.py at " + prepareScriptPath);
}
scp.put(prepareScriptPath, "/usr/bin/", "0755");
String userDataScript = "scripts/network/ping/baremetal_user_data.py";
String userDataScriptPath = Script.findScript("", userDataScript);
if (userDataScriptPath == null) {
throw new ConfigurationException("Can not find baremetal_user_data.py at " + userDataScriptPath);
}
scp.put(userDataScriptPath, "/usr/bin/", "0755");
return true;
} catch (Exception e) {
throw new ConfigurationException(e.getMessage());
} finally {
if (sshConnection != null) {
sshConnection.close();
}
}
}
@Override
public PingCommand getCurrentStatus(long id) {
com.trilead.ssh2.Connection sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
if (sshConnection == null) {
return null;
} else {
SSHCmdHelper.releaseSshConnection(sshConnection);
return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
}
}
protected PreparePxeServerAnswer execute(PreparePxeServerCommand cmd) {
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
try {
sshConnection.connect(null, 60000, 60000);
if (!sshConnection.authenticateWithPassword(_username, _password)) {
s_logger.debug("SSH Failed to authenticate");
throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
_password));
}
String script = String.format("python /usr/bin/prepare_tftp_bootfile.py restore %1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s %10$s %11$s",
_tftpDir, cmd.getMac(), _storageServer, _share, _dir, cmd.getTemplate(), _cifsUserName, _cifsPassword, cmd.getIp(), cmd.getNetMask(), cmd.getGateWay());
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
return new PreparePxeServerAnswer(cmd, "prepare PING at " + _ip + " failed, command:" + script);
}
s_logger.debug("Prepare Ping PXE server successfully");
return new PreparePxeServerAnswer(cmd);
} catch (Exception e){
s_logger.debug("Prepare PING pxe server failed", e);
return new PreparePxeServerAnswer(cmd, e.getMessage());
} finally {
if (sshConnection != null) {
sshConnection.close();
}
}
}
protected Answer execute(prepareCreateTemplateCommand cmd) {
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
try {
sshConnection.connect(null, 60000, 60000);
if (!sshConnection.authenticateWithPassword(_username, _password)) {
s_logger.debug("SSH Failed to authenticate");
throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
_password));
}
String script = String.format("python /usr/bin/prepare_tftp_bootfile.py backup %1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s %10$s %11$s",
_tftpDir, cmd.getMac(), _storageServer, _share, _dir, cmd.getTemplate(), _cifsUserName, _cifsPassword, cmd.getIp(), cmd.getNetMask(), cmd.getGateWay());
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
return new Answer(cmd, false, "prepare for creating template failed, command:" + script);
}
s_logger.debug("Prepare for creating template successfully");
return new Answer(cmd, true, "Success");
} catch (Exception e){
s_logger.debug("Prepare for creating baremetal template failed", e);
return new Answer(cmd, false, e.getMessage());
} finally {
if (sshConnection != null) {
sshConnection.close();
}
}
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof PreparePxeServerCommand) {
return execute((PreparePxeServerCommand) cmd);
} else if (cmd instanceof prepareCreateTemplateCommand) {
return execute((prepareCreateTemplateCommand)cmd);
} else if (cmd instanceof VmDataCommand) {
return execute((VmDataCommand)cmd);
} else {
return super.executeRequest(cmd);
}
}
private Answer execute(VmDataCommand cmd) {
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
try {
List<String[]> vmData = cmd.getVmData();
StringBuilder sb = new StringBuilder();
for (String[] data : vmData) {
String folder = data[0];
String file = data[1];
String contents = (data[2] == null) ? "none" : data[2];
sb.append(cmd.getVmIpAddress());
sb.append(",");
sb.append(folder);
sb.append(",");
sb.append(file);
sb.append(",");
sb.append(contents);
sb.append(";");
}
String arg = org.apache.commons.lang.StringUtils.stripEnd(sb.toString(), ";");
sshConnection.connect(null, 60000, 60000);
if (!sshConnection.authenticateWithPassword(_username, _password)) {
s_logger.debug("SSH Failed to authenticate");
throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
_password));
}
String script = String.format("python /usr/bin/baremetal_user_data.py '%s'", arg);
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
return new Answer(cmd, false, "Failed to add user data, command:" + script);
}
return new Answer(cmd, true, "Success");
} catch (Exception e){
s_logger.debug("Prepare for creating baremetal template failed", e);
return new Answer(cmd, false, e.getMessage());
} finally {
if (sshConnection != null) {
sshConnection.close();
}
}
}
}

View File

@ -0,0 +1,178 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.baremetal.database.BaremetalPxeVO;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.dc.Pod;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.GuestType;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.element.NetworkElement;
import com.cloud.offering.NetworkOffering;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.SearchCriteria2;
import com.cloud.utils.db.SearchCriteriaService;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicProfile;
import com.cloud.vm.NicVO;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.VMInstanceDao;
@Local(value = NetworkElement.class)
public class BaremetalPxeElement extends AdapterBase implements NetworkElement {
private static final Logger s_logger = Logger.getLogger(BaremetalPxeElement.class);
private static final Map<Service, Map<Capability, String>> capabilities;
@Inject BaremetalPxeManager _pxeMgr;;
@Inject VMInstanceDao _vmDao;
@Inject NicDao _nicDao;
static {
Capability cap = new Capability(BaremetalPxeManager.BAREMETAL_PXE_CAPABILITY);
Map<Capability, String> baremetalCaps = new HashMap<Capability, String>();
baremetalCaps.put(cap, null);
capabilities = new HashMap<Service, Map<Capability, String>>();
capabilities.put(BaremetalPxeManager.BAREMETAL_PXE_SERVICE, baremetalCaps);
}
@Override
public Map<Service, Map<Capability, String>> getCapabilities() {
return capabilities;
}
@Override
public Provider getProvider() {
return BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER;
}
private boolean canHandle(DeployDestination dest, TrafficType trafficType, GuestType networkType) {
Pod pod = dest.getPod();
if (pod != null && dest.getDataCenter().getNetworkType() == NetworkType.Basic && trafficType == TrafficType.Guest) {
SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
sc.addAnd(sc.getEntity().getPodId(), Op.EQ, pod.getId());
return sc.find() != null;
}
return false;
}
@Override
public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
if (offering.isSystemOnly() || !canHandle(dest, offering.getTrafficType(), network.getGuestType())) {
s_logger.debug("BaremetalPxeElement can not handle network offering: " + offering.getName());
return false;
}
return true;
}
@Override
@DB
public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest,
ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
if (vm.getType() != Type.User || vm.getHypervisorType() != HypervisorType.BareMetal) {
return false;
}
VMInstanceVO vo = _vmDao.findById(vm.getId());
if (vo.getLastHostId() == null) {
Transaction txn = Transaction.currentTxn();
txn.start();
nic.setMacAddress(dest.getHost().getPrivateMacAddress());
NicVO nicVo = _nicDao.findById(nic.getId());
assert vo != null : "Where ths nic " + nic.getId() + " going???";
nicVo.setMacAddress(nic.getMacAddress());
_nicDao.update(nicVo.getId(), nicVo);
txn.commit();
/*This vm is just being created */
if (!_pxeMgr.prepare(vm, nic, dest, context)) {
throw new CloudRuntimeException("Cannot prepare pxe server");
}
}
return false;
}
@Override
public boolean release(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException {
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
return true;
}
@Override
public boolean isReady(PhysicalNetworkServiceProvider provider) {
return true;
}
@Override
public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException,
ResourceUnavailableException {
return true;
}
@Override
public boolean canEnableIndividualServices() {
return false;
}
@Override
public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean verifyServicesCombination(Set<Service> services) {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -0,0 +1,37 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import org.apache.cloudstack.api.ApiConstants;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public class BaremetalPxeKickStartResponse extends BaremetalPxeResponse {
@SerializedName(ApiConstants.TFTP_DIR) @Param(description="Tftp root directory of PXE server")
private String tftpDir;
public String getTftpDir() {
return tftpDir;
}
public void setTftpDir(String tftpDir) {
this.tftpDir = tftpDir;
}
}

View File

@ -0,0 +1,65 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.List;
import com.cloud.baremetal.database.BaremetalPxeVO;
import com.cloud.deploy.DeployDestination;
import com.cloud.host.HostVO;
import com.cloud.network.Network;
import com.cloud.network.Network.Provider;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.PluggableService;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachineProfile;
public interface BaremetalPxeManager extends Manager, PluggableService {
public enum BaremetalPxeType {
PING,
KICK_START,
}
boolean prepare(VirtualMachineProfile profile, NicProfile nic, DeployDestination dest, ReservationContext context);
boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl);
BaremetalPxeType getPxeServerType(HostVO host);
BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd);
BaremetalPxeResponse getApiResponse(BaremetalPxeVO vo);
List<BaremetalPxeResponse> listPxeServers(ListBaremetalPxePingServersCmd cmd);
boolean addUserData(NicProfile nic, VirtualMachineProfile<UserVm> vm);
public static final Network.Service BAREMETAL_PXE_SERVICE = new Network.Service("BaremetalPxeService");
public static final String BAREMETAL_PXE_CAPABILITY = "BaremetalPxe";
public static final String BAREMETAL_PXE_SERVICE_PROPERTIES = "baremetalpxe_commands.properties";
public static final Provider BAREMETAL_PXE_SERVICE_PROVIDER = new Provider("BaremetalPxeProvider", true);;
public static final Provider BAREMETAL_USERDATA_PROVIDER = new Provider("BaremetaUserdataProvider", true);
}

View File

@ -0,0 +1,242 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupPxeServerCommand;
import com.cloud.agent.api.routing.VmDataCommand;
import com.cloud.baremetal.database.BaremetalPxeVO;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.network.PhysicalNetworkVO;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ResourceStateAdapter;
import com.cloud.resource.ServerResource;
import com.cloud.resource.UnableDeleteHostException;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.uservm.UserVm;
import com.cloud.utils.StringUtils;
import com.cloud.utils.component.Adapters;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.SearchCriteria2;
import com.cloud.utils.db.SearchCriteriaService;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicProfile;
import com.cloud.vm.NicVO;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
@Local(value = {BaremetalPxeManager.class})
public class BaremetalPxeManagerImpl implements BaremetalPxeManager, ResourceStateAdapter {
private static final org.apache.log4j.Logger s_logger = Logger.getLogger(BaremetalPxeManagerImpl.class);
protected String _name;
@Inject DataCenterDao _dcDao;
@Inject HostDao _hostDao;
@Inject AgentManager _agentMgr;
@Inject ResourceManager _resourceMgr;
@Inject(adapter=BaremetalPxeService.class)
protected Adapters<BaremetalPxeService> _services;
@Inject UserVmDao _vmDao;
@Inject ServiceOfferingDao _serviceOfferingDao;
@Inject NicDao _nicDao;
@Inject ConfigurationDao _configDao;
@Inject PhysicalNetworkDao _phynwDao;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_name = name;
_resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
return true;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
_resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName());
return true;
}
@Override
public String getName() {
return _name;
}
protected BaremetalPxeService getServiceByType(String type) {
BaremetalPxeService _service;
_service = _services.get(type);
if (_service == null) {
throw new CloudRuntimeException("Cannot find PXE service for " + type);
}
return _service;
}
@Override
public boolean prepare(VirtualMachineProfile profile, NicProfile nic, DeployDestination dest, ReservationContext context) {
//TODO: select type from template
BaremetalPxeType type = BaremetalPxeType.KICK_START;
return getServiceByType(type.toString()).prepare(profile, nic, dest, context);
}
@Override
public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl) {
//TODO: select type from template
BaremetalPxeType type = BaremetalPxeType.PING;
return getServiceByType(type.toString()).prepareCreateTemplate(pxeServerId, vm, templateUrl);
}
@Override
public BaremetalPxeType getPxeServerType(HostVO host) {
if (host.getResource().equalsIgnoreCase(BaremetalPingPxeResource.class.getName())) {
return BaremetalPxeType.PING;
} else {
throw new CloudRuntimeException("Unkown PXE server resource " + host.getResource());
}
}
@Override
public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
// TODO Auto-generated method stub
return null;
}
@Override
public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details,
List<String> hostTags) {
if (!(startup[0] instanceof StartupPxeServerCommand)) {
return null;
}
host.setType(Host.Type.BaremetalPxe);
return host;
}
@Override
public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
// TODO Auto-generated method stub
return null;
}
@Override
public BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd) {
return getServiceByType(cmd.getDeviceType()).addPxeServer(cmd);
}
@Override
public BaremetalPxeResponse getApiResponse(BaremetalPxeVO vo) {
return getServiceByType(vo.getDeviceType()).getApiResponse(vo);
}
@Override
public List<BaremetalPxeResponse> listPxeServers(ListBaremetalPxePingServersCmd cmd) {
return getServiceByType(BaremetalPxeManager.BaremetalPxeType.PING.toString()).listPxeServers(cmd);
}
@Override
public boolean addUserData(NicProfile nic, VirtualMachineProfile<UserVm> profile) {
UserVmVO vm = (UserVmVO) profile.getVirtualMachine();
_vmDao.loadDetails(vm);
String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getServiceOfferingId()).getDisplayText();
String zoneName = _dcDao.findById(vm.getDataCenterIdToDeployIn()).getName();
NicVO nvo = _nicDao.findById(nic.getId());
VmDataCommand cmd = new VmDataCommand(nvo.getIp4Address(), vm.getInstanceName());
cmd.addVmData("userdata", "user-data", vm.getUserData());
cmd.addVmData("metadata", "service-offering", StringUtils.unicodeEscape(serviceOffering));
cmd.addVmData("metadata", "availability-zone", StringUtils.unicodeEscape(zoneName));
cmd.addVmData("metadata", "local-ipv4", nic.getIp4Address());
cmd.addVmData("metadata", "local-hostname", StringUtils.unicodeEscape(vm.getInstanceName()));
cmd.addVmData("metadata", "public-ipv4", nic.getIp4Address());
cmd.addVmData("metadata", "public-hostname", StringUtils.unicodeEscape(vm.getInstanceName()));
cmd.addVmData("metadata", "instance-id", String.valueOf(vm.getId()));
cmd.addVmData("metadata", "vm-id", String.valueOf(vm.getInstanceName()));
cmd.addVmData("metadata", "public-keys", null);
String cloudIdentifier = _configDao.getValue("cloud.identifier");
if (cloudIdentifier == null) {
cloudIdentifier = "";
} else {
cloudIdentifier = "CloudStack-{" + cloudIdentifier + "}";
}
cmd.addVmData("metadata", "cloud-identifier", cloudIdentifier);
List<PhysicalNetworkVO> phys = _phynwDao.listByZone(vm.getDataCenterIdToDeployIn());
if (phys.isEmpty()) {
throw new CloudRuntimeException(String.format("Cannot find physical network in zone %s", vm.getDataCenterIdToDeployIn()));
}
if (phys.size() > 1) {
throw new CloudRuntimeException(String.format("Baremetal only supports one physical network in zone, but zone %s has %s physical networks", vm.getDataCenterIdToDeployIn(), phys.size()));
}
PhysicalNetworkVO phy = phys.get(0);
SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
//TODO: handle both kickstart and PING
//sc.addAnd(sc.getEntity().getPodId(), Op.EQ, vm.getPodIdToDeployIn());
sc.addAnd(sc.getEntity().getPhysicalNetworkId(), Op.EQ, phy.getId());
BaremetalPxeVO pxeVo = sc.find();
if (pxeVo == null) {
throw new CloudRuntimeException("No PXE server found in pod: " + vm.getPodIdToDeployIn() + ", you need to add it before starting VM");
}
try {
Answer ans = _agentMgr.send(pxeVo.getHostId(), cmd);
if (!ans.getResult()) {
s_logger.debug(String.format("Add userdata to vm:%s failed because %s", vm.getInstanceName(), ans.getDetails()));
return false;
} else {
return true;
}
} catch (Exception e) {
s_logger.debug(String.format("Add userdata to vm:%s failed", vm.getInstanceName()), e);
return false;
}
}
@Override
public List<Class<?>> getCommands() {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -0,0 +1,59 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import org.apache.cloudstack.api.ApiConstants;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public class BaremetalPxePingResponse extends BaremetalPxeResponse {
@SerializedName(ApiConstants.PING_STORAGE_SERVER_IP) @Param(description="PING storage server ip")
private String pingStorageServerIp;
@SerializedName(ApiConstants.PING_DIR) @Param(description="Root directory on PING storage server")
private String pingDir;
@SerializedName(ApiConstants.TFTP_DIR) @Param(description="Tftp root directory of PXE server")
private String tftpDir;
public String getPingStorageServerIp() {
return pingStorageServerIp;
}
public void setPingStorageServerIp(String pingStorageServerIp) {
this.pingStorageServerIp = pingStorageServerIp;
}
public String getPingDir() {
return pingDir;
}
public void setPingDir(String pingDir) {
this.pingDir = pingDir;
}
public String getTftpDir() {
return tftpDir;
}
public void setTftpDir(String tftpDir) {
this.tftpDir = tftpDir;
}
}

View File

@ -0,0 +1,157 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.Map;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.IAgentControl;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupPxeServerCommand;
import com.cloud.host.Host.Type;
import com.cloud.resource.ServerResource;
public class BaremetalPxeResourceBase implements ServerResource {
private static final Logger s_logger = Logger.getLogger(BaremetalPxeResourceBase.class);
String _name;
String _guid;
String _username;
String _password;
String _ip;
String _zoneId;
String _podId;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_name = name;
_guid = (String)params.get(BaremetalPxeService.PXE_PARAM_GUID);
_ip = (String)params.get(BaremetalPxeService.PXE_PARAM_IP);
_username = (String)params.get(BaremetalPxeService.PXE_PARAM_USERNAME);
_password = (String)params.get(BaremetalPxeService.PXE_PARAM_PASSWORD);
_zoneId = (String)params.get(BaremetalPxeService.PXE_PARAM_ZONE);
_podId = (String)params.get(BaremetalPxeService.PXE_PARAM_POD);
if (_guid == null) {
throw new ConfigurationException("No Guid specified");
}
if (_zoneId == null) {
throw new ConfigurationException("No Zone specified");
}
if (_ip == null) {
throw new ConfigurationException("No IP specified");
}
if (_username == null) {
throw new ConfigurationException("No username specified");
}
if (_password == null) {
throw new ConfigurationException("No password specified");
}
return true;
}
protected ReadyAnswer execute(ReadyCommand cmd) {
s_logger.debug("Pxe resource " + _name + " is ready");
return new ReadyAnswer(cmd);
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return _name;
}
@Override
public Type getType() {
return Type.BaremetalPxe;
}
@Override
public StartupCommand[] initialize() {
StartupPxeServerCommand cmd = new StartupPxeServerCommand();
cmd.setName(_name);
cmd.setDataCenter(_zoneId);
cmd.setPod(_podId);
cmd.setPrivateIpAddress(_ip);
cmd.setStorageIpAddress("");
cmd.setVersion("");
cmd.setGuid(_guid);
return new StartupCommand[]{cmd};
}
@Override
public PingCommand getCurrentStatus(long id) {
// TODO Auto-generated method stub
return null;
}
@Override
public void disconnected() {
// TODO Auto-generated method stub
}
@Override
public IAgentControl getAgentControl() {
// TODO Auto-generated method stub
return null;
}
@Override
public void setAgentControl(IAgentControl agentControl) {
// TODO Auto-generated method stub
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof ReadyCommand) {
return execute((ReadyCommand) cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
}
}

View File

@ -0,0 +1,71 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public class BaremetalPxeResponse extends BaseResponse {
@SerializedName(ApiConstants.ID) @Param(description="device id of ")
private String id;
@SerializedName(ApiConstants.PHYSICAL_NETWORK_ID) @Param(description="the physical network to which this external dhcp device belongs to")
private String physicalNetworkId;
@SerializedName(ApiConstants.PROVIDER) @Param(description="name of the provider")
private String providerId;
@SerializedName(ApiConstants.POD_ID) @Param(description="pod id where the device is in")
private String podId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPhysicalNetworkId() {
return physicalNetworkId;
}
public void setPhysicalNetworkId(String physicalNetworkId) {
this.physicalNetworkId = physicalNetworkId;
}
public String getProviderId() {
return providerId;
}
public void setProviderId(String providerId) {
this.providerId = providerId;
}
public String getPodId() {
return podId;
}
public void setPodId(String podId) {
this.podId = podId;
}
}

View File

@ -0,0 +1,61 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.util.List;
import com.cloud.baremetal.database.BaremetalPxeVO;
import com.cloud.deploy.DeployDestination;
import com.cloud.host.Host;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.Adapter;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachineProfile;
public interface BaremetalPxeService extends Adapter {
public boolean prepare(VirtualMachineProfile<UserVmVO> profile, NicProfile nic, DeployDestination dest, ReservationContext context);
public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl);
BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd);
BaremetalPxeResponse getApiResponse(BaremetalPxeVO vo);
List<BaremetalPxeResponse> listPxeServers(ListBaremetalPxePingServersCmd cmd);
public static final String PXE_PARAM_TYPE = "type";
public static final String PXE_PARAM_ZONE = "zone";
public static final String PXE_PARAM_POD = "pod";
public static final String PXE_PARAM_IP = "ip";
public static final String PXE_PARAM_GUID = "guid";
public static final String PXE_PARAM_TFTP_DIR = "tftpDir";
public static final String PXE_PARAM_USERNAME = "username";
public static final String PXE_PARAM_PASSWORD = "password";
public static final String PXE_PARAM_PING_STORAGE_SERVER_IP = "pingStorageServerIp";
public static final String PXE_PARAM_PING_ROOT_DIR = "pingDir";
public static final String PXE_PARAM_PING_STORAGE_SERVER_USERNAME = "pingStorageServerUserName";
public static final String PXE_PARAM_PING_STORAGE_SERVER_PASSWORD = "pingStorageServerPassword";
}

View File

@ -0,0 +1,169 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ejb.Local;
import com.cloud.baremetal.manager.BaremetalManager;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.GuestType;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.network.element.IpDeployer;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.UserDataServiceProvider;
import com.cloud.offering.NetworkOffering;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.Inject;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
@Local(value = NetworkElement.class)
public class BaremetalUserdataElement extends AdapterBase implements NetworkElement, UserDataServiceProvider {
private static Map<Service, Map<Capability, String>> capabilities;
@Inject
private BaremetalPxeManager pxeMgr;
static {
capabilities = new HashMap<Service, Map<Capability, String>>();
capabilities.put(Service.UserData, null);
}
private boolean canHandle(DeployDestination dest) {
if (dest.getDataCenter().getNetworkType() == NetworkType.Basic && dest.getHost().getHypervisorType() == HypervisorType.BareMetal) {
return true;
}
return false;
}
@Override
public boolean addPasswordAndUserdata(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest,
ReservationContext context) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
if (!canHandle(dest)) {
return false;
}
if (vm.getType() != VirtualMachine.Type.User) {
return false;
}
return pxeMgr.addUserData(nic, (VirtualMachineProfile<UserVm>) vm);
}
@Override
public boolean savePassword(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm) throws ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public Map<Service, Map<Capability, String>> getCapabilities() {
return capabilities;
}
@Override
public Provider getProvider() {
return BaremetalPxeManager.BAREMETAL_USERDATA_PROVIDER;
}
@Override
public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest,
ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean release(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isReady(PhysicalNetworkServiceProvider provider) {
return true;
}
@Override
public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException,
ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean canEnableIndividualServices() {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean saveUserData(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm)
throws ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean verifyServicesCombination(Set<Service> services) {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -0,0 +1,102 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import java.util.List;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.BaseCmd.CommandType;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.PlugService;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.log4j.Logger;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
public class ListBaremetalDhcpCmd extends BaseListCmd {
private static final Logger s_logger = Logger.getLogger(ListBaremetalDhcpCmd.class);
private static final String s_name = "listexternaldhcpresponse";
@PlugService BaremetalDhcpManager _dhcpMgr;
// ///////////////////////////////////////////////////
// ////////////// API parameters /////////////////////
// ///////////////////////////////////////////////////
@Parameter(name = ApiConstants.ID, type = CommandType.LONG, description = "DHCP server device ID")
private Long id;
@Parameter(name = ApiConstants.POD_ID, type = CommandType.LONG, description = "Pod ID where pxe server is in")
private Long podId;
@Parameter(name = ApiConstants.DHCP_SERVER_TYPE, type = CommandType.STRING, description = "Type of DHCP device")
private String deviceType;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPodId() {
return podId;
}
public void setPodId(Long podId) {
this.podId = podId;
}
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
ResourceAllocationException, NetworkRuleConflictException {
try {
ListResponse<BaremetalDhcpResponse> response = new ListResponse<BaremetalDhcpResponse>();
List<BaremetalDhcpResponse> dhcpResponses = _dhcpMgr.listBaremetalDhcps(this);
response.setResponses(dhcpResponses);
response.setResponseName(getCommandName());
this.setResponseObject(response);
} catch (Exception e) {
s_logger.debug("Exception happend while executing ListBaremetalDhcpCmd");
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
}
}
@Override
public String getCommandName() {
return s_name;
}
}

View File

@ -0,0 +1,92 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import java.util.List;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.BaseCmd.CommandType;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.PlugService;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.log4j.Logger;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
public class ListBaremetalPxePingServersCmd extends BaseListCmd {
private static final Logger s_logger = Logger.getLogger(ListBaremetalPxePingServersCmd.class);
private static final String s_name = "listpingpxeserverresponse";
@PlugService
BaremetalPxeManager _pxeMgr;
// ///////////////////////////////////////////////////
// ////////////// API parameters /////////////////////
// ///////////////////////////////////////////////////
@Parameter(name = ApiConstants.ID, type = CommandType.LONG, description = "Ping pxe server device ID")
private Long id;
@Parameter(name = ApiConstants.POD_ID, type = CommandType.LONG, description = "Pod ID where pxe server is in")
private Long podId;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPodId() {
return podId;
}
public void setPodId(Long podId) {
this.podId = podId;
}
@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
ResourceAllocationException, NetworkRuleConflictException {
try {
ListResponse<BaremetalPxeResponse> response = new ListResponse<BaremetalPxeResponse>();
List<BaremetalPxeResponse> pxeResponses = _pxeMgr.listPxeServers(this);
response.setResponses(pxeResponses);
response.setResponseName(getCommandName());
this.setResponseObject(response);
} catch (Exception e) {
s_logger.debug("Exception happend while executing ListPingPxeServersCmd" ,e);
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
}
}
@Override
public String getCommandName() {
return s_name;
}
}

View File

@ -0,0 +1,74 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.networkservice;
import com.cloud.agent.api.Command;
public class PrepareKickstartPxeServerCommand extends Command {
private String ksFile;
private String repo;
private String templateUuid;
private String mac;
private String ksDevice;
@Override
public boolean executeInSequence() {
return true;
}
public String getKsFile() {
return ksFile;
}
public void setKsFile(String ksFile) {
this.ksFile = ksFile;
}
public String getRepo() {
return repo;
}
public void setRepo(String repo) {
this.repo = repo;
}
public String getTemplateUuid() {
return templateUuid;
}
public void setTemplateUuid(String templateUuid) {
this.templateUuid = templateUuid;
}
public String getMac() {
return mac;
}
public void setMac(String mac) {
this.mac = mac;
}
public String getKsDevice() {
return ksDevice;
}
public void setKsDevice(String ksDevice) {
this.ksDevice = ksDevice;
}
}

View File

@ -0,0 +1,38 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
package com.cloud.baremetal.networkservice;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.SecurityGroupRulesCmd;
public class SecurityGroupHttpClient {
public Answer call(String guestIp, SecurityGroupRulesCmd cmd) {
// TODO Auto-generated method stub
return null;
}
public boolean echo(String ip, long millis, long millis2) {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -903,7 +903,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements
String fname = interfaces[i].getName();
s_logger.debug("matchPifFileInDirectory: file name '"+fname+"'");
if (fname.startsWith("eth") || fname.startsWith("bond")
|| fname.startsWith("vlan")) {
|| fname.startsWith("vlan") || fname.startsWith("em")) {
return fname;
}
}

View File

@ -42,6 +42,7 @@
<module>hypervisors/xen</module>
<module>hypervisors/kvm</module>
<module>hypervisors/simulator</module>
<module>hypervisors/baremetal</module>
<module>network-elements/elastic-loadbalancer</module>
<module>network-elements/ovs</module>
<module>network-elements/nicira-nvp</module>

View File

@ -358,7 +358,13 @@ public enum Config {
DetailBatchQuerySize("Advanced", ManagementServer.class, Integer.class, "detail.batch.query.size", "2000", "Default entity detail batch query size for listing", null),
ConcurrentSnapshotsThresholdPerHost("Advanced", ManagementServer.class, Long.class, "concurrent.snapshots.threshold.perhost",
null, "Limits number of snapshots that can be handled by the host concurrently; default is NULL - unlimited", null);
null, "Limits number of snapshots that can be handled by the host concurrently; default is NULL - unlimited", null),
ExternalBaremetalSystemUrl("Advanced", ManagementServer.class, String.class, "external.baremetal.system.url", null, "url of external baremetal system that CloudStack will talk to", null),
ExternalBaremetalResourceClassName("Advanced", ManagementServer.class, String.class, "external,baremetal.resource.classname", null, "class name for handling external baremetal resource", null),
EnableBaremetalSecurityGroupAgentEcho("Advanced", ManagementServer.class, Boolean.class, "enable.baremetal.securitygroup.agent.echo", "false", "After starting provision process, periodcially echo security agent installed in the template. Treat provisioning as success only if echo successfully", null),
IntervalToEchoBaremetalSecurityGroupAgent("Advanced", ManagementServer.class, Integer.class, "interval.baremetal.securitygroup.agent.echo", "10", "Interval to echo baremetal security group agent, in seconds", null),
TimeoutToEchoBaremetalSecurityGroupAgent("Advanced", ManagementServer.class, Integer.class, "timeout.baremetal.securitygroup.agent.echo", "3600", "Timeout to echo baremetal security group agent, in seconds, the provisioning process will be treated as a failure", null);
private final String _category;
private final Class<?> _componentClass;

View File

@ -368,7 +368,9 @@ public class DomainManagerImpl implements DomainManager, DomainService, Manager
}
_accountMgr.checkAccess(caller, domain);
} else {
domainId = caller.getDomainId();
if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) {
domainId = caller.getDomainId();
}
if (listAll) {
isRecursive = true;
}

View File

@ -1829,14 +1829,14 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
}
// used for vm transitioning to error state
private void updateVmStateForFailedVmCreation(Long vmId) {
private void updateVmStateForFailedVmCreation(Long vmId, Long hostId) {
UserVmVO vm = _vmDao.findById(vmId);
if (vm != null) {
if (vm.getState().equals(State.Stopped)) {
s_logger.debug("Destroying vm " + vm + " as it failed to create");
s_logger.debug("Destroying vm " + vm + " as it failed to create on Host with Id:" + hostId);
try {
_itMgr.stateTransitTo(vm, VirtualMachine.Event.OperationFailedToError, null);
} catch (NoTransitionException e1) {
@ -1854,7 +1854,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
s_logger.warn("Unable to delete volume:" + volume.getId() + " for vm:" + vmId + " whilst transitioning to error state");
}
}
String msg = "Failed to deploy Vm with Id: " + vmId;
String msg = "Failed to deploy Vm with Id: " + vmId + ", on Host with Id: " + hostId;
_alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), msg, msg);
_resourceLimitMgr.decrementResourceCount(vm.getAccountId(), ResourceType.user_vm);
@ -2786,9 +2786,9 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> vmParamPair = null;
try {
vmParamPair = startVirtualMachine(vmId, hostId, additonalParams);
vm = vmParamPair.first();;
vm = vmParamPair.first();
} finally {
updateVmStateForFailedVmCreation(vm.getId());
updateVmStateForFailedVmCreation(vm.getId(), hostId);
}
// Check that the password was passed in and is valid

View File

@ -16,11 +16,13 @@
# under the License.
try:
from common import grammar
import re
from marvin.cloudstackAPI import *
from marvin import cloudstackAPI
except ImportError, e:
pass
import sys
print "ImportError", e
sys.exit(1)
completions = cloudstackAPI.__all__
@ -43,9 +45,12 @@ def main():
completing commands and help docs. This reduces the overall search and
cache_miss (computation) complexity from O(n) to O(1) for any valid cmd.
"""
pattern = re.compile("[A-Z]")
verbs = list(set([x[:pattern.search(x).start()] for x in completions
if pattern.search(x) is not None]).difference(['cloudstack']))
# datastructure {'verb': {cmd': ['api', [params], doc, required=[]]}}
cache_verbs = {}
for verb in grammar:
for verb in verbs:
completions_found = filter(lambda x: x.startswith(verb), completions)
cache_verbs[verb] = {}
for api_name in completions_found:

View File

@ -20,25 +20,26 @@
try:
import atexit
import cmd
import clint
import codecs
import json
import logging
import os
import pdb
import re
import shlex
import sys
import time
import types
from clint.textui import colored
from ConfigParser import ConfigParser, SafeConfigParser
from urllib2 import HTTPError, URLError
from httplib import BadStatusLine
from prettytable import PrettyTable
from common import __version__, config_file, config_fields
from common import grammar, precached_verbs
from common import __version__, config_dir, config_file, config_fields
from common import precached_verbs
from lexer import monkeyprint
from marvin.cloudstackConnection import cloudConnection
from marvin.cloudstackException import cloudstackAPIException
from marvin.cloudstackAPI import *
@ -69,44 +70,52 @@ class CloudMonkeyShell(cmd.Cmd, object):
intro = ("☁ Apache CloudStack 🐵 cloudmonkey " + __version__ +
". Type help or ? to list commands.\n")
ruler = "="
config_dir = config_dir
config_file = config_file
config_fields = config_fields
grammar = grammar
# datastructure {'verb': {cmd': ['api', [params], doc, required=[]]}}
cache_verbs = precached_verbs
config_options = []
def __init__(self, pname):
def __init__(self, pname, verbs):
self.program_name = pname
self.verbs = verbs
global config_fields
first_time = False
if not os.path.exists(self.config_dir):
os.makedirs(self.config_dir)
if os.path.exists(self.config_file):
config = self.read_config()
else:
for key in self.config_fields.keys():
setattr(self, key, self.config_fields[key])
config = self.write_config()
first_time = True
config = self.write_config(first_time)
for section in config_fields.keys():
for key in config_fields[section].keys():
try:
self.config_options.append(key)
setattr(self, key, config.get(section, key))
except Exception:
print "Please fix `%s` in %s" % (key, self.config_file)
sys.exit()
if first_time:
print "Welcome! Using `set` configure the necessary settings:"
print " ".join(sorted(self.config_fields.keys()))
print " ".join(sorted(self.config_options))
print "Config file:", self.config_file
print "For debugging, tail -f", self.log_file, "\n"
for key in self.config_fields.keys():
try:
setattr(self, key, config.get('CLI', key))
self.config_fields[key] = config.get('CLI', key)
except Exception:
print "Please fix `%s` config in %s" % (key, self.config_file)
sys.exit()
self.prompt = self.prompt.strip() + " " # Cosmetic fix for prompt
logging.basicConfig(filename=self.log_file,
level=logging.DEBUG, format=log_fmt)
logger.debug("Loaded config fields:\n%s" % self.config_fields)
logger.debug("Loaded config fields:\n%s" % map(lambda x: "%s=%s" %
(x, getattr(self, x)),
self.config_options))
cmd.Cmd.__init__(self)
# Update config if config_file does not exist
if not os.path.exists(self.config_file):
config = self.write_config()
# Enable history support
try:
if os.path.exists(self.history_file):
readline.read_history_file(self.history_file)
@ -123,11 +132,16 @@ class CloudMonkeyShell(cmd.Cmd, object):
self.print_shell("Error: config_file not found", e)
return config
def write_config(self):
def write_config(self, first_time=False):
global config_fields
config = ConfigParser()
config.add_section('CLI')
for key in self.config_fields.keys():
config.set('CLI', key, getattr(self, key))
for section in config_fields.keys():
config.add_section(section)
for key in config_fields[section].keys():
if first_time:
config.set(section, key, config_fields[section][key])
else:
config.set(section, key, getattr(self, key))
with open(self.config_file, 'w') as cfg:
config.write(cfg)
return config
@ -145,35 +159,19 @@ class CloudMonkeyShell(cmd.Cmd, object):
print("^C")
def print_shell(self, *args):
output = ""
try:
for arg in args:
arg = str(arg)
if isinstance(type(args), types.NoneType):
continue
if self.color == 'true':
if str(arg).count(self.ruler) == len(str(arg)):
print colored.green(arg),
elif 'Error' in arg:
print colored.red(arg),
elif ":\n=" in arg:
print colored.red(arg),
elif ':' in arg:
print colored.blue(arg),
elif 'type' in arg:
print colored.green(arg),
elif 'state' in arg or 'count' in arg:
print colored.magenta(arg),
elif 'id =' in arg:
print colored.yellow(arg),
elif 'name =' in arg:
print colored.cyan(arg),
else:
print arg,
else:
print arg,
print
output += arg
if self.color == 'true':
monkeyprint(output)
else:
print output
except Exception, e:
print colored.red("Error: "), e
self.print_shell("Error: " + e)
def print_result(self, result, result_filter=None):
if result is None or len(result) == 0:
@ -181,7 +179,7 @@ class CloudMonkeyShell(cmd.Cmd, object):
def printer_helper(printer, toprow):
if printer:
print printer
self.print_shell(printer)
return PrettyTable(toprow)
def print_result_tabular(result, result_filter=None):
@ -202,16 +200,16 @@ class CloudMonkeyShell(cmd.Cmd, object):
if printer and row:
printer.add_row(row)
if printer:
print printer
self.print_shell(printer)
def print_result_as_dict(result, result_filter=None):
for key in sorted(result.keys(),
key=lambda x: x != 'id' and x != 'count' and x):
for key in sorted(result.keys(), key=lambda x:
x not in ['id', 'count', 'name'] and x):
if not (isinstance(result[key], list) or
isinstance(result[key], dict)):
self.print_shell("%s = %s" % (key, result[key]))
else:
self.print_shell(key + ":\n" + len(key) * self.ruler)
self.print_shell(key + ":")
self.print_result(result[key], result_filter)
def print_result_as_list(result, result_filter=None):
@ -361,7 +359,7 @@ class CloudMonkeyShell(cmd.Cmd, object):
command.required)
if len(missing_args) > 0:
self.print_shell("Missing arguments:", ' '.join(missing_args))
self.print_shell("Missing arguments: ", ' '.join(missing_args))
return
isAsync = False
@ -381,13 +379,13 @@ class CloudMonkeyShell(cmd.Cmd, object):
def completedefault(self, text, line, begidx, endidx):
partitions = line.partition(" ")
verb = partitions[0]
rline = partitions[2].partition(" ")
verb = partitions[0].strip()
rline = partitions[2].lstrip().partition(" ")
subject = rline[0]
separator = rline[1]
params = rline[2]
params = rline[2].lstrip()
if verb not in self.grammar:
if verb not in self.verbs:
return []
autocompletions = []
@ -401,7 +399,7 @@ class CloudMonkeyShell(cmd.Cmd, object):
self.cache_verbs[verb][subject][1])
search_string = text
if self.tabularize == "true":
if self.tabularize == "true" and subject != "":
autocompletions.append("filter=")
return [s for s in autocompletions if s.startswith(search_string)]
@ -436,13 +434,13 @@ class CloudMonkeyShell(cmd.Cmd, object):
args = args.strip().partition(" ")
key, value = (args[0], args[2])
setattr(self, key, value) # keys and attributes should have same names
self.prompt = self.prompt.strip() + " " # prompt fix
self.prompt = self.prompt.strip() + " " # prompt fix
self.write_config()
def complete_set(self, text, line, begidx, endidx):
mline = line.partition(" ")[2]
offs = len(mline) - len(text)
return [s[offs:] for s in self.config_fields.keys()
return [s[offs:] for s in self.config_options
if s.startswith(mline)]
def do_shell(self, args):
@ -513,22 +511,22 @@ class CloudMonkeyShell(cmd.Cmd, object):
def main():
# Create handlers on the fly using closures
self = CloudMonkeyShell
global grammar
for rule in grammar:
def add_grammar(rule):
pattern = re.compile("[A-Z]")
verbs = list(set([x[:pattern.search(x).start()] for x in completions
if pattern.search(x) is not None]).difference(['cloudstack']))
for verb in verbs:
def add_grammar(verb):
def grammar_closure(self, args):
if self.pipe_runner("%s %s" % (rule, args)):
if self.pipe_runner("%s %s" % (verb, args)):
return
try:
args_partition = args.partition(" ")
res = self.cache_verbs[rule][args_partition[0]]
res = self.cache_verbs[verb][args_partition[0]]
cmd = res[0]
helpdoc = res[2]
args = args_partition[2]
except KeyError, e:
self.print_shell("Error: invalid %s api arg" % rule, e)
self.print_shell("Error: invalid %s api arg" % verb, e)
return
if ' --help' in args or ' -h' in args:
self.print_shell(helpdoc)
@ -536,12 +534,12 @@ def main():
self.default("%s %s" % (cmd, args))
return grammar_closure
grammar_handler = add_grammar(rule)
grammar_handler.__doc__ = "%ss resources" % rule.capitalize()
grammar_handler.__name__ = 'do_' + rule
setattr(self, grammar_handler.__name__, grammar_handler)
grammar_handler = add_grammar(verb)
grammar_handler.__doc__ = "%ss resources" % verb.capitalize()
grammar_handler.__name__ = 'do_' + verb
setattr(CloudMonkeyShell, grammar_handler.__name__, grammar_handler)
shell = CloudMonkeyShell(sys.argv[0])
shell = CloudMonkeyShell(sys.argv[0], verbs)
if len(sys.argv) > 1:
shell.onecmd(' '.join(sys.argv[1:]))
else:

View File

@ -17,34 +17,43 @@
# under the License.
# Use following rules for versioning:
# <cloudstack major version>.<cloudstack minor version>.<cli increment>
__version__ = "4.0.0"
# <cloudstack version>-<cli increment, starts from 0>
__version__ = "4.1.0-0"
try:
from os.path import expanduser
import os
from precache import precached_verbs
except ImportError, e:
precached_verbs = {}
# Add config key:value
config_file = os.path.expanduser('~/.cloudmonkey_config')
config_fields = {'host': 'localhost', 'port': '8080',
'protocol': 'http', 'path': '/client/api',
'apikey': '', 'secretkey': '',
'timeout': '3600', 'asyncblock': 'true',
'prompt': '🐵 cloudmonkey>', 'color': 'true',
'tabularize': 'false',
'log_file':
os.path.expanduser('~/.cloudmonkey_log'),
'history_file':
os.path.expanduser('~/.cloudmonkey_history')}
param_type = ['boolean', 'date', 'float', 'integer', 'short', 'list',
'long', 'object', 'map', 'string', 'tzdate', 'uuid']
# Add verbs in grammar
grammar = ['create', 'list', 'delete', 'update', 'lock',
'enable', 'activate', 'disable', 'add', 'remove',
'attach', 'detach', 'associate', 'disassociate', 'generate', 'ldap',
'assign', 'authorize', 'change', 'register', 'configure',
'start', 'restart', 'reboot', 'stop', 'reconnect',
'cancel', 'destroy', 'revoke', 'mark', 'reset',
'copy', 'extract', 'migrate', 'restore', 'suspend',
'get', 'query', 'prepare', 'deploy', 'upload']
config_dir = expanduser('~/.cloudmonkey')
config_file = expanduser(config_dir + '/config')
# cloudmonkey config fields
config_fields = {'core': {}, 'ui': {}, 'server': {}, 'user': {}}
# core
config_fields['core']['cache_file'] = expanduser(config_dir + '/cache')
config_fields['core']['history_file'] = expanduser(config_dir + '/history')
config_fields['core']['log_file'] = expanduser(config_dir + '/log')
# ui
config_fields['ui']['color'] = 'true'
config_fields['ui']['prompt'] = '> '
config_fields['ui']['tabularize'] = 'false'
# server
config_fields['server']['asyncblock'] = 'true'
config_fields['server']['host'] = 'localhost'
config_fields['server']['path'] = '/client/api'
config_fields['server']['port'] = '8080'
config_fields['server']['protocol'] = 'http'
config_fields['server']['timeout'] = '3600'
# user
config_fields['user']['apikey'] = ''
config_fields['user']['secretkey'] = ''

View File

@ -0,0 +1,121 @@
# -*- coding: utf-8 -*-
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
try:
from pygments import highlight
from pygments.console import ansiformat
from pygments.formatter import Formatter
from pygments.formatters import Terminal256Formatter
from pygments.lexer import bygroups, include, RegexLexer
from pygments.token import *
import sys
except ImportError, e:
print e
MONKEY_COLORS = {
Token: '',
Whitespace: 'reset',
Text: 'reset',
Name: 'green',
Operator: 'teal',
Operator.Word: 'lightgray',
String: 'purple',
Keyword: '_red_',
Error: 'red',
Literal: 'yellow',
Number: 'blue',
}
def get_colorscheme():
return MONKEY_COLORS
class MonkeyLexer(RegexLexer):
keywords = ['[a-z]*id', '^[a-z A-Z]*:']
attributes = ['[Tt]rue', '[Ff]alse']
params = ['[a-z]*[Nn]ame', 'type', '[Ss]tate']
uuid_rgx = r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
date_rgx = r'[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9:]{8}-[0-9]{4}'
def makelistre(lis):
return r'(' + r'|'.join(lis) + r')'
tokens = {
'root': [
(r' ', Whitespace),
(date_rgx, Number),
(uuid_rgx, Literal),
(r'(?:\b\d+\b(?:-\b\d+|%)?)', Number),
(r'^[-=]*\n', Operator.Word),
(r'Error', Error),
(makelistre(keywords), Keyword),
(makelistre(attributes), Literal),
(makelistre(params) + r'( = )(.*)', bygroups(Name, Operator,
String)),
(makelistre(params), Name),
(r'(^[a-zA-Z]* )(=)', bygroups(Name, Operator)),
(r'\S+', Text),
]
}
def analyse_text(text):
npos = text.find('\n')
if npos < 3:
return False
return text[0] == '[' and text[npos - 1] == ']'
class MonkeyFormatter(Formatter):
def __init__(self, **options):
Formatter.__init__(self, **options)
self.colorscheme = get_colorscheme()
def format(self, tokensource, outfile):
self.encoding = outfile.encoding
return Formatter.format(self, tokensource, outfile)
def format_unencoded(self, tokensource, outfile):
for ttype, value in tokensource:
color = self.colorscheme.get(ttype)
while color is None:
ttype = ttype[:-1]
color = self.colorscheme.get(ttype)
if color:
spl = value.split('\n')
for line in spl[:-1]:
if line:
outfile.write(ansiformat(color, line))
outfile.write('\n')
if spl[-1]:
outfile.write(ansiformat(color, spl[-1]))
else:
outfile.write(value)
def monkeyprint(text):
fmter = MonkeyFormatter()
lexer = MonkeyLexer()
lexer.encoding = 'utf-8'
fmter.encoding = 'utf-8'
highlight(text, lexer, fmter, sys.stdout)

View File

@ -26,7 +26,7 @@ from cloudmonkey import __version__
name = 'cloudmonkey'
version = __version__
requires = ['clint>=0.3.0',
requires = ['Pygments>=1.5',
'prettytable>=0.6',
]

4254
tools/whisker/LICENSE Normal file

File diff suppressed because it is too large Load Diff

689
tools/whisker/NOTICE Normal file
View File

@ -0,0 +1,689 @@
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
This distribution contains third party resources requiring the following notices:
For
cloud-ejb-api-3.0.jar
cloud-email.jar
cloud-jstl-1.2.jar
jaxb-api-2.1.jar
jaxb-impl-2.1.7.jar
jaxb-xjc-2.1.7.jar
jta-1.1.jar
mail-1.4.jar
NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
(CDDL)
The code released under the CDDL shall be governed by the laws of the State of
California (excluding conflict-of-law provisions). Any litigation relating to
this License shall be subject to the jurisdiction of the Federal Courts of the
Northern District of California and the state courts of the State of California,
with venue lying in Santa Clara County, California.
For
cloud-javax.persistence-2.0.0.jar
EclipseLink 2.0.0
Dec 10th, 2009
About
The EclipseLink project's goal is to provide a complete persistence framework
that is both comprehensive and universal. It will run in any Java environment
and read and write objects to virtually any type of data source, including
relational databases, and XML. EclipseLink will focus on providing leading edge
support, including advanced feature extensions, for the dominant persistence
standards for each target data source; Java Persistence API (JPA) for relational
databases, Java API for XML Binding (JAXB) for XML, Service Data Objects (SDO),
and Database Web services (DBWS).
For tips on getting started with EclipseLink, please see the following
resources:
EclipseLink 2.0.0 Release Notes Documentation Examples and How To License
The Eclipse Foundation makes available all content in this plug-in ("Content").
Unless otherwise indicated below, the Content is provided to you under the terms
and conditions of the Eclipse Public License Version 1.0 ("EPL") and Eclipse
Distribution License Version 1.0 ("EDL"). A copy of the EPL is available at
http://www.eclipse.org/legal/epl-v10.html and a copy of the EDL is available at
http://www.eclipse.org/org/documents/edl-v10.php. For purposes of the EPL,
"Program" will mean the Content.
If you did not receive this Content directly from the Eclipse Foundation, the
Content is being redistributed by another party ("Redistributor") and different
terms and conditions may apply to your use of any object code in the Content.
Check the Redistributor's license that was provided with the Content. If no such
license exists, contact the Redistributor. Unless otherwise indicated below, the
terms and conditions of the EPL and EDL still apply to any source code in the
Content and such source code may be obtained at http://www.eclipse.org.
Third Party Content
The Content includes items that have been sourced from third parties as set out
below. If you did not receive this Content directly from the Eclipse Foundation,
the following is provided for informational purposes only, and you should look
to the Redistributor's license for terms and conditions of use.
Foundation Dependencies ASM EclipseLink JPA ANTLR Java Persistence API (JPA) 1.0
- EJB 3.0 Java Persistence API (JPA) 2.0 EARLY ACCESS EclipseLink MOXy Java
Architecture for XML Binding (JAXB) Java Mail Java Activation Framework
Streaming API for XML (StAX) EclipseLink SDO Service Data Objects (SDO)
Utilities Java Connector Xerces WSDL4J 1.6.2 ASM v1.5.3
The EclipseLink Project includes ASM for the purpose of byte code weaving. The
AMS library is re-packaged within the source of the project
(org.persistence.eclipse.internal.libraries.asm.*) to avoid version collisions
with other usage of ASM. A custom patch has been added to the ASM 1.5.3 source
to handle an issue with other usages. This fix has also been contributed back to
the ASM project for inclusion in later projects.
The source code is available within the project's subversion repository. The
binaries are distributed within the eclipselink.jar and in the
org.eclipse.persistence.asm_2.0.0.v*.jar bundle.
http://asm.objectweb.org/license.html
Copyright (c) 2000-2005 INRIA, France Telecom, All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer. Redistributions in binary form must
reproduce the above copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with the
distribution. Neither the name of the copyright holders nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY
THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSEARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BELIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, ORCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OFSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER INCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OFTHE POSSIBILITY OF SUCH DAMAGE.
ANTLR v3.0
The ANTLR library (license) is included within EclipseLink Project to enable
parsing of the Java Persistence Query language (JP QL). The ANTLR library is re-
packaged within the project in the
org.eclipse.persistence.internal.libraries.antlr.* packages.
The source is available with the project's subversion repository. The binaries
are distributed within the eclipselink.jar and in the
org.eclipse.persistence.antlr_2.0.0.v*.jar bundle.
Java Architecture for XML Binding (JAXB) v2.0.5
The JAXB libraries distributed under CDDL v1.0 are included within the
EclipseLink Project to enable the MOXY component's implementation of JAXB.
JAXB Libraries:
/jlib/moxy/javax.xml.bind_2.1.12.v20090708-1500.jar /jlib/moxy/jaxb-impl.jar
/jlib/moxy/jaxb.xjc.jar Java Persistence (JPA) 1.0 - EJB 3.0
The Java Persistence API, included with EJB 3.0, is available for download from
the ejb-api directory in the glassfish CVS repository.It is distributed under
CDDLv1.0 . The jar is being shipped as an OSGi bundle and is required for
compilation of some container based fuctionality.
Java Persistence (JPA) 2.0.
EclipseLink is the Java Persistence (JPA) 2.0 Reference Implementation (JSR
317). The JPA 2.0 specification API is included in EclipseLink under the EPL and
EDL licenses.
Java Mail v1.4
The Java Mail library (mail.jar) is distributed with the JAXB v2.0.5 under CDDL
v1.0 and is included within the EclipseLink Project distribution to support Web
Services attachment handling in the MOXy component. It is only required when
using Java SE 5 (Java Mail is included in Java SE 6).
Java Activation Framework v1.1
The Java Activation Framework (activation.jar) is distributed with the JAXB
v2.0.5 under CDDL v1.0 and is included within the EclipseLink Project
distribution to support Web Services attachment handling in the MOXy component.
It is only required when using Java SE 5 (The Java Activation Framework is
included in Java SE 6).
Streaming API for XML (StAX) v1.0
The Streaming API for XML (StAX) library (jsr173_1.0_api.jar) is distributed
with the JAXB v2.0.5 under CDDL v1.0 and is included within the EclipseLink
Project distribution as an optional XML processing approach in the MOXy
component.
Service Data Objects (SDO) v2.1.1
The Service Data Objects (SDO) API is distributed under a CDDLv1.0 and custom
license. It provides the standard API implemented by the EclipseLink Project's
SDO component.
Java Connector v1.5
The JCA 1.5 API is available for download from the connector-api directory in
the glassfish CVS repository. It is distributed under CDDLv1.0 .
This jar is being shipped and required by the Workbench only. When using
EclipseLink in a container where JCA integration is required that container will
provide the necessary API libraries.
Xerces v2.9.0
Xerces 2.9.0 is available from the Xerces home page. It is distributed under
Apache 2.0.
This jar is shipped for the Workbench's use only in the reading and writing of
XML configuration files.
WSDL4j v1.6.2
WSDL4J 1.6.2 is available for download from the wsdl4j project. It distributed
under CPLv1.0 .
This jar is being shipped as a OSGi bundle and is only required for the DBWS
Builder utility.
For
cloud-commons-logging-1.1.1.jar
commons-logging-1.1.1.jar
// ------------------------------------------------------------------
// NOTICE file corresponding to the section 4d of The Apache License,
// Version 2.0, in this case for Commons Logging
// ------------------------------------------------------------------
Commons Logging
Copyright 2001-2007 The Apache Software Foundation
This product includes/uses software(s) developed by 'an unknown organization'
- Unnamed - avalon-framework:avalon-framework:jar:4.1.3
- Unnamed - log4j:log4j:jar:1.2.12
- Unnamed - logkit:logkit:jar:1.0.1
For
neethi-2.0.4.jar
=========================================================================
== NOTICE file corresponding to the section 4 d of ==
== the Apache License, Version 2.0, ==
== in this case for the Apache AXIOM distribution. ==
=========================================================================
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
Portions Copyright 2006 International Business Machines Corp.
Please read the different LICENSE files present in the licenses directory of
this distribution.
For
cloud-jasypt-1.9.jar
Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org)
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 distribution includes cryptographic software. The country in
which you currently reside may have restrictions on the import,
possession, use, and/or re-export to another country, of
encryption software. BEFORE using any encryption software, please
check your country's laws, regulations and policies concerning the
import, possession, or use, and re-export of encryption software, to
see if this is permitted. See http://www.wassenaar.org/ for more
information.
The U.S. Government Department of Commerce, Bureau of Industry and
Security (BIS), has classified this software as Export Commodity
Control Number (ECCN) 5D002.C.1, which includes information security
software using or performing cryptographic functions with asymmetric
algorithms. The form and manner of this distribution makes it
eligible for export under the License Exception ENC Technology
Software Unrestricted (TSU) exception (see the BIS Export
Administration Regulations, Section 740.13) for both object code and
source code.
The following provides more details on the cryptographic software
used (note that this software is not included in the distribution):
* The PBE Encryption facilities require the Java Cryptography
extensions: http://java.sun.com/javase/technologies/security/.
---------------------------------
Distributions of this software may include software developed by
The Apache Software Foundation (http://www.apache.org/).
---------------------------------
ICU License - ICU 1.8.1 and later
COPYRIGHT AND PERMISSION NOTICE
Copyright (c) 1995-2006 International Business Machines
Corporation and others
All rights reserved.
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish,
distribute, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so,
provided that the above copyright notice(s) and this
permission notice appear in all copies of the Software and
that both the above copyright notice(s) and this
permission notice appear in supporting documentation.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO
EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
USE OR PERFORMANCE OF THIS SOFTWARE.
Except as contained in this notice, the name of a copyright
holder shall not be used in advertising or otherwise to
promote the sale, use or other dealings in this Software
without prior written authorization of the copyright holder.
For
jquery.md5.js
jQuery MD5 Plugin 1.2.1
https://github.com/blueimp/jQuery-MD5
Copyright 2010, Sebastian Tschan
https://blueimp.net
Licensed under the MIT license:
http://creativecommons.org/licenses/MIT/
Based on
A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
Digest Algorithm, as defined in RFC 1321.
Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
Distributed under the BSD License
See http://pajhome.org.uk/crypt/md5 for more info.
For
XmlSchema-1.4.3.jar
Portions Copyright 2006 International Business Machines Corp.
For
cloud-trilead-ssh2-build213.jar
Trilead SSH-2 for Java includes code that was written by Dr. Christian Plattner
during his PhD at ETH Zurich. The license states the following:
Copyright (c) 2005 - 2006 Swiss Federal Institute of Technology (ETH Zurich),
Department of Computer Science (http://www.inf.ethz.ch),
Christian Plattner. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
a.) Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
b.) Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
c.) Neither the name of ETH Zurich nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
The Java implementations of the AES, Blowfish and 3DES ciphers have been
taken (and slightly modified) from the cryptography package released by
"The Legion Of The Bouncy Castle".
Their license states the following:
Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle
(http://www.bouncycastle.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
For
jquery.js
jQuery JavaScript Library v1.3.2
http://jquery.com/
Copyright (c) 2009 John Resig
Dual licensed under the MIT and GPL licenses.
http://docs.jquery.com/License
Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
Revision: 6246
For
axis2-1.5.1.jar
axis2-adb-1.5.1.jar
axis2-ant-plugin-1.5.1.jar
axis2-codegen-1.4.1.jar
axis2-jaxbri-1.5.1.jar
axis2-jaxws-1.5.1.jar
axis2-jibx-1.5.1.jar
axis2-json-1.5.1.jar
axis2-kernel-1.5.1.jar
axis2-transport-http-1.5.1.jar
axis2-transport-local-1.5.1.jar
axis2-webapp-1.5.1.war
cloud-axis.jar
=========================================================================
== NOTICE file corresponding to the section 4 d of ==
== the Apache License, Version 2.0, ==
== in this case for the Apache Axis2 distribution. ==
=========================================================================
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
Portions Copyright 2006 International Business Machines Corp.
Portions Copyright 2005-2007 WSO2, Inc.
This product also includes schemas and specification developed by:
- the W3C consortium (http://www.w3c.org)
This product also includes WS-* schemas developed by International
Business Machines Corporation, Microsoft Corporation, BEA Systems,
TIBCO Software, SAP AG, Sonic Software, and VeriSign
This product also includes a WSDL developed by salesforce.com
- Copyright 1999-2006 salesforce.com, inc.
Portions of the included xmlbeans library were originally based on the following:
- software copyright (c) 2000-2003, BEA Systems, <http://www.bea.com/>.
Please read the different LICENSE files present in the lib directory of
this distribution.
For
xml-apis.jar
=========================================================================
== NOTICE file corresponding to section 4(d) of the Apache License, ==
== Version 2.0, in this case for the Apache xml-commons xml-apis ==
== distribution. ==
=========================================================================
Apache XML Commons XML APIs
Copyright 2006 The Apache Software Foundation.
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
Portions of this software were originally based on the following:
- software copyright (c) 1999, IBM Corporation., http://www.ibm.com.
- software copyright (c) 1999, Sun Microsystems., http://www.sun.com.
- software copyright (c) 2000 World Wide Web Consortium, http://www.w3.org
For
cloud-commons-codec-1.5.jar
commons-codec-1.4.jar
Apache Commons Codec
Copyright 2002-2011 The Apache Software Foundation
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
--------------------------------------------------------------------------------
src/test/org/apache/commons/codec/language/DoubleMetaphoneTest.java contains
test data from http://aspell.sourceforge.net/test/batch0.tab.
Copyright (C) 2002 Kevin Atkinson (kevina@gnu.org). Verbatim copying
and distribution of this entire article is permitted in any medium,
provided this notice is preserved.
--------------------------------------------------------------------------------
For
jquery.js
jQuery JavaScript Library v1.6.1
http://jquery.com/
Copyright 2011, John Resig
Dual licensed under the MIT or GPL Version 2 licenses.
http://jquery.org/license
Includes Sizzle.js
http://sizzlejs.com/
Copyright 2011, The Dojo Foundation
Released under the MIT, BSD, and GPL Licenses.
Date: Thu May 12 15:04:36 2011 -0400
For
rampart-lib
Apache Rampart
Copyright 2010 The Apache Software Foundation
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
Please read the different LICENSE files present in the lib directory of
this distribution.
For
xercesImpl.jar
=========================================================================
== NOTICE file corresponding to section 4(d) of the Apache License, ==
== Version 2.0, in this case for the Apache Xerces Java distribution. ==
=========================================================================
Apache Xerces Java
Copyright 1999-2012 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
Portions of this software were originally based on the following:
- software copyright (c) 1999, IBM Corporation., http://www.ibm.com.
- software copyright (c) 1999, Sun Microsystems., http://www.sun.com.
- voluntary contributions made by Paul Eng on behalf of the
Apache Software Foundation that were originally developed at iClick, Inc.,
software copyright (c) 1999.
For
jquery.colorhelpers.js
Plugin for jQuery for working with colors.
Version 1.1.
Inspiration from jQuery color animation plugin by John Resig.
Released under the MIT license by Ole Laursen, October 2009.
For
woden-api-1.0M8.jar
woden-impl-dom-1.0M8.jar
=========================================================================
== NOTICE file corresponding to the section 4 d of ==
== the Apache License, Version 2.0, ==
== in this case for the Apache Woden distribution. ==
=========================================================================
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
This product also includes software developed by :
- IBM Corporation (http://www.ibm.com),
WSDL4J was the initial code contribution for the Apache Woden
project and some of the WSDL4J design and code has been reused.
- The W3C Consortium (http://www.w3c.org),
Common W3C XML Schema and DTD files are packaged with Apache Woden.
Please read the different LICENSE files present in the root directory of
this distribution.
For
axiom-api-1.2.8.jar
axiom-impl-1.2.8.jar
Axiom includes software from other projects, as follows:
This software includes the Woodstox High-performance XML processor
http://woodstox.codehaus.org/
licensed under the Apache License, Version 2.0
This software includes the Jaxen XPath library
http://jaxen.codehaus.org/
licensed under the following BSD 3 Clause license:
================================================================================
Copyright 2003-2006 The Werken Company. All Rights Reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Jaxen Project nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================
For
wss4j-1.5.8.jar
Apache WebServices - WSS4J
Copyright 2004-2011 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
This product includes software Copyright University of Southampton IT
Innovation Centre, 2006 (http://www.it-innovation.soton.ac.uk).

File diff suppressed because it is too large Load Diff

View File

@ -404,7 +404,7 @@ of liability.
</text>
</license>
<license
name='Mozilla Public License, Version 1.0'
name='Mozilla Public License, Version 1.1'
id='MPL1'
url='http://www.mozilla.org/MPL/1.1/' >
<template>
@ -2425,7 +2425,7 @@ Innovation Centre, 2006 (http://www.it-innovation.soton.ac.uk).
url='http://www.adiscon.com/' />
</organisations>
<primary-license id='ApacheLicenseVersion2'>
<copyright-notice>Copyright (c) 2012 The Apache Software Foundation</copyright-notice>
<copyright-notice>Copyright (c) 2013 The Apache Software Foundation</copyright-notice>
</primary-license>
<primary-notice id="foo">
This product includes software developed at
@ -2654,299 +2654,4 @@ Copyright (c) 2010-2011 OpenStack, LLC.
</by-organisation>
</with-license>
</within>
<!-- Resources below this line are binary dependencies that are only pulled in during the build process. -->
<within dir='target/jar'>
<with-license id='MIT'>
<copyright-notice>
Copyright (C) 2008 Tóth István &lt;stoty@tvnet.hu&gt;
2008-2012 Daniel Veillard &lt;veillard@redhat.com&gt;
2009-2011 Bryan Kearney &lt;bkearney@redhat.com&gt;
</copyright-notice>
<by-organisation id='libvirt.org'>
<resource name='libvirt-java-0.4.9' />
</by-organisation>
</with-license>
<with-license id="ApacheLicenseVersion2">
<copyright-notice>
Copyright (c) 2012 The Apache Software Foundation
</copyright-notice>
<by-organisation id="apache.org.2">
<resource name="cloud-axis.jar" source="http://axis.apache.org/axis/" notice='axis2.notice'/>
<resource name="cloud-commons-codec-1.5.jar" source="http://commons.apache.org/codec/" notice="codec" />
<resource name="cloud-commons-collections-3.2.1.jar" source="http://commons.apache.org/collections/"/>
<resource name="cloud-commons-configuration-1.8.jar" source="http://commons.apache.org/configuration/"/>
<resource name="cloud-commons-dbcp-1.4.jar" source="http://commons.apache.org/dbcp/" />
<resource name="cloud-commons-httpclient-3.1.jar" source="http://hc.apache.org/httpclient-3.x/" />
<resource name="cloud-commons-lang-2.6.jar" source="http://commons.apache.org/lang/" />
<resource name="cloud-commons-logging-1.1.1.jar" source="http://commons.apache.org/logging/" notice="logging" />
<resource name="cloud-commons-pool-1.5.6.jar" source="http://commons.apache.org/pool/" />
<resource name="cloud-log4j.jar" source="http://logging.apache.org/log4j/" />
<resource name="cloud-log4j-extras.jar" source="http://logging.apache.org/log4j/companions/extras/" />
<resource name="cloud-ws-commons-util-1.0.2.jar" source="http://ws.apache.org/commons/util/" />
<resource name="cloud-xmlrpc-client-3.1.3.jar" source="http://ws.apache.org/xmlrpc/client.html" />
<resource name="cloud-xmlrpc-common-3.1.3.jar" source="http://ws.apache.org/xmlrpc/xmlrpc-common/" />
<resource name="cloud-cglib.jar" source='http://cglib.sourceforge.net/' />
</by-organisation>
</with-license>
<with-license id="ApacheLicenseVersion1.1">
<copyright-notice>
Copyright (c) 2012 The Apache Software Foundation
</copyright-notice>
<by-organisation id="apache.org.2">
<resource name="cloud-commons-discovery.jar" source="http://commons.apache.org/discovery/" />
</by-organisation>
</with-license>
<with-license id="ApacheLicenseVersion2">
<copyright-notice>
Copyright (c) 2007-2010, The JASYPT team (http://www.jasypt.org)
</copyright-notice>
<by-organisation id='jasypt.org'>
<resource name='cloud-jasypt-1.9.jar' source='http://www.jasypt.org' notice='jasypt.notice' />
</by-organisation>
</with-license>
<with-license id="ApacheLicenseVersion2">
<copyright-notice>
Copyright (c) 2003-2007 Luck Consulting Pty Ltd
</copyright-notice>
<by-organisation id="luck">
<resource name="cloud-ehcache.jar" source="http://ehcache.org/" />
</by-organisation>
</with-license>
<with-license id='CDDL'>
<copyright-notice>
Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved.
</copyright-notice>
<by-organisation id='glassfish.org'>
<resource name='cloud-ejb-api-3.0.jar' source='http://repo1.maven.org/maven2/javax/ejb/ejb-api/3.0/ejb-api-3.0-sources.jar' notice='cddlnotice' />
<resource name='cloud-jstl-1.2.jar' source='http://jstl.java.net/' notice='cddlnotice' />
</by-organisation>
</with-license>
<with-license id='CDDL'>
<copyright-notice>
Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
</copyright-notice>
<by-organisation id='oracle.com'>
<resource name='cloud-email.jar' source='http://kenai.com/projects/javamail' notice='cddlnotice' />
</by-organisation>
</with-license>
<with-license id='ApacheLicenseVersion2'>
<copyright-notice>
Copyright (c) 2009 Google Inc.
</copyright-notice>
<by-organisation id='google.com'>
<resource name='cloud-google-gson-1.7.1.jar' source='http://code.google.com/p/google-gson/' />
</by-organisation>
</with-license>
<with-license id='EclipseDistributionLicense1'>
<copyright-notice>
Copyright (c) 2012 The Eclipse Foundation.
</copyright-notice>
<by-organisation id='eclipse.org'>
<resource name='cloud-javax.persistence-2.0.0.jar' source='http://wiki.eclipse.org/EclipseLink/Release/2.0.0' notice='eclipse.persistence' />
</by-organisation>
</with-license>
<with-license id='BSD3ClauseGeneric'>
<copyright-notice>
Copyright (c) 2009, Caringo, Inc.
</copyright-notice>
<by-organisation id='caringo.com'>
<resource name='CAStorSDK.jar' source='http://www.castor.org/download.html' />
</by-organisation>
</with-license>
<with-license id='BSD3ClauseGeneric'>
<copyright-notice>
Copyright (c) 2002-2011 Atsuhiko Yamanaka, JCraft,Inc.
</copyright-notice>
<by-organisation id='jcraft.com'>
<resource name='cloud-jsch-0.1.42.jar' source='http://www.jcraft.com/jsch/' />
</by-organisation>
</with-license>
<with-license id='CPL1'>
<copyright-notice>
Copyright (c) IBM Corp 2006
</copyright-notice>
<by-organisation id='ibm.com'>
<resource name='cloud-wsdl4j-1.6.2.jar' source='http://sourceforge.net/projects/wsdl4j/' />
<resource name='cloud-wsdl4j.jar' source='http://sourceforge.net/projects/wsdl4j/' />
</by-organisation>
</with-license>
<with-license id='xstream.bsd'>
<copyright-notice />
<by-organisation id='xstream.codehaus.com'>
<resource name='cloud-xstream-1.3.1.jar' source='http://xstream.codehaus.org/repository.html' />
</by-organisation>
</with-license>
<with-license id='bouncy.mit'>
<copyright-notice />
<by-organisation id='bouncy.castle'>
<resource name='cloud-bcprov-jdk16-1.45.jar' source='http://repo1.maven.org/maven2/org/bouncycastle/bcprov-jdk16/1.45/bcprov-jdk16-1.45-sources.jar' />
</by-organisation>
</with-license>
<with-license id='BSD3ClauseGeneric'>
<copyright-notice>
Copyright (c) 2007-2008 Trilead AG (http://www.trilead.com)
All rights reserved.
</copyright-notice>
<by-organisation id='trilead.com'>
<resource name='cloud-trilead-ssh2-build213.jar' source='http://sourceforge.net/projects/orion-ssh2/' notice='trilead.notice' />
</by-organisation>
</with-license>
<with-license id='ApacheLicenseVersion2'>
<copyright-notice />
<by-organisation id='jetty.codehaus.com'>
<resource name='jetty-6.1.26.jar' source='http://repo1.maven.org/maven2/org/mortbay/jetty/jetty/6.1.26/jetty-6.1.26-sources.jar' />
<resource name='jetty-util-6.1.26.jar' source='http://repo1.maven.org/maven2/org/mortbay/jetty/jetty-util/6.1.26/jetty-util-6.1.26-sources.jar' />
</by-organisation>
</with-license>
<with-license id='CPL1'>
<copyright-notice />
<by-organisation id='junit.org'>
<resource name='cloud-junit.jar' source='http://kentbeck.github.com/junit/' />
</by-organisation>
</with-license>
<public-domain>
<by-organisation id='distcomplab.emory'>
<resource name='cloud-backport-util-concurrent-3.0.jar' source='http://backport-jsr166.sourceforge.net/' />
</by-organisation>
</public-domain>
</within>
<within dir='deps/awsapi-lib'>
<with-license id='ApacheLicenseVersion2'>
<copyright-notice>
Copyright (c) 2004-2008 The Apache Software Foundation
</copyright-notice>
<by-organisation id='apache.org.2'>
<resource name='XmlSchema-1.4.3.jar' notice='xmlschema.notice' />
</by-organisation>
</with-license>
<with-license id='antlr2'>
<copyright-notice />
<by-organisation id='antlr2.org'>
<resource name='antlr-2.7.6.jar' source='http://repo1.maven.org/maven2/antlr/antlr/2.7.6/antlr-2.7.6-sources.jar' />
</by-organisation>
</with-license>
<with-license id='MIT'>
<copyright-notice>
Copyright (c) 2004-2011 QOS.ch
</copyright-notice>
<by-organisation id='qos.ch'>
<resource name='slf4j-api-1.5.11.jar' source='https://github.com/qos-ch/slf4j' />
<resource name='slf4j-jdk14-1.5.11.jar' source='https://github.com/qos-ch/slf4j' />
</by-organisation>
</with-license>
<with-license id="ApacheLicenseVersion2">
<copyright-notice>
Copyright (c) 2004-2012 The Apache Software Foundation
</copyright-notice>
<by-organisation id="apache.org.2">
<resource name="apache-log4j-extras-1.0.jar" source="http://logging.apache.org/log4j/companions/extras/" />
<resource name="axiom-api-1.2.8.jar" source="http://ws.apache.org/axiom/source-repository.html" notice="axiom.notice" />
<resource name="axiom-impl-1.2.8.jar" source="http://ws.apache.org/axiom/source-repository.html" notice="axiom.notice" />
<resource name="axis2-1.5.1.jar" source="http://axis.apache.org/axis/" notice='axis2.notice' />
<resource name="axis2-codegen-1.4.1.jar" source="http://axis.apache.org/axis/" notice='axis2.notice' />
<resource name="axis2-adb-1.5.1.jar" source="http://axis.apache.org/axis/" notice='axis2.notice' />
<resource name="axis2-ant-plugin-1.5.1.jar" source="http://axis.apache.org/axis/" notice='axis2.notice' />
<resource name="axis2-jaxbri-1.5.1.jar" source="http://axis.apache.org/axis/" notice='axis2.notice' />
<resource name="axis2-jaxws-1.5.1.jar" source="http://axis.apache.org/axis/" notice='axis2.notice' />
<resource name="axis2-jibx-1.5.1.jar" source="http://axis.apache.org/axis/" notice='axis2.notice' />
<resource name="axis2-json-1.5.1.jar" source="http://axis.apache.org/axis/" notice='axis2.notice' />
<resource name="axis2-kernel-1.5.1.jar" source="http://axis.apache.org/axis/" notice='axis2.notice' />
<resource name="axis2-transport-http-1.5.1.jar" source="http://axis.apache.org/axis/" notice='axis2.notice' />
<resource name="axis2-transport-local-1.5.1.jar" source="http://axis.apache.org/axis/" notice='axis2.notice' />
<resource name="axis2-webapp-1.5.1.war" source="http://axis.apache.org/axis/" notice='axis2.notice' />
<resource name="commons-codec-1.4.jar" source="http://commons.apache.org/codec/" notice="codec" />
<resource name="commons-collections-3.1.jar" source="http://commons.apache.org/collections/"/>
<resource name='commons-fileupload-1.2.jar' source='http://commons.apache.org/fileupload/' />
<resource name="commons-httpclient-3.1.jar" source="http://hc.apache.org/httpclient-3.x/" />
<resource name='commons-io-1.4.jar' source='http://commons.apache.org/io/' />
<resource name="commons-logging-1.1.1.jar" source="http://commons.apache.org/logging/" notice="logging" />
<resource name="httpcore-4.0.jar" source="http://hc.apache.org/httpcomponents-core-ga/" />
<resource name="log4j-1.2.15.jar" source="http://logging.apache.org/log4j/" />
<resource name="neethi-2.0.4.jar" source="http://svn.apache.org/viewvc/webservices/commons/tags/neethi/2.0.4/" notice='neethi.notice' />
<resource name="rampart-lib" source="http://axis.apache.org/axis2/java/rampart/download/1.5/download.cgi" notice='rampart.notice' />
<resource name="woden-api-1.0M8.jar" source='http://svn.apache.org/viewvc/webservices/woden/tags/1.0M8_20080423/' notice='woden.notice' />
<resource name="woden-impl-dom-1.0M8.jar" source='http://svn.apache.org/viewvc/webservices/woden/tags/1.0M8_20080423/' notice='woden.notice' />
<resource name='xercesImpl.jar' source='http://xerces.apache.org/xerces2-j/source-repository.html' notice='xerces.notice' />
<resource name='xml-apis.jar' source='http://repo1.maven.org/maven2/xml-apis/xml-apis/1.3.04/xml-apis-1.3.04-sources.jar' notice='xml-apis.notice' />
<resource name='wss4j-1.5.8.jar' source='http://ws.apache.org/wss4j/source-repository.html' notice='wss4j.notice' />
</by-organisation>
</with-license>
<with-license id='ApacheLicenseVersion2'>
<copyright-notice>
Copyright (c) 2009 Google Inc.
</copyright-notice>
<by-organisation id='google.com'>
<resource name='cloud-gson.jar' source='http://code.google.com/p/google-gson/' />
</by-organisation>
</with-license>
<with-license id='dom4j.license'>
<copyright-notice />
<by-organisation id='dom4j.sourceforge.net'>
<!-- TODO: Need to have a review of this license! -->
<resource name='dom4j-1.6.1.jar' source='http://dom4j.sourceforge.net/source-repository.html' />
</by-organisation>
</with-license>
<with-license id='CDDL'>
<copyright-notice>
Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
</copyright-notice>
<by-organisation id='oracle.com'>
<resource name='jaxb-api-2.1.jar' source='http://repo1.maven.org/maven2/javax/xml/bind/jaxb-api/2.1/jaxb-api-2.1-sources.jar' notice='cddlnotice' />
<resource name='jaxb-impl-2.1.7.jar' source='http://repo1.maven.org/maven2/com/sun/xml/bind/jaxb-impl/2.1.7/jaxb-impl-2.1.7-sources.jar' notice='cddlnotice' />
<resource name='jaxb-xjc-2.1.7.jar' source='http://repo1.maven.org/maven2/com/sun/xml/bind/jaxb-xjc/2.1.7/jaxb-xjc-2.1.7-sources.jar' notice='cddlnotice' />
</by-organisation>
</with-license>
<with-license id='CDDL'>
<copyright-notice>
Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved.
</copyright-notice>
<by-organisation id='glassfish.org'>
<resource name='jta-1.1.jar' source='http://repo1.maven.org/maven2/javax/transaction/jta/1.1/jta-1.1-sources.jar' notice='cddlnotice' />
</by-organisation>
</with-license>
<with-license id='BSD3ClauseGeneric'>
<copyright-notice>
Copyright (c) 2002-2011 Atsuhiko Yamanaka, JCraft,Inc.
</copyright-notice>
<by-organisation id='jcraft.com'>
<resource name='jsch-0.1.42.jar' source='http://www.jcraft.com/jsch/' />
</by-organisation>
</with-license>
<with-license id='ApacheLicenseVersion2'>
<copyright-notice />
<by-organisation id='json-simple'>
<resource name='json_simple-1.1.jar' source='http://code.google.com/p/json-simple/source/checkout' />
</by-organisation>
</with-license>
<with-license id='CDDL'>
<copyright-notice>
Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
</copyright-notice>
<by-organisation id='oracle.com'>
<resource name='mail-1.4.jar' source='http://kenai.com/projects/javamail' notice='cddlnotice' />
</by-organisation>
</with-license>
<with-license id='CPL1'>
<copyright-notice />
<by-organisation id='junit.org'>
<resource name='junit-4.8.1.jar' source='http://kentbeck.github.com/junit/' />
</by-organisation>
</with-license>
<with-license id='MPL1'>
<copyright-notice />
<license-parameters>
<parameter><name>PROJECT</name><value>Javassist</value></parameter>
<parameter><name>INITIAL_DEVELOPER</name><value>Shigeru Chiba</value></parameter>
<parameter><name>INITIAL_DEVELOPER_COPYRIGHT</name><value>1999-2008 Shigeru Chiba</value></parameter>
<parameter><name>CONTRIBUTORS</name><value></value></parameter>
<parameter><name>ALT_LIC_NAME</name><value>GNU Lesser General Public License Version 2.1 or later</value></parameter>
<parameter><name>ALT_LIC_SHORT</name><value>LGPL</value></parameter>
</license-parameters>
<by-organisation id='person:shigeru.chiba'>
<resource name='javassist-3.9.0.GA.jar' source='http://sourceforge.net/projects/jboss/files/Javassist/' />
</by-organisation>
</with-license>
</within>
</manifest>

View File

@ -441,15 +441,11 @@ body.login {
div.list-view table tbody td span {
display: block;
float: left;
max-width: 160px;
max-width: 100%;
word-wrap: break-word;
text-indent: 0;
margin-left: 12px;
line-height: 15px;
overflow: hidden;
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
div.list-view div.toolbar div.section-switcher div.section-select label {

View File

@ -18,7 +18,7 @@
(function($, cloudStack) {
var zoneObjs, hypervisorObjs, featuredTemplateObjs, communityTemplateObjs, myTemplateObjs, featuredIsoObjs, community, networkObjs;
var selectedZoneObj, selectedTemplateObj, selectedHypervisor, selectedDiskOfferingObj;
var step5ContainerType = 'nothing-to-select'; //'nothing-to-select', 'select-network', 'select-security-group'
var step5ContainerType = 'nothing-to-select'; //'nothing-to-select', 'select-network', 'select-security-group', 'select-advanced-sg'(advanced sg-enabled zone)
cloudStack.instanceWizard = {
maxDiskOfferingSize: function() {
@ -64,7 +64,7 @@
return $.grep(network.service, function(service) {
return service.name == 'SecurityGroup';
}).length;
}).length;
}).length; //return total number of selected sg networks
},
// Data providers for each wizard step
@ -520,7 +520,7 @@
}
//step 5: select network
if (step5ContainerType == 'select-network') {
if (step5ContainerType == 'select-network' || step5ContainerType == 'select-advanced-sg') {
var array2 = [];
var defaultNetworkId = args.data.defaultNetwork; //args.data.defaultNetwork might be equal to string "new-network" or a network ID

View File

@ -9736,7 +9736,7 @@
args.response.success({data:{}});
},
error: function(json) {
args.response.error(parseXMLHttpResponse(XMLHttpResponse));
args.response.error(parseXMLHttpResponse(json));
}
});
},

View File

@ -827,9 +827,15 @@
data: cloudStack.serializeForm($form)
});
if (!advSGFilter) {
if (advSGFilter == 0) { //when total number of selected sg networks is 0, then 'Select Security Group' is skipped, go to step 6 directly
showStep(6);
}
else { //when total number of selected sg networks > 0
if($activeStep.find('input[type=checkbox]:checked').size() > 1) { //when total number of selected networks > 1
cloudStack.dialog.notice({ message: "Can't create a vm with multiple networks one of which is Security Group enabled" });
return false;
}
}
}
}

View File

@ -189,6 +189,7 @@
var $dialog = $snapshots.dialog({
title: _l('label.action.recurring.snapshot'),
dialogClass: 'recurring-snapshots',
closeOnEscape:false,
width: 600,
buttons: [
{
@ -210,4 +211,4 @@
return $dialog;
};
};
}(cloudStack, jQuery));
}(cloudStack, jQuery));

View File

@ -57,22 +57,80 @@
var fields = $.map(args.form.fields, function(value, key) {
return key;
})
$(fields).each(function() {
var ret = function() {
return $formContainer.dialog({
dialogClass: 'create-form',
closeOnEscape: false,
draggable: false,
width: 400,
title: _l(args.form.title),
open: function() {
if (args.form.preFilter) {
args.form.preFilter({ $form: $form, context: args.context });
}
},
buttons: [
{
text: createLabel ? createLabel : _l('label.ok'),
'class': 'ok',
click: function() {
if (!complete($formContainer)) { return false; }
$('div.overlay').remove();
$('.tooltip-box').remove();
$formContainer.remove();
$(this).dialog('destroy');
$('.hovered-elem').hide();
return true;
}
},
{
text: _l('label.cancel'),
'class': 'cancel',
click: function() {
$('div.overlay').remove();
$('.tooltip-box').remove();
$formContainer.remove();
$(this).dialog('destroy');
$('.hovered-elem').hide();
}
}
]
}).closest('.ui-dialog').overlay();
};
var isLastAsync = function(idx) {
for(var i = idx+1; i < $(fields).length ; i++) {
var f = args.form.fields[$(fields).get(i)];
if(f.select || f.dynamic){
return false;
}
}
return true;
};
var isAsync = false;
var isNoDialog = args.noDialog ? args.noDialog : false;
$(fields).each(function(idx, element) {
var key = this;
var field = args.form.fields[key];
var $formItem = $('<div>')
.addClass('form-item')
.attr({ rel: key });
if(field.isHidden != null) {
if (typeof(field.isHidden) == 'boolean' && field.isHidden == true)
$formItem.hide();
else if (typeof(field.isHidden) == 'function' && field.isHidden() == true)
$formItem.hide();
if (typeof(field.isHidden) == 'boolean' && field.isHidden == true)
$formItem.hide();
else if (typeof(field.isHidden) == 'function' && field.isHidden() == true)
$formItem.hide();
}
$formItem.appendTo($form);
//Handling Escape KeyPress events
@ -96,7 +154,7 @@
closeOnEscape: false
}); */
// Label field
var $name = $('<div>').addClass('name')
.appendTo($formItem)
.append(
@ -104,9 +162,10 @@
);
// red asterisk
var $astersikSpan = $('<span>').addClass('field-required').html('*');
$name.find('label').prepend($astersikSpan);
if (field.validation == null || field.validation.required == false) {
var $astersikSpan = $('<span>').addClass('field-required').html('*');
$name.find('label').prepend($astersikSpan);
if (field.validation == null || field.validation.required == false) {
$astersikSpan.hide();
}
@ -169,6 +228,7 @@
// Determine field type of input
if (field.select) {
isAsync = true;
selectArgs = {
context: args.context,
response: {
@ -193,6 +253,10 @@
}
$input.trigger('change');
if((!isNoDialog) && isLastAsync(idx)) {
ret();
}
}
}
};
@ -200,7 +264,7 @@
selectFn = field.select;
$input = $('<select>')
.attr({ name: key })
.data('dialog-select-fn', function(args) {
.data('dialog-select-fn', function(args) {
selectFn(args ? $.extend(true, {}, selectArgs, args) : selectArgs);
})
.appendTo($value);
@ -221,21 +285,21 @@
var dependsOnArgs = {};
$input.find('option').remove();
if (!$target.children().size()) return true;
dependsOnArgs[dependsOn] = $target.val();
selectFn($.extend(selectArgs, dependsOnArgs));
selectFn($.extend(selectArgs, dependsOnArgs));
return true;
});
if (!$dependsOn.is('select')) {
selectFn(selectArgs);
selectFn(selectArgs);
}
} else {
selectFn(selectArgs);
selectFn(selectArgs);
}
} else if (field.isBoolean) {
if (field.multiArray) {
@ -263,7 +327,7 @@
} else {
// This is mainly for IE compatibility
setTimeout(function() {
$input.attr('checked', false);
$input.attr('checked', false);
}, 100);
}
}
@ -277,6 +341,7 @@
});
}
} else if (field.dynamic) {
isAsync = true;
// Generate a 'sub-create-form' -- append resulting fields
$input = $('<div>').addClass('dynamic-input').appendTo($value);
$form.hide();
@ -297,6 +362,9 @@
// Form should be slightly wider
$form.closest(':ui-dialog').dialog('option', { position: 'center',closeOnEscape: false });
if((!isNoDialog) && isLastAsync(idx)) {
ret();
}
}
}
});
@ -308,63 +376,64 @@
if (field.defaultValue) {
$input.val(field.defaultValue);
}
} else if (field.isDatepicker) { //jQuery datepicker
$input = $('<input>').attr({
name: key,
type: 'text'
}).appendTo($value);
} else if (field.isDatepicker) { //jQuery datepicker
$input = $('<input>').attr({
name: key,
type: 'text'
}).appendTo($value);
if (field.defaultValue) {
$input.val(field.defaultValue);
}
if (field.id) {
$input.attr('id', field.id);
}
$input.addClass("disallowSpecialCharacters");
$input.datepicker({dateFormat: 'yy-mm-dd'});
} else if(field.range) { //2 text fields on the same line (e.g. port range: startPort - endPort)
$input = $.merge(
// Range start
$('<input>').attr({
type: 'text',
name: field.range[0]
}),
if (field.defaultValue) {
$input.val(field.defaultValue);
}
if (field.id) {
$input.attr('id', field.id);
}
$input.addClass("disallowSpecialCharacters");
$input.datepicker({dateFormat: 'yy-mm-dd'});
// Range end
$('<input>').attr({
type: 'text',
name: field.range[1]
})
).appendTo(
$('<div>').addClass('range-edit').appendTo($value)
);
$input.wrap($('<div>').addClass('range-item'));
$input.addClass("disallowSpecialCharacters");
} else { //text field
$input = $('<input>').attr({
name: key,
type: field.password || field.isPassword ? 'password' : 'text'
}).appendTo($value);
} else if(field.range) {//2 text fields on the same line (e.g. port range: startPort - endPort)
$input = $.merge(
// Range start
$('<input>').attr({
type: 'text',
name: field.range[0]
}),
if (field.defaultValue) {
$input.val(field.defaultValue);
}
if (field.id) {
$input.attr('id', field.id);
}
// Range end
$('<input>').attr({
type: 'text',
name: field.range[1]
})
).appendTo(
$('<div>').addClass('range-edit').appendTo($value)
);
$input.wrap($('<div>').addClass('range-item'));
$input.addClass("disallowSpecialCharacters");
} else { //text field
$input = $('<input>').attr({
name: key,
type: field.password || field.isPassword ? 'password' : 'text'
}).appendTo($value);
if (field.defaultValue) {
$input.val(field.defaultValue);
}
if (field.id) {
$input.attr('id', field.id);
}
$input.addClass("disallowSpecialCharacters");
}
if(field.validation != null)
if(field.validation != null)
$input.data('validation-rules', field.validation);
else
else
$input.data('validation-rules', {});
var fieldLabel = field.label;
var inputId = $input.attr('id') ? $input.attr('id') : fieldLabel.replace(/\./g,'_');
$input.attr('id', inputId);
$name.find('label').attr('for', inputId);
@ -380,29 +449,32 @@
attachTo: '.form-item'
});
}
/* $input.blur(function() {
console.log('tooltip remove->' + $input.attr('name'));
});*/
});
var getFormValues = function() {
var formValues = {};
$.each(args.form.fields, function(key) {});
};
// Setup form validation
// Setup form validation
$formContainer.find('form').validate();
$formContainer.find('input, select').each(function() {
$formContainer.find('input, select').each(function() {
if ($(this).data('validation-rules')) {
$(this).rules('add', $(this).data('validation-rules'));
}
else {
$(this).rules('add', {});
}
});
$form.find('select').trigger('change');
else {
$(this).rules('add', {});
}
});
$form.find('select').trigger('change');
var complete = function($formContainer) {
var $form = $formContainer.find('form');
var data = cloudStack.serializeForm($form);
@ -429,93 +501,48 @@
$formContainer: $formContainer,
completeAction: complete
};
} else if (!isAsync) {
return ret();
}
return $formContainer.dialog({
dialogClass: 'create-form',
closeOnEscape: false,
draggable: false,
width: 400,
title: _l(args.form.title),
open: function() {
if (args.form.preFilter) {
args.form.preFilter({ $form: $form, context: args.context });
}
},
buttons: [
{
text: createLabel ? createLabel : _l('label.ok'),
'class': 'ok',
click: function() {
if (!complete($formContainer)) { return false; }
$('div.overlay').remove();
$('.tooltip-box').remove();
$formContainer.remove();
$(this).dialog('destroy');
$('.hovered-elem').hide();
return true;
}
},
{
text: _l('label.cancel'),
'class': 'cancel',
click: function() {
$('div.overlay').remove();
$('.tooltip-box').remove();
$formContainer.remove();
$(this).dialog('destroy');
$('.hovered-elem').hide();
}
}
]
}).closest('.ui-dialog').overlay();
},
/**
/**
* to change a property(e.g. validation) of a createForm field after a createForm is rendered
*/
createFormField: {
validation: {
required: {
add: function($formField) {
var $input = $formField.find('input, select');
var validationRules = $input.data('validation-rules');
if(validationRules == null || validationRules.required == null || validationRules.required == false) {
$formField.find('.name').find('label').find('span.field-required').css('display', 'inline'); //show red asterisk
if(validationRules == null)
validationRules = {};
validationRules.required = true;
$input.data('validation-rules', validationRules);
$input.rules('add', { required: true });
}
},
remove: function($formField) {
createFormField: {
validation: {
required: {
add: function($formField) {
var $input = $formField.find('input, select');
var validationRules = $input.data('validation-rules');
if(validationRules != null && validationRules.required != null && validationRules.required == true) {
$formField.find('.name').find('label').find('span.field-required').hide(); //hide red asterisk
delete validationRules.required;
$input.data('validation-rules', validationRules);
var validationRules = $input.data('validation-rules');
if(validationRules == null || validationRules.required == null || validationRules.required == false) {
$formField.find('.name').find('label').find('span.field-required').css('display', 'inline'); //show red asterisk
if(validationRules == null)
validationRules = {};
validationRules.required = true;
$input.data('validation-rules', validationRules);
$input.rules('add', { required: true });
}
},
remove: function($formField) {
var $input = $formField.find('input, select');
var validationRules = $input.data('validation-rules');
if(validationRules != null && validationRules.required != null && validationRules.required == true) {
$formField.find('.name').find('label').find('span.field-required').hide(); //hide red asterisk
delete validationRules.required;
$input.data('validation-rules', validationRules);
$input.rules('remove', 'required');
$formField.find('.value').find('label.error').hide();
}
}
}
}
},
$input.rules('remove', 'required');
$formField.find('.value').find('label.error').hide();
}
}
}
}
},
/**
* Confirmation dialog
*/

View File

@ -36,5 +36,73 @@
<defaultGoal>install</defaultGoal>
<sourceDirectory>src</sourceDirectory>
<testSourceDirectory>test</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>target/dependencies</outputDirectory>
<includeScope>runtime</includeScope>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>generate-resource</id>
<phase>generate-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<copy overwrite="true"
todir="${basedir}/target/transformed">
<fileset dir="${basedir}/../client/tomcatconf">
<include name="**/db.properties.in" />
</fileset>
<globmapper from="*.in" to="*" />
<filterchain>
<filterreader
classname="org.apache.tools.ant.filters.ReplaceTokens">
<param type="propertiesfile"
value="${basedir}/../build/replace.properties" />
</filterreader>
</filterchain>
</copy>
</target>
<target>
<copy overwrite="true"
todir="${basedir}/target/transformed">
<fileset dir="${basedir}/conf">
<include name="*.in" />
</fileset>
<globmapper from="*.in" to="*" />
<filterchain>
<filterreader
classname="org.apache.tools.ant.filters.ReplaceTokens">
<param type="propertiesfile"
value="${basedir}/../build/replace.properties" />
</filterreader>
</filterchain>
</copy>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>