components/openstack/neutron/files/agent/solaris/interface.py
changeset 4975 6445e44cfccd
parent 4389 a44bb9a2917e
child 5405 66fd59fecd68
--- a/components/openstack/neutron/files/agent/solaris/interface.py	Tue Oct 13 09:20:24 2015 -0700
+++ b/components/openstack/neutron/files/agent/solaris/interface.py	Fri Oct 16 15:53:02 2015 -0700
@@ -14,18 +14,33 @@
 #
 # @author: Girish Moodalbail, Oracle, Inc.
 
+import rad.bindings.com.oracle.solaris.rad.evscntl_1 as evsbind
+import rad.client as radcli
+import rad.connect as radcon
+
 from oslo.config import cfg
 
 from neutron.agent.linux import utils
 from neutron.agent.solaris import net_lib
+from neutron.common import exceptions
+from neutron.openstack.common import log as logging
 
 
+LOG = logging.getLogger(__name__)
+
 OPTS = [
     cfg.StrOpt('evs_controller', default='ssh://evsuser@localhost',
                help=_("An URI that specifies an EVS controller"))
 ]
 
 
+class EVSControllerError(exceptions.NeutronException):
+    message = _("EVS controller: %(errmsg)s")
+
+    def __init__(self, evs_errmsg):
+        super(EVSControllerError, self).__init__(errmsg=evs_errmsg)
+
+
 class SolarisVNICDriver(object):
     """Driver used to manage Solaris EVS VNICs.
 
@@ -54,6 +69,9 @@
             raise SystemExit(_("'user' and 'hostname' need to be specified "
                                "for evs_controller"))
 
+        # save the user and EVS controller info
+        self.uh = uh
+        self._rad_connection = None
         # set the controller property for this host
         cmd = ['/usr/sbin/evsadm', 'show-prop', '-co', 'value', '-p',
                'controller']
@@ -63,17 +81,31 @@
                    'controller=%s' % (conf.evs_controller)]
             utils.execute(cmd)
 
+    @property
+    def rad_connection(self):
+        if (self._rad_connection is not None and
+                self._rad_connection._closed is None):
+            return self._rad_connection
+
+        LOG.debug(_("Connecting to EVS Controller at %s as %s") %
+                  (self.uh[1], self.uh[0]))
+
+        self._rad_connection = radcon.connect_ssh(self.uh[1], user=self.uh[0])
+        return self._rad_connection
+
     def fini_l3(self, device_name):
         ipif = net_lib.IPInterface(device_name)
         ipif.delete_ip()
 
-    def init_l3(self, device_name, ip_cidrs):
+    def init_l3(self, device_name, ip_cidrs, addrconf=False):
         """Set the L3 settings for the interface using data from the port.
            ip_cidrs: list of 'X.X.X.X/YY' strings
         """
         ipif = net_lib.IPInterface(device_name)
         for ip_cidr in ip_cidrs:
             ipif.create_address(ip_cidr)
+        if addrconf:
+            ipif.create_addrconf()
 
     # TODO(gmoodalb): - probably take PREFIX?? for L3
     def get_device_name(self, port):
@@ -86,27 +118,42 @@
              namespace=None, prefix=None, protection=False):
         """Plug in the interface."""
 
-        evs_vport = ('%s/%s') % (network_id, port_id)
-        dl = net_lib.Datalink(datalink_name)
+        try:
+            evsc = self.rad_connection.get_object(evsbind.EVSController())
+            vports_info = evsc.getVPortInfo("vport=%s" % (port_id))
+            if vports_info:
+                vport_info = vports_info[0]
+                # This is to handle HA when the 1st DHCP/L3 agent is down and
+                # the second DHCP/L3 agent tries to connect its VNIC to EVS, we
+                # will end up in "vport in use" error. So, we need to reset the
+                # vport before we connect the VNIC to EVS.
+                if vport_info.status == evsbind.VPortStatus.USED:
+                    LOG.debug(_("Retrieving EVS: %s"), vport_info.evsuuid)
+                    pat = radcli.ADRGlobPattern({'uuid': network_id,
+                                                 'tenant': tenant_id})
+                    evs_objs = self.rad_connection.list_objects(evsbind.EVS(),
+                                                                pat)
+                    if evs_objs:
+                        evs = self.rad_connection.get_object(evs_objs[0])
+                        evs.resetVPort(port_id, "force=yes")
 
-        # This is to handle HA when the 1st DHCP/L3 agent is down and
-        # the second DHCP/L3 agent tries to connect its VNIC to EVS, we will
-        # end up in "vport in use" error. So, we need to reset the vport
-        # before we connect the VNIC to EVS.
-        cmd = ['/usr/sbin/evsadm', 'show-vport', '-f',
-               'vport=%s' % port_id, '-co', 'evs,vport,status']
-        stdout = utils.execute(cmd)
-        evsname, vportname, status = stdout.strip().split(':')
-        if status == 'used':
-            cmd = ['/usr/sbin/evsadm', 'reset-vport', '-T', tenant_id,
-                   '%s/%s' % (evsname, vportname)]
-            utils.execute(cmd)
+                if not protection:
+                    LOG.debug(_("Retrieving VPort: %s"), port_id)
+                    pat = radcli.ADRGlobPattern({'uuid': port_id,
+                                                 'tenant': tenant_id,
+                                                 'evsuuid': network_id})
+                    vport_objs = self.rad_connection.list_objects(
+                        evsbind.VPort(), pat)
+                    if vport_objs:
+                        vport = self.rad_connection.get_object(vport_objs[0])
+                        vport.setProperty("protection=none")
+        except radcli.ObjectError as oe:
+            raise EVSControllerError(oe.get_payload().errmsg)
+        finally:
+            self.rad_connection.close()
 
-        if not protection:
-            cmd = ['/usr/sbin/evsadm', 'set-vportprop', '-T', tenant_id,
-                   '-p', 'protection=none', evs_vport]
-            utils.execute(cmd)
-
+        dl = net_lib.Datalink(datalink_name)
+        evs_vport = "%s/%s" % (network_id, port_id)
         dl.connect_vnic(evs_vport, tenant_id)
 
     def unplug(self, device_name, namespace=None, prefix=None):