text: # 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.
  
  """
      P1 tests for Load balancing rules for secondary IP feature, this is an
      enhancement to the Multiple IPs per NIC feature
  
      Test Plan: https://cwiki.apache.org/confluence/display/CLOUDSTACK/
      TestPlan+%3AConfiguring+load+balancing+rules+for+VM+nic+secondary+ips
  
      Issue Link: https://issues.apache.org/jira/browse/CLOUDSTACK-4840
  
      Feature Specifications: https://cwiki.apache.org/confluence/display/
      CLOUDSTACK/Configuring+load+balancing+rules+for+VM+nic+secondary+ips
  """
  
  # Import Local Modules
  from nose.plugins.attrib import attr
  from marvin.cloudstackTestCase import cloudstackTestCase
  import unittest
  from marvin.lib.base import (
      Account,
      ServiceOffering,
      VirtualMachine,
      LoadBalancerRule,
      NIC,
      PublicIPAddress,
      Router,
      NetworkOffering,
      Network,
      FireWallRule,
      NATRule
  )
  from marvin.lib.common import (get_domain,
                                 get_zone,
                                 get_template,
                                 verifyNetworkState,
                                 wait_for_cleanup,
                                 add_netscaler
                                 )
  
  from marvin.lib.utils import (validateList,
                                random_gen,
                                cleanup_resources)
  from marvin.cloudstackAPI import (restartNetwork)
  from marvin.sshClient import SshClient
  from marvin.codes import PASS
  
  
  def IsIpAssignedToLoadBalancerRule(self, lbrule, iplist):
      """List Load Balancer Rule Instances and verify that
      IP is present in the list"""
  
      exceptionMessage = ""
      isIpAssignedToLbRule = True
      try:
          lbruleinstances = LoadBalancerRule.listLoadBalancerRuleInstances(
              self.apiclient,
              id=lbrule.id,
              lbvmips=True
          )
  
          self.assertEqual(validateList(lbruleinstances)[0], PASS,
                           "lbruleinstances list validation failed")
  
          lbruleips = [str(ipaddress) for lbruleinstance in lbruleinstances
                       for ipaddress in lbruleinstance.lbvmipaddresses]
  
          for ip in iplist:
              self.assertTrue(ip in lbruleips,
                              "IP address in lbruleinstances list not matching\
                            with ips assigned to lb rule")
      except Exception as e:
          isIpAssignedToLbRule = False
          exceptionMessage = e
      return [isIpAssignedToLbRule, exceptionMessage]
  
  
  class TestAssignLBRule(cloudstackTestCase):
  
      @classmethod
      def setUpClass(cls):
          cloudstackTestClient = super(TestAssignLBRule,
                                       cls).getClsTestClient()
          cls.api_client = cloudstackTestClient.getApiClient()
  
          cls.testdata = cloudstackTestClient.getParsedTestDataConfig()
          # Get Zone, Domain and templates
          cls.domain = get_domain(cls.api_client)
          cls.zone = get_zone(
              cls.api_client,
              cloudstackTestClient.getZoneForTests())
  
          template = get_template(cls.api_client,
                                  cls.zone.id,
                                  cls.testdata["ostype"])
          # Set Zones and disk offerings
          cls.testdata["virtual_machine"]["zoneid"] = cls.zone.id
          cls.testdata["virtual_machine"]["template"] = template.id
          cls._cleanup = []
          try:
              cls.hypervisor = cloudstackTestClient.getHypervisorInfo()
              # As Hyperv is GUI based VM, it requires more resources to be
              # able to SSH properly to it
              if cls.hypervisor.lower() == 'hyperv':
                  cls.testdata["service_offering"]["name"] = "Medium Instance"
                  cls.testdata["service_offering"]["memory"] = "1024"
                  cls.testdata["service_offering"]["cpuspeed"] = "1024"
  
              cls.service_offering = ServiceOffering.create(
                  cls.api_client,
                  cls.testdata["service_offering"])
              cls._cleanup.append(cls.service_offering)
          except Exception as e:
              cls.tearDownClass()
              raise unittest.SkipTest(e)
          return
  
      def setUp(self):
          self.apiclient = self.testClient.getApiClient()
          self.cleanup = []
          try:
              self.account = Account.create(self.apiclient,
                                            self.testdata["account"],
                                            domainid=self.domain.id)
              self.cleanup.append(self.account)
              self.virtual_machine = VirtualMachine.create(
                  self.api_client,
                  self.testdata["virtual_machine"],
                  accountid=self.account.name,
                  domainid=self.account.domainid,
                  serviceofferingid=self.service_offering.id,
                  mode=self.zone.networktype)
          except Exception as e:
              self.tearDown()
              raise e
  
      def tearDown(self):
          try:
              # Clean up, terminate the created accounts, domains etc
              cleanup_resources(self.apiclient, self.cleanup)
          except Exception as e:
              raise Exception("Warning: Exception during cleanup : %s" % e)
          return
  
      @classmethod
      def tearDownClass(cls):
          try:
              # Cleanup resources used
              cleanup_resources(cls.api_client, cls._cleanup)
          except Exception as e:
              raise Exception("Warning: Exception during cleanup : %s" % e)
          return
  
      @attr(tags=["advanced", "selfservice"], required_hardware="false")
      def test_01_lb_rule_for_primary_ip(self):
          """Create LB rule for primary IP
  
          steps:
          # 1. Add secondary IP to the VM
          # 2. Associate a public IP for the network
          # 3. Create load balancer rule for this IP
          # 4. Assign load balancer rule for primary ip address of VM
          # 5. List and verify that load balancer rule is successfully added
          """
  
          NIC.addIp(self.apiclient, id=self.virtual_machine.nic[0].id)
  
          public_ip = PublicIPAddress.create(
              self.apiclient,
              accountid=self.account.name,
              zoneid=self.zone.id,
              domainid=self.account.domainid,
              networkid=self.virtual_machine.nic[0].networkid)
  
          lb_rule = LoadBalancerRule.create(
              self.apiclient,
              self.testdata["lbrule"],
              ipaddressid=public_ip.ipaddress.id,
              accountid=self.account.name,
              networkid=self.virtual_machine.nic[0].networkid,
              domainid=self.account.domainid)
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.virtual_machine.nic[0].ipaddress)}]
  
          lb_rule.assign(
              self.apiclient,
              vmidipmap=vmidipmap
          )
  
          response = IsIpAssignedToLoadBalancerRule(
              self, lb_rule, [
                  self.virtual_machine.nic[0].ipaddress])
          self.assertTrue(response[0], response[1])
  
          lbrules = LoadBalancerRule.list(
              self.apiclient,
              virtualmachineid=self.virtual_machine.id,
              listall=True)
  
          self.assertEqual(validateList(lbrules)[0], PASS,
                           "lb rules list validation failed")
  
          self.assertEqual(lb_rule.id, lbrules[0].id, "LB rules does not match")
          return
  
      @attr(tags=["advanced", "selfservice"], required_hardware="false")
      def test_02_lb_rule_for_primary_ip(self):
          """Create LB rule for secondary IP
  
          steps:
          # 1. Add secondary IP to the VM
          # 2. Associate a public IP for the network
          # 3. Create load balancer rule for this IP
          # 4. Assign load balancer rule for secondary ip address of VM
          # 5. List and verify that load balancer rule is successfully added"""
  
          secondaryip = NIC.addIp(
              self.apiclient,
              id=self.virtual_machine.nic[0].id)
  
          public_ip = PublicIPAddress.create(
              self.apiclient,
              accountid=self.account.name,
              zoneid=self.zone.id,
              domainid=self.account.domainid,
              networkid=self.virtual_machine.nic[0].networkid)
  
          lb_rule = LoadBalancerRule.create(
              self.apiclient,
              self.testdata["lbrule"],
              ipaddressid=public_ip.ipaddress.id,
              accountid=self.account.name,
              networkid=self.virtual_machine.nic[0].networkid,
              domainid=self.account.domainid)
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(secondaryip.ipaddress)}]
  
          lb_rule.assign(
              self.apiclient,
              vmidipmap=vmidipmap
          )
  
          response = IsIpAssignedToLoadBalancerRule(self, lb_rule,
                                                    [secondaryip.ipaddress])
          self.assertTrue(response[0], response[1])
  
          lbrules = LoadBalancerRule.list(
              self.apiclient,
              virtualmachineid=self.virtual_machine.id,
              listall=True)
  
          self.assertEqual(validateList(lbrules)[0], PASS,
                           "lb rules list validation failed")
  
          self.assertEqual(lb_rule.id, lbrules[0].id, "LB rules does not match")
          return
  
      @attr(tags=["advanced", "selfservice"], required_hardware="false")
      def test_03_lb_rule_for_primary_and_secondary_ip(self):
          """Create LB rule for primary and secondary IP
  
          steps:
          # 1. Add secondary IP to the VM
          # 2. Associate a public IP for the network
          # 3. Create load balancer rule for this IP
          # 4. Assign load balancer rule to both primary
          #    and secondary ip address of VM
          # 5. List and verify that load balancer rule is successfully added"""
  
          secondaryip = NIC.addIp(
              self.apiclient,
              id=self.virtual_machine.nic[0].id)
  
          public_ip = PublicIPAddress.create(
              self.apiclient,
              accountid=self.account.name,
              zoneid=self.zone.id,
              domainid=self.account.domainid,
              networkid=self.virtual_machine.nic[0].networkid)
  
          lb_rule = LoadBalancerRule.create(
              self.apiclient,
              self.testdata["lbrule"],
              ipaddressid=public_ip.ipaddress.id,
              accountid=self.account.name,
              networkid=self.virtual_machine.nic[0].networkid,
              domainid=self.account.domainid)
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.virtual_machine.nic[0].ipaddress)},
                       {"vmid": str(self.virtual_machine.id),
                        "vmip": str(secondaryip.ipaddress)}]
  
          lb_rule.assign(
              self.apiclient,
              vmidipmap=vmidipmap
          )
  
          response = IsIpAssignedToLoadBalancerRule(
              self, lb_rule, [
                  self.virtual_machine.nic[0].ipaddress, secondaryip.ipaddress])
          self.assertTrue(response[0], response[1])
  
          lbrules = LoadBalancerRule.list(
              self.apiclient,
              virtualmachineid=self.virtual_machine.id,
              listall=True)
  
          self.assertEqual(validateList(lbrules)[0], PASS,
                           "lb rules list validation failed")
  
          self.assertEqual(lb_rule.id, lbrules[0].id, "LB rules does not match")
          return
  
      @attr(tags=["advanced", "selfservice"], required_hardware="false")
      def test_04_lb_rule_primary_secondary_multiple_vms(self):
          """Create LB rule for primary and secondary IPs of multiple VMs
  
          steps:
          # 1. Deploy two VMs in same network and add secondary IP for both
          # 2. Associate a public IP for the network
          # 3. Create load balancer rule for this IP
          # 4. Assign load balancer rule to both primary and
          #    secondary ip address of both VMs
          # 5. List and verify that load balancer rule is successfully added"""
  
          secondaryip_vm1 = NIC.addIp(self.apiclient,
                                      id=self.virtual_machine.nic[0].id
                                      )
  
          self.virtual_machine2 = VirtualMachine.create(
              self.api_client,
              self.testdata["virtual_machine"],
              accountid=self.account.name,
              domainid=self.account.domainid,
              serviceofferingid=self.service_offering.id,
              mode=self.zone.networktype,
              networkids=[self.virtual_machine.nic[0].networkid, ])
  
          secondaryip_vm2 = NIC.addIp(self.apiclient,
                                      id=self.virtual_machine2.nic[0].id
                                      )
  
          public_ip = PublicIPAddress.create(
              self.apiclient,
              accountid=self.account.name,
              zoneid=self.zone.id,
              domainid=self.account.domainid,
              networkid=self.virtual_machine.nic[0].networkid)
  
          lb_rule = LoadBalancerRule.create(
              self.apiclient,
              self.testdata["lbrule"],
              ipaddressid=public_ip.ipaddress.id,
              accountid=self.account.name,
              networkid=self.virtual_machine.nic[0].networkid,
              domainid=self.account.domainid)
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.virtual_machine.nic[0].ipaddress)},
                       {"vmid": str(self.virtual_machine.id),
                        "vmip": str(secondaryip_vm1.ipaddress)},
                       {"vmid": str(self.virtual_machine2.id),
                        "vmip": str(self.virtual_machine2.nic[0].ipaddress)},
                       {"vmid": str(self.virtual_machine2.id),
                        "vmip": str(secondaryip_vm2.ipaddress)}]
  
          lb_rule.assign(
              self.apiclient,
              vmidipmap=vmidipmap
          )
  
          iplist = [self.virtual_machine.nic[0].ipaddress,
                    secondaryip_vm1.ipaddress,
                    self.virtual_machine2.nic[0].ipaddress,
                    secondaryip_vm2.ipaddress]
  
          response = IsIpAssignedToLoadBalancerRule(self, lb_rule, iplist)
          self.assertTrue(response[0], response[1])
  
          lbrules = LoadBalancerRule.list(
              self.apiclient,
              virtualmachineid=self.virtual_machine.id,
              listall=True)
  
          self.assertEqual(validateList(lbrules)[0], PASS,
                           "lb rules list validation failed")
  
          self.assertEqual(lb_rule.id, lbrules[0].id, "LB rules does not match")
  
          lbrules = LoadBalancerRule.list(
              self.apiclient,
              virtualmachineid=self.virtual_machine2.id,
              listall=True)
  
          self.assertEqual(validateList(lbrules)[0], PASS,
                           "lb rules list validation failed")
  
          self.assertEqual(lb_rule.id, lbrules[0].id, "LB rules does not match")
          return
  
  
  class TestFailureScenarios(cloudstackTestCase):
  
      @classmethod
      def setUpClass(cls):
          cloudstackTestClient = super(TestFailureScenarios,
                                       cls).getClsTestClient()
          cls.api_client = cloudstackTestClient.getApiClient()
          cls.testdata = cloudstackTestClient.getParsedTestDataConfig()
          # Get Zone, Domain and templates
          cls.domain = get_domain(cls.api_client)
          cls.zone = get_zone(
              cls.api_client,
              cloudstackTestClient.getZoneForTests())
  
          template = get_template(cls.api_client,
                                  cls.zone.id,
                                  cls.testdata["ostype"])
          # Set Zones and disk offerings
          cls.testdata["virtual_machine"]["zoneid"] = cls.zone.id
          cls.testdata["virtual_machine"]["template"] = template.id
          cls._cleanup = []
  
          try:
              cls.hypervisor = cloudstackTestClient.getHypervisorInfo()
              # As Hyperv is GUI based VM, it requires more resources to be
              # able to SSH properly to it
              if cls.hypervisor.lower() == 'hyperv':
                  cls.testdata["service_offering"]["name"] = "Medium Instance"
                  cls.testdata["service_offering"]["memory"] = "1024"
                  cls.testdata["service_offering"]["cpuspeed"] = "1024"
  
              cls.service_offering = ServiceOffering.create(
                  cls.api_client,
                  cls.testdata["service_offering"])
              cls._cleanup.append(cls.service_offering)
          except Exception as e:
              cls.tearDownClass()
              raise unittest.SkipTest(e)
          return
  
      def setUp(self):
          self.apiclient = self.testClient.getApiClient()
          self.cleanup = []
  
          try:
              self.account = Account.create(self.apiclient,
                                            self.testdata["account"],
                                            domainid=self.domain.id)
              self.cleanup.append(self.account)
              self.virtual_machine = VirtualMachine.create(
                  self.api_client,
                  self.testdata["virtual_machine"],
                  accountid=self.account.name,
                  domainid=self.account.domainid,
                  serviceofferingid=self.service_offering.id,
                  mode=self.zone.networktype)
          except Exception as e:
              self.tearDown()
              raise e
  
      def tearDown(self):
          try:
              cleanup_resources(self.apiclient, self.cleanup)
          except Exception as e:
              raise Exception("Warning: Exception during cleanup : %s" % e)
          return
  
      @classmethod
      def tearDownClass(cls):
          try:
              # Cleanup resources used
              cleanup_resources(cls.api_client, cls._cleanup)
          except Exception as e:
              raise Exception("Warning: Exception during cleanup : %s" % e)
          return
  
      @attr(tags=["advanced", "selfservice"], required_hardware="false")
      def test_05_lb_rule_wrong_vm_id(self):
          """Try to assign LB rule to secondary IP by giving wrong vm id
  
          steps:
          # 1. Add secondary IP for VM
          # 2. Associate a public IP for the network
          # 3. Create load balancer rule for this IP
          # 4. Try to assign load balancer rule for
          #    secondary IP of VM by specifying invalid vm id, it should fail"""
  
          secondaryip = NIC.addIp(
              self.apiclient,
              id=self.virtual_machine.nic[0].id)
  
          public_ip = PublicIPAddress.create(
              self.apiclient,
              accountid=self.account.name,
              zoneid=self.zone.id,
              domainid=self.account.domainid,
              networkid=self.virtual_machine.nic[0].networkid)
  
          lb_rule = LoadBalancerRule.create(
              self.apiclient,
              self.testdata["lbrule"],
              ipaddressid=public_ip.ipaddress.id,
              accountid=self.account.name,
              networkid=self.virtual_machine.nic[0].networkid,
              domainid=self.account.domainid)
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id) + random_gen(),
                        "vmip": str(secondaryip.ipaddress)}]
  
          with self.assertRaises(Exception):
              lb_rule.assign(self.apiclient,
                             vmidipmap=vmidipmap)
          return
  
      @attr(tags=["advanced", "selfservice"], required_hardware="false")
      def test_06_lb_rule_wrong_vm_ip(self):
          """Try to assign LB rule to secondary IP by giving wrong ip
  
          steps:
          # 1. Add secondary IP for VM
          # 2. Associate a public IP for the network
          # 3. Create load balancer rule for this IP
          # 4. Try to assign load balancer rule by specifying
          #    wrong ip and correct vm id, the task should fail"""
  
          secondaryip = NIC.addIp(
              self.apiclient,
              id=self.virtual_machine.nic[0].id)
  
          public_ip = PublicIPAddress.create(
              self.apiclient,
              accountid=self.account.name,
              zoneid=self.zone.id,
              domainid=self.account.domainid,
              networkid=self.virtual_machine.nic[0].networkid)
  
          lb_rule = LoadBalancerRule.create(
              self.apiclient,
              self.testdata["lbrule"],
              ipaddressid=public_ip.ipaddress.id,
              accountid=self.account.name,
              networkid=self.virtual_machine.nic[0].networkid,
              domainid=self.account.domainid)
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(secondaryip.ipaddress) + random_gen()}]
  
          with self.assertRaises(Exception):
              lb_rule.assign(self.apiclient,
                             vmidipmap=vmidipmap)
          return
  
      @unittest.skip("Failing-WIP")
      @attr(tags=["advanced", "selfservice"], required_hardware="false")
      def test_07_lb_rule_used_ip(self):
          """Try to assign secondary IP to lb rule which is already assigned to another
             LB rule
  
          steps:
          # 1. Add secondary IP for VM
          # 2. Associate two public IPs for the network
          # 3. Create load balancer rule for both the IPs
          # 4. Assign load balancer rule 1 to secondary IP
          # 5. Try to assign load balancer rule 2 to secondary IP, the operation
               should fail"""
  
          secondaryip = NIC.addIp(
              self.apiclient,
              id=self.virtual_machine.nic[0].id)
  
          public_ip1 = PublicIPAddress.create(
              self.apiclient,
              accountid=self.account.name,
              zoneid=self.zone.id,
              domainid=self.account.domainid,
              networkid=self.virtual_machine.nic[0].networkid)
  
          lb_rule1 = LoadBalancerRule.create(
              self.apiclient,
              self.testdata["lbrule"],
              ipaddressid=public_ip1.ipaddress.id,
              accountid=self.account.name,
              networkid=self.virtual_machine.nic[0].networkid,
              domainid=self.account.domainid)
  
          public_ip2 = PublicIPAddress.create(
              self.apiclient,
              accountid=self.account.name,
              zoneid=self.zone.id,
              domainid=self.account.domainid,
              networkid=self.virtual_machine.nic[0].networkid)
  
          lb_rule2 = LoadBalancerRule.create(
              self.apiclient,
              self.testdata["lbrule"],
              ipaddressid=public_ip2.ipaddress.id,
              accountid=self.account.name,
              networkid=self.virtual_machine.nic[0].networkid,
              domainid=self.account.domainid)
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(secondaryip.ipaddress)}]
  
          lb_rule1.assign(self.apiclient,
                          vmidipmap=vmidipmap)
  
          iplist = [secondaryip.ipaddress]
  
          response = IsIpAssignedToLoadBalancerRule(self, lb_rule1, iplist)
          self.assertTrue(response[0], response[1])
  
          with self.assertRaises(Exception):
              lb_rule2.assign(self.apiclient,
                              vmidipmap=vmidipmap)
          return
  
      @attr(tags=["advanced", "selfservice"], required_hardware="false")
      def test_08_lb_rule_remove_used_ip(self):
          """Try to remove secondary IP with load balancer rule configured for it
  
          steps:
          # 1. Add secondary IP for VM
          # 2. Associate public IP for the network
          # 3. Create load balancer rule for IP
          # 4. Assign load balancer rule to secondary IP
          # 5. Try to remove the secondary IP form NIC,
               the operation should fail"""
  
          secondaryip = NIC.addIp(
              self.apiclient,
              id=self.virtual_machine.nic[0].id)
  
          public_ip1 = PublicIPAddress.create(
              self.apiclient,
              accountid=self.account.name,
              zoneid=self.zone.id,
              domainid=self.account.domainid,
              networkid=self.virtual_machine.nic[0].networkid)
  
          lb_rule1 = LoadBalancerRule.create(
              self.apiclient,
              self.testdata["lbrule"],
              ipaddressid=public_ip1.ipaddress.id,
              accountid=self.account.name,
              networkid=self.virtual_machine.nic[0].networkid,
              domainid=self.account.domainid)
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(secondaryip.ipaddress)}]
  
          lb_rule1.assign(self.apiclient,
                          vmidipmap=vmidipmap)
  
          iplist = [secondaryip.ipaddress]
  
          response = IsIpAssignedToLoadBalancerRule(self, lb_rule1, iplist)
          self.assertTrue(response[0], response[1])
  
          with self.assertRaises(Exception):
              NIC.removeIp(self.apiclient, ipaddressid=secondaryip.id)
          return
  
  
  class TestListLBRuleInstances(cloudstackTestCase):
  
      @classmethod
      def setUpClass(cls):
          cloudstackTestClient = super(TestListLBRuleInstances,
                                       cls).getClsTestClient()
          cls.api_client = cloudstackTestClient.getApiClient()
          cls.testdata = cloudstackTestClient.getParsedTestDataConfig()
          # Get Zone, Domain and templates
          cls.domain = get_domain(cls.api_client)
          cls.zone = get_zone(
              cls.api_client,
              cloudstackTestClient.getZoneForTests())
  
          template = get_template(cls.api_client,
                                  cls.zone.id,
                                  cls.testdata["ostype"])
          # Set Zones and disk offerings
          cls.testdata["virtual_machine"]["zoneid"] = cls.zone.id
          cls.testdata["virtual_machine"]["template"] = template.id
          cls._cleanup = []
  
          try:
              cls.hypervisor = cloudstackTestClient.getHypervisorInfo()
              # As Hyperv is GUI based VM, it requires more resources to be
              # able to SSH properly to it
              if cls.hypervisor.lower() == 'hyperv':
                  cls.testdata["service_offering"]["name"] = "Medium Instance"
                  cls.testdata["service_offering"]["memory"] = "1024"
                  cls.testdata["service_offering"]["cpuspeed"] = "1024"
  
              cls.service_offering = ServiceOffering.create(
                  cls.api_client,
                  cls.testdata["service_offering"])
              cls._cleanup.append(cls.service_offering)
          except Exception as e:
              cls.tearDownClass()
              raise unittest.SkipTest(e)
          return
  
      def setUp(self):
          self.apiclient = self.testClient.getApiClient()
          self.cleanup = []
  
          try:
              self.account = Account.create(self.apiclient,
                                            self.testdata["account"],
                                            domainid=self.domain.id)
              self.cleanup.append(self.account)
              self.virtual_machine = VirtualMachine.create(
                  self.api_client,
                  self.testdata["virtual_machine"],
                  accountid=self.account.name,
                  domainid=self.account.domainid,
                  serviceofferingid=self.service_offering.id,
                  mode=self.zone.networktype)
          except Exception as e:
              self.tearDown()
              raise e
  
      def tearDown(self):
          try:
              cleanup_resources(self.apiclient, self.cleanup)
          except Exception as e:
              raise Exception("Warning: Exception during cleanup : %s" % e)
          return
  
      @classmethod
      def tearDownClass(cls):
          try:
              # Cleanup resources used
              cleanup_resources(cls.api_client, cls._cleanup)
          except Exception as e:
              raise Exception("Warning: Exception during cleanup : %s" % e)
          return
  
      @attr(tags=["advanced", "selfservice"], required_hardware="false")
      def test_09_lbvmips_true(self):
          """List load balancer instances by passing lbvmips flag True
  
          steps:
          # 1. Add secondary IP for VM
          # 2. Associate public IP for the network
          # 3. Create load balancer rule for IP
          # 4. Assign load balancer rule to secondary IP
          # 5. List loadbalancer instances by specifying lbvmips flag as True
          # 6. List of load balancer instances should contain the secondary
               IP of VM used to assign lb rule to"""
  
          secondaryip = NIC.addIp(self.apiclient,
                                  id=self.virtual_machine.nic[0].id)
  
          public_ip = PublicIPAddress.create(
              self.apiclient,
              accountid=self.account.name,
              zoneid=self.zone.id,
              domainid=self.account.domainid,
              networkid=self.virtual_machine.nic[0].networkid)
  
          lb_rule = LoadBalancerRule.create(
              self.apiclient,
              self.testdata["lbrule"],
              ipaddressid=public_ip.ipaddress.id,
              accountid=self.account.name,
              networkid=self.virtual_machine.nic[0].networkid,
              domainid=self.account.domainid)
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(secondaryip.ipaddress)}]
  
          lb_rule.assign(self.apiclient,
                         vmidipmap=vmidipmap)
  
          iplist = [secondaryip.ipaddress]
  
          response = IsIpAssignedToLoadBalancerRule(self, lb_rule, iplist)
          self.assertTrue(response[0], response[1])
  
          lbruleinstances = LoadBalancerRule.listLoadBalancerRuleInstances(
              self.apiclient,
              id=lb_rule.id,
              lbvmips=True
          )
  
          self.assertEqual(validateList(lbruleinstances)[0], PASS,
                           "lbruleinstances list validation failed")
  
          self.assertEqual(str(lbruleinstances[0].lbvmipaddresses[
                           0]), secondaryip.ipaddress, "IP address in lbruleinstances list not matching\
                            with secondary ip assigned to lb rule")
  
          return
  
      @attr(tags=["advanced", "selfservice"], required_hardware="false")
      def test_10_lbvmips_false(self):
          """List load balancer instances by passing lbvmips flag False
  
          steps:
          # 1. Add secondary IP for VM
          # 2. Associate public IP for the network
          # 3. Create load balancer rule for IP
          # 4. Assign load balancer rule to secondary IP
          # 5. List loadbalancer instances by specifying lbvmips flag as False
          # 6. List of load balancer instances should not list\
               the vm ip addresses to which load balancer rule
               has been assigned"""
  
          secondaryip = NIC.addIp(self.apiclient,
                                  id=self.virtual_machine.nic[0].id)
  
          public_ip = PublicIPAddress.create(
              self.apiclient,
              accountid=self.account.name,
              zoneid=self.zone.id,
              domainid=self.account.domainid,
              networkid=self.virtual_machine.nic[0].networkid)
  
          lb_rule = LoadBalancerRule.create(
              self.apiclient,
              self.testdata["lbrule"],
              ipaddressid=public_ip.ipaddress.id,
              accountid=self.account.name,
              networkid=self.virtual_machine.nic[0].networkid,
              domainid=self.account.domainid)
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(secondaryip.ipaddress)}]
  
          lb_rule.assign(self.apiclient,
                         vmidipmap=vmidipmap)
  
          iplist = [secondaryip.ipaddress]
          response = IsIpAssignedToLoadBalancerRule(self, lb_rule, iplist)
          self.assertTrue(response[0], response[1])
  
          lbruleinstances = LoadBalancerRule.listLoadBalancerRuleInstances(
              self.apiclient,
              id=lb_rule.id,
              lbvmips=False
          )
  
          self.assertEqual(validateList(lbruleinstances)[0], PASS,
                           "lbruleinstances list validation failed")
  
          self.assertTrue(lbruleinstances[0].lbvmipaddresses is None,
                          "IP address in lbruleinstances list not matching\
                            with secondary ip assigned to lb rule")
  
          return
  
  
  class TestLbRuleFunctioning(cloudstackTestCase):
  
      @classmethod
      def setUpClass(cls):
          cloudstackTestClient = super(TestLbRuleFunctioning,
                                       cls).getClsTestClient()
          cls.api_client = cloudstackTestClient.getApiClient()
          cls.testdata = cloudstackTestClient.getParsedTestDataConfig()
          # Get Zone, Domain and templates
          cls.domain = get_domain(cls.api_client)
          cls.zone = get_zone(
              cls.api_client,
              cloudstackTestClient.getZoneForTests())
  
          template = get_template(cls.api_client,
                                  cls.zone.id,
                                  cls.testdata["ostype"])
          # Set Zones and disk offerings
          cls.testdata["virtual_machine"]["zoneid"] = cls.zone.id
          cls.testdata["virtual_machine"]["template"] = template.id
          cls._cleanup = []
  
          try:
              cls.hypervisor = cloudstackTestClient.getHypervisorInfo()
              # As Hyperv is GUI based VM, it requires more resources to be
              # able to SSH properly to it
              if cls.hypervisor.lower() == 'hyperv':
                  cls.testdata["service_offering"]["name"] = "Medium Instance"
                  cls.testdata["service_offering"]["memory"] = "1024"
                  cls.testdata["service_offering"]["cpuspeed"] = "1024"
  
              cls.service_offering = ServiceOffering.create(
                  cls.api_client,
                  cls.testdata["service_offering"])
              cls._cleanup.append(cls.service_offering)
          except Exception as e:
              cls.tearDownClass()
              raise unittest.SkipTest(e)
          return
  
      def setUp(self):
          self.apiclient = self.testClient.getApiClient()
          self.cleanup = []
  
          try:
              self.account = Account.create(self.apiclient,
                                            self.testdata["account"],
                                            domainid=self.domain.id)
              self.cleanup.append(self.account)
              self.virtual_machine = VirtualMachine.create(
                  self.api_client,
                  self.testdata["virtual_machine"],
                  accountid=self.account.name,
                  domainid=self.account.domainid,
                  serviceofferingid=self.service_offering.id,
                  mode=self.zone.networktype)
  
              self.secondaryip = NIC.addIp(self.apiclient,
                                           id=self.virtual_machine.nic[0].id)
  
              self.public_ip = PublicIPAddress.create(
                  self.apiclient,
                  accountid=self.account.name,
                  zoneid=self.zone.id,
                  domainid=self.account.domainid,
                  networkid=self.virtual_machine.nic[0].networkid)
  
              FireWallRule.create(
                  self.apiclient,
                  ipaddressid=self.public_ip.ipaddress.id,
                  protocol='TCP',
                  cidrlist=[
                      self.testdata["fwrule"]["cidr"]],
                  startport=self.testdata["fwrule"]["startport"],
                  endport=self.testdata["fwrule"]["endport"])
  
              # To make secondary IP working for VM, we have to configure it on
              # VM after acquiring it
              # Hence create NAT rule for public IP and SSH to it
              # using the primary IP of VM
              # After SSH is successful, configure the secondary IP on VM,
              # delete the NAT rule and then create LB rule for secondary IP
  
              nat_rule = NATRule.create(
                  self.apiclient,
                  self.virtual_machine,
                  self.testdata["natrule"],
                  ipaddressid=self.public_ip.ipaddress.id,
                  networkid=self.virtual_machine.nic[0].networkid)
  
              sshClient = SshClient(self.public_ip.ipaddress.ipaddress,
                                    self.testdata['natrule']["publicport"],
                                    self.virtual_machine.username,
                                    self.virtual_machine.password
                                    )
              response = sshClient.execute("netstat -i")
              # Sample Reponse:
              # [u'Kernel Interface table',
              # u'Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg',
              # u'eth2 1500  0   29     0     0       0      38    0       0     0    BMRU',
              # u'lo   16436 0   4      0     0       0       4    0       0
              # 0    LRU']}
  
              # We need to extract default interface out of the response
              defaultEthernetDevice = str(response[2].split()[0])
  
              cmd = "ip addr add {0}/24 broadcast {0} dev {1}".format(
                  self.secondaryip.ipaddress, defaultEthernetDevice)
              sshClient.execute(cmd)
              sshClient.execute("ip addr show")
  
              # Deleting NAT rule after configuring secondary IP
              nat_rule.delete(self.apiclient)
  
              self.testdata["lbrule"]["publicport"] = 22
              self.testdata["lbrule"]["privateport"] = 22
  
              self.lb_rule = LoadBalancerRule.create(
                  self.apiclient,
                  self.testdata["lbrule"],
                  ipaddressid=self.public_ip.ipaddress.id,
                  accountid=self.account.name,
                  networkid=self.virtual_machine.nic[0].networkid,
                  domainid=self.account.domainid)
          except Exception as e:
              self.tearDown()
              raise e
  
      def tearDown(self):
          try:
              cleanup_resources(self.apiclient, self.cleanup)
          except Exception as e:
              raise Exception("Warning: Exception during cleanup : %s" % e)
          return
  
      @classmethod
      def tearDownClass(cls):
          try:
              # Cleanup resources used
              cleanup_resources(cls.api_client, cls._cleanup)
          except Exception as e:
              raise Exception("Warning: Exception during cleanup : %s" % e)
          return
  
      @attr(tags=["advanced"], required_hardware="true")
      def test_11_ssh_to_secondary_ip(self):
          """SSH to VM using LB rule assigned to secondary IP of VM
  
          steps:
          # 1. Add secondary IP for VM
          # 2. Associate public IP for the network
          # 3. Create load balancer rule for IP
          # 4. Assign load balancer rule to secondary IP
          # 5. Try to SSH to VM using the public IP"""
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.secondaryip.ipaddress)}]
  
          self.lb_rule.assign(self.apiclient,
                              vmidipmap=vmidipmap)
  
          iplist = [self.secondaryip.ipaddress]
          response = IsIpAssignedToLoadBalancerRule(self, self.lb_rule, iplist)
          self.assertTrue(response[0], response[1])
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
          return
  
      @unittest.skip("Failing-WIP")
      @attr(tags=["advanced"], required_hardware="true")
      def test_12_ssh_to_primary_secondary_ip(self):
          """SSH to VM using LB rule assigned to primary and secondary IP of VM
  
          steps:
          # 1. Add secondary IP for VM
          # 2. Associate public IP for the network
          # 3. Create load balancer rule for IP
          # 4. Assign load balancer rule to primary and secondary IP of VM
          # 5. Try to SSH to VM using the public IP
          # 6. Delete the primary IP
          # 7. Try to list load balancer rule, the operation should fail
          # 8. Try to SSH to VM using the public IP, the operation should fail"""
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.secondaryip.ipaddress)}]
  
          self.lb_rule.assign(self.apiclient,
                              vmidipmap=vmidipmap)
  
          iplist = [self.secondaryip.ipaddress]
          response = IsIpAssignedToLoadBalancerRule(self, self.lb_rule, iplist)
          self.assertTrue(response[0], response[1])
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
  
          self.public_ip.delete(self.apiclient)
  
          with self.assertRaises(Exception):
              LoadBalancerRule.list(self.apiclient, id=self.lb_rule.id)
  
          with self.assertRaises(Exception):
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          return
  
      @attr(tags=["advanced"], required_hardware="true")
      def test_13_delete_lb_rule(self):
          """SSH to VM after deleting LB rule
  
          steps:
          # 1. Add secondary IP for VM
          # 2. Associate public IP for the network
          # 3. Create load balancer rule for IP
          # 4. Assign load balancer rule to primary and secondary IP of VM
          # 5. Try to SSH to VM using the public IP, it should succeed
          # 6. Delete the LB rule
          # 7. Try to SSH to VM using the public IP, operation should fail"""
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.secondaryip.ipaddress)}]
  
          self.lb_rule.assign(self.apiclient,
                              vmidipmap=vmidipmap)
  
          iplist = [self.secondaryip.ipaddress]
          response = IsIpAssignedToLoadBalancerRule(self, self.lb_rule, iplist)
          self.assertTrue(response[0], response[1])
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
  
          self.lb_rule.delete(self.apiclient)
  
          with self.assertRaises(Exception):
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          return
  
      @attr(tags=["advanced"], required_hardware="true")
      def test_14_remove_lb_rule_secondary_ip(self):
          """ssh to vm after removing secondary ip from load balancer rule
  
          steps:
          # 1. add secondary ip for vm
          # 2. associate public ip for the network
          # 3. create load balancer rule for ip
          # 4. assign load balancer rule to primary and secondary ip of vm
          # 5. try to ssh to vm using the public ip, it should succeed
          # 6. remove the secondary ip of vm from the load balancer rule
          # 7. try to ssh to vm using the public ip, it should succeed"""
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.secondaryip.ipaddress)},
                       {"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.virtual_machine.nic[0].ipaddress)}]
  
          self.lb_rule.assign(self.apiclient,
                              vmidipmap=vmidipmap)
  
          iplist = [self.secondaryip.ipaddress,
                    self.virtual_machine.nic[0].ipaddress]
          response = IsIpAssignedToLoadBalancerRule(self, self.lb_rule, iplist)
          self.assertTrue(response[0], response[1])
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.secondaryip.ipaddress)}]
  
          self.lb_rule.remove(self.apiclient,
                              vmidipmap=vmidipmap)
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
          return
  
      @attr(tags=["advanced"], required_hardware="true")
      def test_15_remove_lb_rule_primary_ip(self):
          """ssh to vm after removing secondary ip from load balancer rule
  
          steps:
          # 1. Add secondary ip for vm
          # 2. Associate public ip for the network
          # 3. Create load balancer rule for ip
          # 4. Assign load balancer rule to primary and secondary ip of vm
          # 5. Try to ssh to vm using the public ip, it should succeed
          # 6. Remove the primary ip of vm from the load balancer rule
          # 7. Try to ssh to vm using the public ip, it should succeed"""
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.secondaryip.ipaddress)},
                       {"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.virtual_machine.nic[0].ipaddress)}]
  
          self.lb_rule.assign(self.apiclient,
                              vmidipmap=vmidipmap)
  
          iplist = [self.secondaryip.ipaddress,
                    self.virtual_machine.nic[0].ipaddress]
          response = IsIpAssignedToLoadBalancerRule(self, self.lb_rule, iplist)
          self.assertTrue(response[0], response[1])
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.virtual_machine.nic[0].ipaddress)}]
  
          self.lb_rule.remove(self.apiclient,
                              vmidipmap=vmidipmap)
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
          return
  
      @attr(tags=["advanced"], required_hardware="true")
      def test_16_delete_vm_from_lb_rule(self):
          """ssh to vm after removing secondary ip from load balancer rule
  
          steps:
          # 1. Add secondary ip for vm
          # 2. Associate public ip for the network
          # 3. Create load balancer rule for ip
          # 4. Assign load balancer rule to secondary ip of vm
          # 5. Try to ssh to vm using the public ip, it should succeed
          # 6. Remove the VM from load balancer rule
          # 7. Try to list the load balancer rules for the VM,
          #    list should be empty
          # 8. Try to SSH to VM using the public IP, the opeation should fail"""
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.secondaryip.ipaddress)}]
  
          self.lb_rule.assign(self.apiclient,
                              vmidipmap=vmidipmap)
  
          iplist = [self.secondaryip.ipaddress]
          response = IsIpAssignedToLoadBalancerRule(self, self.lb_rule, iplist)
          self.assertTrue(response[0], response[1])
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
  
          self.lb_rule.remove(self.apiclient, vms=[self.virtual_machine])
  
          lbrules = LoadBalancerRule.list(
              self.apiclient,
              virtualmachineid=self.virtual_machine.id,
              listall=True)
          self.assertTrue(lbrules is None,
                          "LB rules list should be empty")
  
          with self.assertRaises(Exception):
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          return
  
      @attr(tags=["advanced"], required_hardware="true")
      def test_20_destroy_recover_vm(self):
          """Verify LB rules after destroying and recovering VM
  
          steps:
          # 1. Add secondary ip for vm
          # 2. Associate public ip for the network
          # 3. Create load balancer rule for ip
          # 4. Assign load balancer rule to secondary ip of vm
          # 5. Try to ssh to vm using the public ip, it should succeed
          # 6. Destroy VM
          # 7 Recover the VM
          # 8.Try to list the LB rule, it should be present"""
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.secondaryip.ipaddress)}]
  
          self.lb_rule.assign(self.apiclient,
                              vmidipmap=vmidipmap)
  
          iplist = [self.secondaryip.ipaddress]
          response = IsIpAssignedToLoadBalancerRule(self, self.lb_rule, iplist)
          self.assertTrue(response[0], response[1])
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
  
          # Destroy VM
          self.virtual_machine.delete(self.apiclient, expunge=False)
          # Recover VM
          self.virtual_machine.recover(self.apiclient)
          self.virtual_machine.start(self.apiclient)
  
          lbruleinstances = LoadBalancerRule.listLoadBalancerRuleInstances(
              self.apiclient,
              id=self.lb_rule.id,
              lbvmips=True
          )
          self.assertEqual(validateList(lbruleinstances)[0], PASS,
                           "lbruleinstances list validation failed")
  
          self.assertEqual(str(lbruleinstances[0].lbvmipaddresses[
                           0]), self.secondaryip.ipaddress, "IP address in lbruleinstances list not matching\
                            with secondary ip assigned to lb rule")
          return
  
      @attr(tags=["advanced"], required_hardware="true")
      def test_21_modify_lb_rule_algorithm(self):
          """Verify LB rule functioning with different algorithm
  
          steps:
          # 1. Add secondary ip for vm
          # 2. Associate public ip for the network
          # 3. Create load balancer rule for ip using roundrobin algorithm
          # 4. Assign load balancer rule to secondary ip of vm
          # 5. Try to ssh to vm using the public ip, it should succeed
          # 6. Update the algorithm of LB rule as leastconn
          # 7. Try to SSH to VM, it should succeed"""
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.secondaryip.ipaddress)}]
  
          self.lb_rule.assign(self.apiclient,
                              vmidipmap=vmidipmap)
  
          iplist = [self.secondaryip.ipaddress]
          response = IsIpAssignedToLoadBalancerRule(self, self.lb_rule, iplist)
          self.assertTrue(response[0], response[1])
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
  
          self.lb_rule.update(self.apiclient, algorithm="leastconn")
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
          return
  
  
  class TestNetworkOperations(cloudstackTestCase):
  
      @classmethod
      def setUpClass(cls):
          cloudstackTestClient = super(TestNetworkOperations,
                                       cls).getClsTestClient()
          cls.api_client = cloudstackTestClient.getApiClient()
          cls.testdata = cloudstackTestClient.getParsedTestDataConfig()
          # Get Zone, Domain and templates
          cls.domain = get_domain(cls.api_client)
          cls.zone = get_zone(
              cls.api_client,
              cloudstackTestClient.getZoneForTests())
  
          template = get_template(cls.api_client,
                                  cls.zone.id,
                                  cls.testdata["ostype"])
          # Set Zones and disk offerings
          cls.testdata["virtual_machine"]["zoneid"] = cls.zone.id
          cls.testdata["virtual_machine"]["template"] = template.id
          cls._cleanup = []
  
          try:
              cls.hypervisor = cloudstackTestClient.getHypervisorInfo()
              # As Hyperv is GUI based VM, it requires more resources to be
              # able to SSH properly to it
              if cls.hypervisor.lower() == 'hyperv':
                  cls.testdata["service_offering"]["name"] = "Medium Instance"
                  cls.testdata["service_offering"]["memory"] = "1024"
                  cls.testdata["service_offering"]["cpuspeed"] = "1024"
  
              cls.service_offering = ServiceOffering.create(
                  cls.api_client,
                  cls.testdata["service_offering"])
              cls._cleanup.append(cls.service_offering)
          except Exception as e:
              cls.tearDownClass()
              raise unittest.SkipTest(e)
          return
  
      def setUp(self):
          self.apiclient = self.testClient.getApiClient()
          self.cleanup = []
  
          try:
              self.account = Account.create(self.apiclient,
                                            self.testdata["account"],
                                            domainid=self.domain.id)
              self.cleanup.append(self.account)
              self.virtual_machine = VirtualMachine.create(
                  self.api_client,
                  self.testdata["virtual_machine"],
                  accountid=self.account.name,
                  domainid=self.account.domainid,
                  serviceofferingid=self.service_offering.id,
                  mode=self.zone.networktype)
              self.secondaryip = NIC.addIp(self.apiclient,
                                           id=self.virtual_machine.nic[0].id)
  
              self.public_ip = PublicIPAddress.create(
                  self.apiclient,
                  accountid=self.account.name,
                  zoneid=self.zone.id,
                  domainid=self.account.domainid,
                  networkid=self.virtual_machine.nic[0].networkid)
  
              FireWallRule.create(
                  self.apiclient,
                  ipaddressid=self.public_ip.ipaddress.id,
                  protocol='TCP',
                  cidrlist=[
                      self.testdata["fwrule"]["cidr"]],
                  startport=self.testdata["fwrule"]["startport"],
                  endport=self.testdata["fwrule"]["endport"])
  
              # To make secondary IP working for VM, we have to configure it
              # on VM after acquiring it
              # Hence create NAT rule for public IP and SSH to it
              # using the primary IP of VM
              # After SSH is successful, configure the secondary IP on VM,
              # delete the NAT rule  and then create LB rule for secondary IP
  
              nat_rule = NATRule.create(
                  self.apiclient,
                  self.virtual_machine,
                  self.testdata["natrule"],
                  ipaddressid=self.public_ip.ipaddress.id,
                  networkid=self.virtual_machine.nic[0].networkid)
  
              sshClient = SshClient(self.public_ip.ipaddress.ipaddress,
                                    self.testdata['natrule']["publicport"],
                                    self.virtual_machine.username,
                                    self.virtual_machine.password
                                    )
              response = sshClient.execute("netstat -i")
              # Sample Reponse:
              # [u'Kernel Interface table',
              # u'Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg',
              # u'eth2 1500  0   29     0     0       0      38    0       0     0    BMRU',
              # u'lo   16436 0   4      0     0       0       4    0       0
              # 0    LRU']}
  
              # We need to extract default interface out of the response
              defaultEthernetDevice = str(response[2].split()[0])
  
              cmd = "ip addr add {0}/24 broadcast {0} dev {1}".format(
                  self.secondaryip.ipaddress, defaultEthernetDevice)
              sshClient.execute(cmd)
              sshClient.execute("ip addr show")
  
              # Deleting NAT rule after configuring secondary IP
              nat_rule.delete(self.apiclient)
  
              self.testdata["lbrule"]["publicport"] = 22
              self.testdata["lbrule"]["privateport"] = 22
  
              self.lb_rule = LoadBalancerRule.create(
                  self.apiclient,
                  self.testdata["lbrule"],
                  ipaddressid=self.public_ip.ipaddress.id,
                  accountid=self.account.name,
                  networkid=self.virtual_machine.nic[0].networkid,
                  domainid=self.account.domainid)
          except Exception as e:
              self.tearDown()
              raise e
  
      def tearDown(self):
          try:
              cleanup_resources(self.apiclient, self.cleanup)
          except Exception as e:
              raise Exception("Warning: Exception during cleanup : %s" % e)
          return
  
      @classmethod
      def tearDownClass(cls):
          try:
              # Cleanup resources used
              cleanup_resources(cls.api_client, cls._cleanup)
          except Exception as e:
              raise Exception("Warning: Exception during cleanup : %s" % e)
          return
  
      @attr(tags=["advanced"], required_hardware="true")
      def test_17_restart_router(self):
          """Verify LB rules after restarting router VM
  
          steps:
          # 1. Add secondary ip for vm
          # 2. Associate public ip for the network
          # 3. Create load balancer rule for ip using roundrobin algorithm
          # 4. Assign load balancer rule to secondary ip of vm
          # 5. Try to ssh to vm using the public ip, it should succeed
          # 6. List the router associated with the network and restart the router
          # 7. List the LB rule, it should be present
          # 8. Try to SSH to VM, it should succeed"""
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.secondaryip.ipaddress)},
                       {"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.virtual_machine.nic[0].ipaddress)}]
  
          self.lb_rule.assign(self.apiclient,
                              vmidipmap=vmidipmap)
  
          iplist = [self.secondaryip.ipaddress,
                    self.virtual_machine.nic[0].ipaddress]
          response = IsIpAssignedToLoadBalancerRule(self, self.lb_rule, iplist)
          self.assertTrue(response[0], response[1])
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
  
          routers = Router.list(
              self.apiclient,
              networkid=self.virtual_machine.nic[0].networkid,
              listall=True)
          self.assertEqual(
              validateList(routers)[0],
              PASS,
              "routers list validation failed")
  
          Router.reboot(self.apiclient, id=routers[0].id)
  
          lbrules = LoadBalancerRule.list(
              self.apiclient,
              id=self.lb_rule.id,
              listll=True)
          self.assertEqual(
              validateList(lbrules)[0],
              PASS,
              "lbrules list validation failed")
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
          return
  
      @attr(tags=["advanced"], required_hardware="true")
      def test_18_restart_network_cleanup_true(self):
          """Verfy LB rules after restarting the network with cleanup flag set to True
  
          steps:
          # 1. Add secondary ip for vm
          # 2. Associate public ip for the network
          # 3. Create load balancer rule for ip using roundrobin algorithm
          # 4. Assign load balancer rule to secondary ip of vm
          # 5. Try to ssh to vm using the public ip, it should succeed
          # 6. Restart the network with cleanup flag set to True
          # 7. List the LB rule, it should be present
          # 8. Try to SSH to VM, it should succeed"""
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.secondaryip.ipaddress)},
                       {"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.virtual_machine.nic[0].ipaddress)}]
  
          self.lb_rule.assign(self.apiclient,
                              vmidipmap=vmidipmap)
  
          iplist = [self.secondaryip.ipaddress,
                    self.virtual_machine.nic[0].ipaddress]
          response = IsIpAssignedToLoadBalancerRule(self, self.lb_rule, iplist)
          self.assertTrue(response[0], response[1])
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
  
          cmd = restartNetwork.restartNetworkCmd()
          cmd.id = self.virtual_machine.nic[0].networkid
          cmd.cleanup = True
          self.apiclient.restartNetwork(cmd)
  
          lbrules = LoadBalancerRule.list(
              self.apiclient,
              id=self.lb_rule.id,
              listll=True)
          self.assertEqual(
              validateList(lbrules)[0],
              PASS,
              "lbrules list validation failed")
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
          return
  
      @attr(tags=["advanced"], required_hardware="true")
      def test_19_restart_network_cleanup_false(self):
          """Verfy LB rules after restarting the network with cleanup flag set to False
  
          steps:
          # 1. Add secondary ip for vm
          # 2. Associate public ip for the network
          # 3. Create load balancer rule for ip using roundrobin algorithm
          # 4. Assign load balancer rule to secondary ip of vm
          # 5. Try to ssh to vm using the public ip, it should succeed
          # 6. Restart the network with cleanup flag set to False
          # 7. List the LB rule, it should be present
          # 8. Try to SSH to VM, it should succeed"""
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.secondaryip.ipaddress)},
                       {"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.virtual_machine.nic[0].ipaddress)}]
  
          self.lb_rule.assign(self.apiclient,
                              vmidipmap=vmidipmap)
  
          iplist = [self.secondaryip.ipaddress,
                    self.virtual_machine.nic[0].ipaddress]
          response = IsIpAssignedToLoadBalancerRule(self, self.lb_rule, iplist)
          self.assertTrue(response[0], response[1])
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
  
          cmd = restartNetwork.restartNetworkCmd()
          cmd.id = self.virtual_machine.nic[0].networkid
          cmd.cleanup = False
          self.apiclient.restartNetwork(cmd)
  
          lbrules = LoadBalancerRule.list(
              self.apiclient,
              id=self.lb_rule.id,
              listll=True)
          self.assertEqual(
              validateList(lbrules)[0],
              PASS,
              "lbrules list validation failed")
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
          return
  
      @attr(tags=["advanced"], required_hardware="true")
      def test_22_network_gc(self):
          """Verify LB rule functioning to secondary IP after network GC
  
          steps:
          # 1. Add secondary ip for vm
          # 2. Associate public ip for the network
          # 3. Create load balancer rule for ip using roundrobin algorithm
          # 4. Assign load balancer rule to secondary ip of vm
          # 5. Try to ssh to vm using the public ip, it should succeed
          # 6. Stop the VM
          # 7. Wait for the network.gc time interval
          # 7. Check the state of the network, it should be allocated
          # 8. Check the state of the related router VM, it should be stopped
          # 9. Start the virtual machine
          # 8. Check the state of the network, it should be implemented now
          # 11.Check the state of the router, it should be running
          # 12.Try to SSH to the VM using public IP, it should be successful"""
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.secondaryip.ipaddress)},
                       {"vmid": str(self.virtual_machine.id),
                        "vmip": str(self.virtual_machine.nic[0].ipaddress)}]
  
          self.lb_rule.assign(self.apiclient,
                              vmidipmap=vmidipmap)
  
          iplist = [self.secondaryip.ipaddress,
                    self.virtual_machine.nic[0].ipaddress]
          response = IsIpAssignedToLoadBalancerRule(self, self.lb_rule, iplist)
          self.assertTrue(response[0], response[1])
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
  
          self.virtual_machine.stop(self.apiclient)
  
          wait_for_cleanup(self.apiclient, ["network.gc.wait",
                                            "network.gc.interval"])
  
          response = verifyNetworkState(
              self.api_client,
              self.virtual_machine.nic[0].networkid,
              "allocated")
          exceptionOccured = response[0]
          isNetworkInDesiredState = response[1]
          exceptionMessage = response[2]
  
          if (exceptionOccured or (not isNetworkInDesiredState)):
              self.fail(exceptionMessage)
  
          routers = Router.list(
              self.apiclient,
              networkid=self.virtual_machine.nic[0].networkid,
              listall=True)
          self.assertEqual(
              validateList(routers)[0],
              PASS,
              "routers list validation failed")
          self.assertEqual(
              str(routers[0].state).lower(),
              "stopped",
              "Router should be in stopped state"
          )
  
          self.virtual_machine.start(self.apiclient)
  
          response = verifyNetworkState(
              self.api_client,
              self.virtual_machine.nic[0].networkid,
              "implemented")
          exceptionOccured = response[0]
          isNetworkInDesiredState = response[1]
          exceptionMessage = response[2]
  
          if (exceptionOccured or (not isNetworkInDesiredState)):
              self.fail(exceptionMessage)
  
          routers = Router.list(
              self.apiclient,
              networkid=self.virtual_machine.nic[0].networkid,
              listall=True)
          self.assertEqual(
              validateList(routers)[0],
              PASS,
              "routers list validation failed")
          self.assertEqual(
              str(routers[0].state).lower(),
              "running",
              "Router should be in running state")
  
          try:
              SshClient(self.public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
          return
  
  
  class TestExternalLoadBalancer(cloudstackTestCase):
  
      @classmethod
      def setUpClass(cls):
          cloudstackTestClient = super(TestExternalLoadBalancer,
                                       cls).getClsTestClient()
          cls.api_client = cloudstackTestClient.getApiClient()
          cls.testdata = cloudstackTestClient.getParsedTestDataConfig()
          # Get Zone, Domain and templates
          cls.domain = get_domain(cls.api_client)
          cls.zone = get_zone(
              cls.api_client,
              cloudstackTestClient.getZoneForTests())
  
          template = get_template(cls.api_client,
                                  cls.zone.id,
                                  cls.testdata["ostype"])
          # Set Zones and disk offerings
          cls.testdata["virtual_machine"]["zoneid"] = cls.zone.id
          cls.testdata["virtual_machine"]["template"] = template.id
          cls._cleanup = []
          cls.testdata["configurableData"]\
              ["netscaler"]["lbdevicededicated"] = False
  
          try:
              cls.netscaler = add_netscaler(
                  cls.api_client,
                  cls.zone.id,
                  cls.testdata["configurableData"]["netscaler"])
              cls._cleanup.append(cls.netscaler)
          except Exception as e:
              raise unittest.SkipTest("Failed to add netscaler device: %s" % e)
  
          try:
              cls.hypervisor = cloudstackTestClient.getHypervisorInfo()
              # As Hyperv is GUI based VM, it requires more resources to be
              # able to SSH properly to it
              if cls.hypervisor.lower() == 'hyperv':
                  cls.testdata["service_offering"]["name"] = "Medium Instance"
                  cls.testdata["service_offering"]["memory"] = "1024"
                  cls.testdata["service_offering"]["cpuspeed"] = "1024"
  
              cls.service_offering = ServiceOffering.create(
                  cls.api_client,
                  cls.testdata["service_offering"])
              cls._cleanup.append(cls.service_offering)
          except Exception as e:
              cls.tearDownClass()
              raise unittest.SkipTest(e)
          return
  
      def setUp(self):
          self.apiclient = self.testClient.getApiClient()
          self.cleanup = []
  
          try:
              self.account = Account.create(self.apiclient,
                                            self.testdata["account"],
                                            domainid=self.domain.id)
              self.cleanup.append(self.account)
          except Exception as e:
              self.tearDown()
              raise e
  
      def tearDown(self):
          try:
              cleanup_resources(self.apiclient, self.cleanup)
          except Exception as e:
              raise Exception("Warning: Exception during cleanup : %s" % e)
          return
  
      @classmethod
      def tearDownClass(cls):
          try:
              # Cleanup resources used
              cleanup_resources(cls.api_client, cls._cleanup)
          except Exception as e:
              raise Exception("Warning: Exception during cleanup : %s" % e)
          return
  
      @attr(tags=["advancedns", "provisioning"], required_hardware="true")
      def test_23_lb_rule_functioning_with_netscaler(self):
          """Verify LB rule functioning for secondary IP with LB handled
             through Netscaler device
  
          steps:
          # 1. Add secondary ip for vm
          # 2. Associate public ip for the network
          # 3. Create load balancer rule for ip using roundrobin algorithm
          # 4. Assign load balancer rule to secondary ip of vm
          # 5. Try to ssh to vm using the public ip, it should succeed
          # 6. Update the algorithm of LB rule as leastconn
          # 7. Try to SSH to VM, it should succeed"""
  
          # Creating Network Offerign with LB as Netscalar
          nwoff_netscaler = NetworkOffering.create(
              self.apiclient,
              self.testdata["nw_off_isolated_netscaler"]
          )
          # Enable Network offering
          nwoff_netscaler.update(self.apiclient, state='Enabled')
          # Creating a Network Using the Network Offering
          network = Network.create(
              self.apiclient,
              self.testdata["network"],
              accountid=self.account.name,
              domainid=self.domain.id,
              networkofferingid=nwoff_netscaler.id,
              zoneid=self.zone.id
          )
  
          self.virtual_machine = VirtualMachine.create(
              self.api_client,
              self.testdata["virtual_machine"],
              accountid=self.account.name,
              domainid=self.account.domainid,
              serviceofferingid=self.service_offering.id,
              mode=self.zone.networktype,
              networkids=[network.id])
  
          secondaryip = NIC.addIp(self.apiclient,
                                  id=self.virtual_machine.nic[0].id)
  
          public_ip = PublicIPAddress.create(
              self.apiclient,
              accountid=self.account.name,
              zoneid=self.zone.id,
              domainid=self.account.domainid,
              networkid=self.virtual_machine.nic[0].networkid)
  
          FireWallRule.create(
              self.apiclient,
              ipaddressid=public_ip.ipaddress.id,
              protocol='TCP',
              cidrlist=[
                  self.testdata["fwrule"]["cidr"]],
              startport=self.testdata["fwrule"]["startport"],
              endport=self.testdata["fwrule"]["endport"])
  
          nat_rule = NATRule.create(
              self.apiclient,
              self.virtual_machine,
              self.testdata["natrule"],
              ipaddressid=public_ip.ipaddress.id,
              networkid=self.virtual_machine.nic[0].networkid)
  
          sshClient = SshClient(public_ip.ipaddress.ipaddress,
                                self.testdata['natrule']["publicport"],
                                self.virtual_machine.username,
                                self.virtual_machine.password
                                )
          response = sshClient.execute("netstat -i")
          # Sample Reponse:
          # [u'Kernel Interface table',
          # u'Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg',
          # u'eth2 1500  0   29     0     0       0      38    0       0     0    BMRU',
          # u'lo   16436 0   4      0     0       0       4    0       0     0
          # LRU']}
  
          # We need to extract default interface out of the response
          defaultEthernetDevice = str(response[2].split()[0])
  
          cmd = "ip addr add {0}/24 broadcast {0} dev {1}".format(
              secondaryip.ipaddress, defaultEthernetDevice)
          sshClient.execute(cmd)
          sshClient.execute("ip addr show")
  
          # Deleting NAT rule after configuring secondary IP
          nat_rule.delete(self.apiclient)
  
          self.testdata["lbrule"]["publicport"] = 22
          self.testdata["lbrule"]["privateport"] = 22
  
          lb_rule = LoadBalancerRule.create(
              self.apiclient,
              self.testdata["lbrule"],
              ipaddressid=public_ip.ipaddress.id,
              accountid=self.account.name,
              networkid=self.virtual_machine.nic[0].networkid,
              domainid=self.account.domainid)
  
          vmidipmap = [{"vmid": str(self.virtual_machine.id),
                        "vmip": str(secondaryip.ipaddress)}]
  
          lb_rule.assign(self.apiclient,
                         vmidipmap=vmidipmap)
  
          iplist = [secondaryip.ipaddress]
          response = IsIpAssignedToLoadBalancerRule(self, lb_rule, iplist)
          self.assertTrue(response[0], response[1])
  
          try:
              SshClient(public_ip.ipaddress.ipaddress,
                        self.testdata['lbrule']["publicport"],
                        self.virtual_machine.username,
                        self.virtual_machine.password
                        )
          except Exception as e:
              self.fail("Exception during SSH : %s" % e)
  
          return
  