Several fixes related to async_set, ip addressing, and memif interfaces for VPP 13/8713/2
authorMarcel Enguehard <[email protected]>
Mon, 9 Oct 2017 06:44:59 +0000 (08:44 +0200)
committerMarcel Enguehard <[email protected]>
Mon, 9 Oct 2017 06:55:46 +0000 (08:55 +0200)
Change-Id: I26b7928751f41ea66ba47bb1becac33cf5195915
Signed-off-by: Marcel Enguehard <[email protected]>
15 files changed:
examples/tutorial/tutorial06-acm-icn17-vpp.json [new file with mode: 0644]
examples/tutorial/tutorial06-acm-icn17.json [new file with mode: 0644]
netmodel/interfaces/process/__init__.py
vicn/core/resource.py
vicn/core/resource_mgr.py
vicn/resource/icn/central.py
vicn/resource/icn/cicn.py
vicn/resource/ip/central.py
vicn/resource/lxd/lxc_container.py
vicn/resource/vpp/interface.py
vicn/resource/vpp/memif_link.py
vicn/resource/vpp/scripts.py
vicn/resource/vpp/vpp.py
vicn/resource/vpp/vpp_commands.py
www/img/smartphone.png [new file with mode: 0644]

diff --git a/examples/tutorial/tutorial06-acm-icn17-vpp.json b/examples/tutorial/tutorial06-acm-icn17-vpp.json
new file mode 100644 (file)
index 0000000..406ac34
--- /dev/null
@@ -0,0 +1,141 @@
+{
+       "resources": [
+       {
+               "type": "Group",
+                       "name": "virtual"
+       },
+       {
+               "type": "Physical",
+               "name": "server",
+               "hostname": "localhost"
+       },
+       {
+               "type": "LxcImage",
+               "name": "cicn-image",
+               "node": "server",
+               "image": "ubuntu1604-cicnsuite-rc4"
+       },
+       {
+               "type": "GUI",
+               "port": 8000,
+               "groups": ["virtual"]
+       },
+       {
+               "type" : "LxcContainer",
+               "image": "cicn-image",
+               "name" : "cons",
+               "groups": [ "virtual" ],
+               "category": "user",
+               "node" : "server"
+       },
+       {
+               "type" : "LxcContainer",
+               "image": "cicn-image",
+               "name" : "prod",
+               "groups": [ "virtual" ],
+               "category": "video-server",
+               "node" : "server"
+       },
+       {
+               "type" : "LxcContainer",
+               "image": "cicn-image",
+               "name" : "core1",
+               "groups": [ "virtual" ],
+               "category": "icn-router-vpp",
+               "node" : "server"
+       },
+       {
+               "type" : "LxcContainer",
+               "image": "cicn-image",
+               "name" : "core2",
+               "groups": [ "virtual" ],
+               "category": "icn-router-vpp",
+               "node" : "server"
+       },
+       {
+               "type": "DpdkDevice",
+               "name": "core1-dpdk1",
+               "mac_address": "08:00:27:5c:5b:f1",
+               "node": "core1",
+               "device_name": "GigabitEthernet0/9/0",
+               "pci_address": "0000:00:09.0"
+       },
+       {
+               "type": "DpdkDevice",
+               "name": "core2-dpdk1",
+               "mac_address": "08:00:27:8c:e3:49",
+               "node": "core2",
+               "device_name": "GigabitEthernet0/a/0",
+               "pci_address": "0000:00:0a.0"
+       },
+       {
+               "type": "VPP",
+               "node": "core1",
+               "name": "vpp-core1"
+       },
+       {
+               "type": "VPP",
+               "node": "core2",
+               "name": "vpp-core2"
+       },
+       {
+               "type": "Link",
+               "src_node": "cons",
+               "dst_node": "core1",
+               "groups": [ "virtual" ]
+       },
+       {
+               "type": "PhyLink",
+               "src": "core1-dpdk1",
+               "dst": "core2-dpdk1",
+               "groups": [ "virtual" ]
+       },
+       {
+               "type": "Link",
+               "src_node": "core2",
+               "dst_node": "prod",
+               "groups": [ "virtual" ]
+       },
+       {
+               "type": "CentralIP",
+               "ip4_data_prefix": "192.168.42.0/24",
+               "ip6_data_prefix": "9002::/16",
+               "ip_routing_strategy": "spt",
+               "groups": [
+                       "virtual"
+               ]
+       },
+       {
+               "type": "MetisForwarder",
+               "cache_size": 0,
+               "node": "cons"
+       },
+       {
+               "type": "CICNForwarder",
+               "node": "core1",
+               "name": "vpp_core1"
+       },
+       {
+               "type": "CICNForwarder",
+               "node": "core2",
+               "name": "vpp_core2"
+       },
+       {
+               "type": "MetisForwarder",
+               "cache_size": 0,
+               "node": "prod"
+       },
+       {
+               "type": "WebServer",
+               "prefixes": [
+                       "/webserver"
+               ],
+               "node": "prod"
+       },
+       {
+               "type": "CentralICN",
+               "groups": [ "virtual" ],
+               "face_protocol": "udp4"
+       }
+       ]
+}
diff --git a/examples/tutorial/tutorial06-acm-icn17.json b/examples/tutorial/tutorial06-acm-icn17.json
new file mode 100644 (file)
index 0000000..e65e44d
--- /dev/null
@@ -0,0 +1,115 @@
+{
+    "resources": [
+   {
+        "type": "Group",
+        "name": "virtual"
+    },
+    {
+        "type": "Physical",
+            "name": "server",
+            "hostname": "localhost"
+    },
+    {
+        "type": "LxcImage",
+        "name": "cicn-image",
+        "node": "server",
+        "image": "ubuntu1604-cicnsuite-rc4"
+    },
+    {
+        "type": "GUI",
+        "port": 8000,
+       "groups": ["virtual"]
+    },
+    {
+        "type" : "LxcContainer",
+        "image": "cicn-image",
+        "name" : "cons",
+        "groups": [ "virtual" ],
+       "category": "user",
+        "node" : "server"
+    },
+    {
+        "type" : "LxcContainer",
+        "image": "cicn-image",
+        "name" : "prod",
+        "groups": [ "virtual" ],
+       "category": "video-server",
+        "node" : "server"
+    },
+    {
+        "type" : "LxcContainer",
+        "image": "cicn-image",
+        "name" : "core1",
+        "groups": [ "virtual" ],
+       "category": "icn-router",
+        "node" : "server"
+    },
+    {
+        "type" : "LxcContainer",
+        "image": "cicn-image",
+        "name" : "core2",
+        "groups": [ "virtual" ],
+       "category": "icn-router",
+        "node" : "server"
+    },
+   {
+        "type": "Link",
+        "src_node": "cons",
+        "dst_node": "core1",
+        "groups": [ "virtual" ]
+    },
+    {
+        "type": "Link",
+        "src_node": "core1",
+        "dst_node": "core2",
+        "groups": [ "virtual" ]
+    },
+    {
+        "type": "Link",
+        "src_node": "core2",
+        "dst_node": "prod",
+        "groups": [ "virtual" ]
+    },
+    {
+        "type": "CentralIP",
+        "ip4_data_prefix": "192.168.42.0/24",
+        "ip6_data_prefix": "9002::/16",
+        "ip_routing_strategy": "spt",
+        "groups": [
+            "virtual"
+        ]
+    },
+    {
+        "type": "MetisForwarder",
+        "cache_size": 0,
+        "node": "cons"
+    },
+    {
+        "type": "MetisForwarder",
+        "cache_size": 2000,
+        "node": "core1"
+    },
+    {
+        "type": "MetisForwarder",
+        "cache_size": 0,
+        "node": "core2"
+    },
+    {
+        "type": "MetisForwarder",
+        "cache_size": 0,
+        "node": "prod"
+    },
+    {
+        "type": "WebServer",
+        "prefixes": [
+            "/webserver"
+        ],
+        "node": "prod"
+    },
+    {
+        "type": "CentralICN",
+        "groups": [ "virtual" ],
+        "face_protocol": "udp4"
+    }
+    ]
+}
index 59bf6f9..9f3d3c1 100644 (file)
@@ -90,7 +90,7 @@ class BWMThread(Process):
             if line:
                 record = self._parse_line(line.strip())
                 # We use 'total' to push the statistics back to VICN
-                if record['iface_name'] == 'total':
+                if record.get('iface_name') == 'total':
                     for interfaces in self.groups_of_interfaces:
                         if not len(interfaces) > 1:
                             # If the tuple contains only one interface, grab
index 878a810..a80e09e 100644 (file)
@@ -467,7 +467,7 @@ class BaseResource(Object):  #, ABC, metaclass=ResourceMetaclass):
             self._state.manager.attribute_set(self, attribute_name, value)
 
     async def async_set(self, attribute_name, value, current=False,
-            set_reverse=True, blocking=None):
+            set_reverse=True):
         """
         Example:
          - setting the ip address on a node's interface
@@ -478,7 +478,12 @@ class BaseResource(Object):  #, ABC, metaclass=ResourceMetaclass):
         """
         value = self._set(attribute_name, value, current=current,
                 set_reverse=set_reverse)
-        await self._state.manager.attribute_set_async(self, attribute_name, value)
+        if self.is_local_attribute(attribute_name) or current:
+              if value is None:
+                  attribute = self.get_attribute(attribute_name)
+              vars(self)[attribute_name] = value
+        else:
+            await self._state.manager.attribute_async_set(self, attribute_name, value)
 
     def set_many(self, attribute_dict, current=False):
         if not attribute_dict:
index 8db7f04..b4aa6bb 100644 (file)
@@ -587,7 +587,7 @@ class ResourceManager(metaclass=Singleton):
         await self.wait_attr_init(resource, attribute)
         return resource.get(attribute)
 
-    async def _attribute_set(self, resource, attribute_name, value):
+    async def _attribute_set(self, resource, attribute_name, value, blocking=False):
         with await resource._state.write_lock:
 
             attr_state = resource._state.attr_state[attribute_name]
@@ -632,8 +632,8 @@ class ResourceManager(metaclass=Singleton):
                 raise RuntimeError("Resource cannot be in state".format(
                             resource_state))
 
-#        if blocking:
-#            await self.wait_attr_clean(resource, attribute_name)
+        if blocking:
+            await self.wait_attr_clean(resource, attribute_name)
 
     def attribute_set(self, resource, attribute_name, value):
         # Add the current operation to the pending list
@@ -643,15 +643,13 @@ class ResourceManager(metaclass=Singleton):
                 value)
         asyncio.ensure_future(self._attribute_set(resource, attribute_name, value))
 
-    async def attribute_set_async(self, resource, attribute_name, value):
+    async def attribute_async_set(self, resource, attribute_name, value):
         # Add the current operation to the pending list
         # NOTE: collections are unordered and can be updated concurrently
         #self._attribute_set_pending_value(resource, attribute_name)
         resource._state.dirty[attribute_name].trigger(Operations.SET,
                 value)
-        await self._attribute_set(resource, attribute_name, value)
-
-
+        await self._attribute_set(resource, attribute_name, value, blocking=True)
 
     #---------------------------------------------------------------------------
     # Resource dependency management
index aa8ea35..fd272bf 100644 (file)
@@ -81,6 +81,8 @@ class ICNFaces(Resource):
     def __delete__(self):
         raise NotImplementedError
 
+    def __after__(self):
+        return ("VPPInterface",)
     #--------------------------------------------------------------------------
     # Internal methods
     #--------------------------------------------------------------------------
@@ -102,7 +104,11 @@ class ICNFaces(Resource):
 
             map_ = data['map_node_interface']
             src = self._state.manager.by_uuid(map_[src_node_uuid])
+            if src.has_vpp_child:
+                src = src.vppinterface
             dst = self._state.manager.by_uuid(map_[dst_node_uuid])
+            if dst.has_vpp_child:
+                dst = dst.vppinterface
 
             log.debug('{} -> {} ({} -> {})'.format(src_node_uuid,
                         dst_node_uuid, src.device_name, dst.device_name))
index 8ab36ec..597692c 100644 (file)
@@ -71,7 +71,7 @@ class CICNForwarder(Forwarder):
     @inherit_parent
     def __get__(self):
         def parse(rv):
-            if rv.return_value > 0 or 'cicn: not enabled' in rv.stdout:
+            if rv.return_value > 0 or 'cicn: not enabled' in rv.stdout or "Forwarder : disabled" in rv.stdout:
                 raise ResourceNotFound
         return BashTask(self.node, CMD_VPP_CICN_GET,
                 lock = self.node.vpp.vppctl_lock, parse=parse)
@@ -134,6 +134,9 @@ class CICNForwarder(Forwarder):
 
     def _get_cache_size(self):
         def parse(rv):
-            return int(rv.stdout)
+            if not rv.stdout:
+                return 0
+            else:
+                return int(rv.stdout)
         return BashTask(self.node, CMD_VPP_CICN_GET_CACHE_SIZE, parse=parse,
                 lock = self.node.vpp.vppctl_lock)
index 0c39772..75b590e 100644 (file)
@@ -82,7 +82,8 @@ class IPRoutes(Resource):
                     node_uuid = interface.node._state.uuid
                     if not node_uuid in origins:
                         origins[node_uuid] = list()
-                    origins[node_uuid].append(interface.ip4_address.canonical_prefix())
+                    if interface.ip4_address:
+                        origins[node_uuid].append(interface.ip4_address.canonical_prefix())
                     if interface.ip6_address:
                         origins[node_uuid].append(interface.ip6_address.canonical_prefix())
         return origins
@@ -113,7 +114,6 @@ class IPRoutes(Resource):
             # Avoid duplicate routes due to multiple paths in the network
             if not src_node in ip_routes:
                 ip_routes[src_node] = set()
-                #XXX Untested for VPP
                 #When you set up an IP address ip/prefix_len (ip addr add), you already create a route
                 #towards ip/prefix_len
                 for interface in src_node.interfaces:
index a9f8483..3222cc8 100644 (file)
@@ -19,6 +19,7 @@
 import logging
 import shlex
 import time
+import requests
 
 # Suppress logging from pylxd dependency on ws4py
 # (this needs to be included before pylxd)
index 9dbd7fc..f845e2d 100644 (file)
@@ -34,11 +34,18 @@ from vicn.resource.vpp.vpp_commands import CMD_VPP_CREATE_IFACE, CMD_VPP_CREATE_
 from vicn.resource.vpp.vpp_commands import CMD_VPP_SET_IP, CMD_VPP_SET_UP
 from vicn.resource.vpp.memif_device import MemifDevice
 
+VPP_vers = (17, 7)
+
 GREP_MEMIF_INFO = 'vppctl_wrapper show memif | grep interface --no-group-separator -A 1'
 
 def parse_memif(rv, vppinterface):
     kw_interface = pp.CaselessKeyword('interface')
     kw_key = pp.CaselessKeyword('key')
+    kw_remote_name =  pp.CaselessKeyword('remote-name')
+    kw_remote_if =  pp.CaselessKeyword('remote-interface')
+    kw_id = pp.CaselessKeyword('id')
+    kw_mode = pp.CaselessKeyword('mode')
+    kw_ethernet = pp.CaselessKeyword('ethernet')
     kw_file = pp.CaselessKeyword('file')
     kw_listener = pp.CaselessKeyword('listener')
     kw_connfd = pp.CaselessKeyword('conn-fd')
@@ -51,20 +58,41 @@ def parse_memif(rv, vppinterface):
     r_path = ' *(/[a-zA-Z0-9_\-]*)*\.[a-zA-Z0-9_\-]*'
     r_id = ' *-+[0-9]*'
 
-    single = kw_interface.suppress() + pp.Word(pp.alphanums).setResultsName('interface') + \
-             kw_key.suppress() + pp.Word(pp.alphanums).setResultsName('key') + \
-             kw_file.suppress() + pp.Regex(r_path).setResultsName('path')  # + \
-             # kw_listener.suppress() + pp.Word(pp.alphanums).setResultsName('listener') + \
-             # kw_connfd.suppress() + pp.Regex(r_id).setResultsName('conn-fd') + \
-             # kw_intfd.suppress() + pp.Regex(r_id).setResultsName('int-fd') + \
-             # kw_ringsize.suppress() + pp.Word(pp.nums).setResultsName('ring-size') + \
-             # kw_numc2srings.suppress() + pp.Word(pp.nums).setResultsName('num-c2s-rings') + \
-             # kw_nums2crings.suppress() + pp.Word(pp.nums).setResultsName('num-s2c-rings') + \
-             # kw_buffersize.suppress() + pp.Word(pp.nums).setResultsName('buffer-size')
+    r_remote_name = '"[A-Z]+ [0-9\.]+-[a-z]+"'
+    r_remote_if   = '"[a-zA-Z0-9_\-]+"'
+
+    if VPP_vers >= (17, 7):
+        single = kw_interface.suppress() + pp.Word(pp.alphanums).setResultsName('interface') + \
+                 pp.Optional(kw_remote_name.suppress() + pp.Regex(r_remote_name).setResultsName('remote_name') + \
+                 kw_remote_if.suppress() + pp.Regex(r_remote_if).setResultsName('remote_if')) + \
+                 kw_id.suppress() + pp.Word(pp.alphanums).setResultsName('key') + \
+                 kw_mode.suppress() + kw_ethernet.suppress() + \
+                 kw_file.suppress() + pp.Regex(r_path).setResultsName('path')  # + \
+                 # kw_listener.suppress() + pp.Word(pp.alphanums).setResultsName('listener') + \
+                 # kw_connfd.suppress() + pp.Regex(r_id).setResultsName('conn-fd') + \
+                 # kw_intfd.suppress() + pp.Regex(r_id).setResultsName('int-fd') + \
+                 # kw_ringsize.suppress() + pp.Word(pp.nums).setResultsName('ring-size') + \
+                 # kw_numc2srings.suppress() + pp.Word(pp.nums).setResultsName('num-c2s-rings') + \
+                 # kw_nums2crings.suppress() + pp.Word(pp.nums).setResultsName('num-s2c-rings') + \
+                 # kw_buffersize.suppress() + pp.Word(pp.nums).setResultsName('buffer-size')
+    else:
+        single = kw_interface.suppress() + pp.Word(pp.alphanums).setResultsName('interface') + \
+                 kw_key.suppress() + pp.Word(pp.alphanums).setResultsName('key') + \
+                 kw_file.suppress() + pp.Regex(r_path).setResultsName('path')  # + \
+                 # kw_listener.suppress() + pp.Word(pp.alphanums).setResultsName('listener') + \
+                 # kw_connfd.suppress() + pp.Regex(r_id).setResultsName('conn-fd') + \
+                 # kw_intfd.suppress() + pp.Regex(r_id).setResultsName('int-fd') + \
+                 # kw_ringsize.suppress() + pp.Word(pp.nums).setResultsName('ring-size') + \
+                 # kw_numc2srings.suppress() + pp.Word(pp.nums).setResultsName('num-c2s-rings') + \
+                 # kw_nums2crings.suppress() + pp.Word(pp.nums).setResultsName('num-s2c-rings') + \
+                 # kw_buffersize.suppress() + pp.Word(pp.nums).setResultsName('buffer-size')
 
     multiple = pp.OneOrMore(pp.Group(single))
 
-    results = multiple.parseString(rv.stdout)
+    try:
+         results = multiple.parseString(rv.stdout)
+    except Exception as e:
+         import pdb; pdb.set_trace()
 
     for interface in results:
         if interface['path'] == vppinterface.parent.path_unix_socket + vppinterface.parent.socket_name:
@@ -108,7 +136,7 @@ class VPPInterface(Resource):
         """
         We need CentralIP to get the parent interface IP address
         """
-        return ['CentralIP']
+        return ['CentralIP', 'IpAssignment']
 
     @inherit_parent
     @inline_task
@@ -126,9 +154,23 @@ class VPPInterface(Resource):
         self.parent.has_vpp_child = True
         self.up = True
 
+        self.ip4_address = self.parent.ip4_address
+        self.ip6_address = self.parent.ip6_address
+
         if isinstance(self.parent, MemifDevice):
+            self.device_name = self.parent.device_name
+
             #TODO: add output parsing to get the interface name
-            create_task = BashTask(self.vpp.node, CMD_VPP_CREATE_MEMIFACE, {
+            if VPP_vers >= (17, 7):
+                create_task = BashTask(self.vpp.node, CMD_VPP_CREATE_MEMIFACE, {
+                    'key_label': 'id',
+                    'key': self.parent.key,
+                    'vpp_interface': self,
+                    'master_slave': 'master' if self.parent.master else 'slave'},
+                    lock = self.vpp.vppctl_lock)
+            else:
+                create_task = BashTask(self.vpp.node, CMD_VPP_CREATE_MEMIFACE, {
+                    'key_label': 'key',
                     'key': hex(self.parent.key),
                     'vpp_interface': self,
                     'master_slave': 'master' if self.parent.master else 'slave'},
@@ -143,8 +185,8 @@ class VPPInterface(Resource):
             # Remove ip address in the parent device, it must only be set in
             # the vpp interface otherwise vpp and the linux kernel will reply
             # to non-icn request (e.g., ARP replies, port ureachable etc)
-            self.ip4_address = self.parent.ip4_address
-            self.ip6_address = self.parent.ip6_address
+            self.parent.ip4_address = None
+            self.parent.ip6_address = None
 
             self.device_name = 'host-' + self.parent.device_name
             create_task = BashTask(self.vpp.node, CMD_VPP_CREATE_IFACE,
@@ -155,8 +197,6 @@ class VPPInterface(Resource):
             self.parent.remote.set('offload', False)
 
         elif self.parent.get_type() == 'dpdkdevice':
-            self.ip4_address = self.parent.ip4_address
-            self.ip6_address = self.parent.ip6_address
             self.device_name = self.parent.device_name
         else :
             # Currently assume naively that everything else will be a physical
index 62de03c..25cfeea 100644 (file)
@@ -90,7 +90,7 @@ class MemifLink(Channel):
                 foldername = SHARED_FOLDER_PATH.format(self.src_node.name + '-' + self.dst_node.name),
                 permission = 777)
 
-        self.key = random.randint(0, 2**64)
+        self.key = random.randint(0, 2**31)
 
         self._src = MemifDevice(node = self.src_node,
                 channel = self,
index 06da740..b467df6 100644 (file)
@@ -282,7 +282,7 @@ api-segment {
 '''
 
 APPARMOR_VPP_PROFILE = '''
-lxc.aa_profile = lxc-dpdk
+lxc.apparmor.profile = lxc-dpdk
 lxc.mount.entry = hugetlbfs dev/hugepages hugetlbfs rw,relatime,create=dir 0 0
 lxc.mount.auto = sys:rw'''
 
index 9d4f706..a185c03 100644 (file)
@@ -147,7 +147,10 @@ class VPP(LinuxApplication):
                 if numa in socket_mem:
                     socket_mem_str = socket_mem_str + str(socket_mem[numa])
                 else:
-                    socket_mem_str = socket_mem_str + '0'
+                    if None in socket_mem: #No numa nodes on machine but DpdkDevice has socket mem
+                        socket_mem_str = socket_mem_str+str(socket_mem[None])
+                    else:
+                        socket_mem_str = socket_mem_str + '0'
 
                 if numa < numa_mgr.get_number_of_numa()-1:
                     socket_mem_str = socket_mem_str + ','
index acc8964..e0b7151 100644 (file)
@@ -6,6 +6,7 @@ CMD_VPP_DISABLE = 'systemctl disable vpp.service'
 # 'sleep 1' ensures that VPP has enough time to start
 CMD_VPP_START = '''
 flock /tmp/vppctl.lock -c "systemctl start vpp"
+sleep 2
 '''
 CMD_VPP_STOP = '''
 flock /tmp/vppctl.lock -c "systemctl stop vpp"
@@ -25,7 +26,7 @@ vppctl_wrapper set interface state {vpp_interface.device_name} up
 # generated by VPP, preventing any reboot of VPP and recreation of commands
 CMD_VPP_CREATE_MEMIFACE = '''
 # Create vpp interface from shared_memory
-vppctl_wrapper create memif key {key} socket {vpp_interface.parent.path_unix_socket}{vpp_interface.parent.socket_name} hw-addr {vpp_interface.parent.mac_address} {master_slave}
+vppctl_wrapper create memif {key_label} {key} socket {vpp_interface.parent.path_unix_socket}{vpp_interface.parent.socket_name} hw-addr {vpp_interface.parent.mac_address} {master_slave}
 '''
 CMD_VPP_SET_IP = 'vppctl_wrapper set int ip address {device_name} {ip_address}/{prefix_len}'
 CMD_VPP_SET_UP = 'vppctl_wrapper set int state {netdevice.device_name} {state}'
diff --git a/www/img/smartphone.png b/www/img/smartphone.png
new file mode 100644 (file)
index 0000000..a550603
--- /dev/null
@@ -0,0 +1,17 @@
+<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>Log in - Bitbucket Engineering - GPK1</title><script>
+window.WRM=window.WRM||{};window.WRM._unparsedData=window.WRM._unparsedData||{};window.WRM._unparsedErrors=window.WRM._unparsedErrors||{};
+WRM._unparsedData["com.atlassian.plugins.atlassian-plugins-webresource-plugin:context-path.context-path"]="\u0022\u005C/bitbucket\u0022";
+WRM._unparsedData["com.atlassian.bitbucket.server.feature-wrm-data:nps.survey.inline.dialog.data"]="true";
+WRM._unparsedData["com.atlassian.bitbucket.server.feature-wrm-data:nps.experiment.enabled.by.sen.data"]="false";
+WRM._unparsedData["com.atlassian.analytics.analytics-client:policy-update-init.policy-update-data-provider"]="false";
+WRM._unparsedData["com.atlassian.analytics.analytics-client:programmatic-analytics-init.programmatic-analytics-data-provider"]="false";
+WRM._unparsedData["com.atlassian.bitbucket.server.feature-wrm-data:user.time.zone.onboarding.data"]="true";
+WRM._unparsedData["com.onresolve.stash.groovy.groovyrunner:web-item-response-renderer.web-item-actions-data-provider"]="[]";
+if(window.WRM._dataArrived)window.WRM._dataArrived();</script>
+<link type="text/css" rel="stylesheet" href="/bitbucket/s/82df8258d43f2df4e9585366ca557b2f-CDN/-939794491/2d88633/1/f6c15e06311faedbd487c69e6f778cd6/_/download/contextbatch/css/_super/batch.css" data-wrm-key="_super" data-wrm-batch-type="context" media="all">
+<link type="text/css" rel="stylesheet" href="/bitbucket/s/96d1ecf23add4e429d5b6ac78be1cee6-CDN/-939794491/2d88633/1/ea28cfaf2acbe7b82e7be0a0260044b0/_/download/contextbatch/css/bitbucket.page.login,-_super/batch.css" data-wrm-key="bitbucket.page.login,-_super" data-wrm-batch-type="context" media="all">
+<link type="text/css" rel="stylesheet" href="/bitbucket/s/5a3a87ce25d238c0d4002dc9c05fbf0c-CDN/-939794491/2d88633/1/e3a624d4fc67a5cb809b2d1170261aba/_/download/contextbatch/css/bitbucket.layout.focused,bitbucket.layout.base,atl.general,-_super/batch.css?analytics-enabled=true&amp;analytics-uploadable=true&amp;nps-acknowledged=true&amp;supportedApplication=true" data-wrm-key="bitbucket.layout.focused,bitbucket.layout.base,atl.general,-_super" data-wrm-batch-type="context" media="all">
+<script type="text/javascript" src="/bitbucket/s/2faa0515c8c366460fd78a389fc54d62-CDN/-939794491/2d88633/1/f6c15e06311faedbd487c69e6f778cd6/_/download/contextbatch/js/_super/batch.js?locale=en-US" data-wrm-key="_super" data-wrm-batch-type="context" data-initially-rendered></script>
+<script type="text/javascript" src="/bitbucket/s/4a4cfef7b765f19375f9b621da68887c-CDN/-939794491/2d88633/1/ea28cfaf2acbe7b82e7be0a0260044b0/_/download/contextbatch/js/bitbucket.page.login,-_super/batch.js?locale=en-US" data-wrm-key="bitbucket.page.login,-_super" data-wrm-batch-type="context" data-initially-rendered></script>
+<script type="text/javascript" src="/bitbucket/s/d56f03b50edb7c9704be7e094abecc22-CDN/-939794491/2d88633/1/e3a624d4fc67a5cb809b2d1170261aba/_/download/contextbatch/js/bitbucket.layout.focused,bitbucket.layout.base,atl.general,-_super/batch.js?analytics-enabled=true&amp;analytics-uploadable=true&amp;locale=en-US&amp;nps-acknowledged=true&amp;supportedApplication=true" data-wrm-key="bitbucket.layout.focused,bitbucket.layout.base,atl.general,-_super" data-wrm-batch-type="context" data-initially-rendered></script>
+<meta name="application-name" content="Bitbucket"><link rel="shortcut icon" type="image/x-icon" href="/bitbucket/s/-939794491/2d88633/1/1.0/_/download/resources/com.atlassian.bitbucket.server.bitbucket-web:favicon/favicon.ico" /><link rel="search" href="https://bitbucket-eng-gpk1.cisco.com/bitbucket/plugins/servlet/opensearch-descriptor" type="application/opensearchdescription+xml" title="Bitbucket code search" /></head><body class="aui-page-focused aui-page-focused-small aui-page-size-small bitbucket-theme user-login"><ul id="assistive-skip-links" class="assistive"><li><a href="#content">Skip to content</a></li></ul><div id="page"><!-- start #header --><header id="header" role="banner"><section class="notifications"></section><nav class="aui-header aui-dropdown2-trigger-group" role="navigation"><div class="aui-header-inner"><div class="aui-header-before"><a class=" aui-dropdown2-trigger app-switcher-trigger" aria-controls="app-switcher" aria-haspopup="true" role="button" tabindex="0" data-aui-trigger href="#app-switcher"><span class="aui-icon aui-icon-small aui-iconfont-appswitcher">Linked Applications</span></a><div id="app-switcher" class="aui-dropdown2 aui-style-default" role="menu" aria-hidden="true" data-is-switcher="true" data-environment="{&quot;isUserAdmin&quot;:false,&quot;isAppSuggestionAvailable&quot;:false,&quot;isSiteAdminUser&quot;:false}"><div role="application"><div class="app-switcher-loading">Loading&hellip;</div></div></div></div><div class="aui-header-primary"><h1 id="logo" class="aui-header-logo aui-header-logo-bitbucket"><a href="https://bitbucket-eng-gpk1.cisco.com/bitbucket" class="stash"><span class="aui-header-logo-device">Bitbucket</span></a></h1><meta name="stp-license-product-name" content="Bitbucket"/> <meta name="stp-license-days-to-expiry" content="195"/> <meta name="stp-license-is-admin" content="false"/> <meta name="stp-license-should-keep-banner-hidden" content="true"/><ul class="aui-nav"></ul></div><div class="aui-header-secondary"><ul class="aui-nav"><li class=" help-link"title="Help"><a class=" aui-dropdown2-trigger aui-dropdown2-trigger-arrowless" aria-controls="com.atlassian.bitbucket.server.bitbucket-server-web-fragments-help-menu" aria-haspopup="true" role="button" tabindex="0" data-aui-trigger><span class="aui-icon aui-icon-small aui-iconfont-help">Help</span><span class="icon aui-icon-dropdown"></span></a><div id="com.atlassian.bitbucket.server.bitbucket-server-web-fragments-help-menu" class="aui-dropdown2 aui-style-default" role="menu" aria-hidden="true"><div role="application"><div class="aui-dropdown2-section help-items-section"><ul class="aui-list-truncate" role="presentation"><li role="presentation"><a href="http://docs.atlassian.com/bitbucketserver/docs-0414/Bitbucket+Server+Documentation+Home?utm_campaign=in-app-help&amp;amp;utm_medium=in-app-help&amp;amp;utm_source=stash" title="Go to the online documentation for Bitbucket" data-web-item-key="com.atlassian.bitbucket.server.bitbucket-server-web-fragments:general-help">Online help</a></li><li role="presentation"><a href="https://www.atlassian.com/git?utm_campaign=learn-git&amp;utm_medium=in-app-help&amp;utm_source=stash" title="Learn about Git commands &amp; workflows" data-web-item-key="com.atlassian.bitbucket.server.bitbucket-server-web-fragments:learn-git">Learn Git</a></li><li role="presentation"><a href="/bitbucket/getting-started" class="getting-started-page-link" title="Overview of Bitbucket features" data-web-item-key="com.atlassian.bitbucket.server.bitbucket-server-web-fragments:getting-started-page-help-link">Welcome to Bitbucket</a></li><li role="presentation"><a href="/bitbucket/#" class="keyboard-shortcut-link" title="Discover keyboard shortcuts in Bitbucket" data-web-item-key="com.atlassian.bitbucket.server.bitbucket-server-web-fragments:keyboard-shortcuts-help-link">Keyboard shortcuts</a></li></ul></div></div></div></li><li class=" alerts-menu"title="View system alerts"><a href="#alerts" id="alerts-trigger" class="alerts-menu" title="View system alerts" data-web-item-key="com.atlassian.bitbucket.server.bitbucket-server-web-fragments:global-alerts-menu-item">Alerts</a></li></ul></div></div> <!-- End .aui-header-inner --></nav> <!-- End .aui-header --></header><!-- End #header --><!-- Start #content --><section id="content" role="main" tabindex="-1" data-timezone="0" ><div class="aui-page-panel content-body"><div class="aui-page-panel-inner"><section class="aui-page-panel-content"><h2>Log in</h2><form class="aui top-label prevent-double-submit " action="/bitbucket/j_atl_security_check" method="post" accept-charset="UTF-8"><div class="field-group"><label for="j_username" >Username</label><input class="text long-field" type="text" id="j_username"  name="j_username"  autofocus accesskey="u"/></div><div class="field-group"><label for="j_password" >Password</label><input class="text long-field" type="password" id="j_password"  name="j_password"  accesskey="p"/></div><div class="aui-group"><fieldset class="group checkbox"><div class="checkbox"><input class="checkbox" type="checkbox" id="_atl_remember_me"  name="_atl_remember_me"  checked="checked"  accesskey="r"/><label for="_atl_remember_me" >Keep me logged in</label></div></fieldset></div><div class="aui-group"><input name="next" type="hidden" value="/projects/ICN/repos/vicn/raw/www/img/smartphone.png?at=refs%2Fheads%2Fhicn"/><input class="aui-button aui-button-primary" type="submit" id="submit"  name="submit"  value="Log in" accesskey="s"/><a id="forgot" class="aui-button aui-button-link"  name="forgot" href="/bitbucket/passwordreset" autocomplete="off" tabindex="0">Unable to access your account?</a></div></form></section><!-- .aui-page-panel-content --></div><!-- .aui-page-panel-inner --></div><!-- .aui-page-panel --></section><!-- End #content --><!-- Start #footer --><footer id="footer" role="contentinfo"><section class="notifications"></section><section class="footer-body"><ul><li data-key="footer.license.message">Git repository management for enterprise teams powered by <a href="http://www.atlassian.com/software/bitbucket/">Atlassian Bitbucket</a></li></ul><ul><li>Atlassian Bitbucket <span title="2d88633916d4728474f8176943c3902a66488f86" id="product-version" data-commitid="2d88633916d4728474f8176943c3902a66488f86" data-system-build-number="2d88633"> v4.14.5</span></li><li data-key="footer.links.documentation"><a href="http://docs.atlassian.com/bitbucketserver/docs-0414/Bitbucket+Server+Documentation+Home?utm_campaign=in-app-help&amp;utm_medium=in-app-help&amp;utm_source=stash" target="_blank">Documentation</a></li><li data-key="footer.links.contact.support"><a href="https://support.atlassian.com/secure/SENVerification.jspa?issuetype=1&pid=10740" target="_blank">Contact Support</a></li><li data-key="footer.links.jac"><a href="https://jira.atlassian.com/browse/BSERV" target="_blank">Request a feature</a></li><li data-key="footer.links.about"><a href="/bitbucket/about">About</a></li><li data-key="footer.links.contact.atlassian"><a href="http://www.atlassian.com/company/contact/" target="_blank">Contact Atlassian</a></li></ul><div id="footer-logo"><a href="http://www.atlassian.com/" target="_blank">Atlassian</a></div></section></footer><!-- End #footer --></div><script>require('bitbucket/internal/layout/base').onReady(null, "Bitbucket Engineering - GPK1" ); require('bitbucket/internal/widget/keyboard-shortcuts').onReady();</script><script type="text/javascript">require('bitbucket/internal/page/login').onReady();</script></body></html>
\ No newline at end of file