mirror of https://github.com/apache/cloudstack.git
Merge branch 'master' into disk_io_throttling
This commit is contained in:
commit
288c5b61c9
|
|
@ -47,6 +47,7 @@
|
|||
<xi:include href="Author_Group.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||
</bookinfo>
|
||||
<xi:include href="gsoc-tuna.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||
<xi:include href="gsoc-imduffy15.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||
|
||||
</book>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,395 @@
|
|||
<?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_GSoC_Guide.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.
|
||||
-->
|
||||
|
||||
<chapter id="gsoc-imduffy15">
|
||||
<title>Ians's 2013 GSoC Proposal</title>
|
||||
<para>This chapter describes Ians 2013 Google Summer of Code project within the &PRODUCT; ASF project. It is a copy paste of the submitted proposal.</para>
|
||||
<section id="ldap-user-provisioning">
|
||||
<title>LDAP user provisioning</title>
|
||||
<para>
|
||||
"Need to automate the way the LDAP users are provisioned into cloud stack. This will mean better
|
||||
integration with a LDAP server, ability to import users and a way to define how the LDAP user
|
||||
maps to the cloudstack users."
|
||||
</para>
|
||||
</section>
|
||||
<section id="abstract">
|
||||
<title>Abstract</title>
|
||||
<para>
|
||||
The aim of this project is to provide an more effective mechanism to provision users from LDAP
|
||||
into cloudstack. Currently cloudstack enables LDAP authentication. In this authentication users
|
||||
must be first setup in cloudstack. Once the user is setup in cloudstack they can authenticate
|
||||
using their LDAP username and password. This project will improve Cloudstack LDAP integration
|
||||
by enabling users be setup automatically using their LDAP credential
|
||||
</para>
|
||||
</section>
|
||||
<section id="deliverables">
|
||||
<title>Deliverables</title>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Service that retrieves a list of LDAP users from a configured group</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Extension of the cloudstack UI "Add User" screen to offer user list from LDAP</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Add service for saving new user it details from LDAP</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>BDD unit and acceptance automated testing</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Document change details</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section id="quantifiable-results">
|
||||
<title>Quantifiable Results</title>
|
||||
<informaltable>
|
||||
<tgroup cols="2">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Given</entry>
|
||||
<entry>An administrator wants to add new user to cloudstack and LDAP is setup in cloudstack</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>When</entry>
|
||||
<entry>The administrator opens the "Add User" screen</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Then</entry>
|
||||
<entry>A table of users appears for the current list of users (not already created on cloudstack) from the LDAP group displaying their usernames, given name and email address. The timezone dropdown will still be available beside each user</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
<para/>
|
||||
<informaltable>
|
||||
<tgroup cols="2">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Given</entry>
|
||||
<entry>An administrator wants to add new user to cloudstack and LDAP is not setup in cloudstack</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>When</entry>
|
||||
<entry>The administrator opens the "Add User" screen</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Then</entry>
|
||||
<entry>The current add user screen and functionality is provided</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
<para/>
|
||||
<informaltable>
|
||||
<tgroup cols="2">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Given</entry>
|
||||
<entry>An administrator wants to add new user to cloudstack and LDAP is setup in cloudstack</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>When</entry>
|
||||
<entry>The administrator opens the "Add User" screen and mandatory information is missing</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Then</entry>
|
||||
<entry>These fields will be editable to enable you to populate the name or email address</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
<para/>
|
||||
<informaltable>
|
||||
<tgroup cols="2">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Given</entry>
|
||||
<entry>An administrator wants to add new user to cloudstack, LDAP is setup and the user being created is in the LDAP query group</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>When</entry>
|
||||
<entry>The administrator opens the "Add User" screen</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Then</entry>
|
||||
<entry>There is a list of LDAP users displayed but the user is present in the list</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
<para/>
|
||||
<informaltable>
|
||||
<tgroup cols="2">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Given</entry>
|
||||
<entry>An administrator wants to add a new user to cloudstack, LDAP is setup and the user is not in the query group</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>When</entry>
|
||||
<entry>The administrator opens the "Add User" screen</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Then</entry>
|
||||
<entry>There is a list of LDAP users displayed but the user is not in the list</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
<para/>
|
||||
<informaltable>
|
||||
<tgroup cols="2">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Given</entry>
|
||||
<entry>An administrator wants to add a group of new users to cloudstack</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>When</entry>
|
||||
<entry>The administrator opens the "Add User" screen, selects the users and hits save</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Then</entry>
|
||||
<entry>The list of new users are saved to the database</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
<para/>
|
||||
<informaltable>
|
||||
<tgroup cols="2">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Given</entry>
|
||||
<entry>An administrator has created a new LDAP user on cloudstack</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>When</entry>
|
||||
<entry>The user authenticates against cloudstack with the right credentials</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Then</entry>
|
||||
<entry>They are authorised in cloudstack</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
<para/>
|
||||
<informaltable>
|
||||
<tgroup cols="2">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Given</entry>
|
||||
<entry>A user wants to edit an LDAP user</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>When</entry>
|
||||
<entry>They open the "Edit User" screen</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Then</entry>
|
||||
<entry>The password fields are disabled and cannot be changed</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
<para/>
|
||||
</section>
|
||||
<section id="the-design-document">
|
||||
<title>The Design Document</title>
|
||||
<para>
|
||||
<emphasis role="bold">
|
||||
LDAP user list service
|
||||
</emphasis>
|
||||
</para>
|
||||
<para>
|
||||
<emphasis role="bold">name:</emphasis> ldapUserList
|
||||
</para>
|
||||
<para>
|
||||
<emphasis role="bold">responseObject:</emphasis> LDAPUserResponse {username,email,name}
|
||||
</para>
|
||||
<para>
|
||||
<emphasis role="bold">parameter:</emphasis> listType:enum {NEW, EXISTING,ALL} (Default to ALL if no option provided)
|
||||
</para>
|
||||
<para>
|
||||
Create a new API service call for retreiving the list of users from LDAP. This will call a new
|
||||
ConfigurationService which will retrieve the list of users using the configured search base and the query
|
||||
filter. The list may be filtered in the ConfigurationService based on listType parameter
|
||||
</para>
|
||||
<para>
|
||||
<emphasis role="bold">
|
||||
LDAP Available Service
|
||||
</emphasis>
|
||||
</para>
|
||||
<para>
|
||||
<emphasis role="bold">name:</emphasis> ldapAvailable
|
||||
</para>
|
||||
<para>
|
||||
<emphasis role="bold">responseObject</emphasis> LDAPAvailableResponse {available:boolean}
|
||||
</para>
|
||||
<para>
|
||||
Create a new API service call veriying LDAP is setup correctly verifying the following configuration elements are all set:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>ldap.hostname</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>ldap.port</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>ldap.usessl</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>ldap.queryfilter</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>ldap.searchbase</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>ldap.dn</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>ldap.password</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
<emphasis role="bold">
|
||||
LDAP Save Users Service
|
||||
</emphasis>
|
||||
</para>
|
||||
<para>
|
||||
<emphasis role="bold">name:</emphasis> ldapSaveUsers
|
||||
</para>
|
||||
<para>
|
||||
<emphasis role="bold">responseObject:</emphasis> LDAPSaveUsersRssponse {list<![CDATA[<UserResponse>]]>}
|
||||
</para>
|
||||
<para>
|
||||
<emphasis role="bold">parameter:</emphasis> list of users
|
||||
</para>
|
||||
<para>
|
||||
Saves the list of objects instead. Following the functionality in CreateUserCmd it will
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Create the user via the account service</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Handle the response</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
It will be decided whether a transation should remain over whole save or only over individual users. A list of UserResponse will be returned.
|
||||
</para>
|
||||
<para>
|
||||
<emphasis role="bold">
|
||||
Extension of cloudstack UI "Add User" screen
|
||||
</emphasis>
|
||||
</para>
|
||||
<para>
|
||||
Extend account.js enable the adding of a list of users with editable fields where required. The new "add user" screen for LDAP setup will:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Make an ajax call to the ldapAvailable, ldapuserList and ldapSaveUsers services</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Validate on username, email, firstname and lastname</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
<emphasis role="bold">
|
||||
Extension of cloudstack UI "Edit User" screen
|
||||
</emphasis>
|
||||
</para>
|
||||
<para>
|
||||
Extend account.js to disable the password fields on the edit user screen if LDAP available, specifically:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Make an ajax call to the ldapAvailable, ldapuserList and ldapSaveUsers services</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Validate on username, email, firstname and lastname. Additional server validation will nsure the password has not changed</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</section>
|
||||
<section id="approach">
|
||||
<title>Approach</title>
|
||||
<para>
|
||||
To get started a development cloudstack environment will be created with DevCloud used to verify changes. Once the schedule is agreed with the mentor the deliverables will be broken into small user stories with expected delivery dates set. The development cycle will focus on BDD, enforcing all unit and acceptance tests are written first.
|
||||
</para>
|
||||
<para>
|
||||
A build pipe line for continious delivery environment around cloudstack will be implemented, the following stages will be adopted:
|
||||
</para>
|
||||
<informaltable>
|
||||
<tgroup cols="2">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Stage</entry>
|
||||
<entry>Action</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Commit</entry>
|
||||
<entry>Run unit tests</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Sonar</entry>
|
||||
<entry>Runs code quality metrics</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Acceptance</entry>
|
||||
<entry>Deploys the devcloud and runs all acceptance tests</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Deployment</entry>
|
||||
<entry>Deploy a new management server using Chef</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</section>
|
||||
<section id="about-me">
|
||||
<title>About me</title>
|
||||
<para>
|
||||
I am a Computer Science Student at Dublin City University in Ireland. I have interests in virtualization,
|
||||
automation, information systems, networking and web development
|
||||
</para>
|
||||
<para>
|
||||
I was involved with a project in a K-12(educational) environment of moving their server systems over
|
||||
to a virtualized environment on ESXi. I have good knowledge of programming in Java, PHP and
|
||||
Scripting langages. During the configuration of an automation system for OS deployment I experienced
|
||||
some exposure to scripting in powershell, batch, vbs and bash and configuration of PXE images based
|
||||
of WinPE and Debian.
|
||||
Additionally I am also a mentor in an opensource teaching movement called CoderDojo, we teach kids
|
||||
from the age of 8 everything from web page, HTML 5 game and raspberry pi development. It's really
|
||||
cool.
|
||||
</para>
|
||||
<para>
|
||||
I’m excited at the opportunity and learning experience that cloudstack are offering with this project.
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
@ -25,4 +25,207 @@
|
|||
<chapter id="gsoc-tuna">
|
||||
<title>Nguyen's 2013 GSoC Proposal</title>
|
||||
<para>This chapter describes Nguyen 2013 Google Summer of Code project within the &PRODUCT; ASF project. It is a copy paste of the submitted proposal.</para>
|
||||
<section id="add-xen-xcp-support-for-gre-sdn-controller">
|
||||
<title>Add Xen/XCP support for GRE SDN controller</title>
|
||||
<para>
|
||||
"This project aims to enhance the current native SDN controller in supporting Xen/XCP and integrate successfully the open source SDN controller (FloodLight) driving Open vSwitch through its interfaces."
|
||||
</para>
|
||||
</section>
|
||||
<section id="Abstract">
|
||||
<title>Abstract</title>
|
||||
<para>
|
||||
SDN, standing for Software-Defined Networking, is an approach to building data network equipments and softwares. It were invented by ONRC, Stanford University. SDN basically decouples the control from physical networking boxes and given to a software application called a controller. SDN has three parts: controller, protocols and switch; In which, OpenFlow is an open standard to deploy innovative protocols. Nowaday, more and more datacenters use SDN instead of traditional physical networking boxes. For example, Google announced that they completely built its own switches and SDN confrollers for use in its internal backbone network.
|
||||
</para>
|
||||
<para>
|
||||
OpenvSwitch, an open source software switch, is widely used as a virtual switch in virtualized server environments. It can currently run on any Linux-based virtualization platform, such as: KVM, Xen (XenServer, XCP, Xen hypervisor), VirtualBox... It also has been ported to a number of different operating systems and hardware platforms: Linux, FreeBSD, Windows and even non-POSIX embedded systems. In cloud computing IaaS, using OpenvSwitch instead of Linux bridge on compute nodes becomes an inevitable trend because of its powerful features and the ability of OpenFlow integration as well.
|
||||
</para>
|
||||
<para>
|
||||
In CloudStack, we already have a native SDN controller. With KVM hypervisor, developers can easily install OpenvSwitch module; whereas, Xen even has a build-in one. The combination of SDN controller and OpenvSwitch gives us many advanced things. For example, creating GRE tunnels as an isolation method instead of VLAN is a good try. In this project, we are planning to support GRE tunnels in Xen/XCP hypervisor with the native SDN controller. When it's done, substituting open-sources SDN controllers (floodlight, beacon, pox, nox) for the current one is an amazing next step.
|
||||
</para>
|
||||
</section>
|
||||
<section id="design-desription">
|
||||
<title>Design description</title>
|
||||
<para>
|
||||
CloudStack currently has a native SDN Controller that is used to build meshes of GRE tunnels between Xen hosts. There consists of 4 parts: OVS tunnel manager, OVS Dao/VO, Command/Answer and Ovs tunnel plugin. The details are as follow:
|
||||
</para>
|
||||
<para>
|
||||
<emphasis role="bold">OVS tunnel manager:</emphasis> Consist of OvsElement and OvsTunnelManager.
|
||||
</para>
|
||||
<para>
|
||||
OvsElement is used for controlling Ovs tunnel lifecycle (prepare, release)
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>prepare(network, nic, vm, dest): create tunnel for vm on network to dest</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>release(network, nic, vm): destroy tunnel for vm on network</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
OvsTunnelManager drives bridge configuration and tunnel creation via calling respective commands to Agent.
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>destroyTunnel(vm, network): call OvsDestroyTunnelCommand to destroy tunnel for vm on network</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>createTunnel(vm, network, dest): call OvsCreateTunnelCommand to create tunnel for vm on network to dest</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
<emphasis role="bold">OVS tunnel plugin:</emphasis> These are ovstunnel and ovs-vif-flows.py script, writen as XAPI plugin. The OVS tunnel manager will call them via XML-RPC.
|
||||
</para>
|
||||
<para>
|
||||
Ovstunnel plugin calls corresponding vsctl commands for setting up the OVS bridge, creating GRE tunnels or destroying them.
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>setup_ovs_bridge()</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>destroy_ovs_bridge()</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>create_tunnel()</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>destroy_tunnel()</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
Ovs-vif-flow.py clears or applies rule for VIFs every time it is plugged or unplugged from a OVS bridge.
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>clear_flow()</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>apply_flow()</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
<emphasis role="bold">OVS command/answer:</emphasis> It is designed under the format of requests and answers between Manager and Plugin. These commands will correspondence exactly the mentioned manipulations.
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>OvsSetupBridgeCommand</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>OvsSetupBridgeAnswer</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>OvsDestroyBridgeCommand</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>OvsDestroyBridgeAnswer</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>OvsCreateTunnelCommand</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>OvsCreateTunnelAnswer</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>OvsDestroyTunnelCommand</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>OvsDestroyTunnelAnswer</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>OvsFetchInterfaceCommand</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>OvsFetchInterfaceAnswer</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
<emphasis role="bold">OVS Dao/VO</emphasis>
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>OvsTunnelInterfaceDao</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>OvsTunnelInterfaceVO</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>OvsTunnelNetworkDao</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>OvsTunnelNetworkVO</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section id="integrate-floodLight-as-sdn-controller">
|
||||
<title>Integrate FloodLight as SDN controller</title>
|
||||
<para>
|
||||
I think that we maybe deploy FloodLight Server as a new SystemVM. This VM acts like current SystemVMs. One Floodlight SystemVM per Zone, so it can manage for virtual switches under this zone.
|
||||
</para>
|
||||
</section>
|
||||
<section id="Deliverables">
|
||||
<title>Deliverables</title>
|
||||
<para>
|
||||
GRE has been used as isolation method in CloudStack when deploy with Xen/XCP hosts.
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>User set sdn.ovs.controller parameter in Global Setting to true. He deploys Advance Networking and chooses GRE as isolation method</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Make use of Floodlight instead of native SDN controller.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section id="About-me">
|
||||
<title>About me</title>
|
||||
<para>
|
||||
My name is Nguyen Anh Tu, a young and enthusiastic researcher in Cloud Computing Center - Viettel Research and Development Institute, Vietnam. Since last year, we has built Cloud Platform based on CloudStack, starting with version 3.0.2. As the results, some advanced modules were successfully developed, consists of:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Encrypt Data Volume for VMs.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Dynamic Allocate Memory for VMs by changing policy on Squeeze Daemon.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>AutoScale without using NetScale.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Deploy a new SystemVM type for Intrustion Detection System.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
Given the working experience and recent researches, I have obtained remarkably the understanding of specific knowledges to carry on this project, details as follow:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Java source code on CloudStack: Design Pattern, Spring framework.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Bash, Python programming.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>XAPI plugin.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>XML-RPC.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>OpenVSwitch on Xen.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
Other knowledges:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>XAPI RRD, XenStore.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Ocaml Programming (XAPI functions).</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ COMMIT
|
|||
-A INPUT -i eth0 -p tcp -m tcp --dport 53 -j ACCEPT
|
||||
-A INPUT -i eth1 -p tcp -m state --state NEW --dport 3922 -j ACCEPT
|
||||
-A INPUT -i eth0 -p tcp -m state --state NEW --dport 80 -j ACCEPT
|
||||
-A INPUT -i eth0 -p tcp -m state --state NEW --dport 8080 -j ACCEPT
|
||||
-A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||
-A FORWARD -i eth2 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||
-A FORWARD -i eth0 -o eth0 -m state --state NEW -j ACCEPT
|
||||
|
|
|
|||
|
|
@ -485,7 +485,7 @@ public abstract class ExternalFirewallDeviceManagerImpl extends AdapterBase impl
|
|||
|
||||
if (add && (!reservedIpAddressesForGuestNetwork.contains(network.getGateway()))) {
|
||||
// Insert a new NIC for this guest network to reserve the gateway address
|
||||
_networkMgr.savePlaceholderNic(network, network.getGateway(), null);
|
||||
_networkMgr.savePlaceholderNic(network, network.getGateway(), null, null);
|
||||
}
|
||||
|
||||
// Delete any mappings used for inline external load balancers in this network
|
||||
|
|
|
|||
|
|
@ -774,7 +774,7 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase
|
|||
// If a NIC doesn't exist for the load balancing IP address, create one
|
||||
loadBalancingIpNic = _nicDao.findByIp4AddressAndNetworkId(loadBalancingIpAddress, network.getId());
|
||||
if (loadBalancingIpNic == null) {
|
||||
loadBalancingIpNic = _networkMgr.savePlaceholderNic(network, loadBalancingIpAddress, null);
|
||||
loadBalancingIpNic = _networkMgr.savePlaceholderNic(network, loadBalancingIpAddress, null, null);
|
||||
}
|
||||
|
||||
// Save a mapping between the source IP address and the load balancing IP address NIC
|
||||
|
|
@ -1019,7 +1019,7 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase
|
|||
|
||||
if (add) {
|
||||
// Insert a new NIC for this guest network to reserve the self IP
|
||||
_networkMgr.savePlaceholderNic(guestConfig, selfIp, null);
|
||||
_networkMgr.savePlaceholderNic(guestConfig, selfIp, null, null);
|
||||
} else {
|
||||
// release the self-ip obtained from guest network
|
||||
Nic selfipNic = getPlaceholderNic(guestConfig);
|
||||
|
|
|
|||
|
|
@ -381,7 +381,7 @@ public interface NetworkManager {
|
|||
|
||||
String allocatePublicIpForGuestNic(Long networkId, DataCenter dc, Pod pod, Account caller, String requestedIp) throws InsufficientAddressCapacityException;
|
||||
|
||||
NicVO savePlaceholderNic(Network network, String ip4Address, Type vmType);
|
||||
NicVO savePlaceholderNic(Network network, String ip4Address, String ip6Address, Type vmType);
|
||||
|
||||
DhcpServiceProvider getDhcpServiceProvider(Network network);
|
||||
|
||||
|
|
|
|||
|
|
@ -1481,23 +1481,6 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
|
|||
s_logger.debug("Found existing network configuration for offering " + offering + ": " + configs.get(0));
|
||||
}
|
||||
|
||||
if (errorIfAlreadySetup) {
|
||||
InvalidParameterValueException ex = new InvalidParameterValueException("Found existing network configuration (with specified id) for offering (with specified id)");
|
||||
ex.addProxyObject(offering.getUuid(), "offeringId");
|
||||
ex.addProxyObject(configs.get(0).getUuid(), "networkConfigId");
|
||||
throw ex;
|
||||
} else {
|
||||
return configs;
|
||||
}
|
||||
}
|
||||
} else if (predefined != null && predefined.getCidr() != null && predefined.getBroadcastUri() == null && vpcId == null) {
|
||||
// don't allow to have 2 networks with the same cidr in the same zone for the account
|
||||
List<NetworkVO> configs = _networksDao.listBy(owner.getId(), plan.getDataCenterId(), predefined.getCidr(), true);
|
||||
if (configs.size() > 0) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Found existing network configuration for offering " + offering + ": " + configs.get(0));
|
||||
}
|
||||
|
||||
if (errorIfAlreadySetup) {
|
||||
InvalidParameterValueException ex = new InvalidParameterValueException("Found existing network configuration (with specified id) for offering (with specified id)");
|
||||
ex.addProxyObject(offering.getUuid(), "offeringId");
|
||||
|
|
@ -4342,9 +4325,10 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
|
|||
|
||||
|
||||
@Override
|
||||
public NicVO savePlaceholderNic(Network network, String ip4Address, Type vmType) {
|
||||
public NicVO savePlaceholderNic(Network network, String ip4Address, String ip6Address, Type vmType) {
|
||||
NicVO nic = new NicVO(null, null, network.getId(), null);
|
||||
nic.setIp4Address(ip4Address);
|
||||
nic.setIp6Address(ip6Address);
|
||||
nic.setReservationStrategy(ReservationStrategy.PlaceHolder);
|
||||
nic.setState(Nic.State.Reserved);
|
||||
nic.setVmType(vmType);
|
||||
|
|
|
|||
|
|
@ -2065,17 +2065,24 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel {
|
|||
public NicVO getPlaceholderNicForRouter(Network network, Long podId) {
|
||||
List<NicVO> nics = _nicDao.listPlaceholderNicsByNetworkIdAndVmType(network.getId(), VirtualMachine.Type.DomainRouter);
|
||||
for (NicVO nic : nics) {
|
||||
if (nic.getReserver() == null && nic.getIp4Address() != null) {
|
||||
if (nic.getReserver() == null && (nic.getIp4Address() != null || nic.getIp6Address() != null)) {
|
||||
if (podId == null) {
|
||||
return nic;
|
||||
} else {
|
||||
//return nic only when its ip address belong to the pod range (for the Basic zone case)
|
||||
List<? extends Vlan> vlans = _vlanDao.listVlansForPod(podId);
|
||||
for (Vlan vlan : vlans) {
|
||||
IpAddress ip = _ipAddressDao.findByIpAndNetworkId(network.getId(), nic.getIp4Address());
|
||||
if (ip != null && ip.getVlanId() == vlan.getId()) {
|
||||
return nic;
|
||||
}
|
||||
if (nic.getIp4Address() != null) {
|
||||
IpAddress ip = _ipAddressDao.findByIpAndNetworkId(network.getId(), nic.getIp4Address());
|
||||
if (ip != null && ip.getVlanId() == vlan.getId()) {
|
||||
return nic;
|
||||
}
|
||||
} else {
|
||||
UserIpv6AddressVO ipv6 = _ipv6Dao.findByNetworkIdAndIp(network.getId(), nic.getIp6Address());
|
||||
if (ipv6 != null && ipv6.getVlanId() == vlan.getId()) {
|
||||
return nic;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3044,6 +3044,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
|
|||
_accountGuestVlanMapDao.update(guestVlanMapId, accountGuestVlanMapVO);
|
||||
} else {
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
txn.start();
|
||||
accountGuestVlanMapVO = new AccountGuestVlanMapVO(vlanOwner.getAccountId(), physicalNetworkId);
|
||||
accountGuestVlanMapVO.setGuestVlanRange(startVlan + "-" + endVlan);
|
||||
_accountGuestVlanMapDao.persist(accountGuestVlanMapVO);
|
||||
|
|
|
|||
|
|
@ -221,7 +221,6 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru {
|
|||
throws InsufficientVirtualNetworkCapcityException,
|
||||
InsufficientAddressCapacityException {
|
||||
|
||||
//FIXME - save ipv6 informaiton in the placeholder nic
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
txn.start();
|
||||
_networkMgr.allocateDirectIp(nic, dc, vm, network, requestedIp4Addr, requestedIp6Addr);
|
||||
|
|
@ -229,8 +228,8 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru {
|
|||
if (vm.getType() == VirtualMachine.Type.DomainRouter) {
|
||||
Nic placeholderNic = _networkModel.getPlaceholderNicForRouter(network, null);
|
||||
if (placeholderNic == null) {
|
||||
s_logger.debug("Saving placeholder nic with ip4 address " + nic.getIp4Address() + " and ipv6 address " + requestedIp6Addr + " for the network " + network);
|
||||
_networkMgr.savePlaceholderNic(network, nic.getIp4Address(), VirtualMachine.Type.DomainRouter);
|
||||
s_logger.debug("Saving placeholder nic with ip4 address " + nic.getIp4Address() + " and ipv6 address " + nic.getIp6Address() + " for the network " + network);
|
||||
_networkMgr.savePlaceholderNic(network, nic.getIp4Address(), nic.getIp6Address(), VirtualMachine.Type.DomainRouter);
|
||||
}
|
||||
}
|
||||
txn.commit();
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ public class DirectPodBasedNetworkGuru extends DirectNetworkGuru {
|
|||
Nic placeholderNic = _networkModel.getPlaceholderNicForRouter(network, pod.getId());
|
||||
if (placeholderNic == null) {
|
||||
s_logger.debug("Saving placeholder nic with ip4 address " + nic.getIp4Address() + " for the network " + network);
|
||||
_networkMgr.savePlaceholderNic(network, nic.getIp4Address(), VirtualMachine.Type.DomainRouter);
|
||||
_networkMgr.savePlaceholderNic(network, nic.getIp4Address(), null, VirtualMachine.Type.DomainRouter);
|
||||
}
|
||||
}
|
||||
txn.commit();
|
||||
|
|
|
|||
|
|
@ -1740,30 +1740,34 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
|
|||
s_logger.debug("Adding nic for Virtual Router in Guest network " + guestNetwork);
|
||||
String defaultNetworkStartIp = null, defaultNetworkStartIpv6 = null;
|
||||
if (!setupPublicNetwork) {
|
||||
Nic placeholder = _networkModel.getPlaceholderNicForRouter(guestNetwork, plan.getPodId());
|
||||
if (guestNetwork.getCidr() != null) {
|
||||
Nic placeholder = _networkModel.getPlaceholderNicForRouter(guestNetwork, plan.getPodId());
|
||||
if (placeholder != null) {
|
||||
s_logger.debug("Requesting ip address " + placeholder.getIp4Address() + " stored in placeholder nic for the network " + guestNetwork);
|
||||
defaultNetworkStartIp = placeholder.getIp4Address();
|
||||
} else {
|
||||
String startIp = _networkModel.getStartIpAddress(guestNetwork.getId());
|
||||
if (startIp != null && _ipAddressDao.findByIpAndSourceNetworkId(guestNetwork.getId(), startIp).getAllocatedTime() == null) {
|
||||
defaultNetworkStartIp = startIp;
|
||||
} else if (s_logger.isDebugEnabled()){
|
||||
s_logger.debug("First ip " + startIp + " in network id=" + guestNetwork.getId() +
|
||||
" is already allocated, can't use it for domain router; will get random ip address from the range");
|
||||
}
|
||||
}
|
||||
if (placeholder != null && placeholder.getIp4Address() != null) {
|
||||
s_logger.debug("Requesting ipv4 address " + placeholder.getIp4Address() + " stored in placeholder nic for the network " + guestNetwork);
|
||||
defaultNetworkStartIp = placeholder.getIp4Address();
|
||||
} else {
|
||||
String startIp = _networkModel.getStartIpAddress(guestNetwork.getId());
|
||||
if (startIp != null && _ipAddressDao.findByIpAndSourceNetworkId(guestNetwork.getId(), startIp).getAllocatedTime() == null) {
|
||||
defaultNetworkStartIp = startIp;
|
||||
} else if (s_logger.isDebugEnabled()){
|
||||
s_logger.debug("First ipv4 " + startIp + " in network id=" + guestNetwork.getId() +
|
||||
" is already allocated, can't use it for domain router; will get random ip address from the range");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//FIXME - get ipv6 stored in the placeholder
|
||||
|
||||
if (guestNetwork.getIp6Cidr() != null) {
|
||||
String startIpv6 = _networkModel.getStartIpv6Address(guestNetwork.getId());
|
||||
if (startIpv6 != null && _ipv6Dao.findByNetworkIdAndIp(guestNetwork.getId(), startIpv6) == null) {
|
||||
defaultNetworkStartIpv6 = startIpv6;
|
||||
} else if (s_logger.isDebugEnabled()){
|
||||
s_logger.debug("First ipv6 " + startIpv6 + " in network id=" + guestNetwork.getId() +
|
||||
" is already allocated, can't use it for domain router; will get random ipv6 address from the range");
|
||||
if (placeholder != null && placeholder.getIp6Address() != null) {
|
||||
s_logger.debug("Requesting ipv6 address " + placeholder.getIp6Address() + " stored in placeholder nic for the network " + guestNetwork);
|
||||
defaultNetworkStartIpv6 = placeholder.getIp6Address();
|
||||
} else {
|
||||
String startIpv6 = _networkModel.getStartIpv6Address(guestNetwork.getId());
|
||||
if (startIpv6 != null && _ipv6Dao.findByNetworkIdAndIp(guestNetwork.getId(), startIpv6) == null) {
|
||||
defaultNetworkStartIpv6 = startIpv6;
|
||||
} else if (s_logger.isDebugEnabled()){
|
||||
s_logger.debug("First ipv6 " + startIpv6 + " in network id=" + guestNetwork.getId() +
|
||||
" is already allocated, can't use it for domain router; will get random ipv6 address from the range");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -949,9 +949,9 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian
|
|||
if (router.getVpcId() != null) {
|
||||
if (_networkModel.isProviderSupportServiceInNetwork(guestNetworkId, Service.NetworkACL, Provider.VPCVirtualRouter)) {
|
||||
List<NetworkACLItemVO> networkACLs = _networkACLMgr.listNetworkACLItems(guestNetworkId);
|
||||
s_logger.debug("Found " + networkACLs.size() + " network ACLs to apply as a part of VPC VR " + router
|
||||
+ " start for guest network id=" + guestNetworkId);
|
||||
if (!networkACLs.isEmpty()) {
|
||||
if ((networkACLs != null) && !networkACLs.isEmpty()) {
|
||||
s_logger.debug("Found " + networkACLs.size() + " network ACLs to apply as a part of VPC VR " + router
|
||||
+ " start for guest network id=" + guestNetworkId);
|
||||
createNetworkACLsCommands(networkACLs, router, cmds, guestNetworkId, false);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -294,6 +294,9 @@ public class NetworkACLManagerImpl extends ManagerBase implements NetworkACLMana
|
|||
@Override
|
||||
public List<NetworkACLItemVO> listNetworkACLItems(long guestNtwkId) {
|
||||
Network network = _networkMgr.getNetwork(guestNtwkId);
|
||||
if(network.getNetworkACLId() == null){
|
||||
return null;
|
||||
}
|
||||
return _networkACLItemDao.listByACL(network.getNetworkACLId());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -303,28 +303,30 @@ public class NetworkACLServiceImpl extends ManagerBase implements NetworkACLServ
|
|||
}
|
||||
|
||||
//Validate Protocol
|
||||
//Check if protocol is a number
|
||||
if(StringUtils.isNumeric(protocol)){
|
||||
int protoNumber = Integer.parseInt(protocol);
|
||||
if(protoNumber < 0 || protoNumber > 255){
|
||||
throw new InvalidParameterValueException("Invalid protocol number: " + protoNumber);
|
||||
if(protocol != null){
|
||||
//Check if protocol is a number
|
||||
if(StringUtils.isNumeric(protocol)){
|
||||
int protoNumber = Integer.parseInt(protocol);
|
||||
if(protoNumber < 0 || protoNumber > 255){
|
||||
throw new InvalidParameterValueException("Invalid protocol number: " + protoNumber);
|
||||
}
|
||||
} else {
|
||||
//Protocol is not number
|
||||
//Check for valid protocol strings
|
||||
String supportedProtocols = "tcp,udp,icmp,all";
|
||||
if(!supportedProtocols.contains(protocol.toLowerCase())){
|
||||
throw new InvalidParameterValueException("Invalid protocol: " + protocol);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//Protocol is not number
|
||||
//Check for valid protocol strings
|
||||
String supportedProtocols = "tcp,udp,icmp,all";
|
||||
if(!supportedProtocols.contains(protocol.toLowerCase())){
|
||||
throw new InvalidParameterValueException("Invalid protocol: " + protocol);
|
||||
|
||||
// icmp code and icmp type can't be passed in for any other protocol rather than icmp
|
||||
if (!protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (icmpCode != null || icmpType != null)) {
|
||||
throw new InvalidParameterValueException("Can specify icmpCode and icmpType for ICMP protocol only");
|
||||
}
|
||||
}
|
||||
|
||||
// icmp code and icmp type can't be passed in for any other protocol rather than icmp
|
||||
if (!protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (icmpCode != null || icmpType != null)) {
|
||||
throw new InvalidParameterValueException("Can specify icmpCode and icmpType for ICMP protocol only");
|
||||
}
|
||||
|
||||
if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (portStart != null || portEnd != null)) {
|
||||
throw new InvalidParameterValueException("Can't specify start/end port when protocol is ICMP");
|
||||
if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (portStart != null || portEnd != null)) {
|
||||
throw new InvalidParameterValueException("Can't specify start/end port when protocol is ICMP");
|
||||
}
|
||||
}
|
||||
|
||||
//validate icmp code and type
|
||||
|
|
|
|||
|
|
@ -66,15 +66,8 @@ import com.cloud.user.Account;
|
|||
import com.cloud.user.User;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.ManagerBase;
|
||||
import com.cloud.vm.Nic;
|
||||
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.*;
|
||||
import com.cloud.vm.VirtualMachine.Type;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd;
|
||||
import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd;
|
||||
|
|
@ -924,7 +917,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage
|
|||
|
||||
|
||||
@Override
|
||||
public NicVO savePlaceholderNic(Network network, String ip4Address, Type vmType) {
|
||||
public NicVO savePlaceholderNic(Network network, String ip4Address, String ip6Address, Type vmType) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1393,7 +1393,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage
|
|||
|
||||
|
||||
@Override
|
||||
public NicVO savePlaceholderNic(Network network, String ip4Address, Type vmType) {
|
||||
public NicVO savePlaceholderNic(Network network, String ip4Address, String ip6Address, Type vmType) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -591,6 +591,8 @@ class TestVolumes(cloudstackTestCase):
|
|||
|
||||
if hosts[0].hypervisor == "XenServer":
|
||||
self.virtual_machine.stop(self.apiClient)
|
||||
elif hosts[0].hypervisor.lower() == "vmware":
|
||||
self.skipTest("Resize Volume is unsupported on VmWare")
|
||||
|
||||
self.apiClient.resizeVolume(cmd)
|
||||
count = 0
|
||||
|
|
@ -638,6 +640,9 @@ class TestVolumes(cloudstackTestCase):
|
|||
|
||||
if hosts[0].hypervisor == "XenServer":
|
||||
self.virtual_machine.stop(self.apiClient)
|
||||
elif hosts[0].hypervisor.lower() == "vmware":
|
||||
self.skipTest("Resize Volume is unsupported on VmWare")
|
||||
|
||||
self.debug("Resize Volume ID: %s" % self.volume.id)
|
||||
|
||||
cmd = resizeVolume.resizeVolumeCmd()
|
||||
|
|
|
|||
|
|
@ -5388,9 +5388,9 @@
|
|||
label: 'label.name',
|
||||
validation: { required: true }
|
||||
},
|
||||
url: {
|
||||
label: 'label.url',
|
||||
validation: { required: false }
|
||||
vcenter: {
|
||||
label: 'vcenter',
|
||||
validation: { required: true }
|
||||
},
|
||||
username: {
|
||||
label: 'label.username',
|
||||
|
|
@ -5406,14 +5406,10 @@
|
|||
action: function(args) {
|
||||
var data = {
|
||||
zoneid: args.context.physicalResources[0].id,
|
||||
name: args.data.name
|
||||
};
|
||||
name: args.data.name,
|
||||
vcenter: args.data.vcenter
|
||||
};
|
||||
|
||||
if(args.data.url != null && args.data.url.length > 0) {
|
||||
$.extend(data, {
|
||||
url: args.data.url
|
||||
})
|
||||
}
|
||||
if(args.data.username != null && args.data.username.length > 0) {
|
||||
$.extend(data, {
|
||||
username: args.data.username
|
||||
|
|
|
|||
|
|
@ -359,6 +359,8 @@
|
|||
fields: {
|
||||
name: { label: 'label.name' },
|
||||
sourceipaddress: { label: 'Source IP Address' },
|
||||
sourceport: { label: 'Source Port' },
|
||||
instanceport: { label: 'Instance Port' },
|
||||
algorithm: { label: 'label.algorithm' }
|
||||
},
|
||||
dataProvider: function(args) {
|
||||
|
|
@ -369,8 +371,15 @@
|
|||
},
|
||||
success: function(json) {
|
||||
var items = json.listloadbalancerssresponse.loadbalancer;
|
||||
args.response.success({ data: items });
|
||||
|
||||
if(items != null) {
|
||||
for(var i = 0; i < items.length; i++) {
|
||||
var item = items[i];
|
||||
//there is only one element in loadbalancerrul array property.
|
||||
item.sourceport = item.loadbalancerrule[0].sourceport;
|
||||
item.instanceport = item.loadbalancerrule[0].instanceport;
|
||||
}
|
||||
}
|
||||
args.response.success({ data: items });
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
@ -642,7 +651,21 @@
|
|||
listView: $.extend(true, {}, cloudStack.sections.instances.listView, {
|
||||
type: 'checkbox',
|
||||
filters: false,
|
||||
dataProvider: function(args) {
|
||||
dataProvider: function(args) {
|
||||
var assignedInstances;
|
||||
$.ajax({
|
||||
url: createURL('listLoadBalancers'),
|
||||
data: {
|
||||
id: args.context.internalLoadBalancers[0].id
|
||||
},
|
||||
async: false,
|
||||
success: function(json) {
|
||||
assignedInstances = json.listloadbalancerssresponse.loadbalancer[0].loadbalancerinstance;
|
||||
if(assignedInstances == null)
|
||||
assignedInstances = [];
|
||||
}
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
url: createURL('listVirtualMachines'),
|
||||
data: {
|
||||
|
|
@ -654,11 +677,9 @@
|
|||
|
||||
// Pre-select existing instances in LB rule
|
||||
$(instances).map(function(index, instance) {
|
||||
instance._isSelected = $.grep(
|
||||
args.context.internalLoadBalancers[0].loadbalancerinstance,
|
||||
|
||||
function(lbInstance) {
|
||||
return lbInstance.id == instance.id;
|
||||
instance._isSelected = $.grep(assignedInstances,
|
||||
function(assignedInstance) {
|
||||
return assignedInstance.id == instance.id;
|
||||
}
|
||||
).length ? true : false;
|
||||
});
|
||||
|
|
@ -667,7 +688,7 @@
|
|||
var items = [];
|
||||
if(instances != null) {
|
||||
for(var i = 0; i < instances.length; i++) {
|
||||
if(instances[i]._isSelected = true)
|
||||
if(instances[i]._isSelected == true)
|
||||
continue;
|
||||
else
|
||||
items.push(instances[i]);
|
||||
|
|
@ -701,11 +722,7 @@
|
|||
var jid = data.assigntoloadbalancerruleresponse.jobid;
|
||||
args.response.success({
|
||||
_custom: {
|
||||
jobId: jid,
|
||||
getUpdatedItem: function(json) {
|
||||
$('.list-view').listView('refresh');
|
||||
//return json.queryasyncjobresultresponse.jobresult.volume;
|
||||
}
|
||||
jobId: jid
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3366,10 +3366,11 @@
|
|||
zoneId: args.data.returnedZone.id,
|
||||
username: args.data.cluster.vCenterUsername,
|
||||
password: args.data.cluster.vCenterPassword,
|
||||
name: args.data.cluster.vCenterDatacenter
|
||||
name: args.data.cluster.vCenterDatacenter,
|
||||
vcenter: args.data.cluster.vCenterHost
|
||||
};
|
||||
$.ajax({
|
||||
url: createURL('addVmwareDc&url=' + todb(url)),
|
||||
url: createURL('addVmwareDc'),
|
||||
data: vmwareData,
|
||||
success: function(json) {
|
||||
var item = json.addvmwaredcresponse.vmwaredc;
|
||||
|
|
|
|||
Loading…
Reference in New Issue